@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
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sources":["../../src/errors.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Base class for all fmodata errors\n */\nexport abstract class FMODataError extends Error {\n abstract readonly kind: string;\n readonly timestamp: Date;\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = this.constructor.name;\n this.timestamp = new Date();\n }\n}\n\n// ============================================\n// HTTP Errors (with status codes)\n// ============================================\n\nexport class HTTPError extends FMODataError {\n readonly kind = \"HTTPError\" as const;\n readonly url: string;\n readonly status: number;\n readonly statusText: string;\n readonly response?: any;\n\n constructor(url: string, status: number, statusText: string, response?: any) {\n super(`HTTP ${status} ${statusText} for ${url}`);\n this.url = url;\n this.status = status;\n this.statusText = statusText;\n this.response = response;\n }\n\n // Helper methods for common status checks\n is4xx(): boolean {\n return this.status >= 400 && this.status < 500;\n }\n\n is5xx(): boolean {\n return this.status >= 500 && this.status < 600;\n }\n\n isNotFound(): boolean {\n return this.status === 404;\n }\n\n isUnauthorized(): boolean {\n return this.status === 401;\n }\n\n isForbidden(): boolean {\n return this.status === 403;\n }\n}\n\n// ============================================\n// OData Specific Errors\n// ============================================\n\nexport class ODataError extends FMODataError {\n readonly kind = \"ODataError\" as const;\n readonly url: string;\n readonly code?: string;\n readonly details?: any;\n\n constructor(url: string, message: string, code?: string, details?: any) {\n super(`OData error: ${message}`);\n this.url = url;\n this.code = code;\n this.details = details;\n }\n}\n\nexport class SchemaLockedError extends FMODataError {\n readonly kind = \"SchemaLockedError\" as const;\n readonly url: string;\n readonly code: string;\n readonly details?: any;\n\n constructor(url: string, message: string, details?: any) {\n super(`OData error: ${message}`);\n this.url = url;\n this.code = \"303\";\n this.details = details;\n }\n}\n\n// ============================================\n// Validation Errors\n// ============================================\n\nexport class ValidationError extends FMODataError {\n readonly kind = \"ValidationError\" as const;\n readonly field?: string;\n readonly issues: readonly StandardSchemaV1.Issue[];\n readonly value?: unknown;\n\n constructor(\n message: string,\n issues: readonly StandardSchemaV1.Issue[],\n options?: {\n field?: string;\n value?: unknown;\n cause?: Error[\"cause\"];\n },\n ) {\n super(\n message,\n options?.cause !== undefined ? { cause: options.cause } : undefined,\n );\n this.field = options?.field;\n this.issues = issues;\n this.value = options?.value;\n }\n}\n\nexport class ResponseStructureError extends FMODataError {\n readonly kind = \"ResponseStructureError\" as const;\n readonly expected: string;\n readonly received: any;\n\n constructor(expected: string, received: any) {\n super(`Invalid response structure: expected ${expected}`);\n this.expected = expected;\n this.received = received;\n }\n}\n\nexport class RecordCountMismatchError extends FMODataError {\n readonly kind = \"RecordCountMismatchError\" as const;\n readonly expected: number | \"one\" | \"at-most-one\";\n readonly received: number;\n\n constructor(expected: number | \"one\" | \"at-most-one\", received: number) {\n const expectedStr = typeof expected === \"number\" ? expected : expected;\n super(`Expected ${expectedStr} record(s), but received ${received}`);\n this.expected = expected;\n this.received = received;\n }\n}\n\nexport class InvalidLocationHeaderError extends FMODataError {\n readonly kind = \"InvalidLocationHeaderError\" as const;\n readonly locationHeader?: string;\n\n constructor(message: string, locationHeader?: string) {\n super(message);\n this.locationHeader = locationHeader;\n }\n}\n\nexport class ResponseParseError extends FMODataError {\n readonly kind = \"ResponseParseError\" as const;\n readonly url: string;\n readonly rawText?: string;\n\n constructor(\n url: string,\n message: string,\n options?: { rawText?: string; cause?: Error },\n ) {\n super(message, options?.cause ? { cause: options.cause } : undefined);\n this.url = url;\n this.rawText = options?.rawText;\n }\n}\n\n// ============================================\n// Type Guards\n// ============================================\n\nexport function isHTTPError(error: unknown): error is HTTPError {\n return error instanceof HTTPError;\n}\n\nexport function isValidationError(error: unknown): error is ValidationError {\n return error instanceof ValidationError;\n}\n\nexport function isODataError(error: unknown): error is ODataError {\n return error instanceof ODataError;\n}\n\nexport function isSchemaLockedError(\n error: unknown,\n): error is SchemaLockedError {\n return error instanceof SchemaLockedError;\n}\n\nexport function isResponseStructureError(\n error: unknown,\n): error is ResponseStructureError {\n return error instanceof ResponseStructureError;\n}\n\nexport function isRecordCountMismatchError(\n error: unknown,\n): error is RecordCountMismatchError {\n return error instanceof RecordCountMismatchError;\n}\n\nexport function isResponseParseError(\n error: unknown,\n): error is ResponseParseError {\n return error instanceof ResponseParseError;\n}\n\nexport function isFMODataError(error: unknown): error is FMODataError {\n return error instanceof FMODataError;\n}\n\n// ============================================\n// Union type for all possible errors\n// ============================================\n\n// Re-export ffetch errors (they'll be imported from @fetchkit/ffetch)\nexport type {\n TimeoutError,\n AbortError,\n NetworkError,\n RetryLimitError,\n CircuitOpenError,\n} from \"@fetchkit/ffetch\";\n\nexport type FMODataErrorType =\n | import(\"@fetchkit/ffetch\").TimeoutError\n | import(\"@fetchkit/ffetch\").AbortError\n | import(\"@fetchkit/ffetch\").NetworkError\n | import(\"@fetchkit/ffetch\").RetryLimitError\n | import(\"@fetchkit/ffetch\").CircuitOpenError\n | HTTPError\n | ODataError\n | SchemaLockedError\n | ValidationError\n | ResponseStructureError\n | RecordCountMismatchError\n | InvalidLocationHeaderError\n | ResponseParseError;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sources":["../../src/errors.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Base class for all fmodata errors\n */\nexport abstract class FMODataError extends Error {\n abstract readonly kind: string;\n readonly timestamp: Date;\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = this.constructor.name;\n this.timestamp = new Date();\n }\n}\n\n// ============================================\n// HTTP Errors (with status codes)\n// ============================================\n\nexport class HTTPError extends FMODataError {\n readonly kind = \"HTTPError\" as const;\n readonly url: string;\n readonly status: number;\n readonly statusText: string;\n readonly response?: any;\n\n constructor(url: string, status: number, statusText: string, response?: any) {\n super(`HTTP ${status} ${statusText} for ${url}`);\n this.url = url;\n this.status = status;\n this.statusText = statusText;\n this.response = response;\n }\n\n // Helper methods for common status checks\n is4xx(): boolean {\n return this.status >= 400 && this.status < 500;\n }\n\n is5xx(): boolean {\n return this.status >= 500 && this.status < 600;\n }\n\n isNotFound(): boolean {\n return this.status === 404;\n }\n\n isUnauthorized(): boolean {\n return this.status === 401;\n }\n\n isForbidden(): boolean {\n return this.status === 403;\n }\n}\n\n// ============================================\n// OData Specific Errors\n// ============================================\n\nexport class ODataError extends FMODataError {\n readonly kind = \"ODataError\" as const;\n readonly url: string;\n readonly code?: string;\n readonly details?: any;\n\n constructor(url: string, message: string, code?: string, details?: any) {\n super(`OData error: ${message}`);\n this.url = url;\n this.code = code;\n this.details = details;\n }\n}\n\nexport class SchemaLockedError extends FMODataError {\n readonly kind = \"SchemaLockedError\" as const;\n readonly url: string;\n readonly code: string;\n readonly details?: any;\n\n constructor(url: string, message: string, details?: any) {\n super(`OData error: ${message}`);\n this.url = url;\n this.code = \"303\";\n this.details = details;\n }\n}\n\n// ============================================\n// Validation Errors\n// ============================================\n\nexport class ValidationError extends FMODataError {\n readonly kind = \"ValidationError\" as const;\n readonly field?: string;\n readonly issues: readonly StandardSchemaV1.Issue[];\n readonly value?: unknown;\n\n constructor(\n message: string,\n issues: readonly StandardSchemaV1.Issue[],\n options?: {\n field?: string;\n value?: unknown;\n cause?: Error[\"cause\"];\n },\n ) {\n super(\n message,\n options?.cause !== undefined ? { cause: options.cause } : undefined,\n );\n this.field = options?.field;\n this.issues = issues;\n this.value = options?.value;\n }\n}\n\nexport class ResponseStructureError extends FMODataError {\n readonly kind = \"ResponseStructureError\" as const;\n readonly expected: string;\n readonly received: any;\n\n constructor(expected: string, received: any) {\n super(`Invalid response structure: expected ${expected}`);\n this.expected = expected;\n this.received = received;\n }\n}\n\nexport class RecordCountMismatchError extends FMODataError {\n readonly kind = \"RecordCountMismatchError\" as const;\n readonly expected: number | \"one\" | \"at-most-one\";\n readonly received: number;\n\n constructor(expected: number | \"one\" | \"at-most-one\", received: number) {\n const expectedStr = typeof expected === \"number\" ? expected : expected;\n super(`Expected ${expectedStr} record(s), but received ${received}`);\n this.expected = expected;\n this.received = received;\n }\n}\n\nexport class InvalidLocationHeaderError extends FMODataError {\n readonly kind = \"InvalidLocationHeaderError\" as const;\n readonly locationHeader?: string;\n\n constructor(message: string, locationHeader?: string) {\n super(message);\n this.locationHeader = locationHeader;\n }\n}\n\nexport class ResponseParseError extends FMODataError {\n readonly kind = \"ResponseParseError\" as const;\n readonly url: string;\n readonly rawText?: string;\n\n constructor(\n url: string,\n message: string,\n options?: { rawText?: string; cause?: Error },\n ) {\n super(message, options?.cause ? { cause: options.cause } : undefined);\n this.url = url;\n this.rawText = options?.rawText;\n }\n}\n\nexport class BatchTruncatedError extends FMODataError {\n readonly kind = \"BatchTruncatedError\" as const;\n readonly operationIndex: number;\n readonly failedAtIndex: number;\n\n constructor(operationIndex: number, failedAtIndex: number) {\n super(\n `Operation ${operationIndex} was not executed because operation ${failedAtIndex} failed`,\n );\n this.operationIndex = operationIndex;\n this.failedAtIndex = failedAtIndex;\n }\n}\n\n// ============================================\n// Type Guards\n// ============================================\n\nexport function isHTTPError(error: unknown): error is HTTPError {\n return error instanceof HTTPError;\n}\n\nexport function isValidationError(error: unknown): error is ValidationError {\n return error instanceof ValidationError;\n}\n\nexport function isODataError(error: unknown): error is ODataError {\n return error instanceof ODataError;\n}\n\nexport function isSchemaLockedError(\n error: unknown,\n): error is SchemaLockedError {\n return error instanceof SchemaLockedError;\n}\n\nexport function isResponseStructureError(\n error: unknown,\n): error is ResponseStructureError {\n return error instanceof ResponseStructureError;\n}\n\nexport function isRecordCountMismatchError(\n error: unknown,\n): error is RecordCountMismatchError {\n return error instanceof RecordCountMismatchError;\n}\n\nexport function isResponseParseError(\n error: unknown,\n): error is ResponseParseError {\n return error instanceof ResponseParseError;\n}\n\nexport function isBatchTruncatedError(\n error: unknown,\n): error is BatchTruncatedError {\n return error instanceof BatchTruncatedError;\n}\n\nexport function isFMODataError(error: unknown): error is FMODataError {\n return error instanceof FMODataError;\n}\n\n// ============================================\n// Union type for all possible errors\n// ============================================\n\n// Re-export ffetch errors (they'll be imported from @fetchkit/ffetch)\nexport type {\n TimeoutError,\n AbortError,\n NetworkError,\n RetryLimitError,\n CircuitOpenError,\n} from \"@fetchkit/ffetch\";\n\nexport type FMODataErrorType =\n | import(\"@fetchkit/ffetch\").TimeoutError\n | import(\"@fetchkit/ffetch\").AbortError\n | import(\"@fetchkit/ffetch\").NetworkError\n | import(\"@fetchkit/ffetch\").RetryLimitError\n | import(\"@fetchkit/ffetch\").CircuitOpenError\n | HTTPError\n | ODataError\n | SchemaLockedError\n | ValidationError\n | ResponseStructureError\n | RecordCountMismatchError\n | InvalidLocationHeaderError\n | ResponseParseError\n | BatchTruncatedError;\n"],"names":[],"mappings":"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"}
@@ -1,14 +1,10 @@
1
- export { defineBaseTable } from './client/base-table.js';
2
- export { defineTableOccurrence } from './client/table-occurrence.js';
3
- export { buildOccurrences } from './client/build-occurrences.js';
4
1
  export { FMServerConnection } from './client/filemaker-odata.js';
5
- export type { BaseTable } from './client/base-table.js';
6
- export type { TableOccurrence } from './client/table-occurrence.js';
2
+ export { textField, numberField, dateField, timeField, timestampField, containerField, calcField, type FieldBuilder, fmTableOccurrence, FMTable, type FMTableWithColumns as TableOccurrenceResult, type InferTableSchema, getTableColumns, type Column, isColumn, type FilterExpression, eq, ne, gt, gte, lt, lte, contains, startsWith, endsWith, inArray, notInArray, isNull, isNotNull, and, or, not, type OrderByExpression, asc, desc, } from './orm/index.js';
7
3
  export type { Database } from './client/database.js';
8
4
  export type { EntitySet } from './client/entity-set.js';
9
5
  export type { SchemaManager, Field, StringField, NumericField, DateField, TimeField, TimestampField, ContainerField, } from './client/schema-manager.js';
10
- export type { Result, InferSchemaType, InsertData, UpdateData, ODataRecordMetadata, Metadata, } from './types.js';
6
+ export type { Result, BatchResult, BatchItemResult, InferSchemaType, InsertData, UpdateData, ODataRecordMetadata, Metadata, } from './types.js';
11
7
  export type { Filter, TypedFilter, FieldFilter, StringOperators, NumberOperators, BooleanOperators, DateOperators, LogicalFilter, } from './filter-types.js';
12
8
  export { TimeoutError, AbortError, NetworkError, RetryLimitError, CircuitOpenError, } from '@fetchkit/ffetch';
13
- export { FMODataError, HTTPError, ODataError, SchemaLockedError, ValidationError, ResponseStructureError, RecordCountMismatchError, ResponseParseError, isHTTPError, isValidationError, isODataError, isSchemaLockedError, isResponseStructureError, isRecordCountMismatchError, isResponseParseError, isFMODataError, } from './errors.js';
9
+ export { FMODataError, HTTPError, ODataError, SchemaLockedError, ValidationError, ResponseStructureError, RecordCountMismatchError, ResponseParseError, BatchTruncatedError, isHTTPError, isValidationError, isODataError, isSchemaLockedError, isResponseStructureError, isRecordCountMismatchError, isResponseParseError, isBatchTruncatedError, isFMODataError, } from './errors.js';
14
10
  export type { FMODataErrorType } from './errors.js';
package/dist/esm/index.js CHANGED
@@ -1,14 +1,17 @@
1
- import { defineBaseTable } from "./client/base-table.js";
2
- import { defineTableOccurrence } from "./client/table-occurrence.js";
3
- import { buildOccurrences } from "./client/build-occurrences.js";
4
1
  import { FMServerConnection } from "./client/filemaker-odata.js";
2
+ import { calcField, containerField, dateField, numberField, textField, timeField, timestampField } from "./orm/field-builders.js";
3
+ import { isColumn } from "./orm/column.js";
4
+ import { and, asc, contains, desc, endsWith, eq, gt, gte, inArray, isNotNull, isNull, lt, lte, ne, not, notInArray, or, startsWith } from "./orm/operators.js";
5
+ import { FMTable, fmTableOccurrence, getTableColumns } from "./orm/table.js";
5
6
  import { AbortError, CircuitOpenError, NetworkError, RetryLimitError, TimeoutError } from "@fetchkit/ffetch";
6
- import { FMODataError, HTTPError, ODataError, RecordCountMismatchError, ResponseParseError, ResponseStructureError, SchemaLockedError, ValidationError, isFMODataError, isHTTPError, isODataError, isRecordCountMismatchError, isResponseParseError, isResponseStructureError, isSchemaLockedError, isValidationError } from "./errors.js";
7
+ import { BatchTruncatedError, FMODataError, HTTPError, ODataError, RecordCountMismatchError, ResponseParseError, ResponseStructureError, SchemaLockedError, ValidationError, isBatchTruncatedError, isFMODataError, isHTTPError, isODataError, isRecordCountMismatchError, isResponseParseError, isResponseStructureError, isSchemaLockedError, isValidationError } from "./errors.js";
7
8
  export {
8
9
  AbortError,
10
+ BatchTruncatedError,
9
11
  CircuitOpenError,
10
12
  FMODataError,
11
13
  FMServerConnection,
14
+ FMTable,
12
15
  HTTPError,
13
16
  NetworkError,
14
17
  ODataError,
@@ -19,16 +22,42 @@ export {
19
22
  SchemaLockedError,
20
23
  TimeoutError,
21
24
  ValidationError,
22
- buildOccurrences,
23
- defineBaseTable,
24
- defineTableOccurrence,
25
+ and,
26
+ asc,
27
+ calcField,
28
+ containerField,
29
+ contains,
30
+ dateField,
31
+ desc,
32
+ endsWith,
33
+ eq,
34
+ fmTableOccurrence,
35
+ getTableColumns,
36
+ gt,
37
+ gte,
38
+ inArray,
39
+ isBatchTruncatedError,
40
+ isColumn,
25
41
  isFMODataError,
26
42
  isHTTPError,
43
+ isNotNull,
44
+ isNull,
27
45
  isODataError,
28
46
  isRecordCountMismatchError,
29
47
  isResponseParseError,
30
48
  isResponseStructureError,
31
49
  isSchemaLockedError,
32
- isValidationError
50
+ isValidationError,
51
+ lt,
52
+ lte,
53
+ ne,
54
+ not,
55
+ notInArray,
56
+ numberField,
57
+ or,
58
+ startsWith,
59
+ textField,
60
+ timeField,
61
+ timestampField
33
62
  };
34
63
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Column represents a type-safe reference to a table field.
3
+ * Used in queries, filters, and operators to provide autocomplete and type checking.
4
+ *
5
+ * @template T - The TypeScript type of the column's value
6
+ * @template TableName - The table name as a string literal type (for validation)
7
+ * @template IsContainer - Whether this column represents a container field (cannot be selected)
8
+ */
9
+ export declare class Column<T = any, TableName extends string = string, IsContainer extends boolean = false> {
10
+ readonly fieldName: string;
11
+ readonly entityId?: `FMFID:${string}`;
12
+ readonly tableName: TableName;
13
+ readonly tableEntityId?: `FMTID:${string}`;
14
+ readonly _phantom: T;
15
+ readonly _isContainer: IsContainer;
16
+ constructor(config: {
17
+ fieldName: string;
18
+ entityId?: `FMFID:${string}`;
19
+ tableName: TableName;
20
+ tableEntityId?: `FMTID:${string}`;
21
+ });
22
+ /**
23
+ * Get the field identifier (entity ID if available, otherwise field name).
24
+ * Used when building OData queries.
25
+ */
26
+ getFieldIdentifier(useEntityIds?: boolean): string;
27
+ /**
28
+ * Get the table identifier (entity ID if available, otherwise table name).
29
+ * Used when building OData queries.
30
+ */
31
+ getTableIdentifier(useEntityIds?: boolean): string;
32
+ /**
33
+ * Check if this column is from a specific table.
34
+ * Useful for validation in cross-table operations.
35
+ */
36
+ isFromTable(tableName: string): boolean;
37
+ /**
38
+ * Create a string representation for debugging.
39
+ */
40
+ toString(): string;
41
+ }
42
+ /**
43
+ * Type guard to check if a value is a Column instance.
44
+ */
45
+ export declare function isColumn(value: any): value is Column<any, any, any>;
@@ -0,0 +1,59 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ class Column {
5
+ constructor(config) {
6
+ __publicField(this, "fieldName");
7
+ __publicField(this, "entityId");
8
+ __publicField(this, "tableName");
9
+ __publicField(this, "tableEntityId");
10
+ // Phantom type for TypeScript inference - never actually holds a value
11
+ __publicField(this, "_phantom");
12
+ __publicField(this, "_isContainer");
13
+ this.fieldName = config.fieldName;
14
+ this.entityId = config.entityId;
15
+ this.tableName = config.tableName;
16
+ this.tableEntityId = config.tableEntityId;
17
+ }
18
+ /**
19
+ * Get the field identifier (entity ID if available, otherwise field name).
20
+ * Used when building OData queries.
21
+ */
22
+ getFieldIdentifier(useEntityIds) {
23
+ if (useEntityIds && this.entityId) {
24
+ return this.entityId;
25
+ }
26
+ return this.fieldName;
27
+ }
28
+ /**
29
+ * Get the table identifier (entity ID if available, otherwise table name).
30
+ * Used when building OData queries.
31
+ */
32
+ getTableIdentifier(useEntityIds) {
33
+ if (useEntityIds && this.tableEntityId) {
34
+ return this.tableEntityId;
35
+ }
36
+ return this.tableName;
37
+ }
38
+ /**
39
+ * Check if this column is from a specific table.
40
+ * Useful for validation in cross-table operations.
41
+ */
42
+ isFromTable(tableName) {
43
+ return this.tableName === tableName;
44
+ }
45
+ /**
46
+ * Create a string representation for debugging.
47
+ */
48
+ toString() {
49
+ return `${this.tableName}.${this.fieldName}`;
50
+ }
51
+ }
52
+ function isColumn(value) {
53
+ return value instanceof Column;
54
+ }
55
+ export {
56
+ Column,
57
+ isColumn
58
+ };
59
+ //# sourceMappingURL=column.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column.js","sources":["../../../src/orm/column.ts"],"sourcesContent":["/**\n * Column represents a type-safe reference to a table field.\n * Used in queries, filters, and operators to provide autocomplete and type checking.\n *\n * @template T - The TypeScript type of the column's value\n * @template TableName - The table name as a string literal type (for validation)\n * @template IsContainer - Whether this column represents a container field (cannot be selected)\n */\nexport class Column<\n T = any,\n TableName extends string = string,\n IsContainer extends boolean = false,\n> {\n readonly fieldName: string;\n readonly entityId?: `FMFID:${string}`;\n readonly tableName: TableName;\n readonly tableEntityId?: `FMTID:${string}`;\n\n // Phantom type for TypeScript inference - never actually holds a value\n readonly _phantom!: T;\n readonly _isContainer!: IsContainer;\n\n constructor(config: {\n fieldName: string;\n entityId?: `FMFID:${string}`;\n tableName: TableName;\n tableEntityId?: `FMTID:${string}`;\n }) {\n this.fieldName = config.fieldName;\n this.entityId = config.entityId;\n this.tableName = config.tableName;\n this.tableEntityId = config.tableEntityId;\n }\n\n /**\n * Get the field identifier (entity ID if available, otherwise field name).\n * Used when building OData queries.\n */\n getFieldIdentifier(useEntityIds?: boolean): string {\n if (useEntityIds && this.entityId) {\n return this.entityId;\n }\n return this.fieldName;\n }\n\n /**\n * Get the table identifier (entity ID if available, otherwise table name).\n * Used when building OData queries.\n */\n getTableIdentifier(useEntityIds?: boolean): string {\n if (useEntityIds && this.tableEntityId) {\n return this.tableEntityId;\n }\n return this.tableName;\n }\n\n /**\n * Check if this column is from a specific table.\n * Useful for validation in cross-table operations.\n */\n isFromTable(tableName: string): boolean {\n return this.tableName === tableName;\n }\n\n /**\n * Create a string representation for debugging.\n */\n toString(): string {\n return `${this.tableName}.${this.fieldName}`;\n }\n}\n\n/**\n * Type guard to check if a value is a Column instance.\n */\nexport function isColumn(value: any): value is Column<any, any, any> {\n return value instanceof Column;\n}\n"],"names":[],"mappings":";;;AAQO,MAAM,OAIX;AAAA,EAUA,YAAY,QAKT;AAdM;AACA;AACA;AACA;AAGA;AAAA;AACA;AAQP,SAAK,YAAY,OAAO;AACxB,SAAK,WAAW,OAAO;AACvB,SAAK,YAAY,OAAO;AACxB,SAAK,gBAAgB,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO9B,mBAAmB,cAAgC;AAC7C,QAAA,gBAAgB,KAAK,UAAU;AACjC,aAAO,KAAK;AAAA,IAAA;AAEd,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,mBAAmB,cAAgC;AAC7C,QAAA,gBAAgB,KAAK,eAAe;AACtC,aAAO,KAAK;AAAA,IAAA;AAEd,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,YAAY,WAA4B;AACtC,WAAO,KAAK,cAAc;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAM5B,WAAmB;AACjB,WAAO,GAAG,KAAK,SAAS,IAAI,KAAK,SAAS;AAAA,EAAA;AAE9C;AAKO,SAAS,SAAS,OAA4C;AACnE,SAAO,iBAAiB;AAC1B;"}
@@ -0,0 +1,154 @@
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
+ /**
3
+ * Branded type for container field's database type.
4
+ * This allows TypeScript to distinguish container fields from regular string fields
5
+ * at the type level, enabling compile-time exclusion from select operations.
6
+ */
7
+ export type ContainerDbType = string & {
8
+ 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 declare class FieldBuilder<TOutput = any, TInput = TOutput, TDbType = TOutput, TReadOnly extends boolean = false> {
20
+ private _primaryKey;
21
+ private _notNull;
22
+ private _readOnly;
23
+ private _entityId?;
24
+ private _outputValidator?;
25
+ private _inputValidator?;
26
+ private _fieldType;
27
+ constructor(fieldType: string);
28
+ /**
29
+ * Mark this field as the primary key for the table.
30
+ * Primary keys are automatically read-only.
31
+ */
32
+ primaryKey(): FieldBuilder<TOutput, TInput, TDbType, true>;
33
+ /**
34
+ * Mark this field as non-nullable.
35
+ * Updates the type to exclude null/undefined.
36
+ */
37
+ notNull(): FieldBuilder<NonNullable<TOutput>, NonNullable<TInput>, NonNullable<TDbType>, TReadOnly>;
38
+ /**
39
+ * Mark this field as read-only.
40
+ * Read-only fields are excluded from insert and update operations.
41
+ */
42
+ readOnly(): FieldBuilder<TOutput, TInput, TDbType, true>;
43
+ /**
44
+ * Assign a FileMaker field ID (FMFID) to this field.
45
+ * When useEntityIds is enabled, this ID will be used in API requests instead of the field name.
46
+ */
47
+ entityId(id: `FMFID:${string}`): FieldBuilder<TOutput, TInput, TDbType, TReadOnly>;
48
+ /**
49
+ * Set a validator for the output (reading from database).
50
+ * The output validator transforms/validates data coming FROM the database in list or get operations.
51
+ *
52
+ * @example
53
+ * numberField().readValidator(z.coerce.boolean())
54
+ * // FileMaker returns 0/1, you get true/false
55
+ */
56
+ readValidator<O, VInput = TDbType>(validator: StandardSchemaV1<VInput, O>): FieldBuilder<O, TInput, TDbType, TReadOnly>;
57
+ /**
58
+ * Set a validator for the input (writing to database).
59
+ * The input validator transforms/validates data going TO the database in insert and update operations.
60
+ *
61
+ * @example
62
+ * numberField().writeValidator(z.boolean().transform(v => v ? 1 : 0))
63
+ * // You pass true/false, FileMaker gets 1/0
64
+ */
65
+ writeValidator<I>(validator: StandardSchemaV1<I, TDbType>): FieldBuilder<TOutput, I, TDbType, TReadOnly>;
66
+ /**
67
+ * Get the metadata configuration for this field.
68
+ * @internal Used by fmTableOccurrence to extract field configuration
69
+ */
70
+ _getConfig(): {
71
+ fieldType: string;
72
+ primaryKey: boolean;
73
+ notNull: boolean;
74
+ readOnly: boolean;
75
+ entityId: `FMFID:${string}` | undefined;
76
+ outputValidator: StandardSchemaV1<any, TOutput> | undefined;
77
+ inputValidator: StandardSchemaV1<TInput, any> | undefined;
78
+ };
79
+ /**
80
+ * Clone this builder to allow immutable chaining.
81
+ * @private
82
+ */
83
+ private _clone;
84
+ }
85
+ /**
86
+ * Create a text field (Edm.String in FileMaker OData).
87
+ * By default, text fields are nullable.
88
+ *
89
+ * @example
90
+ * textField() // string | null
91
+ * textField().notNull() // string
92
+ * textField().entityId("FMFID:1") // with entity ID
93
+ */
94
+ export declare function textField(): FieldBuilder<string | null, string | null, string | null, false>;
95
+ /**
96
+ * Create a number field (Edm.Decimal in FileMaker OData).
97
+ * By default, number fields are nullable.
98
+ *
99
+ * @example
100
+ * numberField() // number | null
101
+ * numberField().notNull() // number
102
+ * numberField().outputValidator(z.coerce.boolean()) // transform to boolean on read
103
+ */
104
+ export declare function numberField(): FieldBuilder<number | null, number | null, number | null, false>;
105
+ /**
106
+ * Create a date field (Edm.Date in FileMaker OData).
107
+ * By default, date fields are nullable and represented as ISO date strings (YYYY-MM-DD).
108
+ *
109
+ * @example
110
+ * dateField() // string | null (ISO date format)
111
+ * dateField().notNull() // string
112
+ */
113
+ export declare function dateField(): FieldBuilder<string | null, string | null, string | null, false>;
114
+ /**
115
+ * Create a time field (Edm.TimeOfDay in FileMaker OData).
116
+ * By default, time fields are nullable and represented as ISO time strings (HH:mm:ss).
117
+ *
118
+ * @example
119
+ * timeField() // string | null (ISO time format)
120
+ * timeField().notNull() // string
121
+ */
122
+ export declare function timeField(): FieldBuilder<string | null, string | null, string | null, false>;
123
+ /**
124
+ * Create a timestamp field (Edm.DateTimeOffset in FileMaker OData).
125
+ * By default, timestamp fields are nullable and represented as ISO 8601 strings.
126
+ *
127
+ * @example
128
+ * timestampField() // string | null (ISO 8601 format)
129
+ * timestampField().notNull() // string
130
+ * timestampField().readOnly() // typical for CreationTimestamp
131
+ */
132
+ export declare function timestampField(): FieldBuilder<string | null, string | null, string | null, false>;
133
+ /**
134
+ * Create a container field (Edm.Stream in FileMaker OData).
135
+ * Container fields store binary data and are represented as base64 strings in the API.
136
+ * By default, container fields are nullable.
137
+ *
138
+ * Note: Container fields cannot be selected via .select() - they can only be accessed
139
+ * via .getSingleField() due to FileMaker OData API limitations.
140
+ *
141
+ * @example
142
+ * containerField() // string | null (base64 encoded)
143
+ * containerField().notNull() // string
144
+ */
145
+ export declare function containerField(): FieldBuilder<string | null, string | null, ContainerDbType | null, false>;
146
+ /**
147
+ * Create a calculated field (read-only field computed by FileMaker).
148
+ * Calculated fields are automatically marked as read-only.
149
+ *
150
+ * @example
151
+ * calcField() // string | null
152
+ * calcField().notNull() // string
153
+ */
154
+ export declare function calcField(): FieldBuilder<string | null, string | null, string | null, true>;
@@ -0,0 +1,152 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ class FieldBuilder {
5
+ constructor(fieldType) {
6
+ __publicField(this, "_primaryKey", false);
7
+ __publicField(this, "_notNull", false);
8
+ __publicField(this, "_readOnly", false);
9
+ __publicField(this, "_entityId");
10
+ __publicField(this, "_outputValidator");
11
+ __publicField(this, "_inputValidator");
12
+ __publicField(this, "_fieldType");
13
+ this._fieldType = fieldType;
14
+ }
15
+ /**
16
+ * Mark this field as the primary key for the table.
17
+ * Primary keys are automatically read-only.
18
+ */
19
+ primaryKey() {
20
+ const builder = this._clone();
21
+ builder._primaryKey = true;
22
+ builder._readOnly = true;
23
+ return builder;
24
+ }
25
+ /**
26
+ * Mark this field as non-nullable.
27
+ * Updates the type to exclude null/undefined.
28
+ */
29
+ notNull() {
30
+ const builder = this._clone();
31
+ builder._notNull = true;
32
+ return builder;
33
+ }
34
+ /**
35
+ * Mark this field as read-only.
36
+ * Read-only fields are excluded from insert and update operations.
37
+ */
38
+ readOnly() {
39
+ const builder = this._clone();
40
+ builder._readOnly = true;
41
+ return builder;
42
+ }
43
+ /**
44
+ * Assign a FileMaker field ID (FMFID) to this field.
45
+ * When useEntityIds is enabled, this ID will be used in API requests instead of the field name.
46
+ */
47
+ entityId(id) {
48
+ const builder = this._clone();
49
+ builder._entityId = id;
50
+ return builder;
51
+ }
52
+ /**
53
+ * Set a validator for the output (reading from database).
54
+ * The output validator transforms/validates data coming FROM the database in list or get operations.
55
+ *
56
+ * @example
57
+ * numberField().readValidator(z.coerce.boolean())
58
+ * // FileMaker returns 0/1, you get true/false
59
+ */
60
+ readValidator(validator) {
61
+ const builder = this._clone();
62
+ builder._outputValidator = validator;
63
+ return builder;
64
+ }
65
+ /**
66
+ * Set a validator for the input (writing to database).
67
+ * The input validator transforms/validates data going TO the database in insert and update operations.
68
+ *
69
+ * @example
70
+ * numberField().writeValidator(z.boolean().transform(v => v ? 1 : 0))
71
+ * // You pass true/false, FileMaker gets 1/0
72
+ */
73
+ writeValidator(validator) {
74
+ const builder = this._clone();
75
+ builder._inputValidator = validator;
76
+ return builder;
77
+ }
78
+ /**
79
+ * Get the metadata configuration for this field.
80
+ * @internal Used by fmTableOccurrence to extract field configuration
81
+ */
82
+ _getConfig() {
83
+ return {
84
+ fieldType: this._fieldType,
85
+ primaryKey: this._primaryKey,
86
+ notNull: this._notNull,
87
+ readOnly: this._readOnly,
88
+ entityId: this._entityId,
89
+ outputValidator: this._outputValidator,
90
+ inputValidator: this._inputValidator
91
+ };
92
+ }
93
+ /**
94
+ * Clone this builder to allow immutable chaining.
95
+ * @private
96
+ */
97
+ _clone() {
98
+ const builder = new FieldBuilder(
99
+ this._fieldType
100
+ );
101
+ builder._primaryKey = this._primaryKey;
102
+ builder._notNull = this._notNull;
103
+ builder._readOnly = this._readOnly;
104
+ builder._entityId = this._entityId;
105
+ builder._outputValidator = this._outputValidator;
106
+ builder._inputValidator = this._inputValidator;
107
+ return builder;
108
+ }
109
+ }
110
+ function textField() {
111
+ return new FieldBuilder(
112
+ "text"
113
+ );
114
+ }
115
+ function numberField() {
116
+ return new FieldBuilder(
117
+ "number"
118
+ );
119
+ }
120
+ function dateField() {
121
+ return new FieldBuilder(
122
+ "date"
123
+ );
124
+ }
125
+ function timeField() {
126
+ return new FieldBuilder(
127
+ "time"
128
+ );
129
+ }
130
+ function timestampField() {
131
+ return new FieldBuilder(
132
+ "timestamp"
133
+ );
134
+ }
135
+ function containerField() {
136
+ return new FieldBuilder("container");
137
+ }
138
+ function calcField() {
139
+ const builder = new FieldBuilder("calculated");
140
+ return builder.readOnly();
141
+ }
142
+ export {
143
+ FieldBuilder,
144
+ calcField,
145
+ containerField,
146
+ dateField,
147
+ numberField,
148
+ textField,
149
+ timeField,
150
+ timestampField
151
+ };
152
+ //# sourceMappingURL=field-builders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-builders.js","sources":["../../../src/orm/field-builders.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Branded type for container field's database type.\n * This allows TypeScript to distinguish container fields from regular string fields\n * at the type level, enabling compile-time exclusion from select operations.\n */\nexport type ContainerDbType = string & { readonly __container: true };\n\n/**\n * FieldBuilder provides a fluent API for defining table fields with type-safe metadata.\n * Supports chaining methods to configure primary keys, nullability, read-only status, entity IDs, and validators.\n *\n * @template TOutput - The output type after applying outputValidator (what you get when reading)\n * @template TInput - The input type after applying inputValidator (what you pass when writing)\n * @template TDbType - The database type (what FileMaker stores/expects)\n * @template TReadOnly - Whether this field is read-only (for type-level exclusion from insert/update)\n */\nexport class FieldBuilder<\n TOutput = any,\n TInput = TOutput,\n TDbType = TOutput,\n TReadOnly extends boolean = false,\n> {\n private _primaryKey = false;\n private _notNull = false;\n private _readOnly = false;\n private _entityId?: `FMFID:${string}`;\n private _outputValidator?: StandardSchemaV1<any, TOutput>;\n private _inputValidator?: StandardSchemaV1<TInput, any>;\n private _fieldType: string;\n\n constructor(fieldType: string) {\n this._fieldType = fieldType;\n }\n\n /**\n * Mark this field as the primary key for the table.\n * Primary keys are automatically read-only.\n */\n primaryKey(): FieldBuilder<TOutput, TInput, TDbType, true> {\n const builder = this._clone() as any;\n builder._primaryKey = true;\n builder._readOnly = true; // Primary keys are automatically read-only\n return builder;\n }\n\n /**\n * Mark this field as non-nullable.\n * Updates the type to exclude null/undefined.\n */\n notNull(): FieldBuilder<\n NonNullable<TOutput>,\n NonNullable<TInput>,\n NonNullable<TDbType>,\n TReadOnly\n > {\n const builder = this._clone() as any;\n builder._notNull = true;\n return builder;\n }\n\n /**\n * Mark this field as read-only.\n * Read-only fields are excluded from insert and update operations.\n */\n readOnly(): FieldBuilder<TOutput, TInput, TDbType, true> {\n const builder = this._clone() as any;\n builder._readOnly = true;\n return builder;\n }\n\n /**\n * Assign a FileMaker field ID (FMFID) to this field.\n * When useEntityIds is enabled, this ID will be used in API requests instead of the field name.\n */\n entityId(\n id: `FMFID:${string}`,\n ): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {\n const builder = this._clone();\n builder._entityId = id;\n return builder;\n }\n\n /**\n * Set a validator for the output (reading from database).\n * The output validator transforms/validates data coming FROM the database in list or get operations.\n *\n * @example\n * numberField().readValidator(z.coerce.boolean())\n * // FileMaker returns 0/1, you get true/false\n */\n readValidator<O, VInput = TDbType>(\n validator: StandardSchemaV1<VInput, O>,\n ): FieldBuilder<O, TInput, TDbType, TReadOnly> {\n const builder = this._clone() as any;\n builder._outputValidator = validator;\n return builder;\n }\n\n /**\n * Set a validator for the input (writing to database).\n * The input validator transforms/validates data going TO the database in insert and update operations.\n *\n * @example\n * numberField().writeValidator(z.boolean().transform(v => v ? 1 : 0))\n * // You pass true/false, FileMaker gets 1/0\n */\n writeValidator<I>(\n validator: StandardSchemaV1<I, TDbType>,\n ): FieldBuilder<TOutput, I, TDbType, TReadOnly> {\n const builder = this._clone() as any;\n builder._inputValidator = validator;\n return builder;\n }\n\n /**\n * Get the metadata configuration for this field.\n * @internal Used by fmTableOccurrence to extract field configuration\n */\n _getConfig() {\n return {\n fieldType: this._fieldType,\n primaryKey: this._primaryKey,\n notNull: this._notNull,\n readOnly: this._readOnly,\n entityId: this._entityId,\n outputValidator: this._outputValidator,\n inputValidator: this._inputValidator,\n };\n }\n\n /**\n * Clone this builder to allow immutable chaining.\n * @private\n */\n private _clone(): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {\n const builder = new FieldBuilder<TOutput, TInput, TDbType, TReadOnly>(\n this._fieldType,\n );\n builder._primaryKey = this._primaryKey;\n builder._notNull = this._notNull;\n builder._readOnly = this._readOnly;\n builder._entityId = this._entityId;\n builder._outputValidator = this._outputValidator;\n builder._inputValidator = this._inputValidator;\n return builder;\n }\n}\n\n/**\n * Create a text field (Edm.String in FileMaker OData).\n * By default, text fields are nullable.\n *\n * @example\n * textField() // string | null\n * textField().notNull() // string\n * textField().entityId(\"FMFID:1\") // with entity ID\n */\nexport function textField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"text\",\n );\n}\n\n/**\n * Create a number field (Edm.Decimal in FileMaker OData).\n * By default, number fields are nullable.\n *\n * @example\n * numberField() // number | null\n * numberField().notNull() // number\n * numberField().outputValidator(z.coerce.boolean()) // transform to boolean on read\n */\nexport function numberField(): FieldBuilder<\n number | null,\n number | null,\n number | null,\n false\n> {\n return new FieldBuilder<number | null, number | null, number | null, false>(\n \"number\",\n );\n}\n\n/**\n * Create a date field (Edm.Date in FileMaker OData).\n * By default, date fields are nullable and represented as ISO date strings (YYYY-MM-DD).\n *\n * @example\n * dateField() // string | null (ISO date format)\n * dateField().notNull() // string\n */\nexport function dateField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"date\",\n );\n}\n\n/**\n * Create a time field (Edm.TimeOfDay in FileMaker OData).\n * By default, time fields are nullable and represented as ISO time strings (HH:mm:ss).\n *\n * @example\n * timeField() // string | null (ISO time format)\n * timeField().notNull() // string\n */\nexport function timeField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"time\",\n );\n}\n\n/**\n * Create a timestamp field (Edm.DateTimeOffset in FileMaker OData).\n * By default, timestamp fields are nullable and represented as ISO 8601 strings.\n *\n * @example\n * timestampField() // string | null (ISO 8601 format)\n * timestampField().notNull() // string\n * timestampField().readOnly() // typical for CreationTimestamp\n */\nexport function timestampField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"timestamp\",\n );\n}\n\n/**\n * Create a container field (Edm.Stream in FileMaker OData).\n * Container fields store binary data and are represented as base64 strings in the API.\n * By default, container fields are nullable.\n *\n * Note: Container fields cannot be selected via .select() - they can only be accessed\n * via .getSingleField() due to FileMaker OData API limitations.\n *\n * @example\n * containerField() // string | null (base64 encoded)\n * containerField().notNull() // string\n */\nexport function containerField(): FieldBuilder<\n string | null,\n string | null,\n ContainerDbType | null,\n false\n> {\n return new FieldBuilder<\n string | null,\n string | null,\n ContainerDbType | null,\n false\n >(\"container\");\n}\n\n/**\n * Create a calculated field (read-only field computed by FileMaker).\n * Calculated fields are automatically marked as read-only.\n *\n * @example\n * calcField() // string | null\n * calcField().notNull() // string\n */\nexport function calcField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n true\n> {\n const builder = new FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n >(\"calculated\");\n return builder.readOnly();\n}\n"],"names":[],"mappings":";;;AAkBO,MAAM,aAKX;AAAA,EASA,YAAY,WAAmB;AARvB,uCAAc;AACd,oCAAW;AACX,qCAAY;AACZ;AACA;AACA;AACA;AAGN,SAAK,aAAa;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpB,aAA2D;AACnD,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,cAAc;AACtB,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,UAKE;AACM,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,WAAW;AACZ,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,WAAyD;AACjD,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,SACE,IACmD;AAC7C,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,cACE,WAC6C;AACvC,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,mBAAmB;AACpB,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,eACE,WAC8C;AACxC,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,kBAAkB;AACnB,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,aAAa;AACJ,WAAA;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,iBAAiB,KAAK;AAAA,MACtB,gBAAgB,KAAK;AAAA,IACvB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOM,SAA4D;AAClE,UAAM,UAAU,IAAI;AAAA,MAClB,KAAK;AAAA,IACP;AACA,YAAQ,cAAc,KAAK;AAC3B,YAAQ,WAAW,KAAK;AACxB,YAAQ,YAAY,KAAK;AACzB,YAAQ,YAAY,KAAK;AACzB,YAAQ,mBAAmB,KAAK;AAChC,YAAQ,kBAAkB,KAAK;AACxB,WAAA;AAAA,EAAA;AAEX;AAWO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAWO,SAAS,cAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAUO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAUO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAWO,SAAS,iBAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAcO,SAAS,iBAKd;AACO,SAAA,IAAI,aAKT,WAAW;AACf;AAUO,SAAS,YAKd;AACM,QAAA,UAAU,IAAI,aAKlB,YAAY;AACd,SAAO,QAAQ,SAAS;AAC1B;"}
@@ -0,0 +1,4 @@
1
+ export { FieldBuilder, textField, numberField, dateField, timeField, timestampField, containerField, calcField, type ContainerDbType, } from './field-builders.js';
2
+ export { Column, isColumn } from './column.js';
3
+ export { FilterExpression, eq, ne, gt, gte, lt, lte, contains, startsWith, endsWith, inArray, notInArray, isNull, isNotNull, and, or, not, OrderByExpression, isOrderByExpression, asc, desc, } from './operators.js';
4
+ export { fmTableOccurrence, FMTable, type FMTableWithColumns, type InferTableSchema, getTableName, getTableEntityId, getDefaultSelect, getBaseTableConfig, isUsingEntityIds, getFieldId, getFieldName, getTableId, getTableColumns, } from './table.js';