@proofkit/fmodata 0.1.0-alpha.13 → 0.1.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +489 -334
  2. package/dist/esm/client/batch-builder.d.ts +7 -4
  3. package/dist/esm/client/batch-builder.js +84 -25
  4. package/dist/esm/client/batch-builder.js.map +1 -1
  5. package/dist/esm/client/builders/default-select.d.ts +7 -0
  6. package/dist/esm/client/builders/default-select.js +42 -0
  7. package/dist/esm/client/builders/default-select.js.map +1 -0
  8. package/dist/esm/client/builders/expand-builder.d.ts +43 -0
  9. package/dist/esm/client/builders/expand-builder.js +173 -0
  10. package/dist/esm/client/builders/expand-builder.js.map +1 -0
  11. package/dist/esm/client/builders/index.d.ts +8 -0
  12. package/dist/esm/client/builders/query-string-builder.d.ts +15 -0
  13. package/dist/esm/client/builders/query-string-builder.js +25 -0
  14. package/dist/esm/client/builders/query-string-builder.js.map +1 -0
  15. package/dist/esm/client/builders/response-processor.d.ts +39 -0
  16. package/dist/esm/client/builders/response-processor.js +170 -0
  17. package/dist/esm/client/builders/response-processor.js.map +1 -0
  18. package/dist/esm/client/builders/select-mixin.d.ts +31 -0
  19. package/dist/esm/client/builders/select-mixin.js +30 -0
  20. package/dist/esm/client/builders/select-mixin.js.map +1 -0
  21. package/dist/esm/client/builders/select-utils.d.ts +8 -0
  22. package/dist/esm/client/builders/select-utils.js +15 -0
  23. package/dist/esm/client/builders/select-utils.js.map +1 -0
  24. package/dist/esm/client/builders/shared-types.d.ts +39 -0
  25. package/dist/esm/client/builders/table-utils.d.ts +35 -0
  26. package/dist/esm/client/builders/table-utils.js +45 -0
  27. package/dist/esm/client/builders/table-utils.js.map +1 -0
  28. package/dist/esm/client/database.d.ts +3 -22
  29. package/dist/esm/client/database.js +14 -76
  30. package/dist/esm/client/database.js.map +1 -1
  31. package/dist/esm/client/delete-builder.d.ts +11 -15
  32. package/dist/esm/client/delete-builder.js +26 -26
  33. package/dist/esm/client/delete-builder.js.map +1 -1
  34. package/dist/esm/client/entity-set.d.ts +32 -32
  35. package/dist/esm/client/entity-set.js +92 -69
  36. package/dist/esm/client/entity-set.js.map +1 -1
  37. package/dist/esm/client/error-parser.d.ts +12 -0
  38. package/dist/esm/client/error-parser.js +30 -0
  39. package/dist/esm/client/error-parser.js.map +1 -0
  40. package/dist/esm/client/filemaker-odata.d.ts +2 -4
  41. package/dist/esm/client/filemaker-odata.js +1 -5
  42. package/dist/esm/client/filemaker-odata.js.map +1 -1
  43. package/dist/esm/client/insert-builder.d.ts +7 -9
  44. package/dist/esm/client/insert-builder.js +70 -24
  45. package/dist/esm/client/insert-builder.js.map +1 -1
  46. package/dist/esm/client/query/expand-builder.d.ts +35 -0
  47. package/dist/esm/client/query/index.d.ts +3 -0
  48. package/dist/esm/client/query/query-builder.d.ts +134 -0
  49. package/dist/esm/client/query/query-builder.js +505 -0
  50. package/dist/esm/client/query/query-builder.js.map +1 -0
  51. package/dist/esm/client/query/response-processor.d.ts +22 -0
  52. package/dist/esm/client/query/types.d.ts +52 -0
  53. package/dist/esm/client/query/url-builder.d.ts +71 -0
  54. package/dist/esm/client/query/url-builder.js +107 -0
  55. package/dist/esm/client/query/url-builder.js.map +1 -0
  56. package/dist/esm/client/query-builder.d.ts +1 -111
  57. package/dist/esm/client/record-builder.d.ts +56 -63
  58. package/dist/esm/client/record-builder.js +158 -297
  59. package/dist/esm/client/record-builder.js.map +1 -1
  60. package/dist/esm/client/response-processor.d.ts +3 -3
  61. package/dist/esm/client/update-builder.d.ts +16 -21
  62. package/dist/esm/client/update-builder.js +56 -30
  63. package/dist/esm/client/update-builder.js.map +1 -1
  64. package/dist/esm/errors.d.ts +8 -1
  65. package/dist/esm/errors.js +17 -0
  66. package/dist/esm/errors.js.map +1 -1
  67. package/dist/esm/index.d.ts +3 -7
  68. package/dist/esm/index.js +37 -8
  69. package/dist/esm/index.js.map +1 -1
  70. package/dist/esm/orm/column.d.ts +45 -0
  71. package/dist/esm/orm/column.js +59 -0
  72. package/dist/esm/orm/column.js.map +1 -0
  73. package/dist/esm/orm/field-builders.d.ts +154 -0
  74. package/dist/esm/orm/field-builders.js +152 -0
  75. package/dist/esm/orm/field-builders.js.map +1 -0
  76. package/dist/esm/orm/index.d.ts +4 -0
  77. package/dist/esm/orm/operators.d.ts +175 -0
  78. package/dist/esm/orm/operators.js +221 -0
  79. package/dist/esm/orm/operators.js.map +1 -0
  80. package/dist/esm/orm/table.d.ts +341 -0
  81. package/dist/esm/orm/table.js +211 -0
  82. package/dist/esm/orm/table.js.map +1 -0
  83. package/dist/esm/transform.d.ts +20 -21
  84. package/dist/esm/transform.js +34 -34
  85. package/dist/esm/transform.js.map +1 -1
  86. package/dist/esm/types.d.ts +16 -13
  87. package/dist/esm/types.js.map +1 -1
  88. package/dist/esm/validation.d.ts +14 -4
  89. package/dist/esm/validation.js +45 -1
  90. package/dist/esm/validation.js.map +1 -1
  91. package/package.json +20 -17
  92. package/src/client/batch-builder.ts +100 -32
  93. package/src/client/builders/default-select.ts +69 -0
  94. package/src/client/builders/expand-builder.ts +236 -0
  95. package/src/client/builders/index.ts +11 -0
  96. package/src/client/builders/query-string-builder.ts +41 -0
  97. package/src/client/builders/response-processor.ts +273 -0
  98. package/src/client/builders/select-mixin.ts +74 -0
  99. package/src/client/builders/select-utils.ts +34 -0
  100. package/src/client/builders/shared-types.ts +41 -0
  101. package/src/client/builders/table-utils.ts +87 -0
  102. package/src/client/database.ts +19 -160
  103. package/src/client/delete-builder.ts +46 -51
  104. package/src/client/entity-set.ts +227 -302
  105. package/src/client/error-parser.ts +59 -0
  106. package/src/client/filemaker-odata.ts +3 -14
  107. package/src/client/insert-builder.ts +124 -43
  108. package/src/client/query/expand-builder.ts +164 -0
  109. package/src/client/query/index.ts +13 -0
  110. package/src/client/query/query-builder.ts +816 -0
  111. package/src/client/query/response-processor.ts +244 -0
  112. package/src/client/query/types.ts +102 -0
  113. package/src/client/query/url-builder.ts +179 -0
  114. package/src/client/query-builder.ts +8 -1454
  115. package/src/client/record-builder.ts +325 -585
  116. package/src/client/response-processor.ts +4 -5
  117. package/src/client/update-builder.ts +102 -73
  118. package/src/errors.ts +22 -1
  119. package/src/index.ts +55 -5
  120. package/src/orm/column.ts +78 -0
  121. package/src/orm/field-builders.ts +296 -0
  122. package/src/orm/index.ts +60 -0
  123. package/src/orm/operators.ts +428 -0
  124. package/src/orm/table.ts +759 -0
  125. package/src/transform.ts +62 -48
  126. package/src/types.ts +20 -63
  127. package/src/validation.ts +76 -4
  128. package/LICENSE.md +0 -21
  129. package/dist/esm/client/base-table.d.ts +0 -128
  130. package/dist/esm/client/base-table.js +0 -57
  131. package/dist/esm/client/base-table.js.map +0 -1
  132. package/dist/esm/client/build-occurrences.d.ts +0 -74
  133. package/dist/esm/client/build-occurrences.js +0 -31
  134. package/dist/esm/client/build-occurrences.js.map +0 -1
  135. package/dist/esm/client/query-builder.js +0 -900
  136. package/dist/esm/client/query-builder.js.map +0 -1
  137. package/dist/esm/client/table-occurrence.d.ts +0 -86
  138. package/dist/esm/client/table-occurrence.js +0 -58
  139. package/dist/esm/client/table-occurrence.js.map +0 -1
  140. package/src/client/base-table.ts +0 -178
  141. package/src/client/build-occurrences.ts +0 -155
  142. package/src/client/query-builder.ts.bak +0 -1457
  143. package/src/client/table-occurrence.ts +0 -156
@@ -0,0 +1,296 @@
1
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
2
+
3
+ /**
4
+ * Branded type for container field's database type.
5
+ * This allows TypeScript to distinguish container fields from regular string fields
6
+ * at the type level, enabling compile-time exclusion from select operations.
7
+ */
8
+ export type ContainerDbType = string & { readonly __container: true };
9
+
10
+ /**
11
+ * FieldBuilder provides a fluent API for defining table fields with type-safe metadata.
12
+ * Supports chaining methods to configure primary keys, nullability, read-only status, entity IDs, and validators.
13
+ *
14
+ * @template TOutput - The output type after applying outputValidator (what you get when reading)
15
+ * @template TInput - The input type after applying inputValidator (what you pass when writing)
16
+ * @template TDbType - The database type (what FileMaker stores/expects)
17
+ * @template TReadOnly - Whether this field is read-only (for type-level exclusion from insert/update)
18
+ */
19
+ export class FieldBuilder<
20
+ TOutput = any,
21
+ TInput = TOutput,
22
+ TDbType = TOutput,
23
+ TReadOnly extends boolean = false,
24
+ > {
25
+ private _primaryKey = false;
26
+ private _notNull = false;
27
+ private _readOnly = false;
28
+ private _entityId?: `FMFID:${string}`;
29
+ private _outputValidator?: StandardSchemaV1<any, TOutput>;
30
+ private _inputValidator?: StandardSchemaV1<TInput, any>;
31
+ private _fieldType: string;
32
+
33
+ constructor(fieldType: string) {
34
+ this._fieldType = fieldType;
35
+ }
36
+
37
+ /**
38
+ * Mark this field as the primary key for the table.
39
+ * Primary keys are automatically read-only.
40
+ */
41
+ primaryKey(): FieldBuilder<TOutput, TInput, TDbType, true> {
42
+ const builder = this._clone() as any;
43
+ builder._primaryKey = true;
44
+ builder._readOnly = true; // Primary keys are automatically read-only
45
+ return builder;
46
+ }
47
+
48
+ /**
49
+ * Mark this field as non-nullable.
50
+ * Updates the type to exclude null/undefined.
51
+ */
52
+ notNull(): FieldBuilder<
53
+ NonNullable<TOutput>,
54
+ NonNullable<TInput>,
55
+ NonNullable<TDbType>,
56
+ TReadOnly
57
+ > {
58
+ const builder = this._clone() as any;
59
+ builder._notNull = true;
60
+ return builder;
61
+ }
62
+
63
+ /**
64
+ * Mark this field as read-only.
65
+ * Read-only fields are excluded from insert and update operations.
66
+ */
67
+ readOnly(): FieldBuilder<TOutput, TInput, TDbType, true> {
68
+ const builder = this._clone() as any;
69
+ builder._readOnly = true;
70
+ return builder;
71
+ }
72
+
73
+ /**
74
+ * Assign a FileMaker field ID (FMFID) to this field.
75
+ * When useEntityIds is enabled, this ID will be used in API requests instead of the field name.
76
+ */
77
+ entityId(
78
+ id: `FMFID:${string}`,
79
+ ): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {
80
+ const builder = this._clone();
81
+ builder._entityId = id;
82
+ return builder;
83
+ }
84
+
85
+ /**
86
+ * Set a validator for the output (reading from database).
87
+ * The output validator transforms/validates data coming FROM the database in list or get operations.
88
+ *
89
+ * @example
90
+ * numberField().readValidator(z.coerce.boolean())
91
+ * // FileMaker returns 0/1, you get true/false
92
+ */
93
+ readValidator<O, VInput = TDbType>(
94
+ validator: StandardSchemaV1<VInput, O>,
95
+ ): FieldBuilder<O, TInput, TDbType, TReadOnly> {
96
+ const builder = this._clone() as any;
97
+ builder._outputValidator = validator;
98
+ return builder;
99
+ }
100
+
101
+ /**
102
+ * Set a validator for the input (writing to database).
103
+ * The input validator transforms/validates data going TO the database in insert and update operations.
104
+ *
105
+ * @example
106
+ * numberField().writeValidator(z.boolean().transform(v => v ? 1 : 0))
107
+ * // You pass true/false, FileMaker gets 1/0
108
+ */
109
+ writeValidator<I>(
110
+ validator: StandardSchemaV1<I, TDbType>,
111
+ ): FieldBuilder<TOutput, I, TDbType, TReadOnly> {
112
+ const builder = this._clone() as any;
113
+ builder._inputValidator = validator;
114
+ return builder;
115
+ }
116
+
117
+ /**
118
+ * Get the metadata configuration for this field.
119
+ * @internal Used by fmTableOccurrence to extract field configuration
120
+ */
121
+ _getConfig() {
122
+ return {
123
+ fieldType: this._fieldType,
124
+ primaryKey: this._primaryKey,
125
+ notNull: this._notNull,
126
+ readOnly: this._readOnly,
127
+ entityId: this._entityId,
128
+ outputValidator: this._outputValidator,
129
+ inputValidator: this._inputValidator,
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Clone this builder to allow immutable chaining.
135
+ * @private
136
+ */
137
+ private _clone(): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {
138
+ const builder = new FieldBuilder<TOutput, TInput, TDbType, TReadOnly>(
139
+ this._fieldType,
140
+ );
141
+ builder._primaryKey = this._primaryKey;
142
+ builder._notNull = this._notNull;
143
+ builder._readOnly = this._readOnly;
144
+ builder._entityId = this._entityId;
145
+ builder._outputValidator = this._outputValidator;
146
+ builder._inputValidator = this._inputValidator;
147
+ return builder;
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Create a text field (Edm.String in FileMaker OData).
153
+ * By default, text fields are nullable.
154
+ *
155
+ * @example
156
+ * textField() // string | null
157
+ * textField().notNull() // string
158
+ * textField().entityId("FMFID:1") // with entity ID
159
+ */
160
+ export function textField(): FieldBuilder<
161
+ string | null,
162
+ string | null,
163
+ string | null,
164
+ false
165
+ > {
166
+ return new FieldBuilder<string | null, string | null, string | null, false>(
167
+ "text",
168
+ );
169
+ }
170
+
171
+ /**
172
+ * Create a number field (Edm.Decimal in FileMaker OData).
173
+ * By default, number fields are nullable.
174
+ *
175
+ * @example
176
+ * numberField() // number | null
177
+ * numberField().notNull() // number
178
+ * numberField().outputValidator(z.coerce.boolean()) // transform to boolean on read
179
+ */
180
+ export function numberField(): FieldBuilder<
181
+ number | null,
182
+ number | null,
183
+ number | null,
184
+ false
185
+ > {
186
+ return new FieldBuilder<number | null, number | null, number | null, false>(
187
+ "number",
188
+ );
189
+ }
190
+
191
+ /**
192
+ * Create a date field (Edm.Date in FileMaker OData).
193
+ * By default, date fields are nullable and represented as ISO date strings (YYYY-MM-DD).
194
+ *
195
+ * @example
196
+ * dateField() // string | null (ISO date format)
197
+ * dateField().notNull() // string
198
+ */
199
+ export function dateField(): FieldBuilder<
200
+ string | null,
201
+ string | null,
202
+ string | null,
203
+ false
204
+ > {
205
+ return new FieldBuilder<string | null, string | null, string | null, false>(
206
+ "date",
207
+ );
208
+ }
209
+
210
+ /**
211
+ * Create a time field (Edm.TimeOfDay in FileMaker OData).
212
+ * By default, time fields are nullable and represented as ISO time strings (HH:mm:ss).
213
+ *
214
+ * @example
215
+ * timeField() // string | null (ISO time format)
216
+ * timeField().notNull() // string
217
+ */
218
+ export function timeField(): FieldBuilder<
219
+ string | null,
220
+ string | null,
221
+ string | null,
222
+ false
223
+ > {
224
+ return new FieldBuilder<string | null, string | null, string | null, false>(
225
+ "time",
226
+ );
227
+ }
228
+
229
+ /**
230
+ * Create a timestamp field (Edm.DateTimeOffset in FileMaker OData).
231
+ * By default, timestamp fields are nullable and represented as ISO 8601 strings.
232
+ *
233
+ * @example
234
+ * timestampField() // string | null (ISO 8601 format)
235
+ * timestampField().notNull() // string
236
+ * timestampField().readOnly() // typical for CreationTimestamp
237
+ */
238
+ export function timestampField(): FieldBuilder<
239
+ string | null,
240
+ string | null,
241
+ string | null,
242
+ false
243
+ > {
244
+ return new FieldBuilder<string | null, string | null, string | null, false>(
245
+ "timestamp",
246
+ );
247
+ }
248
+
249
+ /**
250
+ * Create a container field (Edm.Stream in FileMaker OData).
251
+ * Container fields store binary data and are represented as base64 strings in the API.
252
+ * By default, container fields are nullable.
253
+ *
254
+ * Note: Container fields cannot be selected via .select() - they can only be accessed
255
+ * via .getSingleField() due to FileMaker OData API limitations.
256
+ *
257
+ * @example
258
+ * containerField() // string | null (base64 encoded)
259
+ * containerField().notNull() // string
260
+ */
261
+ export function containerField(): FieldBuilder<
262
+ string | null,
263
+ string | null,
264
+ ContainerDbType | null,
265
+ false
266
+ > {
267
+ return new FieldBuilder<
268
+ string | null,
269
+ string | null,
270
+ ContainerDbType | null,
271
+ false
272
+ >("container");
273
+ }
274
+
275
+ /**
276
+ * Create a calculated field (read-only field computed by FileMaker).
277
+ * Calculated fields are automatically marked as read-only.
278
+ *
279
+ * @example
280
+ * calcField() // string | null
281
+ * calcField().notNull() // string
282
+ */
283
+ export function calcField(): FieldBuilder<
284
+ string | null,
285
+ string | null,
286
+ string | null,
287
+ true
288
+ > {
289
+ const builder = new FieldBuilder<
290
+ string | null,
291
+ string | null,
292
+ string | null,
293
+ false
294
+ >("calculated");
295
+ return builder.readOnly();
296
+ }
@@ -0,0 +1,60 @@
1
+ // Field builders - main API for defining table schemas
2
+ export {
3
+ FieldBuilder,
4
+ textField,
5
+ numberField,
6
+ dateField,
7
+ timeField,
8
+ timestampField,
9
+ containerField,
10
+ calcField,
11
+ type ContainerDbType,
12
+ } from "./field-builders";
13
+
14
+ // Column references - used in queries and filters
15
+ export { Column, isColumn } from "./column";
16
+
17
+ // Filter operators - eq, gt, lt, and, or, etc.
18
+ export {
19
+ FilterExpression,
20
+ eq,
21
+ ne,
22
+ gt,
23
+ gte,
24
+ lt,
25
+ lte,
26
+ contains,
27
+ startsWith,
28
+ endsWith,
29
+ inArray,
30
+ notInArray,
31
+ isNull,
32
+ isNotNull,
33
+ and,
34
+ or,
35
+ not,
36
+ // OrderBy operators
37
+ OrderByExpression,
38
+ isOrderByExpression,
39
+ asc,
40
+ desc,
41
+ } from "./operators";
42
+
43
+ // Table definition - fmTableOccurrence function
44
+ export {
45
+ fmTableOccurrence,
46
+ FMTable,
47
+ type FMTableWithColumns,
48
+ type InferTableSchema,
49
+ // Helper functions for accessing FMTable internals
50
+ getTableName,
51
+ getTableEntityId,
52
+ // getTableFields,
53
+ getDefaultSelect,
54
+ getBaseTableConfig,
55
+ isUsingEntityIds,
56
+ getFieldId,
57
+ getFieldName,
58
+ getTableId,
59
+ getTableColumns,
60
+ } from "./table";