UNPKG

@proofkit/fmodata

Version:
247 lines (212 loc) 6.17 kB
import type { FFetchOptions } from "@fetchkit/ffetch"; import type { ExecutionContext } from "../types"; type GenericField = { name: string; nullable?: boolean; primary?: boolean; unique?: boolean; global?: boolean; repetitions?: number; }; type StringField = GenericField & { type: "string"; maxLength?: number; default?: "USER" | "USERNAME" | "CURRENT_USER"; }; type NumericField = GenericField & { type: "numeric"; }; type DateField = GenericField & { type: "date"; default?: "CURRENT_DATE" | "CURDATE"; }; type TimeField = GenericField & { type: "time"; default?: "CURRENT_TIME" | "CURTIME"; }; type TimestampField = GenericField & { type: "timestamp"; default?: "CURRENT_TIMESTAMP" | "CURTIMESTAMP"; }; type ContainerField = GenericField & { type: "container"; externalSecurePath?: string; }; export type Field = | StringField | NumericField | DateField | TimeField | TimestampField | ContainerField; export type { StringField, NumericField, DateField, TimeField, TimestampField, ContainerField, }; type FileMakerField = Omit<Field, "type" | "repetitions" | "maxLength"> & { type: string; }; type TableDefinition = { tableName: string; fields: FileMakerField[]; }; export class SchemaManager { public constructor( private readonly databaseName: string, private readonly context: ExecutionContext, ) {} public async createTable( tableName: string, fields: Field[], options?: RequestInit & FFetchOptions, ): Promise<TableDefinition> { const result = await this.context._makeRequest<TableDefinition>( `/${this.databaseName}/FileMaker_Tables`, { method: "POST", body: JSON.stringify({ tableName, fields: fields.map(SchemaManager.compileFieldDefinition), }), ...options, }, ); if (result.error) { throw result.error; } return result.data; } public async addFields( tableName: string, fields: Field[], options?: RequestInit & FFetchOptions, ): Promise<TableDefinition> { const result = await this.context._makeRequest<TableDefinition>( `/${this.databaseName}/FileMaker_Tables/${tableName}`, { method: "PATCH", body: JSON.stringify({ fields: fields.map(SchemaManager.compileFieldDefinition), }), ...options, }, ); if (result.error) { throw result.error; } return result.data; } public async deleteTable( tableName: string, options?: RequestInit & FFetchOptions, ): Promise<void> { const result = await this.context._makeRequest( `/${this.databaseName}/FileMaker_Tables/${tableName}`, { method: "DELETE", ...options }, ); if (result.error) { throw result.error; } } public async deleteField( tableName: string, fieldName: string, options?: RequestInit & FFetchOptions, ): Promise<void> { const result = await this.context._makeRequest( `/${this.databaseName}/FileMaker_Tables/${tableName}/${fieldName}`, { method: "DELETE", ...options, }, ); if (result.error) { throw result.error; } } public async createIndex( tableName: string, fieldName: string, options?: RequestInit & FFetchOptions, ): Promise<{ indexName: string }> { const result = await this.context._makeRequest<{ indexName: string }>( `/${this.databaseName}/FileMaker_Indexes/${tableName}`, { method: "POST", body: JSON.stringify({ indexName: fieldName }), ...options, }, ); if (result.error) { throw result.error; } return result.data; } public async deleteIndex( tableName: string, fieldName: string, options?: RequestInit & FFetchOptions, ): Promise<void> { const result = await this.context._makeRequest( `/${this.databaseName}/FileMaker_Indexes/${tableName}/${fieldName}`, { method: "DELETE", ...options, }, ); if (result.error) { throw result.error; } } private static compileFieldDefinition(field: Field): FileMakerField { let type: string = field.type; const repetitions = field.repetitions; // Handle string fields - convert to varchar and add maxLength if present if (field.type === "string") { type = "varchar"; const stringField = field as StringField; if (stringField.maxLength !== undefined) { type += `(${stringField.maxLength})`; } } // Add repetitions suffix if present if (repetitions !== undefined) { type += `[${repetitions}]`; } // Build the result object, excluding type, maxLength, and repetitions const result: any = { name: field.name, type, }; // Add optional properties that FileMaker expects if (field.nullable !== undefined) result.nullable = field.nullable; if (field.primary !== undefined) result.primary = field.primary; if (field.unique !== undefined) result.unique = field.unique; if (field.global !== undefined) result.global = field.global; // Add type-specific properties if (field.type === "string") { const stringField = field as StringField; if (stringField.default !== undefined) result.default = stringField.default; } else if (field.type === "date") { const dateField = field as DateField; if (dateField.default !== undefined) result.default = dateField.default; } else if (field.type === "time") { const timeField = field as TimeField; if (timeField.default !== undefined) result.default = timeField.default; } else if (field.type === "timestamp") { const timestampField = field as TimestampField; if (timestampField.default !== undefined) result.default = timestampField.default; } else if (field.type === "container") { const containerField = field as ContainerField; if (containerField.externalSecurePath !== undefined) result.externalSecurePath = containerField.externalSecurePath; } return result as FileMakerField; } }