feat: add type definitions (FormDefinition, FormField, settings)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Luca Oelfke 2026-02-13 13:12:39 +01:00
parent e9e87d52b1
commit b6f7d0db64

93
src/types.ts Normal file
View file

@ -0,0 +1,93 @@
// ---------------------------------------------------------------------------
// Field Types
// ---------------------------------------------------------------------------
export type FieldType =
| 'text'
| 'textarea'
| 'number'
| 'toggle'
| 'date'
| 'dropdown'
| 'tags'
| 'note-link'
| 'folder-picker'
| 'rating';
export interface FormField {
id: string;
label: string;
type: FieldType;
required: boolean;
defaultValue?: string | number | boolean | string[];
placeholder?: string;
/** For dropdown: list of options. For tags: suggested tags. */
options?: string[];
/** For note-link: restrict to files in this folder. */
folder?: string;
}
// ---------------------------------------------------------------------------
// Form Definition
// ---------------------------------------------------------------------------
export interface FormDefinition {
id: string;
name: string;
icon: string;
mode: 'create' | 'update';
// mode: "create" only
targetFolder?: string;
fileNameTemplate?: string;
bodyTemplate?: string;
// mode: "update" only
targetFile?: 'active' | 'prompt';
fields: FormField[];
}
// ---------------------------------------------------------------------------
// Settings
// ---------------------------------------------------------------------------
export interface FormfireSettings {
forms: FormDefinition[];
}
export const DEFAULT_SETTINGS: FormfireSettings = {
forms: [],
};
// ---------------------------------------------------------------------------
// Utilities
// ---------------------------------------------------------------------------
/** Recursively merge source into target. Arrays are replaced, not merged. */
export function deepMerge<T extends Record<string, unknown>>(
target: T,
source: Partial<T>,
): T {
const result = { ...target };
for (const key of Object.keys(source) as (keyof T)[]) {
const srcVal = source[key];
const tgtVal = target[key];
if (
srcVal !== null &&
typeof srcVal === 'object' &&
!Array.isArray(srcVal) &&
tgtVal !== null &&
typeof tgtVal === 'object' &&
!Array.isArray(tgtVal)
) {
result[key] = deepMerge(
tgtVal as Record<string, unknown>,
srcVal as Record<string, unknown>,
) as T[keyof T];
} else if (srcVal !== undefined) {
result[key] = srcVal as T[keyof T];
}
}
return result;
}