@proofkit/fmodata
Version:
FileMaker OData API client
190 lines (189 loc) • 8.61 kB
TypeScript
import { StandardSchemaV1 } from '@standard-schema/spec';
/**
* Branded type for container field's database type.
* This allows TypeScript to distinguish container fields from regular string fields
* at the type level, enabling compile-time exclusion from select operations.
*/
export type ContainerDbType = string & {
readonly __container: true;
};
export interface ListFieldOptions<TItem = string, TAllowNull extends boolean = false> {
itemValidator?: StandardSchemaV1<unknown, TItem>;
allowNull?: TAllowNull;
}
/**
* FieldBuilder provides a fluent API for defining table fields with type-safe metadata.
* Supports chaining methods to configure primary keys, nullability, read-only status, entity IDs, and validators.
*
* @template TOutput - The output type after applying outputValidator (what you get when reading)
* @template TInput - The input type after applying inputValidator (what you pass when writing)
* @template TDbType - The database type (what FileMaker stores/expects)
* @template TReadOnly - Whether this field is read-only (for type-level exclusion from insert/update)
*/
export declare class FieldBuilder<TOutput = any, TInput = TOutput, TDbType = TOutput, TReadOnly extends boolean = false> {
private _primaryKey;
private _notNull;
private _readOnly;
private _entityId?;
private _outputValidator?;
private _inputValidator?;
private readonly _fieldType;
private _comment?;
constructor(fieldType: string);
/**
* Mark this field as the primary key for the table.
* Primary keys are automatically read-only and non-nullable.
*/
primaryKey(): FieldBuilder<NonNullable<TOutput>, NonNullable<TInput>, NonNullable<TDbType>, true>;
/**
* Mark this field as non-nullable.
* Updates the type to exclude null/undefined.
*/
notNull(): FieldBuilder<NonNullable<TOutput>, NonNullable<TInput>, NonNullable<TDbType>, TReadOnly>;
/**
* Mark this field as read-only.
* Read-only fields are excluded from insert and update operations.
*/
readOnly(): FieldBuilder<TOutput, TInput, TDbType, true>;
/**
* Assign a FileMaker field ID (FMFID) to this field.
* When useEntityIds is enabled, this ID will be used in API requests instead of the field name.
*/
entityId(id: `FMFID:${string}`): FieldBuilder<TOutput, TInput, TDbType, TReadOnly>;
/**
* Set a validator for the output (reading from database).
* The output validator transforms/validates data coming FROM the database in list or get operations.
*
* @example
* numberField().readValidator(z.coerce.boolean())
* // FileMaker returns 0/1, you get true/false
*/
readValidator<O, VInput = TDbType>(validator: StandardSchemaV1<VInput, O>): FieldBuilder<O, TInput, TDbType, TReadOnly>;
/**
* Set a validator for the input (writing to database).
* The input validator transforms/validates data going TO the database in insert, update, and filter operations.
*
* @example
* numberField().writeValidator(z.boolean().transform(v => v ? 1 : 0))
* // You pass true/false, FileMaker gets 1/0
*/
writeValidator<I>(validator: StandardSchemaV1<I, TDbType>): FieldBuilder<TOutput, I, TDbType, TReadOnly>;
/**
* Add a comment to this field for metadata purposes.
* This helps future developers understand the purpose of the field.
*
* @example
* textField().comment("Account name of the user who last modified each record")
*/
comment(comment: string): FieldBuilder<TOutput, TInput, TDbType, TReadOnly>;
/**
* Get the metadata configuration for this field.
* @internal Used by fmTableOccurrence to extract field configuration
*/
_getConfig(): {
fieldType: string;
primaryKey: boolean;
notNull: boolean;
readOnly: boolean;
entityId: `FMFID:${string}` | undefined;
outputValidator: StandardSchemaV1<any, TOutput> | undefined;
inputValidator: StandardSchemaV1<TInput, any> | undefined;
comment: string | undefined;
};
/**
* Clone this builder to allow immutable chaining.
* @private
*/
private _clone;
}
/**
* Create a text field (Edm.String in FileMaker OData).
* By default, text fields are nullable.
*
* @example
* textField() // string | null
* textField().notNull() // string
* textField().entityId("FMFID:1") // with entity ID
*/
export declare function textField(): FieldBuilder<string | null, string | null, string | null, false>;
type ListOutput<TItem, TAllowNull extends boolean> = TAllowNull extends true ? TItem[] | null : TItem[];
type ListInput<TItem, TAllowNull extends boolean> = TAllowNull extends true ? TItem[] | null : TItem[];
/**
* Create a text-backed FileMaker return-delimited list field.
* By default, null/empty input is normalized to an empty array (`allowNull: false`).
*
* @example
* listField() // output: string[], input: string[]
* listField({ allowNull: true }) // output/input: string[] | null
* listField({ itemValidator: z.coerce.number().int() }) // output/input: number[]
*/
export declare function listField(): FieldBuilder<string[], string[], string | null, false>;
export declare function listField<TAllowNull extends boolean = false>(options: ListFieldOptions<string, TAllowNull>): FieldBuilder<ListOutput<string, TAllowNull>, ListInput<string, TAllowNull>, string | null, false>;
export declare function listField<TItem, TAllowNull extends boolean = false>(options: {
itemValidator: StandardSchemaV1<unknown, TItem>;
allowNull?: TAllowNull;
}): FieldBuilder<ListOutput<TItem, TAllowNull>, ListInput<TItem, TAllowNull>, string | null, false>;
/**
* Create a number field (Edm.Decimal in FileMaker OData).
* By default, number fields are nullable.
*
* @example
* numberField() // number | null
* numberField().notNull() // number
* numberField().outputValidator(z.coerce.boolean()) // transform to boolean on read
*/
export declare function numberField(): FieldBuilder<number | null, number | null, number | null, false>;
/**
* Create a date field (Edm.Date in FileMaker OData).
* By default, date fields are nullable and represented as ISO date strings (YYYY-MM-DD),
* while accepting either ISO strings or Date objects as input.
*
* @example
* dateField() // output: string | null (ISO date format), input: string | Date | null
* dateField().notNull() // string
*/
export declare function dateField(): FieldBuilder<string | null, string | Date | null, string | null, false>;
/**
* Create a time field (Edm.TimeOfDay in FileMaker OData).
* By default, time fields are nullable and represented as ISO time strings (HH:mm:ss),
* while accepting either ISO strings or Date objects as input.
*
* @example
* timeField() // output: string | null (ISO time format), input: string | Date | null
* timeField().notNull() // string
*/
export declare function timeField(): FieldBuilder<string | null, string | Date | null, string | null, false>;
/**
* Create a timestamp field (Edm.DateTimeOffset in FileMaker OData).
* By default, timestamp fields are nullable and represented as ISO 8601 strings,
* while accepting either ISO strings or Date objects as input.
*
* @example
* timestampField() // output: string | null (ISO 8601 format), input: string | Date | null
* timestampField().notNull() // string
* timestampField().readOnly() // typical for CreationTimestamp
*/
export declare function timestampField(): FieldBuilder<string | null, string | Date | null, string | null, false>;
/**
* Create a container field (Edm.Stream in FileMaker OData).
* Container fields store binary data and are represented as base64 strings in the API.
* By default, container fields are nullable.
*
* Note: Container fields cannot be selected via .select() - they can only be accessed
* via .getSingleField() due to FileMaker OData API limitations.
*
* @example
* containerField() // string | null (base64 encoded)
* containerField().notNull() // string
*/
export declare function containerField(): FieldBuilder<string | null, string | null, ContainerDbType | null, false>;
/**
* Create a calculated field (read-only field computed by FileMaker).
* Calculated fields are automatically marked as read-only.
*
* @example
* calcField() // string | null
* calcField().notNull() // string
*/
export declare function calcField(): FieldBuilder<string | null, string | null, string | null, true>;
export {};