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

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 -5
  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 +12 -19
  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 +9 -12
  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 +133 -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 -64
  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 +17 -25
  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 +73 -12
  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 +22 -17
  92. package/src/client/batch-builder.ts +102 -33
  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 +48 -52
  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 +126 -44
  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 +826 -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 +336 -586
  116. package/src/client/response-processor.ts +4 -5
  117. package/src/client/update-builder.ts +113 -75
  118. package/src/errors.ts +22 -1
  119. package/src/index.ts +58 -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 +88 -63
  127. package/src/validation.ts +76 -4
  128. package/LICENSE.md +0 -21
  129. package/dist/esm/client/base-table.d.ts +0 -128
  130. package/dist/esm/client/base-table.js +0 -57
  131. package/dist/esm/client/base-table.js.map +0 -1
  132. package/dist/esm/client/build-occurrences.d.ts +0 -74
  133. package/dist/esm/client/build-occurrences.js +0 -31
  134. package/dist/esm/client/build-occurrences.js.map +0 -1
  135. package/dist/esm/client/query-builder.js +0 -900
  136. package/dist/esm/client/query-builder.js.map +0 -1
  137. package/dist/esm/client/table-occurrence.d.ts +0 -86
  138. package/dist/esm/client/table-occurrence.js +0 -58
  139. package/dist/esm/client/table-occurrence.js.map +0 -1
  140. package/src/client/base-table.ts +0 -178
  141. package/src/client/build-occurrences.ts +0 -155
  142. package/src/client/query-builder.ts.bak +0 -1457
  143. package/src/client/table-occurrence.ts +0 -156
@@ -0,0 +1,71 @@
1
+ import { FMTable } from '../../orm/table.js';
2
+ import { ExecutionContext } from '../../types.js';
3
+ /**
4
+ * Configuration for navigation from RecordBuilder or EntitySet
5
+ */
6
+ export interface NavigationConfig {
7
+ recordId?: string | number;
8
+ relation: string;
9
+ sourceTableName: string;
10
+ baseRelation?: string;
11
+ basePath?: string;
12
+ }
13
+ /**
14
+ * Builds OData query URLs for different navigation modes.
15
+ * Handles:
16
+ * - Record navigation: /database/sourceTable('recordId')/relation
17
+ * - Entity set navigation: /database/sourceTable/relation
18
+ * - Count endpoint: /database/tableId/$count
19
+ * - Standard queries: /database/tableId
20
+ */
21
+ export declare class QueryUrlBuilder {
22
+ private databaseName;
23
+ private occurrence;
24
+ private context;
25
+ constructor(databaseName: string, occurrence: FMTable<any, any>, context: ExecutionContext);
26
+ /**
27
+ * Builds the full URL for a query request.
28
+ *
29
+ * @param queryString - The OData query string (e.g., "?$filter=...&$select=...")
30
+ * @param options - Options including whether this is a count query, useEntityIds override, and navigation config
31
+ */
32
+ build(queryString: string, options: {
33
+ isCount?: boolean;
34
+ useEntityIds?: boolean;
35
+ navigation?: NavigationConfig;
36
+ }): string;
37
+ /**
38
+ * Builds URL for record navigation: /database/sourceTable('recordId')/relation
39
+ * or /database/sourceTable/baseRelation('recordId')/relation for chained navigations
40
+ */
41
+ private buildRecordNavigation;
42
+ /**
43
+ * Builds URL for entity set navigation: /database/sourceTable/relation
44
+ * or /database/basePath/relation for chained navigations
45
+ */
46
+ private buildEntitySetNavigation;
47
+ /**
48
+ * Builds a query string path (without database prefix) for getQueryString().
49
+ * Used when the full URL is not needed.
50
+ */
51
+ buildPath(queryString: string, options?: {
52
+ useEntityIds?: boolean;
53
+ navigation?: NavigationConfig;
54
+ }): string;
55
+ /**
56
+ * Build URL for record operations (single record by ID).
57
+ * Used by RecordBuilder to build URLs like /database/table('id').
58
+ *
59
+ * @param recordId - The record ID
60
+ * @param queryString - The OData query string (e.g., "?$select=...")
61
+ * @param options - Options including operation type and useEntityIds override
62
+ */
63
+ buildRecordUrl(recordId: string | number, queryString: string, options?: {
64
+ operation?: "getSingleField";
65
+ operationParam?: string;
66
+ useEntityIds?: boolean;
67
+ isNavigateFromEntitySet?: boolean;
68
+ navigateSourceTableName?: string;
69
+ navigateRelation?: string;
70
+ }): string;
71
+ }
@@ -0,0 +1,107 @@
1
+ import { getTableName } from "../../orm/table.js";
2
+ import { resolveTableId } from "../builders/table-utils.js";
3
+ class QueryUrlBuilder {
4
+ constructor(databaseName, occurrence, context) {
5
+ this.databaseName = databaseName;
6
+ this.occurrence = occurrence;
7
+ this.context = context;
8
+ }
9
+ /**
10
+ * Builds the full URL for a query request.
11
+ *
12
+ * @param queryString - The OData query string (e.g., "?$filter=...&$select=...")
13
+ * @param options - Options including whether this is a count query, useEntityIds override, and navigation config
14
+ */
15
+ build(queryString, options) {
16
+ const tableId = resolveTableId(
17
+ this.occurrence,
18
+ getTableName(this.occurrence),
19
+ this.context,
20
+ options.useEntityIds
21
+ );
22
+ const navigation = options.navigation;
23
+ if ((navigation == null ? void 0 : navigation.recordId) && (navigation == null ? void 0 : navigation.relation)) {
24
+ return this.buildRecordNavigation(queryString, tableId, navigation);
25
+ }
26
+ if (navigation == null ? void 0 : navigation.relation) {
27
+ return this.buildEntitySetNavigation(queryString, tableId, navigation);
28
+ }
29
+ if (options.isCount) {
30
+ return `/${this.databaseName}/${tableId}/$count${queryString}`;
31
+ }
32
+ return `/${this.databaseName}/${tableId}${queryString}`;
33
+ }
34
+ /**
35
+ * Builds URL for record navigation: /database/sourceTable('recordId')/relation
36
+ * or /database/sourceTable/baseRelation('recordId')/relation for chained navigations
37
+ */
38
+ buildRecordNavigation(queryString, tableId, navigation) {
39
+ const { sourceTableName, baseRelation, recordId, relation } = navigation;
40
+ const base = baseRelation ? `${sourceTableName}/${baseRelation}('${recordId}')` : `${sourceTableName}('${recordId}')`;
41
+ return `/${this.databaseName}/${base}/${relation}${queryString}`;
42
+ }
43
+ /**
44
+ * Builds URL for entity set navigation: /database/sourceTable/relation
45
+ * or /database/basePath/relation for chained navigations
46
+ */
47
+ buildEntitySetNavigation(queryString, tableId, navigation) {
48
+ const { sourceTableName, basePath, relation } = navigation;
49
+ const base = basePath || sourceTableName;
50
+ return `/${this.databaseName}/${base}/${relation}${queryString}`;
51
+ }
52
+ /**
53
+ * Builds a query string path (without database prefix) for getQueryString().
54
+ * Used when the full URL is not needed.
55
+ */
56
+ buildPath(queryString, options) {
57
+ const useEntityIds = options == null ? void 0 : options.useEntityIds;
58
+ const navigation = options == null ? void 0 : options.navigation;
59
+ const tableId = resolveTableId(
60
+ this.occurrence,
61
+ getTableName(this.occurrence),
62
+ this.context,
63
+ useEntityIds
64
+ );
65
+ if ((navigation == null ? void 0 : navigation.recordId) && (navigation == null ? void 0 : navigation.relation)) {
66
+ const { sourceTableName, baseRelation, recordId, relation } = navigation;
67
+ const base = baseRelation ? `${sourceTableName}/${baseRelation}('${recordId}')` : `${sourceTableName}('${recordId}')`;
68
+ return queryString ? `/${base}/${relation}${queryString}` : `/${base}/${relation}`;
69
+ }
70
+ if (navigation == null ? void 0 : navigation.relation) {
71
+ const { sourceTableName, basePath, relation } = navigation;
72
+ const base = basePath || sourceTableName;
73
+ return queryString ? `/${base}/${relation}${queryString}` : `/${base}/${relation}`;
74
+ }
75
+ return queryString ? `/${tableId}${queryString}` : `/${tableId}`;
76
+ }
77
+ /**
78
+ * Build URL for record operations (single record by ID).
79
+ * Used by RecordBuilder to build URLs like /database/table('id').
80
+ *
81
+ * @param recordId - The record ID
82
+ * @param queryString - The OData query string (e.g., "?$select=...")
83
+ * @param options - Options including operation type and useEntityIds override
84
+ */
85
+ buildRecordUrl(recordId, queryString, options) {
86
+ const tableId = resolveTableId(
87
+ this.occurrence,
88
+ getTableName(this.occurrence),
89
+ this.context,
90
+ options == null ? void 0 : options.useEntityIds
91
+ );
92
+ let url;
93
+ if ((options == null ? void 0 : options.isNavigateFromEntitySet) && options.navigateSourceTableName && options.navigateRelation) {
94
+ url = `/${this.databaseName}/${options.navigateSourceTableName}/${options.navigateRelation}('${recordId}')`;
95
+ } else {
96
+ url = `/${this.databaseName}/${tableId}('${recordId}')`;
97
+ }
98
+ if ((options == null ? void 0 : options.operation) === "getSingleField" && options.operationParam) {
99
+ url += `/${options.operationParam}`;
100
+ }
101
+ return url + queryString;
102
+ }
103
+ }
104
+ export {
105
+ QueryUrlBuilder
106
+ };
107
+ //# sourceMappingURL=url-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-builder.js","sources":["../../../../src/client/query/url-builder.ts"],"sourcesContent":["import type { FMTable } from \"../../orm/table\";\nimport { getTableName } from \"../../orm/table\";\nimport { resolveTableId } from \"../builders/table-utils\";\nimport type { ExecutionContext } from \"../../types\";\n\n/**\n * Configuration for navigation from RecordBuilder or EntitySet\n */\nexport interface NavigationConfig {\n recordId?: string | number;\n relation: string;\n sourceTableName: string;\n baseRelation?: string; // For chained navigations from navigated EntitySets\n basePath?: string; // Full base path for chained entity set navigations\n}\n\n/**\n * Builds OData query URLs for different navigation modes.\n * Handles:\n * - Record navigation: /database/sourceTable('recordId')/relation\n * - Entity set navigation: /database/sourceTable/relation\n * - Count endpoint: /database/tableId/$count\n * - Standard queries: /database/tableId\n */\nexport class QueryUrlBuilder {\n constructor(\n private databaseName: string,\n private occurrence: FMTable<any, any>,\n private context: ExecutionContext,\n ) {}\n\n /**\n * Builds the full URL for a query request.\n *\n * @param queryString - The OData query string (e.g., \"?$filter=...&$select=...\")\n * @param options - Options including whether this is a count query, useEntityIds override, and navigation config\n */\n build(\n queryString: string,\n options: {\n isCount?: boolean;\n useEntityIds?: boolean;\n navigation?: NavigationConfig;\n },\n ): string {\n const tableId = resolveTableId(\n this.occurrence,\n getTableName(this.occurrence),\n this.context,\n options.useEntityIds,\n );\n\n const navigation = options.navigation;\n if (navigation?.recordId && navigation?.relation) {\n return this.buildRecordNavigation(queryString, tableId, navigation);\n }\n if (navigation?.relation) {\n return this.buildEntitySetNavigation(queryString, tableId, navigation);\n }\n if (options.isCount) {\n return `/${this.databaseName}/${tableId}/$count${queryString}`;\n }\n return `/${this.databaseName}/${tableId}${queryString}`;\n }\n\n /**\n * Builds URL for record navigation: /database/sourceTable('recordId')/relation\n * or /database/sourceTable/baseRelation('recordId')/relation for chained navigations\n */\n private buildRecordNavigation(\n queryString: string,\n tableId: string,\n navigation: NavigationConfig,\n ): string {\n const { sourceTableName, baseRelation, recordId, relation } = navigation;\n const base = baseRelation\n ? `${sourceTableName}/${baseRelation}('${recordId}')`\n : `${sourceTableName}('${recordId}')`;\n return `/${this.databaseName}/${base}/${relation}${queryString}`;\n }\n\n /**\n * Builds URL for entity set navigation: /database/sourceTable/relation\n * or /database/basePath/relation for chained navigations\n */\n private buildEntitySetNavigation(\n queryString: string,\n tableId: string,\n navigation: NavigationConfig,\n ): string {\n const { sourceTableName, basePath, relation } = navigation;\n const base = basePath || sourceTableName;\n return `/${this.databaseName}/${base}/${relation}${queryString}`;\n }\n\n /**\n * Builds a query string path (without database prefix) for getQueryString().\n * Used when the full URL is not needed.\n */\n buildPath(\n queryString: string,\n options?: { useEntityIds?: boolean; navigation?: NavigationConfig },\n ): string {\n const useEntityIds = options?.useEntityIds;\n const navigation = options?.navigation;\n const tableId = resolveTableId(\n this.occurrence,\n getTableName(this.occurrence),\n this.context,\n useEntityIds,\n );\n\n if (navigation?.recordId && navigation?.relation) {\n const { sourceTableName, baseRelation, recordId, relation } = navigation;\n const base = baseRelation\n ? `${sourceTableName}/${baseRelation}('${recordId}')`\n : `${sourceTableName}('${recordId}')`;\n return queryString\n ? `/${base}/${relation}${queryString}`\n : `/${base}/${relation}`;\n }\n if (navigation?.relation) {\n const { sourceTableName, basePath, relation } = navigation;\n const base = basePath || sourceTableName;\n return queryString\n ? `/${base}/${relation}${queryString}`\n : `/${base}/${relation}`;\n }\n return queryString ? `/${tableId}${queryString}` : `/${tableId}`;\n }\n\n /**\n * Build URL for record operations (single record by ID).\n * Used by RecordBuilder to build URLs like /database/table('id').\n *\n * @param recordId - The record ID\n * @param queryString - The OData query string (e.g., \"?$select=...\")\n * @param options - Options including operation type and useEntityIds override\n */\n buildRecordUrl(\n recordId: string | number,\n queryString: string,\n options?: {\n operation?: \"getSingleField\";\n operationParam?: string;\n useEntityIds?: boolean;\n isNavigateFromEntitySet?: boolean;\n navigateSourceTableName?: string;\n navigateRelation?: string;\n },\n ): string {\n const tableId = resolveTableId(\n this.occurrence,\n getTableName(this.occurrence),\n this.context,\n options?.useEntityIds,\n );\n\n // Build the base URL depending on whether this came from a navigated EntitySet\n let url: string;\n if (\n options?.isNavigateFromEntitySet &&\n options.navigateSourceTableName &&\n options.navigateRelation\n ) {\n // From navigated EntitySet: /sourceTable/relation('recordId')\n url = `/${this.databaseName}/${options.navigateSourceTableName}/${options.navigateRelation}('${recordId}')`;\n } else {\n // Normal record: /tableName('recordId') - use FMTID if configured\n url = `/${this.databaseName}/${tableId}('${recordId}')`;\n }\n\n if (options?.operation === \"getSingleField\" && options.operationParam) {\n url += `/${options.operationParam}`;\n }\n\n return url + queryString;\n }\n}\n"],"names":[],"mappings":";;AAwBO,MAAM,gBAAgB;AAAA,EAC3B,YACU,cACA,YACA,SACR;AAHQ,SAAA,eAAA;AACA,SAAA,aAAA;AACA,SAAA,UAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASV,MACE,aACA,SAKQ;AACR,UAAM,UAAU;AAAA,MACd,KAAK;AAAA,MACL,aAAa,KAAK,UAAU;AAAA,MAC5B,KAAK;AAAA,MACL,QAAQ;AAAA,IACV;AAEA,UAAM,aAAa,QAAQ;AACvB,SAAA,yCAAY,cAAY,yCAAY,WAAU;AAChD,aAAO,KAAK,sBAAsB,aAAa,SAAS,UAAU;AAAA,IAAA;AAEpE,QAAI,yCAAY,UAAU;AACxB,aAAO,KAAK,yBAAyB,aAAa,SAAS,UAAU;AAAA,IAAA;AAEvE,QAAI,QAAQ,SAAS;AACnB,aAAO,IAAI,KAAK,YAAY,IAAI,OAAO,UAAU,WAAW;AAAA,IAAA;AAE9D,WAAO,IAAI,KAAK,YAAY,IAAI,OAAO,GAAG,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO/C,sBACN,aACA,SACA,YACQ;AACR,UAAM,EAAE,iBAAiB,cAAc,UAAU,SAAa,IAAA;AAC9D,UAAM,OAAO,eACT,GAAG,eAAe,IAAI,YAAY,KAAK,QAAQ,OAC/C,GAAG,eAAe,KAAK,QAAQ;AAC5B,WAAA,IAAI,KAAK,YAAY,IAAI,IAAI,IAAI,QAAQ,GAAG,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,yBACN,aACA,SACA,YACQ;AACR,UAAM,EAAE,iBAAiB,UAAU,SAAa,IAAA;AAChD,UAAM,OAAO,YAAY;AAClB,WAAA,IAAI,KAAK,YAAY,IAAI,IAAI,IAAI,QAAQ,GAAG,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhE,UACE,aACA,SACQ;AACR,UAAM,eAAe,mCAAS;AAC9B,UAAM,aAAa,mCAAS;AAC5B,UAAM,UAAU;AAAA,MACd,KAAK;AAAA,MACL,aAAa,KAAK,UAAU;AAAA,MAC5B,KAAK;AAAA,MACL;AAAA,IACF;AAEI,SAAA,yCAAY,cAAY,yCAAY,WAAU;AAChD,YAAM,EAAE,iBAAiB,cAAc,UAAU,SAAa,IAAA;AAC9D,YAAM,OAAO,eACT,GAAG,eAAe,IAAI,YAAY,KAAK,QAAQ,OAC/C,GAAG,eAAe,KAAK,QAAQ;AAC5B,aAAA,cACH,IAAI,IAAI,IAAI,QAAQ,GAAG,WAAW,KAClC,IAAI,IAAI,IAAI,QAAQ;AAAA,IAAA;AAE1B,QAAI,yCAAY,UAAU;AACxB,YAAM,EAAE,iBAAiB,UAAU,SAAa,IAAA;AAChD,YAAM,OAAO,YAAY;AAClB,aAAA,cACH,IAAI,IAAI,IAAI,QAAQ,GAAG,WAAW,KAClC,IAAI,IAAI,IAAI,QAAQ;AAAA,IAAA;AAE1B,WAAO,cAAc,IAAI,OAAO,GAAG,WAAW,KAAK,IAAI,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWhE,eACE,UACA,aACA,SAQQ;AACR,UAAM,UAAU;AAAA,MACd,KAAK;AAAA,MACL,aAAa,KAAK,UAAU;AAAA,MAC5B,KAAK;AAAA,MACL,mCAAS;AAAA,IACX;AAGI,QAAA;AACJ,SACE,mCAAS,4BACT,QAAQ,2BACR,QAAQ,kBACR;AAEM,YAAA,IAAI,KAAK,YAAY,IAAI,QAAQ,uBAAuB,IAAI,QAAQ,gBAAgB,KAAK,QAAQ;AAAA,IAAA,OAClG;AAEL,YAAM,IAAI,KAAK,YAAY,IAAI,OAAO,KAAK,QAAQ;AAAA,IAAA;AAGrD,SAAI,mCAAS,eAAc,oBAAoB,QAAQ,gBAAgB;AAC9D,aAAA,IAAI,QAAQ,cAAc;AAAA,IAAA;AAGnC,WAAO,MAAM;AAAA,EAAA;AAEjB;"}
@@ -1,111 +1 @@
1
- import { QueryOptions } from 'odata-query';
2
- import { ExecutionContext, ExecutableBuilder, WithSystemFields, Result, InferSchemaType, ExecuteOptions, ConditionallyWithODataAnnotations, ExtractSchemaFromOccurrence } from '../types.js';
3
- import { Filter } from '../filter-types.js';
4
- import { TableOccurrence } from './table-occurrence.js';
5
- import { BaseTable } from './base-table.js';
6
- import { FFetchOptions } from '@fetchkit/ffetch';
7
- import { StandardSchemaV1 } from '@standard-schema/spec';
8
- type ExtractNavigationNames<O extends TableOccurrence<any, any, any, any> | undefined> = O extends TableOccurrence<any, any, infer Nav, any> ? Nav extends Record<string, any> ? keyof Nav & string : never : never;
9
- type FindNavigationTarget<O extends TableOccurrence<any, any, any, any> | undefined, Name extends string> = O extends TableOccurrence<any, any, infer Nav, any> ? Nav extends Record<string, any> ? Name extends keyof Nav ? Nav[Name] : TableOccurrence<BaseTable<Record<string, StandardSchemaV1>, any, any, any>, any, any, any> : TableOccurrence<BaseTable<Record<string, StandardSchemaV1>, any, any, any>, any, any, any> : TableOccurrence<BaseTable<Record<string, StandardSchemaV1>, any, any, any>, any, any, any>;
10
- type GetTargetSchemaType<O extends TableOccurrence<any, any, any, any> | undefined, Rel extends string> = [FindNavigationTarget<O, Rel>] extends [
11
- TableOccurrence<infer BT, any, any, any>
12
- ] ? [BT] extends [BaseTable<infer S, any, any, any>] ? [S] extends [Record<string, StandardSchemaV1>] ? InferSchemaType<S> : Record<string, any> : Record<string, any> : Record<string, any>;
13
- export type ExpandedRelations = Record<string, {
14
- schema: any;
15
- selected: any;
16
- }>;
17
- export type QueryReturnType<T extends Record<string, any>, Selected extends keyof T, SingleMode extends "exact" | "maybe" | false, IsCount extends boolean, Expands extends ExpandedRelations> = IsCount extends true ? number : SingleMode extends "exact" ? Pick<T, Selected> & {
18
- [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
19
- } : SingleMode extends "maybe" ? (Pick<T, Selected> & {
20
- [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
21
- }) | null : (Pick<T, Selected> & {
22
- [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
23
- })[];
24
- export declare class QueryBuilder<T extends Record<string, any>, Selected extends keyof T = keyof T, SingleMode extends "exact" | "maybe" | false = false, IsCount extends boolean = false, Occ extends TableOccurrence<any, any, any, any> | undefined = undefined, Expands extends ExpandedRelations = {}> implements ExecutableBuilder<QueryReturnType<T, Selected, SingleMode, IsCount, Expands>> {
25
- private queryOptions;
26
- private expandConfigs;
27
- private singleMode;
28
- private isCountMode;
29
- private occurrence?;
30
- private tableName;
31
- private databaseName;
32
- private context;
33
- private isNavigate?;
34
- private navigateRecordId?;
35
- private navigateRelation?;
36
- private navigateSourceTableName?;
37
- private navigateBaseRelation?;
38
- private navigateBasePath?;
39
- private databaseUseEntityIds;
40
- constructor(config: {
41
- occurrence?: Occ;
42
- tableName: string;
43
- databaseName: string;
44
- context: ExecutionContext;
45
- databaseUseEntityIds?: boolean;
46
- });
47
- /**
48
- * Helper to merge database-level useEntityIds with per-request options
49
- */
50
- private mergeExecuteOptions;
51
- /**
52
- * Gets the table ID (FMTID) if using entity IDs, otherwise returns the table name
53
- * @param useEntityIds - Optional override for entity ID usage
54
- */
55
- private getTableId;
56
- select<K extends keyof T>(...fields: K[]): QueryBuilder<T, K, SingleMode, IsCount, Occ, Expands>;
57
- /**
58
- * Transforms our filter format to odata-query's expected format
59
- * - Arrays of operators are converted to AND conditions
60
- * - Single operator objects pass through as-is
61
- * - Shorthand values are handled by odata-query
62
- */
63
- private transformFilter;
64
- filter(filter: Filter<ExtractSchemaFromOccurrence<Occ>>): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands>;
65
- orderBy(orderBy: QueryOptions<T>["orderBy"]): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands>;
66
- top(count: number): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands>;
67
- skip(count: number): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands>;
68
- /**
69
- * Formats select fields for use in query strings.
70
- * - Transforms field names to FMFIDs if using entity IDs
71
- * - Wraps "id" fields in double quotes
72
- * - URL-encodes special characters but preserves spaces
73
- */
74
- private formatSelectFields;
75
- /**
76
- * Builds expand validation configs from internal expand configurations.
77
- * These are used to validate expanded navigation properties.
78
- */
79
- private buildExpandValidationConfigs;
80
- /**
81
- * Builds OData expand query string from expand configurations.
82
- * Handles nested expands recursively.
83
- * Transforms relation names to FMTIDs if using entity IDs.
84
- */
85
- private buildExpandString;
86
- expand<Rel extends ExtractNavigationNames<Occ> | (string & {}), TargetOcc extends FindNavigationTarget<Occ, Rel> = FindNavigationTarget<Occ, Rel>, TargetSchema extends GetTargetSchemaType<Occ, Rel> = GetTargetSchemaType<Occ, Rel>, TargetSelected extends keyof TargetSchema = keyof TargetSchema>(relation: Rel, callback?: (builder: QueryBuilder<TargetSchema, keyof TargetSchema, false, false, TargetOcc extends TableOccurrence<any, any, any, any> ? TargetOcc : undefined>) => QueryBuilder<WithSystemFields<TargetSchema>, TargetSelected, any, any, any>): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands & {
87
- [K in Rel]: {
88
- schema: TargetSchema;
89
- selected: TargetSelected;
90
- };
91
- }>;
92
- single(): QueryBuilder<T, Selected, "exact", IsCount, Occ, Expands>;
93
- maybeSingle(): QueryBuilder<T, Selected, "maybe", IsCount, Occ, Expands>;
94
- count(): QueryBuilder<T, Selected, SingleMode, true, Occ, Expands>;
95
- execute<EO extends ExecuteOptions>(options?: RequestInit & FFetchOptions & EO): Promise<Result<IsCount extends true ? number : SingleMode extends "exact" ? ConditionallyWithODataAnnotations<Pick<T, Selected> & {
96
- [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
97
- }, EO["includeODataAnnotations"] extends true ? true : false> : SingleMode extends "maybe" ? ConditionallyWithODataAnnotations<Pick<T, Selected> & {
98
- [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
99
- }, EO["includeODataAnnotations"] extends true ? true : false> | null : ConditionallyWithODataAnnotations<Pick<T, Selected> & {
100
- [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
101
- }, EO["includeODataAnnotations"] extends true ? true : false>[]>>;
102
- getQueryString(): string;
103
- getRequestConfig(): {
104
- method: string;
105
- url: string;
106
- body?: any;
107
- };
108
- toRequest(baseUrl: string, options?: ExecuteOptions): Request;
109
- processResponse(response: Response, options?: ExecuteOptions): Promise<Result<QueryReturnType<T, Selected, SingleMode, IsCount, Expands>>>;
110
- }
111
- export {};
1
+ export { QueryBuilder, type TypeSafeOrderBy, type ExpandedRelations, type QueryReturnType, } from './query/index.js';
@@ -1,25 +1,31 @@
1
- import { ExecutionContext, ExecutableBuilder, Result, InferSchemaType, ExecuteOptions, WithSystemFields, ConditionallyWithODataAnnotations } from '../types.js';
2
- import { TableOccurrence } from './table-occurrence.js';
3
- import { BaseTable } from './base-table.js';
1
+ import { ExecutionContext, ExecutableBuilder, Result, ExecuteOptions, ConditionallyWithODataAnnotations, ExecuteMethodOptions } from '../types.js';
2
+ import { FMTable, InferSchemaOutputFromFMTable, ValidExpandTarget, ExtractTableName } from '../orm/table.js';
4
3
  import { QueryBuilder } from './query-builder.js';
5
- import { FFetchOptions } from '@fetchkit/ffetch';
6
- import { StandardSchemaV1 } from '@standard-schema/spec';
7
- type ExtractSchemaFromOccurrence<O> = O extends TableOccurrence<infer BT, any, any, any> ? BT extends BaseTable<infer S, any, any, any> ? S : never : never;
8
- type ExtractNavigationNames<O extends TableOccurrence<any, any, any, any> | undefined> = O extends TableOccurrence<any, any, infer Nav, any> ? Nav extends Record<string, any> ? keyof Nav & string : never : never;
9
- type FindNavigationTarget<O extends TableOccurrence<any, any, any, any> | undefined, Name extends string> = O extends TableOccurrence<any, any, infer Nav, any> ? Nav extends Record<string, any> ? Name extends keyof Nav ? Nav[Name] : TableOccurrence<BaseTable<Record<string, StandardSchemaV1>, any, any, any>, any, any, any> : TableOccurrence<BaseTable<Record<string, StandardSchemaV1>, any, any, any>, any, any, any> : TableOccurrence<BaseTable<Record<string, StandardSchemaV1>, any, any, any>, any, any, any>;
10
- type GetTargetSchemaType<O extends TableOccurrence<any, any, any, any> | undefined, Rel extends string> = [FindNavigationTarget<O, Rel>] extends [
11
- TableOccurrence<infer BT, any, any, any>
12
- ] ? [BT] extends [BaseTable<infer S, any, any, any>] ? [S] extends [Record<string, StandardSchemaV1>] ? InferSchemaType<S> : Record<string, any> : Record<string, any> : Record<string, any>;
13
- export type ExpandedRelations = Record<string, {
14
- schema: any;
15
- selected: any;
16
- }>;
17
- export type RecordReturnType<T extends Record<string, any>, IsSingleField extends boolean, FieldKey extends keyof T, Selected extends keyof T, Expands extends ExpandedRelations> = IsSingleField extends true ? T[FieldKey] : Pick<T, Selected> & {
18
- [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
4
+ import { Column } from '../orm/column.js';
5
+ import { ExpandedRelations } from './builders/index.js';
6
+ /**
7
+ * Extract the value type from a Column.
8
+ * This uses the phantom type stored in Column to get the actual value type.
9
+ */
10
+ type ExtractColumnType<C> = C extends Column<infer T, any> ? T : never;
11
+ /**
12
+ * Map a select object to its return type.
13
+ * For each key in the select object, extract the type from the corresponding Column.
14
+ */
15
+ type MapSelectToReturnType<TSelect extends Record<string, Column<any, any>>, TSchema extends Record<string, any>> = {
16
+ [K in keyof TSelect]: ExtractColumnType<TSelect[K]>;
19
17
  };
20
- export declare class RecordBuilder<T extends Record<string, any>, IsSingleField extends boolean = false, FieldKey extends keyof T = keyof T, Occ extends TableOccurrence<any, any, any, any> | undefined = TableOccurrence<any, any, any, any> | undefined, Selected extends keyof T = keyof T, Expands extends ExpandedRelations = {}> implements ExecutableBuilder<RecordReturnType<T, IsSingleField, FieldKey, Selected, Expands>> {
21
- private occurrence?;
22
- private tableName;
18
+ export type RecordReturnType<Schema extends Record<string, any>, IsSingleField extends boolean, FieldKey extends keyof Schema, Selected extends keyof Schema | Record<string, Column<any, ExtractTableName<FMTable<any, any>>>>, Expands extends ExpandedRelations> = IsSingleField extends true ? Schema[FieldKey] : [
19
+ Selected
20
+ ] extends [Record<string, Column<any, any>>] ? MapSelectToReturnType<Selected, Schema> & {
21
+ [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
22
+ } : [
23
+ Selected
24
+ ] extends [keyof Schema] ? Pick<Schema, Selected> & {
25
+ [K in keyof Expands]: Pick<Expands[K]["schema"], Expands[K]["selected"]>[];
26
+ } : never;
27
+ export declare class RecordBuilder<Occ extends FMTable<any, any> = FMTable<any, any>, IsSingleField extends boolean = false, FieldKey extends keyof InferSchemaOutputFromFMTable<NonNullable<Occ>> = keyof InferSchemaOutputFromFMTable<NonNullable<Occ>>, Selected extends keyof InferSchemaOutputFromFMTable<NonNullable<Occ>> | Record<string, Column<any, ExtractTableName<NonNullable<Occ>>>> = keyof InferSchemaOutputFromFMTable<NonNullable<Occ>>, Expands extends ExpandedRelations = {}> implements ExecutableBuilder<RecordReturnType<InferSchemaOutputFromFMTable<NonNullable<Occ>>, IsSingleField, FieldKey, Selected, Expands>> {
28
+ private table;
23
29
  private databaseName;
24
30
  private context;
25
31
  private recordId;
@@ -31,9 +37,9 @@ export declare class RecordBuilder<T extends Record<string, any>, IsSingleField
31
37
  private databaseUseEntityIds;
32
38
  private selectedFields?;
33
39
  private expandConfigs;
40
+ private fieldMapping?;
34
41
  constructor(config: {
35
- occurrence?: Occ;
36
- tableName: string;
42
+ occurrence: Occ;
37
43
  databaseName: string;
38
44
  context: ExecutionContext;
39
45
  recordId: string | number;
@@ -48,68 +54,54 @@ export declare class RecordBuilder<T extends Record<string, any>, IsSingleField
48
54
  * @param useEntityIds - Optional override for entity ID usage
49
55
  */
50
56
  private getTableId;
51
- getSingleField<K extends keyof T>(field: K): RecordBuilder<T, true, K, Occ, keyof T, {}>;
52
57
  /**
53
- * Select specific fields to retrieve from the record.
54
- * Only the selected fields will be returned in the response.
58
+ * Creates a new RecordBuilder with modified configuration.
59
+ * Used by select() to create new instances.
60
+ */
61
+ private cloneWithChanges;
62
+ getSingleField<K extends keyof InferSchemaOutputFromFMTable<NonNullable<Occ>>>(field: K): RecordBuilder<Occ, true, K, keyof InferSchemaOutputFromFMTable<NonNullable<Occ>>, {}>;
63
+ /**
64
+ * Select fields using column references.
65
+ * Allows renaming fields by using different keys in the object.
66
+ * Container fields cannot be selected and will cause a type error.
55
67
  *
56
68
  * @example
57
- * ```typescript
58
- * const contact = await db.from("contacts").get("uuid").select("name", "email").execute();
59
- * // contact.data has type { name: string; email: string }
60
- * ```
69
+ * db.from(contacts).get("uuid").select({
70
+ * name: contacts.name,
71
+ * userEmail: contacts.email // renamed!
72
+ * })
73
+ *
74
+ * @param fields - Object mapping output keys to column references (container fields excluded)
75
+ * @returns RecordBuilder with updated selected fields
61
76
  */
62
- select<K extends keyof T>(...fields: K[]): RecordBuilder<T, false, FieldKey, Occ, K, Expands>;
77
+ select<TSelect extends Record<string, Column<any, ExtractTableName<Occ>, false>>>(fields: TSelect): RecordBuilder<Occ, false, FieldKey, TSelect, Expands>;
63
78
  /**
64
79
  * Expand a navigation property to include related records.
65
80
  * Supports nested select, filter, orderBy, and expand operations.
66
81
  *
67
82
  * @example
68
83
  * ```typescript
69
- * // Simple expand
70
- * const contact = await db.from("contacts").get("uuid").expand("users").execute();
84
+ * // Simple expand with FMTable object
85
+ * const contact = await db.from(contacts).get("uuid").expand(users).execute();
71
86
  *
72
87
  * // Expand with select
73
- * const contact = await db.from("contacts").get("uuid")
74
- * .expand("users", b => b.select("username", "email"))
88
+ * const contact = await db.from(contacts).get("uuid")
89
+ * .expand(users, b => b.select({ username: users.username, email: users.email }))
75
90
  * .execute();
76
91
  * ```
77
92
  */
78
- expand<Rel extends ExtractNavigationNames<Occ> | (string & {}), TargetOcc extends FindNavigationTarget<Occ, Rel> = FindNavigationTarget<Occ, Rel>, TargetSchema extends GetTargetSchemaType<Occ, Rel> = GetTargetSchemaType<Occ, Rel>, TargetSelected extends keyof TargetSchema = keyof TargetSchema>(relation: Rel, callback?: (builder: QueryBuilder<TargetSchema, keyof TargetSchema, false, false, TargetOcc extends TableOccurrence<any, any, any, any> ? TargetOcc : undefined>) => QueryBuilder<WithSystemFields<TargetSchema>, TargetSelected, any, any, any>): RecordBuilder<T, false, FieldKey, Occ, Selected, Expands & {
79
- [K in Rel]: {
80
- schema: TargetSchema;
81
- selected: TargetSelected;
93
+ expand<TargetTable extends FMTable<any, any>>(targetTable: ValidExpandTarget<Occ, TargetTable>, callback?: (builder: QueryBuilder<TargetTable, keyof InferSchemaOutputFromFMTable<TargetTable>, false, false>) => QueryBuilder<TargetTable, any, any, any, any>): RecordBuilder<Occ, false, FieldKey, Selected, Expands & {
94
+ [K in ExtractTableName<TargetTable>]: {
95
+ schema: InferSchemaOutputFromFMTable<TargetTable>;
96
+ selected: keyof InferSchemaOutputFromFMTable<TargetTable>;
82
97
  };
83
98
  }>;
84
- navigate<RelationName extends ExtractNavigationNames<Occ>>(relationName: RelationName): QueryBuilder<ExtractSchemaFromOccurrence<FindNavigationTarget<Occ, RelationName>> extends Record<string, StandardSchemaV1> ? InferSchemaType<ExtractSchemaFromOccurrence<FindNavigationTarget<Occ, RelationName>>> : Record<string, any>>;
85
- navigate(relationName: string): QueryBuilder<{
86
- ROWID: number;
87
- ROWMODID: number;
88
- [key: string]: any;
89
- }>;
90
- /**
91
- * Formats select fields for use in query strings.
92
- * - Transforms field names to FMFIDs if using entity IDs
93
- * - Wraps "id" fields in double quotes
94
- * - URL-encodes special characters but preserves spaces
95
- */
96
- private formatSelectFields;
97
- /**
98
- * Builds expand validation configs from internal expand configurations.
99
- * These are used to validate expanded navigation properties.
100
- */
101
- private buildExpandValidationConfigs;
102
- /**
103
- * Builds OData expand query string from expand configurations.
104
- * Handles nested expands recursively.
105
- * Transforms relation names to FMTIDs if using entity IDs.
106
- */
107
- private buildExpandString;
99
+ navigate<TargetTable extends FMTable<any, any>>(targetTable: ValidExpandTarget<Occ, TargetTable>): QueryBuilder<TargetTable, keyof InferSchemaOutputFromFMTable<TargetTable>, false, false>;
108
100
  /**
109
101
  * Builds the complete query string including $select and $expand parameters.
110
102
  */
111
103
  private buildQueryString;
112
- execute<EO extends ExecuteOptions>(options?: RequestInit & FFetchOptions & EO): Promise<Result<ConditionallyWithODataAnnotations<RecordReturnType<T, IsSingleField, FieldKey, Selected, Expands>, EO["includeODataAnnotations"] extends true ? true : false>>>;
104
+ execute<EO extends ExecuteOptions>(options?: ExecuteMethodOptions<EO>): Promise<Result<ConditionallyWithODataAnnotations<RecordReturnType<InferSchemaOutputFromFMTable<NonNullable<Occ>>, IsSingleField, FieldKey, Selected, Expands>, EO["includeODataAnnotations"] extends true ? true : false>>>;
113
105
  getRequestConfig(): {
114
106
  method: string;
115
107
  url: string;
@@ -120,6 +112,6 @@ export declare class RecordBuilder<T extends Record<string, any>, IsSingleField
120
112
  */
121
113
  getQueryString(): string;
122
114
  toRequest(baseUrl: string, options?: ExecuteOptions): Request;
123
- processResponse(response: Response, options?: ExecuteOptions): Promise<Result<RecordReturnType<T, IsSingleField, FieldKey, Selected, Expands>>>;
115
+ processResponse(response: Response, options?: ExecuteOptions): Promise<Result<RecordReturnType<InferSchemaOutputFromFMTable<NonNullable<Occ>>, IsSingleField, FieldKey, Selected, Expands>>>;
124
116
  }
125
117
  export {};