@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 +0,0 @@
1
- {"version":3,"file":"query-builder.js","sources":["../../../src/client/query-builder.ts"],"sourcesContent":["import { QueryOptions } from \"odata-query\";\nimport buildQuery from \"odata-query\";\nimport type {\n ExecutionContext,\n ExecutableBuilder,\n WithSystemFields,\n Result,\n InferSchemaType,\n ExecuteOptions,\n ConditionallyWithODataAnnotations,\n ExtractSchemaFromOccurrence,\n} from \"../types\";\nimport { getAcceptHeader } from \"../types\";\nimport type { Filter } from \"../filter-types\";\nimport type { TableOccurrence } from \"./table-occurrence\";\nimport type { BaseTable } from \"./base-table\";\nimport { validateListResponse, validateSingleResponse } from \"../validation\";\nimport { RecordCountMismatchError } from \"../errors\";\nimport { type FFetchOptions } from \"@fetchkit/ffetch\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport {\n transformFieldNamesArray,\n transformFieldName,\n transformOrderByField,\n transformResponseFields,\n getTableIdentifiers,\n} from \"../transform\";\nimport { safeJsonParse } from \"./sanitize-json\";\n\n/**\n * Default maximum number of records to return in a list query.\n * This prevents stack overflow issues with large datasets while still\n * allowing substantial data retrieval. Users can override with .top().\n */\nconst DEFAULT_TOP = 1000;\n\n// Helper type to extract navigation relation names from an occurrence\ntype ExtractNavigationNames<\n O extends TableOccurrence<any, any, any, any> | undefined,\n> =\n O extends TableOccurrence<any, any, infer Nav, any>\n ? Nav extends Record<string, any>\n ? keyof Nav & string\n : never\n : never;\n\n// Helper type to find target occurrence by relation name\ntype FindNavigationTarget<\n O extends TableOccurrence<any, any, any, any> | undefined,\n Name extends string,\n> =\n O extends TableOccurrence<any, any, infer Nav, any>\n ? Nav extends Record<string, any>\n ? Name extends keyof Nav\n ? Nav[Name]\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, any>,\n any,\n any,\n any\n >\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, any>,\n any,\n any,\n any\n >\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, any>,\n any,\n any,\n any\n >;\n\n// Helper type to get the inferred schema type from a target occurrence\ntype GetTargetSchemaType<\n O extends TableOccurrence<any, any, any, any> | undefined,\n Rel extends string,\n> = [FindNavigationTarget<O, Rel>] extends [\n TableOccurrence<infer BT, any, any, any>,\n]\n ? [BT] extends [BaseTable<infer S, any, any, any>]\n ? [S] extends [Record<string, StandardSchemaV1>]\n ? InferSchemaType<S>\n : Record<string, any>\n : Record<string, any>\n : Record<string, any>;\n\n// Internal type for expand configuration\ntype ExpandConfig = {\n relation: string;\n options?: Partial<QueryOptions<any>>;\n};\n\n// Type to represent expanded relations\nexport type ExpandedRelations = Record<string, { schema: any; selected: any }>;\n\nexport type QueryReturnType<\n T extends Record<string, any>,\n Selected extends keyof T,\n SingleMode extends \"exact\" | \"maybe\" | false,\n IsCount extends boolean,\n Expands extends ExpandedRelations,\n> = IsCount extends true\n ? number\n : SingleMode extends \"exact\"\n ? Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n }\n : SingleMode extends \"maybe\"\n ?\n | (Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n })\n | null\n : (Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n })[];\n\nexport class QueryBuilder<\n T extends Record<string, any>,\n Selected extends keyof T = keyof T,\n SingleMode extends \"exact\" | \"maybe\" | false = false,\n IsCount extends boolean = false,\n Occ extends TableOccurrence<any, any, any, any> | undefined = undefined,\n Expands extends ExpandedRelations = {},\n> implements\n ExecutableBuilder<\n QueryReturnType<T, Selected, SingleMode, IsCount, Expands>\n >\n{\n private queryOptions: Partial<QueryOptions<T>> = {};\n private expandConfigs: ExpandConfig[] = [];\n private singleMode: SingleMode = false as SingleMode;\n private isCountMode = false as IsCount;\n private occurrence?: Occ;\n private tableName: string;\n private databaseName: string;\n private context: ExecutionContext;\n private isNavigate?: boolean;\n private navigateRecordId?: string | number;\n private navigateRelation?: string;\n private navigateSourceTableName?: string;\n private navigateBaseRelation?: string;\n private navigateBasePath?: string; // Full base path for chained entity set navigations\n private databaseUseEntityIds: boolean;\n\n constructor(config: {\n occurrence?: Occ;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n databaseUseEntityIds?: boolean;\n }) {\n this.occurrence = config.occurrence;\n this.tableName = config.tableName;\n this.databaseName = config.databaseName;\n this.context = config.context;\n this.databaseUseEntityIds = config.databaseUseEntityIds ?? false;\n }\n\n /**\n * Helper to merge database-level useEntityIds with per-request options\n */\n private mergeExecuteOptions(\n options?: RequestInit & FFetchOptions & ExecuteOptions,\n ): RequestInit & FFetchOptions & { useEntityIds?: boolean } {\n // If useEntityIds is not set in options, use the database-level setting\n return {\n ...options,\n useEntityIds:\n options?.useEntityIds === undefined\n ? this.databaseUseEntityIds\n : options.useEntityIds,\n };\n }\n\n /**\n * Gets the table ID (FMTID) if using entity IDs, otherwise returns the table name\n * @param useEntityIds - Optional override for entity ID usage\n */\n private getTableId(useEntityIds?: boolean): string {\n if (!this.occurrence) {\n return this.tableName;\n }\n\n const contextDefault = this.context._getUseEntityIds?.() ?? false;\n const shouldUseIds = useEntityIds ?? contextDefault;\n\n if (shouldUseIds) {\n const identifiers = getTableIdentifiers(this.occurrence);\n if (!identifiers.id) {\n throw new Error(\n `useEntityIds is true but TableOccurrence \"${identifiers.name}\" does not have an fmtId defined`,\n );\n }\n return identifiers.id;\n }\n\n return this.occurrence.getTableName();\n }\n\n select<K extends keyof T>(\n ...fields: K[]\n ): QueryBuilder<T, K, SingleMode, IsCount, Occ, Expands> {\n const uniqueFields = [...new Set(fields)];\n const newBuilder = new QueryBuilder<\n T,\n K,\n SingleMode,\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = {\n ...this.queryOptions,\n select: uniqueFields as string[],\n };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = this.singleMode;\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n /**\n * Transforms our filter format to odata-query's expected format\n * - Arrays of operators are converted to AND conditions\n * - Single operator objects pass through as-is\n * - Shorthand values are handled by odata-query\n */\n private transformFilter(\n filter: Filter<ExtractSchemaFromOccurrence<Occ>>,\n ): QueryOptions<T>[\"filter\"] {\n if (typeof filter === \"string\") {\n // Raw string filters pass through\n return filter;\n }\n\n if (Array.isArray(filter)) {\n // Array of filters - odata-query handles this as implicit AND\n return filter.map((f) => this.transformFilter(f as any)) as any;\n }\n\n // Check if it's a logical filter (and/or/not)\n if (\"and\" in filter || \"or\" in filter || \"not\" in filter) {\n const result: any = {};\n if (\"and\" in filter && Array.isArray(filter.and)) {\n result.and = filter.and.map((f: any) => this.transformFilter(f));\n }\n if (\"or\" in filter && Array.isArray(filter.or)) {\n result.or = filter.or.map((f: any) => this.transformFilter(f));\n }\n if (\"not\" in filter && filter.not) {\n result.not = this.transformFilter(filter.not as any);\n }\n return result;\n }\n\n // Transform field filters\n const result: any = {};\n const andConditions: any[] = [];\n\n for (const [field, value] of Object.entries(filter)) {\n // Transform field name to FMFID if using entity IDs AND the feature is enabled\n const shouldTransform =\n this.occurrence?.baseTable && this.databaseUseEntityIds;\n const fieldId = shouldTransform\n ? transformFieldName(field, this.occurrence!.baseTable)\n : field;\n\n if (Array.isArray(value)) {\n // Array of operators - convert to AND conditions\n if (value.length === 1) {\n // Single operator in array - unwrap it\n result[fieldId] = value[0];\n } else {\n // Multiple operators - combine with AND\n // Create separate conditions for each operator\n for (const op of value) {\n andConditions.push({ [fieldId]: op });\n }\n }\n } else if (\n value &&\n typeof value === \"object\" &&\n !(value instanceof Date) &&\n !Array.isArray(value)\n ) {\n // Check if it's an operator object (has operator keys like eq, gt, etc.)\n const operatorKeys = [\n \"eq\",\n \"ne\",\n \"gt\",\n \"ge\",\n \"lt\",\n \"le\",\n \"contains\",\n \"startswith\",\n \"endswith\",\n \"in\",\n ];\n const isOperatorObject = operatorKeys.some((key) => key in value);\n\n if (isOperatorObject) {\n // Single operator object - pass through\n result[fieldId] = value;\n } else {\n // Regular object - might be nested filter, pass through\n result[fieldId] = value;\n }\n } else {\n // Primitive value (shorthand) - pass through\n result[fieldId] = value;\n }\n }\n\n // If we have AND conditions from arrays, combine them\n if (andConditions.length > 0) {\n if (Object.keys(result).length > 0) {\n // We have both regular fields and array-derived AND conditions\n // Combine everything with AND\n return { and: [...andConditions, result] };\n } else {\n // Only array-derived AND conditions\n return { and: andConditions };\n }\n }\n\n return result;\n }\n\n filter(\n filter: Filter<ExtractSchemaFromOccurrence<Occ>>,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n // Transform our filter format to odata-query's expected format\n this.queryOptions.filter = this.transformFilter(filter) as any;\n return this;\n }\n\n orderBy(\n orderBy: QueryOptions<T>[\"orderBy\"],\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n // Transform field names to FMFIDs if using entity IDs\n if (this.occurrence?.baseTable && orderBy) {\n if (Array.isArray(orderBy)) {\n this.queryOptions.orderBy = orderBy.map((field) =>\n transformOrderByField(String(field), this.occurrence!.baseTable),\n );\n } else {\n this.queryOptions.orderBy = transformOrderByField(\n String(orderBy),\n this.occurrence.baseTable,\n );\n }\n } else {\n this.queryOptions.orderBy = orderBy;\n }\n return this;\n }\n\n top(\n count: number,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n this.queryOptions.top = count;\n return this;\n }\n\n skip(\n count: number,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n this.queryOptions.skip = count;\n return this;\n }\n\n /**\n * Formats select fields for use in query strings.\n * - Transforms field names to FMFIDs if using entity IDs\n * - Wraps \"id\" fields in double quotes\n * - URL-encodes special characters but preserves spaces\n */\n private formatSelectFields(\n select: QueryOptions<any>[\"select\"],\n baseTable?: BaseTable<any, any, any, any>,\n useEntityIds?: boolean,\n ): string {\n if (!select) return \"\";\n const selectFieldsArray = Array.isArray(select) ? select : [select];\n\n // Transform to field IDs if using entity IDs AND the feature is enabled\n const shouldTransform =\n baseTable && (useEntityIds ?? this.databaseUseEntityIds);\n const transformedFields = shouldTransform\n ? transformFieldNamesArray(\n selectFieldsArray.map((f) => String(f)),\n baseTable,\n )\n : selectFieldsArray.map((f) => String(f));\n\n return transformedFields\n .map((field) => {\n if (field === \"id\") return `\"id\"`;\n const encodedField = encodeURIComponent(String(field));\n return encodedField.replace(/%20/g, \" \");\n })\n .join(\",\");\n }\n\n /**\n * Builds expand validation configs from internal expand configurations.\n * These are used to validate expanded navigation properties.\n */\n private buildExpandValidationConfigs(\n configs: ExpandConfig[],\n ): import(\"../validation\").ExpandValidationConfig[] {\n return configs.map((config) => {\n // Look up target occurrence from navigation\n const targetOccurrence = this.occurrence?.navigation[config.relation];\n const targetSchema = targetOccurrence?.baseTable?.schema;\n\n // Extract selected fields from options\n const selectedFields = config.options?.select\n ? Array.isArray(config.options.select)\n ? config.options.select.map((f) => String(f))\n : [String(config.options.select)]\n : undefined;\n\n return {\n relation: config.relation,\n targetSchema: targetSchema,\n targetOccurrence: targetOccurrence,\n targetBaseTable: targetOccurrence?.baseTable,\n occurrence: targetOccurrence, // Add occurrence for transformation\n selectedFields: selectedFields,\n nestedExpands: undefined, // TODO: Handle nested expands if needed\n };\n });\n }\n\n /**\n * Builds OData expand query string from expand configurations.\n * Handles nested expands recursively.\n * Transforms relation names to FMTIDs if using entity IDs.\n */\n private buildExpandString(configs: ExpandConfig[]): string {\n if (configs.length === 0) {\n return \"\";\n }\n\n return configs\n .map((config) => {\n // Get target occurrence for this relation\n const targetOccurrence = this.occurrence?.navigation[config.relation];\n\n // When using entity IDs, use the target table's FMTID in the expand parameter\n // FileMaker expects FMTID in $expand when Prefer header is set\n // Only use FMTID if databaseUseEntityIds is enabled\n const shouldUseTableId =\n this.databaseUseEntityIds && targetOccurrence?.isUsingTableId();\n const relationName = shouldUseTableId\n ? targetOccurrence!.getTableId()\n : config.relation;\n\n if (!config.options || Object.keys(config.options).length === 0) {\n // Simple expand without options\n return relationName;\n }\n\n // Build query options for this expand\n const parts: string[] = [];\n\n if (config.options.select) {\n // Pass target base table for field transformation\n const selectFields = this.formatSelectFields(\n config.options.select,\n targetOccurrence?.baseTable,\n );\n parts.push(`$select=${selectFields}`);\n }\n\n if (config.options.filter) {\n // Filter should already be transformed by the nested builder\n // Use odata-query to build filter string\n const filterQuery = buildQuery({ filter: config.options.filter });\n const filterMatch = filterQuery.match(/\\$filter=([^&]+)/);\n if (filterMatch) {\n parts.push(`$filter=${filterMatch[1]}`);\n }\n }\n\n if (config.options.orderBy) {\n // OrderBy should already be transformed by the nested builder\n const orderByValue = Array.isArray(config.options.orderBy)\n ? config.options.orderBy.join(\",\")\n : config.options.orderBy;\n parts.push(`$orderby=${String(orderByValue)}`);\n }\n\n if (config.options.top !== undefined) {\n parts.push(`$top=${config.options.top}`);\n }\n\n if (config.options.skip !== undefined) {\n parts.push(`$skip=${config.options.skip}`);\n }\n\n // Handle nested expands (from expand configs)\n if (config.options.expand) {\n // If expand is a string, it's already been built\n if (typeof config.options.expand === \"string\") {\n parts.push(`$expand=${config.options.expand}`);\n }\n }\n\n if (parts.length === 0) {\n return relationName;\n }\n\n return `${relationName}(${parts.join(\";\")})`;\n })\n .join(\",\");\n }\n\n expand<\n Rel extends ExtractNavigationNames<Occ> | (string & {}),\n TargetOcc extends FindNavigationTarget<Occ, Rel> = FindNavigationTarget<\n Occ,\n Rel\n >,\n TargetSchema extends GetTargetSchemaType<Occ, Rel> = GetTargetSchemaType<\n Occ,\n Rel\n >,\n TargetSelected extends keyof TargetSchema = keyof TargetSchema,\n >(\n relation: Rel,\n callback?: (\n builder: QueryBuilder<\n TargetSchema,\n keyof TargetSchema,\n false,\n false,\n TargetOcc extends TableOccurrence<any, any, any, any>\n ? TargetOcc\n : undefined\n >,\n ) => QueryBuilder<\n WithSystemFields<TargetSchema>,\n TargetSelected,\n any,\n any,\n any\n >,\n ): QueryBuilder<\n T,\n Selected,\n SingleMode,\n IsCount,\n Occ,\n Expands & {\n [K in Rel]: { schema: TargetSchema; selected: TargetSelected };\n }\n > {\n // Look up target occurrence from navigation\n const targetOccurrence = this.occurrence?.navigation[relation as string];\n\n // Helper function to get defaultSelect fields from target occurrence\n const getDefaultSelectFields = (): string[] | undefined => {\n if (!targetOccurrence) return undefined;\n const defaultSelect = targetOccurrence.defaultSelect;\n if (defaultSelect === \"schema\") {\n const schema = targetOccurrence.baseTable?.schema;\n if (schema) {\n return [...new Set(Object.keys(schema))];\n }\n } else if (Array.isArray(defaultSelect)) {\n return [...new Set(defaultSelect)];\n }\n // If \"all\", return undefined (no select restriction)\n return undefined;\n };\n\n if (callback) {\n // Create a new QueryBuilder for the target occurrence\n const targetBuilder = new QueryBuilder<any>({\n occurrence: targetOccurrence,\n tableName: targetOccurrence?.name ?? (relation as string),\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n\n // Cast to the expected type for the callback\n // At runtime, the builder is untyped (any), but at compile-time we enforce proper types\n const typedBuilder = targetBuilder as QueryBuilder<\n TargetSchema,\n keyof TargetSchema,\n false,\n false,\n TargetOcc extends TableOccurrence<any, any, any, any>\n ? TargetOcc\n : undefined\n >;\n\n // Pass to callback and get configured builder\n const configuredBuilder = callback(typedBuilder);\n\n // Extract the builder's query options\n const expandOptions: Partial<QueryOptions<any>> = {\n ...configuredBuilder.queryOptions,\n };\n\n // If callback didn't provide select, apply defaultSelect from target occurrence\n if (!expandOptions.select) {\n const defaultFields = getDefaultSelectFields();\n if (defaultFields) {\n expandOptions.select = defaultFields;\n }\n }\n\n // If the configured builder has nested expands, we need to include them\n if (configuredBuilder.expandConfigs.length > 0) {\n // Build nested expand string from the configured builder's expand configs\n const nestedExpandString = this.buildExpandString(\n configuredBuilder.expandConfigs,\n );\n if (nestedExpandString) {\n // Add nested expand to options\n expandOptions.expand = nestedExpandString as any;\n }\n }\n\n const expandConfig: ExpandConfig = {\n relation: relation as string,\n options: expandOptions,\n };\n\n this.expandConfigs.push(expandConfig);\n } else {\n // Simple expand without callback - apply defaultSelect if available\n const defaultFields = getDefaultSelectFields();\n if (defaultFields) {\n this.expandConfigs.push({\n relation: relation as string,\n options: { select: defaultFields },\n });\n } else {\n this.expandConfigs.push({ relation: relation as string });\n }\n }\n\n return this as any;\n }\n\n single(): QueryBuilder<T, Selected, \"exact\", IsCount, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n \"exact\",\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = \"exact\";\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n maybeSingle(): QueryBuilder<T, Selected, \"maybe\", IsCount, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n \"maybe\",\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = \"maybe\";\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n count(): QueryBuilder<T, Selected, SingleMode, true, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n SingleMode,\n true,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions, count: true };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = this.singleMode;\n newBuilder.isCountMode = true as true;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n async execute<EO extends ExecuteOptions>(\n options?: RequestInit & FFetchOptions & EO,\n ): Promise<\n Result<\n IsCount extends true\n ? number\n : SingleMode extends \"exact\"\n ? ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n >\n : SingleMode extends \"maybe\"\n ? ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n > | null\n : ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n >[]\n >\n > {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n const mergedOptions = this.mergeExecuteOptions(options);\n\n // Format select fields before building query\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryString = buildQuery(queryOptionsWithoutExpand);\n\n // Build custom expand string\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryString.includes(\"?\") ? \"&\" : \"?\";\n queryString = `${queryString}${separator}$expand=${expandString}`;\n }\n\n // Handle navigation from RecordBuilder\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let url: string;\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n } else {\n // Normal navigation: /sourceTable('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n }\n const result = await this.context._makeRequest(url, mergedOptions);\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n return { data: record as any, error: undefined };\n } else {\n const records = resp.value ?? [];\n const stripped = records.map((record: any) => record);\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as\n | (keyof T)[]\n | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return { data: validation.data as any, error: undefined };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return { data: validation.data as any, error: undefined };\n }\n }\n\n // Handle navigation from EntitySet (without record ID)\n if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n return { data: record as any, error: undefined };\n } else {\n const records = resp.value ?? [];\n const stripped = records.map((record: any) => record);\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as\n | (keyof T)[]\n | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return { data: validation.data as any, error: undefined };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return { data: validation.data as any, error: undefined };\n }\n }\n\n // Handle $count endpoint\n if (this.isCountMode) {\n const tableId = this.getTableId(mergedOptions.useEntityIds);\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${tableId}/$count${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n // OData returns count as a string, convert to number\n const count =\n typeof result.data === \"string\" ? Number(result.data) : result.data;\n return { data: count as number, error: undefined } as any;\n }\n\n const tableId = this.getTableId(mergedOptions.useEntityIds);\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${tableId}${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n return { data: record as any, error: undefined };\n } else {\n // Handle list response structure\n const records = resp.value ?? [];\n return { data: records as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as (keyof T)[] | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return {\n data: validation.data as any,\n error: undefined,\n };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return {\n data: validation.data as any,\n error: undefined,\n };\n }\n }\n\n getQueryString(): string {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n // Format select fields before building query - buildQuery treats & as separator,\n // so we need to pre-encode special characters. buildQuery preserves encoded values.\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryParams = buildQuery(queryOptionsWithoutExpand);\n\n // Post-process: buildQuery encodes spaces as %20, but we want to preserve spaces\n // Replace %20 with spaces in the $select part\n if (this.queryOptions.select) {\n queryParams = queryParams.replace(\n /\\$select=([^&]*)/,\n (match, selectValue) => {\n return `$select=${selectValue.replace(/%20/g, \" \")}`;\n },\n );\n }\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryParams.includes(\"?\") ? \"&\" : \"?\";\n queryParams = `${queryParams}${separator}$expand=${expandString}`;\n }\n\n // Handle navigation from RecordBuilder (with record ID)\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let path: string;\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n path = `/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}`;\n } else {\n // Normal navigation: /sourceTableName('recordId')/relationName\n path = `/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}`;\n }\n // Append query params if any exist\n return queryParams ? `${path}${queryParams}` : path;\n }\n\n // Handle navigation from EntitySet (without record ID)\n if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let path: string;\n if (this.navigateBasePath) {\n // Chained navigation: /basePath/relationName (basePath already includes intermediate segments)\n path = `/${this.navigateBasePath}/${this.navigateRelation}`;\n } else {\n // Single navigation: /sourceTableName/relationName\n path = `/${this.navigateSourceTableName}/${this.navigateRelation}`;\n }\n // Append query params if any exist\n return queryParams ? `${path}${queryParams}` : path;\n }\n\n // Default case: return table ID (respects entity ID settings) with query params\n const tableId = this.getTableId(this.databaseUseEntityIds);\n return `/${tableId}${queryParams}`;\n }\n\n getRequestConfig(): { method: string; url: string; body?: any } {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n // Format select fields before building query\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryString = buildQuery(queryOptionsWithoutExpand);\n\n // Build custom expand string\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryString.includes(\"?\") ? \"&\" : \"?\";\n queryString = `${queryString}${separator}$expand=${expandString}`;\n }\n\n let url: string;\n\n // Handle navigation from RecordBuilder (with record ID)\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n } else {\n // Normal navigation: /sourceTable('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n }\n } else if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n // Handle navigation from EntitySet (without record ID)\n if (this.navigateBasePath) {\n // Chained navigation: /basePath/relationName (basePath already includes intermediate segments)\n url = `/${this.databaseName}/${this.navigateBasePath}/${this.navigateRelation}${queryString}`;\n } else {\n // Single navigation: /sourceTableName/relationName\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}${queryString}`;\n }\n } else if (this.isCountMode) {\n // Use getTableId to respect entity ID settings (for batch operations)\n const tableId = this.getTableId(this.databaseUseEntityIds);\n url = `/${this.databaseName}/${tableId}/$count${queryString}`;\n } else {\n // Use getTableId to respect entity ID settings (for batch operations)\n const tableId = this.getTableId(this.databaseUseEntityIds);\n url = `/${this.databaseName}/${tableId}${queryString}`;\n }\n\n return {\n method: \"GET\",\n url,\n };\n }\n\n toRequest(baseUrl: string, options?: ExecuteOptions): Request {\n const config = this.getRequestConfig();\n const fullUrl = `${baseUrl}${config.url}`;\n\n return new Request(fullUrl, {\n method: config.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: getAcceptHeader(options?.includeODataAnnotations),\n },\n });\n }\n\n async processResponse(\n response: Response,\n options?: ExecuteOptions,\n ): Promise<\n Result<QueryReturnType<T, Selected, SingleMode, IsCount, Expands>>\n > {\n // Handle 204 No Content (shouldn't happen for queries, but handle it gracefully)\n if (response.status === 204) {\n // Return empty list for list queries, null for single queries\n if (this.singleMode !== false) {\n if (this.singleMode === \"maybe\") {\n return { data: null as any, error: undefined };\n }\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: [] as any, error: undefined };\n }\n\n // Parse the response body (using safeJsonParse to handle FileMaker's invalid JSON with unquoted ? values)\n let rawData;\n try {\n rawData = await safeJsonParse(response);\n } catch (err) {\n // Check if it's an empty body error (common with 204 responses)\n if (err instanceof SyntaxError && response.status === 204) {\n // Handled above, but just in case\n return { data: [] as any, error: undefined };\n }\n return {\n data: undefined,\n error: {\n name: \"ResponseParseError\",\n message: `Failed to parse response JSON: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n timestamp: new Date(),\n } as any,\n };\n }\n\n if (!rawData) {\n return {\n data: undefined,\n error: {\n name: \"ResponseError\",\n message: \"Response body was empty or null\",\n timestamp: new Date(),\n } as any,\n };\n }\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = options?.useEntityIds ?? this.databaseUseEntityIds;\n\n let transformedData = rawData;\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n transformedData = transformResponseFields(\n rawData,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = transformedData as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n return { data: record as any, error: undefined };\n } else {\n // Handle list response structure\n const records = resp.value ?? [];\n return { data: records as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as (keyof T)[] | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n // Single mode (one() or oneOrNull())\n const validation = await validateSingleResponse<T>(\n transformedData,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n\n if (validation.data === null) {\n return { data: null as any, error: undefined };\n }\n\n return { data: validation.data as any, error: undefined };\n }\n\n // List mode\n const validation = await validateListResponse<T>(\n transformedData,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n\n return { data: validation.data as any, error: undefined };\n }\n}\n"],"names":["result","_a","response","shouldUseIds","expandValidationConfigs","schema","selectedFields","tableId","validation"],"mappings":"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"}
@@ -1,86 +0,0 @@
1
- import { BaseTable } from './base-table.js';
2
- type ExtractSchema<BT> = BT extends BaseTable<infer S, any, any, any> ? S : never;
3
- declare const INTERNAL_NAV: unique symbol;
4
- export declare class TableOccurrence<BT extends BaseTable<any, any, any, any> = any, Name extends string = string, Nav extends Record<string, TableOccurrence<any, any, any, any>> = {}, DefSelect extends "all" | "schema" | readonly (keyof ExtractSchema<BT>)[] = "schema"> {
5
- readonly name: Name;
6
- readonly baseTable: BT;
7
- readonly navigation: Nav;
8
- readonly defaultSelect: DefSelect;
9
- readonly fmtId?: `FMTID:${string}`;
10
- constructor(config: {
11
- readonly name: Name;
12
- readonly baseTable: BT;
13
- readonly defaultSelect?: DefSelect;
14
- readonly fmtId?: `FMTID:${string}`;
15
- /** @internal Used by buildOccurrences - do not use directly */
16
- readonly [INTERNAL_NAV]?: Nav;
17
- });
18
- /**
19
- * Returns the FileMaker table occurrence ID (FMTID) if available, or the table name.
20
- * @returns The FMTID string or the table name
21
- */
22
- getTableId(): string;
23
- /**
24
- * Returns the table occurrence name.
25
- * @returns The table name
26
- */
27
- getTableName(): string;
28
- /**
29
- * Returns true if this TableOccurrence is using FileMaker table occurrence IDs.
30
- */
31
- isUsingTableId(): boolean;
32
- /**
33
- * @internal Creates a new TableOccurrence with navigation - used by buildOccurrences
34
- */
35
- static _withNavigation<BT extends BaseTable<any, any, any, any>, Name extends string, Nav extends Record<string, TableOccurrence<any, any, any, any>>, DefSelect extends "all" | "schema" | readonly (keyof ExtractSchema<BT>)[] = "schema">(base: TableOccurrence<BT, Name, any, DefSelect>, navigation: Nav): TableOccurrence<BT, Name, Nav, DefSelect>;
36
- }
37
- export declare function createTableOccurrence<const Name extends string, BT extends BaseTable<any, any, any, any>, DefSelect extends "all" | "schema" | readonly (keyof ExtractSchema<BT>)[] = "schema">(config: {
38
- name: Name;
39
- baseTable: BT;
40
- defaultSelect?: DefSelect;
41
- fmtId?: `FMTID:${string}`;
42
- }): TableOccurrence<BT, Name, {}, DefSelect>;
43
- /**
44
- * Creates a TableOccurrence with proper TypeScript type inference.
45
- *
46
- * Use this function to create TableOccurrence instances with full type safety.
47
- * For navigation between tables, use `buildOccurrences()` after defining your TOs.
48
- *
49
- * @example
50
- * ```ts
51
- * const users = defineTableOccurrence({
52
- * name: "users",
53
- * baseTable: usersBase,
54
- * });
55
- * ```
56
- *
57
- * @example With entity IDs
58
- * ```ts
59
- * const products = defineTableOccurrence({
60
- * name: "products",
61
- * baseTable: productsBase,
62
- * fmtId: "FMTID:12345",
63
- * });
64
- * ```
65
- *
66
- * @example With navigation (use buildOccurrences)
67
- * ```ts
68
- * const _users = defineTableOccurrence({ name: "users", baseTable: usersBase });
69
- * const _contacts = defineTableOccurrence({ name: "contacts", baseTable: contactsBase });
70
- *
71
- * const [users, contacts] = buildOccurrences({
72
- * occurrences: [_users, _contacts],
73
- * navigation: {
74
- * users: ["contacts"],
75
- * contacts: ["users"],
76
- * },
77
- * });
78
- * ```
79
- */
80
- export declare function defineTableOccurrence<const Name extends string, BT extends BaseTable<any, any, any, any>, const DefSelect extends "all" | "schema" | readonly (keyof ExtractSchema<BT>)[] = "schema">(config: {
81
- readonly name: Name;
82
- readonly baseTable: BT;
83
- readonly fmtId?: `FMTID:${string}`;
84
- readonly defaultSelect?: DefSelect;
85
- }): TableOccurrence<BT, Name, {}, DefSelect>;
86
- export {};
@@ -1,58 +0,0 @@
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
- const INTERNAL_NAV = Symbol("internal-navigation");
5
- class TableOccurrence {
6
- constructor(config) {
7
- __publicField(this, "name");
8
- __publicField(this, "baseTable");
9
- __publicField(this, "navigation");
10
- __publicField(this, "defaultSelect");
11
- __publicField(this, "fmtId");
12
- this.name = config.name;
13
- this.baseTable = config.baseTable;
14
- this.navigation = config[INTERNAL_NAV] ?? {};
15
- this.defaultSelect = config.defaultSelect ?? "schema";
16
- this.fmtId = config.fmtId;
17
- }
18
- /**
19
- * Returns the FileMaker table occurrence ID (FMTID) if available, or the table name.
20
- * @returns The FMTID string or the table name
21
- */
22
- getTableId() {
23
- return this.fmtId ?? this.name;
24
- }
25
- /**
26
- * Returns the table occurrence name.
27
- * @returns The table name
28
- */
29
- getTableName() {
30
- return this.name;
31
- }
32
- /**
33
- * Returns true if this TableOccurrence is using FileMaker table occurrence IDs.
34
- */
35
- isUsingTableId() {
36
- return this.fmtId !== void 0;
37
- }
38
- /**
39
- * @internal Creates a new TableOccurrence with navigation - used by buildOccurrences
40
- */
41
- static _withNavigation(base, navigation) {
42
- return new TableOccurrence({
43
- name: base.name,
44
- baseTable: base.baseTable,
45
- defaultSelect: base.defaultSelect,
46
- fmtId: base.fmtId,
47
- [INTERNAL_NAV]: navigation
48
- });
49
- }
50
- }
51
- function defineTableOccurrence(config) {
52
- return new TableOccurrence(config);
53
- }
54
- export {
55
- TableOccurrence,
56
- defineTableOccurrence
57
- };
58
- //# sourceMappingURL=table-occurrence.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"table-occurrence.js","sources":["../../../src/client/table-occurrence.ts"],"sourcesContent":["import { BaseTable } from \"./base-table\";\n\n// Helper type to extract schema from BaseTable\ntype ExtractSchema<BT> =\n BT extends BaseTable<infer S, any, any, any> ? S : never;\n\n// Symbol for internal navigation setting (used by buildOccurrences)\nconst INTERNAL_NAV = Symbol(\"internal-navigation\");\n\nexport class TableOccurrence<\n BT extends BaseTable<any, any, any, any> = any,\n Name extends string = string,\n Nav extends Record<string, TableOccurrence<any, any, any, any>> = {},\n DefSelect extends\n | \"all\"\n | \"schema\"\n | readonly (keyof ExtractSchema<BT>)[] = \"schema\",\n> {\n public readonly name: Name;\n public readonly baseTable: BT;\n public readonly navigation: Nav;\n public readonly defaultSelect: DefSelect;\n public readonly fmtId?: `FMTID:${string}`;\n\n constructor(config: {\n readonly name: Name;\n readonly baseTable: BT;\n readonly defaultSelect?: DefSelect;\n readonly fmtId?: `FMTID:${string}`;\n /** @internal Used by buildOccurrences - do not use directly */\n readonly [INTERNAL_NAV]?: Nav;\n }) {\n this.name = config.name;\n this.baseTable = config.baseTable;\n this.navigation = (config[INTERNAL_NAV] ?? {}) as Nav;\n this.defaultSelect = (config.defaultSelect ?? \"schema\") as DefSelect;\n this.fmtId = config.fmtId;\n }\n\n /**\n * Returns the FileMaker table occurrence ID (FMTID) if available, or the table name.\n * @returns The FMTID string or the table name\n */\n getTableId(): string {\n return this.fmtId ?? this.name;\n }\n\n /**\n * Returns the table occurrence name.\n * @returns The table name\n */\n getTableName(): string {\n return this.name;\n }\n\n /**\n * Returns true if this TableOccurrence is using FileMaker table occurrence IDs.\n */\n isUsingTableId(): boolean {\n return this.fmtId !== undefined;\n }\n\n /**\n * @internal Creates a new TableOccurrence with navigation - used by buildOccurrences\n */\n static _withNavigation<\n BT extends BaseTable<any, any, any, any>,\n Name extends string,\n Nav extends Record<string, TableOccurrence<any, any, any, any>>,\n DefSelect extends\n | \"all\"\n | \"schema\"\n | readonly (keyof ExtractSchema<BT>)[] = \"schema\",\n >(\n base: TableOccurrence<BT, Name, any, DefSelect>,\n navigation: Nav,\n ): TableOccurrence<BT, Name, Nav, DefSelect> {\n return new TableOccurrence({\n name: base.name,\n baseTable: base.baseTable,\n defaultSelect: base.defaultSelect,\n fmtId: base.fmtId,\n [INTERNAL_NAV]: navigation,\n }) as TableOccurrence<BT, Name, Nav, DefSelect>;\n }\n}\n\n// Helper function to create TableOccurrence with proper type inference\nexport function createTableOccurrence<\n const Name extends string,\n BT extends BaseTable<any, any, any, any>,\n DefSelect extends\n | \"all\"\n | \"schema\"\n | readonly (keyof ExtractSchema<BT>)[] = \"schema\",\n>(config: {\n name: Name;\n baseTable: BT;\n defaultSelect?: DefSelect;\n fmtId?: `FMTID:${string}`;\n}): TableOccurrence<BT, Name, {}, DefSelect> {\n return new TableOccurrence(config);\n}\n\n/**\n * Creates a TableOccurrence with proper TypeScript type inference.\n *\n * Use this function to create TableOccurrence instances with full type safety.\n * For navigation between tables, use `buildOccurrences()` after defining your TOs.\n *\n * @example\n * ```ts\n * const users = defineTableOccurrence({\n * name: \"users\",\n * baseTable: usersBase,\n * });\n * ```\n *\n * @example With entity IDs\n * ```ts\n * const products = defineTableOccurrence({\n * name: \"products\",\n * baseTable: productsBase,\n * fmtId: \"FMTID:12345\",\n * });\n * ```\n *\n * @example With navigation (use buildOccurrences)\n * ```ts\n * const _users = defineTableOccurrence({ name: \"users\", baseTable: usersBase });\n * const _contacts = defineTableOccurrence({ name: \"contacts\", baseTable: contactsBase });\n *\n * const [users, contacts] = buildOccurrences({\n * occurrences: [_users, _contacts],\n * navigation: {\n * users: [\"contacts\"],\n * contacts: [\"users\"],\n * },\n * });\n * ```\n */\nexport function defineTableOccurrence<\n const Name extends string,\n BT extends BaseTable<any, any, any, any>,\n const DefSelect extends\n | \"all\"\n | \"schema\"\n | readonly (keyof ExtractSchema<BT>)[] = \"schema\",\n>(config: {\n readonly name: Name;\n readonly baseTable: BT;\n readonly fmtId?: `FMTID:${string}`;\n readonly defaultSelect?: DefSelect;\n}): TableOccurrence<BT, Name, {}, DefSelect> {\n return new TableOccurrence(config);\n}\n"],"names":[],"mappings":";;;AAOA,MAAM,eAAe,OAAO,qBAAqB;AAE1C,MAAM,gBAQX;AAAA,EAOA,YAAY,QAOT;AAba;AACA;AACA;AACA;AACA;AAUd,SAAK,OAAO,OAAO;AACnB,SAAK,YAAY,OAAO;AACxB,SAAK,aAAc,OAAO,YAAY,KAAK,CAAC;AACvC,SAAA,gBAAiB,OAAO,iBAAiB;AAC9C,SAAK,QAAQ,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtB,aAAqB;AACZ,WAAA,KAAK,SAAS,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5B,eAAuB;AACrB,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMd,iBAA0B;AACxB,WAAO,KAAK,UAAU;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMxB,OAAO,gBASL,MACA,YAC2C;AAC3C,WAAO,IAAI,gBAAgB;AAAA,MACzB,MAAM,KAAK;AAAA,MACX,WAAW,KAAK;AAAA,MAChB,eAAe,KAAK;AAAA,MACpB,OAAO,KAAK;AAAA,MACZ,CAAC,YAAY,GAAG;AAAA,IAAA,CACjB;AAAA,EAAA;AAEL;AAwDO,SAAS,sBAOd,QAK2C;AACpC,SAAA,IAAI,gBAAgB,MAAM;AACnC;"}
@@ -1,178 +0,0 @@
1
- import { StandardSchemaV1 } from "@standard-schema/spec";
2
-
3
- /**
4
- * BaseTable defines the schema and configuration for a table.
5
- * Use `defineBaseTable()` to create instances with proper type inference.
6
- *
7
- * @template Schema - Record of field names to StandardSchemaV1 validators
8
- * @template IdField - The name of the primary key field (optional, automatically read-only)
9
- * @template Required - Additional field names to require on insert (beyond auto-inferred required fields)
10
- * @template ReadOnly - Field names that cannot be modified via insert/update (idField is automatically read-only)
11
- *
12
- * @example Basic table with auto-inferred required fields
13
- * ```ts
14
- * import { z } from "zod";
15
- * import { defineBaseTable } from "@proofkit/fmodata";
16
- *
17
- * const usersTable = defineBaseTable({
18
- * schema: {
19
- * id: z.string(), // Auto-required (not nullable), auto-readOnly (idField)
20
- * name: z.string(), // Auto-required (not nullable)
21
- * email: z.string().nullable(), // Optional (nullable)
22
- * },
23
- * idField: "id",
24
- * });
25
- * // On insert: name is required, email is optional (id is excluded - readOnly)
26
- * // On update: name and email available (id is excluded - readOnly)
27
- * ```
28
- *
29
- * @example Table with additional required and readOnly fields
30
- * ```ts
31
- * import { z } from "zod";
32
- * import { defineBaseTable } from "@proofkit/fmodata";
33
- *
34
- * const usersTable = defineBaseTable({
35
- * schema: {
36
- * id: z.string(), // Auto-required, auto-readOnly (idField)
37
- * createdAt: z.string(), // Read-only system field
38
- * name: z.string(), // Auto-required
39
- * email: z.string().nullable(), // Optional by default...
40
- * legacyField: z.string().nullable(), // Optional by default...
41
- * },
42
- * idField: "id",
43
- * required: ["legacyField"], // Make legacyField required for new inserts
44
- * readOnly: ["createdAt"], // Exclude from insert/update
45
- * });
46
- * // On insert: name and legacyField required; email optional (id and createdAt excluded)
47
- * // On update: all fields optional (id and createdAt excluded)
48
- * ```
49
- *
50
- * @example Table with multiple read-only fields
51
- * ```ts
52
- * import { z } from "zod";
53
- * import { defineBaseTable } from "@proofkit/fmodata";
54
- *
55
- * const usersTable = defineBaseTable({
56
- * schema: {
57
- * id: z.string(),
58
- * createdAt: z.string(),
59
- * modifiedAt: z.string(),
60
- * createdBy: z.string(),
61
- * notes: z.string().nullable(),
62
- * },
63
- * idField: "id",
64
- * readOnly: ["createdAt", "modifiedAt", "createdBy"],
65
- * });
66
- * // On insert/update: only notes is available (id and system fields excluded)
67
- * ```
68
- */
69
- export class BaseTable<
70
- Schema extends Record<string, StandardSchemaV1> = any,
71
- IdField extends keyof Schema | undefined = undefined,
72
- Required extends readonly (keyof Schema | (string & {}))[] = readonly [],
73
- ReadOnly extends readonly (keyof Schema | (string & {}))[] = readonly [],
74
- > {
75
- public readonly schema: Schema;
76
- public readonly idField?: IdField;
77
- public readonly required?: Required;
78
- public readonly readOnly?: ReadOnly;
79
- public readonly fmfIds?: Record<
80
- keyof Schema | (string & {}),
81
- `FMFID:${string}`
82
- >;
83
-
84
- constructor(config: {
85
- schema: Schema;
86
- idField?: IdField;
87
- required?: Required;
88
- readOnly?: ReadOnly;
89
- fmfIds?: Record<string, `FMFID:${string}`>;
90
- }) {
91
- this.schema = config.schema;
92
- this.idField = config.idField;
93
- this.required = config.required;
94
- this.readOnly = config.readOnly;
95
- this.fmfIds = config.fmfIds as
96
- | Record<keyof Schema, `FMFID:${string}`>
97
- | undefined;
98
- }
99
-
100
- /**
101
- * Returns the FileMaker field ID (FMFID) for a given field name, or the field name itself if not using IDs.
102
- * @param fieldName - The field name to get the ID for
103
- * @returns The FMFID string or the original field name
104
- */
105
- getFieldId(fieldName: keyof Schema): string {
106
- if (this.fmfIds && fieldName in this.fmfIds) {
107
- return this.fmfIds[fieldName];
108
- }
109
- return String(fieldName);
110
- }
111
-
112
- /**
113
- * Returns the field name for a given FileMaker field ID (FMFID), or the ID itself if not found.
114
- * @param fieldId - The FMFID to get the field name for
115
- * @returns The field name or the original ID
116
- */
117
- getFieldName(fieldId: string): string {
118
- if (this.fmfIds) {
119
- // Search for the field name that corresponds to this FMFID
120
- for (const [fieldName, fmfId] of Object.entries(this.fmfIds)) {
121
- if (fmfId === fieldId) {
122
- return fieldName;
123
- }
124
- }
125
- }
126
- return fieldId;
127
- }
128
-
129
- /**
130
- * Returns true if this BaseTable is using FileMaker field IDs.
131
- */
132
- isUsingFieldIds(): boolean {
133
- return this.fmfIds !== undefined;
134
- }
135
- }
136
-
137
- /**
138
- * Creates a BaseTable with proper TypeScript type inference.
139
- *
140
- * Use this function to create BaseTable instances with full type safety.
141
- *
142
- * @example Without entity IDs
143
- * ```ts
144
- * const users = defineBaseTable({
145
- * schema: { id: z.string(), name: z.string() },
146
- * idField: "id",
147
- * });
148
- * ```
149
- *
150
- * @example With entity IDs (FileMaker field IDs)
151
- * ```ts
152
- * const products = defineBaseTable({
153
- * schema: { id: z.string(), name: z.string() },
154
- * idField: "id",
155
- * fmfIds: { id: "FMFID:1", name: "FMFID:2" },
156
- * });
157
- * ```
158
- */
159
- export function defineBaseTable<
160
- const Schema extends Record<string, StandardSchemaV1>,
161
- IdField extends keyof Schema | undefined = undefined,
162
- const Required extends readonly (
163
- | keyof Schema
164
- | (string & {})
165
- )[] = readonly [],
166
- const ReadOnly extends readonly (
167
- | keyof Schema
168
- | (string & {})
169
- )[] = readonly [],
170
- >(config: {
171
- schema: Schema;
172
- idField?: IdField;
173
- required?: Required;
174
- readOnly?: ReadOnly;
175
- fmfIds?: { [K in keyof Schema | (string & {})]: `FMFID:${string}` };
176
- }): BaseTable<Schema, IdField, Required, ReadOnly> {
177
- return new BaseTable(config);
178
- }
@@ -1,155 +0,0 @@
1
- import { TableOccurrence } from "./table-occurrence";
2
-
3
- /**
4
- * Extract the name type from a TableOccurrence
5
- */
6
- type ExtractName<TO> =
7
- TO extends TableOccurrence<any, infer Name, any, any> ? Name : never;
8
-
9
- /**
10
- * Extract all names from an array of TableOccurrences as a union
11
- */
12
- type ExtractNames<TOs extends readonly TableOccurrence<any, any, any, any>[]> =
13
- ExtractName<TOs[number]>;
14
-
15
- /**
16
- * Find a TableOccurrence by name from an array
17
- */
18
- type FindByName<
19
- TOs extends readonly TableOccurrence<any, any, any, any>[],
20
- Name extends string,
21
- > = Extract<TOs[number], TableOccurrence<any, Name, any, any>>;
22
-
23
- /**
24
- * Navigation configuration - maps TO names to arrays of navigation target names.
25
- * A table occurrence cannot navigate to itself.
26
- */
27
- type NavigationConfig<
28
- TOs extends readonly TableOccurrence<any, any, any, any>[],
29
- > = {
30
- [K in ExtractNames<TOs>]?: Exclude<ExtractNames<TOs>, K>[];
31
- };
32
-
33
- /**
34
- * Resolve navigation config to actual TO record for a given TO name
35
- */
36
- type ResolveNavForTO<
37
- TOs extends readonly TableOccurrence<any, any, any, any>[],
38
- Nav extends NavigationConfig<TOs> | undefined,
39
- Name extends ExtractNames<TOs>,
40
- > =
41
- Nav extends NavigationConfig<TOs>
42
- ? Nav[Name] extends infer NavNames extends string[]
43
- ? {
44
- [K in NavNames[number]]: FindByName<TOs, K>;
45
- }
46
- : {}
47
- : {};
48
-
49
- /**
50
- * Build the result type - a tuple of TOs with navigation resolved
51
- */
52
- type BuildResult<
53
- TOs extends readonly TableOccurrence<any, any, any, any>[],
54
- Nav extends NavigationConfig<TOs> | undefined,
55
- > = {
56
- [K in keyof TOs]: TOs[K] extends TableOccurrence<
57
- infer BT,
58
- infer Name,
59
- any,
60
- infer DefSelect
61
- >
62
- ? Name extends ExtractNames<TOs>
63
- ? TableOccurrence<BT, Name, ResolveNavForTO<TOs, Nav, Name>, DefSelect>
64
- : TOs[K]
65
- : TOs[K];
66
- };
67
-
68
- /**
69
- * Configuration object for buildOccurrences
70
- */
71
- type BuildOccurrencesConfig<
72
- TOs extends readonly TableOccurrence<any, any, any, any>[],
73
- > = {
74
- occurrences: TOs;
75
- navigation?: NavigationConfig<TOs>;
76
- };
77
-
78
- /**
79
- * Builds TableOccurrences with navigation relationships resolved.
80
- *
81
- * This is the second phase of TO definition - after defining base TOs,
82
- * use this function to link them with navigation relationships.
83
- *
84
- * @example Full navigation
85
- * ```ts
86
- * const [contacts, users] = buildOccurrences({
87
- * occurrences: [_contacts, _users],
88
- * navigation: {
89
- * contacts: ["users"],
90
- * users: ["contacts"],
91
- * },
92
- * });
93
- * ```
94
- *
95
- * @example Partial navigation
96
- * ```ts
97
- * const [contacts, users] = buildOccurrences({
98
- * occurrences: [_contacts, _users],
99
- * navigation: {
100
- * contacts: ["users"],
101
- * },
102
- * });
103
- * ```
104
- *
105
- * @example No navigation
106
- * ```ts
107
- * const [contacts, users] = buildOccurrences({
108
- * occurrences: [_contacts, _users],
109
- * });
110
- * ```
111
- *
112
- * @param config - Configuration object with occurrences array and optional navigation
113
- * @returns Tuple of TableOccurrences with navigation resolved (same order as input)
114
- */
115
- export function buildOccurrences<
116
- const TOs extends readonly TableOccurrence<any, any, any, any>[],
117
- const Nav extends NavigationConfig<TOs> | undefined,
118
- >(config: { occurrences: TOs; navigation?: Nav }): BuildResult<TOs, Nav> {
119
- const { occurrences, navigation } = config;
120
-
121
- // Build a map of name -> TO for quick lookup
122
- const toByName = new Map<string, TableOccurrence<any, any, any, any>>();
123
- for (const to of occurrences) {
124
- toByName.set(to.name, to);
125
- }
126
-
127
- // Build result array with navigation resolved
128
- const result = occurrences.map((to) => {
129
- const navNames = navigation?.[to.name as keyof typeof navigation] as
130
- | string[]
131
- | undefined;
132
-
133
- // Resolve navigation names to actual TOs
134
- const resolvedNav: Record<string, TableOccurrence<any, any, any, any>> = {};
135
- if (navNames) {
136
- for (const navName of navNames) {
137
- // Prevent self-navigation
138
- if (navName === to.name) {
139
- throw new Error(
140
- `TableOccurrence "${to.name}" cannot navigate to itself`,
141
- );
142
- }
143
- const targetTO = toByName.get(navName);
144
- if (targetTO) {
145
- resolvedNav[navName] = targetTO;
146
- }
147
- }
148
- }
149
-
150
- // Create new TO with navigation using internal method
151
- return TableOccurrence._withNavigation(to, resolvedNav);
152
- });
153
-
154
- return result as BuildResult<TOs, Nav>;
155
- }