@proofkit/fmodata 0.1.0-alpha.12 → 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 (142) 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 -296
  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 +5 -2
  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 -1447
  115. package/src/client/record-builder.ts +325 -583
  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/dist/esm/client/base-table.d.ts +0 -128
  129. package/dist/esm/client/base-table.js +0 -57
  130. package/dist/esm/client/base-table.js.map +0 -1
  131. package/dist/esm/client/build-occurrences.d.ts +0 -74
  132. package/dist/esm/client/build-occurrences.js +0 -31
  133. package/dist/esm/client/build-occurrences.js.map +0 -1
  134. package/dist/esm/client/query-builder.js +0 -897
  135. package/dist/esm/client/query-builder.js.map +0 -1
  136. package/dist/esm/client/table-occurrence.d.ts +0 -86
  137. package/dist/esm/client/table-occurrence.js +0 -58
  138. package/dist/esm/client/table-occurrence.js.map +0 -1
  139. package/src/client/base-table.ts +0 -178
  140. package/src/client/build-occurrences.ts +0 -155
  141. package/src/client/query-builder.ts.bak +0 -1457
  142. package/src/client/table-occurrence.ts +0 -156
@@ -1,16 +1,15 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { QueryBuilder } from "./query-builder.js";
4
+ import { QueryBuilder } from "./query/query-builder.js";
5
5
  import { RecordBuilder } from "./record-builder.js";
6
6
  import { InsertBuilder } from "./insert-builder.js";
7
7
  import { DeleteBuilder } from "./delete-builder.js";
8
8
  import { UpdateBuilder } from "./update-builder.js";
9
+ import { getDefaultSelect, FMTable, getTableColumns, getTableName } from "../orm/table.js";
9
10
  class EntitySet {
10
- // Full base path for chained navigations
11
11
  constructor(config) {
12
12
  __publicField(this, "occurrence");
13
- __publicField(this, "tableName");
14
13
  __publicField(this, "databaseName");
15
14
  __publicField(this, "context");
16
15
  __publicField(this, "database");
@@ -19,17 +18,19 @@ class EntitySet {
19
18
  __publicField(this, "navigateRelation");
20
19
  __publicField(this, "navigateSourceTableName");
21
20
  __publicField(this, "navigateBasePath");
21
+ // Full base path for chained navigations
22
+ __publicField(this, "databaseUseEntityIds");
23
+ var _a;
22
24
  this.occurrence = config.occurrence;
23
- this.tableName = config.tableName;
24
25
  this.databaseName = config.databaseName;
25
26
  this.context = config.context;
26
27
  this.database = config.database;
28
+ this.databaseUseEntityIds = ((_a = config.database) == null ? void 0 : _a._useEntityIds) ?? false;
27
29
  }
28
- // Type-only method to help TypeScript infer the schema from occurrence
30
+ // Type-only method to help TypeScript infer the schema from table
29
31
  static create(config) {
30
32
  return new EntitySet({
31
33
  occurrence: config.occurrence,
32
- tableName: config.tableName,
33
34
  databaseName: config.databaseName,
34
35
  context: config.context,
35
36
  database: config.database
@@ -39,30 +40,35 @@ class EntitySet {
39
40
  var _a;
40
41
  const builder = new QueryBuilder({
41
42
  occurrence: this.occurrence,
42
- tableName: this.tableName,
43
43
  databaseName: this.databaseName,
44
44
  context: this.context,
45
- databaseUseEntityIds: ((_a = this.database) == null ? void 0 : _a.isUsingEntityIds()) ?? false
45
+ databaseUseEntityIds: this.databaseUseEntityIds
46
46
  });
47
47
  if (this.occurrence) {
48
- const defaultSelect = this.occurrence.defaultSelect;
49
- if (defaultSelect === "schema") {
50
- const schema = this.occurrence.baseTable.schema;
51
- const fields = Object.keys(schema);
52
- const uniqueFields = [...new Set(fields)];
53
- return builder.select(...uniqueFields).top(1e3);
54
- } else if (Array.isArray(defaultSelect)) {
55
- const uniqueFields = [
56
- ...new Set(defaultSelect)
57
- ];
58
- return builder.select(...uniqueFields).top(1e3);
48
+ const defaultSelectValue = getDefaultSelect(this.occurrence);
49
+ const tableSchema = this.occurrence[FMTable.Symbol.Schema];
50
+ if (tableSchema) {
51
+ const zodSchema = (_a = tableSchema["~standard"]) == null ? void 0 : _a.schema;
52
+ if (zodSchema && typeof zodSchema === "object" && "shape" in zodSchema) {
53
+ zodSchema.shape;
54
+ }
55
+ }
56
+ if (defaultSelectValue === "schema") {
57
+ const allColumns = getTableColumns(
58
+ this.occurrence
59
+ );
60
+ return builder.select(allColumns).top(1e3);
61
+ } else if (typeof defaultSelectValue === "object") {
62
+ return builder.select(defaultSelectValue).top(1e3);
59
63
  }
60
64
  }
61
- if (this.isNavigateFromEntitySet) {
62
- builder.isNavigate = true;
63
- builder.navigateRelation = this.navigateRelation;
64
- builder.navigateSourceTableName = this.navigateSourceTableName;
65
- builder.navigateBasePath = this.navigateBasePath;
65
+ if (this.isNavigateFromEntitySet && this.navigateRelation && this.navigateSourceTableName) {
66
+ builder.navigation = {
67
+ relation: this.navigateRelation,
68
+ sourceTableName: this.navigateSourceTableName,
69
+ basePath: this.navigateBasePath
70
+ // recordId is intentionally not set (undefined) to indicate navigation from EntitySet
71
+ };
66
72
  }
67
73
  return builder.top(1e3);
68
74
  }
@@ -70,92 +76,107 @@ class EntitySet {
70
76
  var _a;
71
77
  const builder = new RecordBuilder({
72
78
  occurrence: this.occurrence,
73
- tableName: this.tableName,
74
79
  databaseName: this.databaseName,
75
80
  context: this.context,
76
81
  recordId: id,
77
- databaseUseEntityIds: ((_a = this.database) == null ? void 0 : _a.isUsingEntityIds()) ?? false
82
+ databaseUseEntityIds: this.databaseUseEntityIds
78
83
  });
79
84
  if (this.occurrence) {
80
- const defaultSelect = this.occurrence.defaultSelect;
81
- if (defaultSelect === "schema") {
82
- const schema = this.occurrence.baseTable.schema;
83
- const fields = Object.keys(schema);
84
- const uniqueFields = [...new Set(fields)];
85
- const selectedBuilder = builder.select(...uniqueFields);
86
- if (this.isNavigateFromEntitySet) {
87
- selectedBuilder.isNavigateFromEntitySet = true;
88
- selectedBuilder.navigateRelation = this.navigateRelation;
89
- selectedBuilder.navigateSourceTableName = this.navigateSourceTableName;
85
+ const defaultSelectValue = getDefaultSelect(this.occurrence);
86
+ const tableSchema = this.occurrence[FMTable.Symbol.Schema];
87
+ if (tableSchema) {
88
+ const zodSchema = (_a = tableSchema["~standard"]) == null ? void 0 : _a.schema;
89
+ if (zodSchema && typeof zodSchema === "object" && "shape" in zodSchema) {
90
+ zodSchema.shape;
91
+ }
92
+ }
93
+ if (defaultSelectValue === "schema") {
94
+ const allColumns = getTableColumns(
95
+ this.occurrence
96
+ );
97
+ const selectedBuilder = builder.select(allColumns);
98
+ if (this.isNavigateFromEntitySet && this.navigateRelation && this.navigateSourceTableName) {
99
+ selectedBuilder.navigation = {
100
+ relation: this.navigateRelation,
101
+ sourceTableName: this.navigateSourceTableName,
102
+ basePath: this.navigateBasePath
103
+ };
90
104
  }
91
105
  return selectedBuilder;
92
- } else if (Array.isArray(defaultSelect)) {
93
- const uniqueFields = [
94
- ...new Set(defaultSelect)
95
- ];
96
- const selectedBuilder = builder.select(...uniqueFields);
97
- if (this.isNavigateFromEntitySet) {
98
- selectedBuilder.isNavigateFromEntitySet = true;
99
- selectedBuilder.navigateRelation = this.navigateRelation;
100
- selectedBuilder.navigateSourceTableName = this.navigateSourceTableName;
106
+ } else if (typeof defaultSelectValue === "object" && defaultSelectValue !== null && !Array.isArray(defaultSelectValue)) {
107
+ const selectedBuilder = builder.select(
108
+ defaultSelectValue
109
+ );
110
+ if (this.isNavigateFromEntitySet && this.navigateRelation && this.navigateSourceTableName) {
111
+ selectedBuilder.navigation = {
112
+ relation: this.navigateRelation,
113
+ sourceTableName: this.navigateSourceTableName,
114
+ basePath: this.navigateBasePath
115
+ };
101
116
  }
102
117
  return selectedBuilder;
103
118
  }
104
119
  }
105
- if (this.isNavigateFromEntitySet) {
106
- builder.isNavigateFromEntitySet = true;
107
- builder.navigateRelation = this.navigateRelation;
108
- builder.navigateSourceTableName = this.navigateSourceTableName;
120
+ if (this.isNavigateFromEntitySet && this.navigateRelation && this.navigateSourceTableName) {
121
+ builder.navigation = {
122
+ relation: this.navigateRelation,
123
+ sourceTableName: this.navigateSourceTableName,
124
+ basePath: this.navigateBasePath
125
+ };
109
126
  }
110
127
  return builder;
111
128
  }
112
129
  // Implementation
113
130
  insert(data, options) {
114
- var _a;
115
- const returnPref = (options == null ? void 0 : options.returnFullRecord) === false ? "minimal" : "representation";
131
+ const returnPreference = (options == null ? void 0 : options.returnFullRecord) === false ? "minimal" : "representation";
116
132
  return new InsertBuilder({
117
133
  occurrence: this.occurrence,
118
- tableName: this.tableName,
119
134
  databaseName: this.databaseName,
120
135
  context: this.context,
121
136
  data,
122
- returnPreference: returnPref,
123
- databaseUseEntityIds: ((_a = this.database) == null ? void 0 : _a.isUsingEntityIds()) ?? false
137
+ // Input type is validated/transformed at runtime
138
+ returnPreference,
139
+ databaseUseEntityIds: this.databaseUseEntityIds
124
140
  });
125
141
  }
126
142
  // Implementation
127
143
  update(data, options) {
128
- var _a;
129
- const returnPref = (options == null ? void 0 : options.returnFullRecord) === true ? "representation" : "minimal";
144
+ const returnPreference = (options == null ? void 0 : options.returnFullRecord) === true ? "representation" : "minimal";
130
145
  return new UpdateBuilder({
131
146
  occurrence: this.occurrence,
132
- tableName: this.tableName,
133
147
  databaseName: this.databaseName,
134
148
  context: this.context,
135
149
  data,
136
- returnPreference: returnPref,
137
- databaseUseEntityIds: ((_a = this.database) == null ? void 0 : _a.isUsingEntityIds()) ?? false
150
+ // Input type is validated/transformed at runtime
151
+ returnPreference,
152
+ databaseUseEntityIds: this.databaseUseEntityIds
138
153
  });
139
154
  }
140
155
  delete() {
141
- var _a;
142
156
  return new DeleteBuilder({
143
157
  occurrence: this.occurrence,
144
- tableName: this.tableName,
145
158
  databaseName: this.databaseName,
146
159
  context: this.context,
147
- databaseUseEntityIds: ((_a = this.database) == null ? void 0 : _a.isUsingEntityIds()) ?? false
160
+ databaseUseEntityIds: this.databaseUseEntityIds
148
161
  });
149
162
  }
150
163
  // Implementation
151
- navigate(relationName) {
152
- var _a;
153
- const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[relationName];
164
+ navigate(targetTable) {
165
+ let relationName;
166
+ relationName = getTableName(targetTable);
167
+ if (this.occurrence && FMTable.Symbol.NavigationPaths in this.occurrence) {
168
+ const navigationPaths = this.occurrence[FMTable.Symbol.NavigationPaths];
169
+ if (navigationPaths && !navigationPaths.includes(relationName)) {
170
+ console.warn(
171
+ `Cannot navigate to "${relationName}". Valid navigation paths: ${navigationPaths.length > 0 ? navigationPaths.join(", ") : "none"}`
172
+ );
173
+ }
174
+ }
154
175
  const entitySet = new EntitySet({
155
- occurrence: targetOccurrence,
156
- tableName: (targetOccurrence == null ? void 0 : targetOccurrence.name) ?? relationName,
176
+ occurrence: targetTable,
157
177
  databaseName: this.databaseName,
158
- context: this.context
178
+ context: this.context,
179
+ database: this.database
159
180
  });
160
181
  entitySet.isNavigateFromEntitySet = true;
161
182
  entitySet.navigateRelation = relationName;
@@ -166,7 +187,9 @@ class EntitySet {
166
187
  entitySet.navigateBasePath = `${this.navigateSourceTableName}/${this.navigateRelation}`;
167
188
  entitySet.navigateSourceTableName = this.navigateSourceTableName;
168
189
  } else {
169
- entitySet.navigateSourceTableName = this.tableName;
190
+ entitySet.navigateSourceTableName = getTableName(
191
+ this.occurrence
192
+ );
170
193
  }
171
194
  return entitySet;
172
195
  }
@@ -1 +1 @@
1
- {"version":3,"file":"entity-set.js","sources":["../../../src/client/entity-set.ts"],"sourcesContent":["import type {\n ExecutionContext,\n InferSchemaType,\n WithSystemFields,\n InsertData,\n UpdateData,\n} from \"../types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { BaseTable } from \"./base-table\";\nimport type { TableOccurrence } from \"./table-occurrence\";\nimport { QueryBuilder } from \"./query-builder\";\nimport { RecordBuilder } from \"./record-builder\";\nimport { InsertBuilder } from \"./insert-builder\";\nimport { DeleteBuilder } from \"./delete-builder\";\nimport { UpdateBuilder } from \"./update-builder\";\nimport { Database } from \"./database\";\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 extract schema from a TableOccurrence\ntype ExtractSchemaFromOccurrence<O> =\n O extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<infer S, any, any, any>\n ? S\n : never\n : never;\n\n// Helper type to extract defaultSelect from a TableOccurrence\ntype ExtractDefaultSelect<O> =\n O extends TableOccurrence<infer BT, any, any, infer DefSelect>\n ? BT extends BaseTable<infer S, any, any, any>\n ? DefSelect extends \"all\"\n ? keyof S\n : DefSelect extends \"schema\"\n ? keyof S\n : DefSelect extends readonly (infer K)[]\n ? K & keyof S\n : keyof S\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\nexport class EntitySet<\n Schema extends Record<string, StandardSchemaV1> = any,\n Occ extends TableOccurrence<any, any, any, any> | undefined = undefined,\n> {\n private occurrence?: Occ;\n private tableName: string;\n private databaseName: string;\n private context: ExecutionContext;\n private database: Database<any>; // Database instance for accessing occurrences\n private isNavigateFromEntitySet?: boolean;\n private navigateRelation?: string;\n private navigateSourceTableName?: string;\n private navigateBasePath?: string; // Full base path for chained navigations\n\n constructor(config: {\n occurrence?: Occ;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n database?: any;\n }) {\n this.occurrence = config.occurrence;\n this.tableName = config.tableName;\n this.databaseName = config.databaseName;\n this.context = config.context;\n this.database = config.database;\n }\n\n // Type-only method to help TypeScript infer the schema from occurrence\n static create<\n OccurrenceSchema extends Record<string, StandardSchemaV1>,\n Occ extends\n | TableOccurrence<\n BaseTable<OccurrenceSchema, any, any, any>,\n any,\n any,\n any\n >\n | undefined = undefined,\n >(config: {\n occurrence?: Occ;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n database: Database<any>;\n }): EntitySet<OccurrenceSchema, Occ> {\n return new EntitySet<OccurrenceSchema, Occ>({\n occurrence: config.occurrence,\n tableName: config.tableName,\n databaseName: config.databaseName,\n context: config.context,\n database: config.database,\n });\n }\n\n list(): QueryBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<any, any, any, any>\n ? ExtractDefaultSelect<Occ>\n : keyof InferSchemaType<Schema>,\n false,\n false,\n Occ\n > {\n const builder = new QueryBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<any, any, any, any>\n ? ExtractDefaultSelect<Occ>\n : keyof InferSchemaType<Schema>,\n false,\n false,\n Occ\n >({\n occurrence: this.occurrence as Occ,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.database?.isUsingEntityIds() ?? false,\n });\n\n // Apply defaultSelect if occurrence exists and select hasn't been called\n if (this.occurrence) {\n const defaultSelect = this.occurrence.defaultSelect;\n\n if (defaultSelect === \"schema\") {\n // Extract field names from schema\n const schema = this.occurrence.baseTable.schema;\n const fields = Object.keys(schema) as (keyof InferSchemaType<Schema>)[];\n // Deduplicate fields (same as select method)\n const uniqueFields = [...new Set(fields)];\n return builder.select(...uniqueFields).top(1000);\n } else if (Array.isArray(defaultSelect)) {\n // Use the provided field names, deduplicated\n const uniqueFields = [\n ...new Set(defaultSelect),\n ] as (keyof InferSchemaType<Schema>)[];\n return builder.select(...uniqueFields).top(1000);\n }\n // If defaultSelect is \"all\", no changes needed (current behavior)\n }\n\n // Propagate navigation context if present\n if (this.isNavigateFromEntitySet) {\n (builder as any).isNavigate = true;\n (builder as any).navigateRelation = this.navigateRelation;\n (builder as any).navigateSourceTableName = this.navigateSourceTableName;\n (builder as any).navigateBasePath = this.navigateBasePath;\n // navigateRecordId is intentionally not set (undefined) to indicate navigation from EntitySet\n }\n\n // Apply default pagination limit of 1000 records to prevent stack overflow\n // with large datasets. Users can override with .top() if needed.\n return builder.top(1000);\n }\n\n get(\n id: string | number,\n ): RecordBuilder<\n InferSchemaType<Schema>,\n false,\n keyof InferSchemaType<Schema>,\n Occ,\n Occ extends TableOccurrence<any, any, any, any>\n ? ExtractDefaultSelect<Occ>\n : keyof InferSchemaType<Schema>,\n {}\n > {\n const builder = new RecordBuilder<\n InferSchemaType<Schema>,\n false,\n keyof InferSchemaType<Schema>,\n Occ,\n keyof InferSchemaType<Schema>,\n {}\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n recordId: id,\n databaseUseEntityIds: this.database?.isUsingEntityIds() ?? false,\n });\n\n // Apply defaultSelect if occurrence exists\n if (this.occurrence) {\n const defaultSelect = this.occurrence.defaultSelect;\n\n if (defaultSelect === \"schema\") {\n // Extract field names from schema\n const schema = this.occurrence.baseTable.schema;\n const fields = Object.keys(schema) as (keyof InferSchemaType<Schema>)[];\n // Deduplicate fields (same as select method)\n const uniqueFields = [...new Set(fields)];\n const selectedBuilder = builder.select(...uniqueFields);\n // Propagate navigation context if present\n if (this.isNavigateFromEntitySet) {\n (selectedBuilder as any).isNavigateFromEntitySet = true;\n (selectedBuilder as any).navigateRelation = this.navigateRelation;\n (selectedBuilder as any).navigateSourceTableName = this.navigateSourceTableName;\n }\n return selectedBuilder as any;\n } else if (Array.isArray(defaultSelect)) {\n // Use the provided field names, deduplicated\n const uniqueFields = [\n ...new Set(defaultSelect),\n ] as (keyof InferSchemaType<Schema>)[];\n const selectedBuilder = builder.select(...uniqueFields);\n // Propagate navigation context if present\n if (this.isNavigateFromEntitySet) {\n (selectedBuilder as any).isNavigateFromEntitySet = true;\n (selectedBuilder as any).navigateRelation = this.navigateRelation;\n (selectedBuilder as any).navigateSourceTableName = this.navigateSourceTableName;\n }\n return selectedBuilder as any;\n }\n // If defaultSelect is \"all\", no changes needed (current behavior)\n }\n\n // Propagate navigation context if present\n if (this.isNavigateFromEntitySet) {\n (builder as any).isNavigateFromEntitySet = true;\n (builder as any).navigateRelation = this.navigateRelation;\n (builder as any).navigateSourceTableName = this.navigateSourceTableName;\n }\n return builder as any;\n }\n\n // Overload: when returnFullRecord is explicitly false\n insert(\n data: Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? InsertData<BT>\n : Partial<InferSchemaType<Schema>>\n : Partial<InferSchemaType<Schema>>,\n options: { returnFullRecord: false },\n ): InsertBuilder<InferSchemaType<Schema>, Occ, \"minimal\">;\n\n // Overload: when returnFullRecord is true or omitted (default)\n insert(\n data: Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? InsertData<BT>\n : Partial<InferSchemaType<Schema>>\n : Partial<InferSchemaType<Schema>>,\n options?: { returnFullRecord?: true },\n ): InsertBuilder<InferSchemaType<Schema>, Occ, \"representation\">;\n\n // Implementation\n insert(\n data: Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? InsertData<BT>\n : Partial<InferSchemaType<Schema>>\n : Partial<InferSchemaType<Schema>>,\n options?: { returnFullRecord?: boolean },\n ): InsertBuilder<InferSchemaType<Schema>, Occ, \"minimal\" | \"representation\"> {\n const returnPref =\n options?.returnFullRecord === false ? \"minimal\" : \"representation\";\n return new InsertBuilder<InferSchemaType<Schema>, Occ, typeof returnPref>({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n data: data as Partial<InferSchemaType<Schema>>,\n returnPreference: returnPref as any,\n databaseUseEntityIds: this.database?.isUsingEntityIds() ?? false,\n });\n }\n\n // Overload: when returnFullRecord is explicitly true\n update(\n data: Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? UpdateData<BT>\n : Partial<InferSchemaType<Schema>>\n : Partial<InferSchemaType<Schema>>,\n options: { returnFullRecord: true },\n ): UpdateBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? BT\n : BaseTable<Schema, any, any, any>\n : BaseTable<Schema, any, any, any>,\n \"representation\"\n >;\n\n // Overload: when returnFullRecord is false or omitted (default returns count)\n update(\n data: Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? UpdateData<BT>\n : Partial<InferSchemaType<Schema>>\n : Partial<InferSchemaType<Schema>>,\n options?: { returnFullRecord?: false },\n ): UpdateBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? BT\n : BaseTable<Schema, any, any, any>\n : BaseTable<Schema, any, any, any>,\n \"minimal\"\n >;\n\n // Implementation\n update(\n data: Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? UpdateData<BT>\n : Partial<InferSchemaType<Schema>>\n : Partial<InferSchemaType<Schema>>,\n options?: { returnFullRecord?: boolean },\n ): UpdateBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? BT\n : BaseTable<Schema, any, any, any>\n : BaseTable<Schema, any, any, any>,\n \"minimal\" | \"representation\"\n > {\n const returnPref =\n options?.returnFullRecord === true ? \"representation\" : \"minimal\";\n return new UpdateBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? BT\n : BaseTable<Schema, any, any, any>\n : BaseTable<Schema, any, any, any>,\n typeof returnPref\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n data: data as Partial<InferSchemaType<Schema>>,\n returnPreference: returnPref as any,\n databaseUseEntityIds: this.database?.isUsingEntityIds() ?? false,\n });\n }\n\n delete(): DeleteBuilder<InferSchemaType<Schema>> {\n return new DeleteBuilder<InferSchemaType<Schema>>({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.database?.isUsingEntityIds() ?? false,\n });\n }\n\n // Overload for valid relation names - returns typed EntitySet\n navigate<RelationName extends ExtractNavigationNames<Occ>>(\n relationName: RelationName,\n ): EntitySet<\n ExtractSchemaFromOccurrence<\n FindNavigationTarget<Occ, RelationName>\n > extends Record<string, StandardSchemaV1>\n ? ExtractSchemaFromOccurrence<FindNavigationTarget<Occ, RelationName>>\n : Record<string, StandardSchemaV1>,\n FindNavigationTarget<Occ, RelationName>\n >;\n // Overload for arbitrary strings - returns generic EntitySet\n navigate(\n relationName: string,\n ): EntitySet<Record<string, StandardSchemaV1>, undefined>;\n // Implementation\n navigate(relationName: string): EntitySet<any, any> {\n // Use the target occurrence if available, otherwise allow untyped navigation\n // (useful when types might be incomplete)\n const targetOccurrence = this.occurrence?.navigation[relationName];\n const entitySet = new EntitySet<any, any>({\n occurrence: targetOccurrence,\n tableName: targetOccurrence?.name ?? relationName,\n databaseName: this.databaseName,\n context: this.context,\n });\n // Store the navigation info in the EntitySet\n // We'll need to pass this through when creating QueryBuilders\n (entitySet as any).isNavigateFromEntitySet = true;\n (entitySet as any).navigateRelation = relationName;\n\n // Build the full base path for chained navigations\n // The base path should contain all segments BEFORE the final relation\n if (this.isNavigateFromEntitySet && this.navigateBasePath) {\n // Already have a base path from previous navigation - extend it with current relation\n (entitySet as any).navigateBasePath =\n `${this.navigateBasePath}/${this.navigateRelation}`;\n (entitySet as any).navigateSourceTableName = this.navigateSourceTableName;\n } else if (this.isNavigateFromEntitySet && this.navigateRelation) {\n // First chained navigation - create base path from source/relation\n (entitySet as any).navigateBasePath =\n `${this.navigateSourceTableName}/${this.navigateRelation}`;\n (entitySet as any).navigateSourceTableName = this.navigateSourceTableName;\n } else {\n // Initial navigation - source is just the table name\n (entitySet as any).navigateSourceTableName = this.tableName;\n }\n return entitySet;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entity-set.js","sources":["../../../src/client/entity-set.ts"],"sourcesContent":["import type { ExecutionContext, InferSchemaType } from \"../types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { QueryBuilder } from \"./query\";\nimport { RecordBuilder } from \"./record-builder\";\nimport { InsertBuilder } from \"./insert-builder\";\nimport { DeleteBuilder } from \"./delete-builder\";\nimport { UpdateBuilder } from \"./update-builder\";\nimport { Database } from \"./database\";\nimport type {\n FMTable,\n InferSchemaOutputFromFMTable,\n InferInputSchemaFromFMTable,\n InsertDataFromFMTable,\n UpdateDataFromFMTable,\n ValidExpandTarget,\n ExtractTableName,\n FMTableWithColumns,\n InferFieldOutput,\n} from \"../orm/table\";\nimport {\n FMTable as FMTableClass,\n getDefaultSelect,\n getNavigationPaths,\n getTableName,\n getTableColumns,\n getTableFields,\n} from \"../orm/table\";\nimport type { Column } from \"../orm/column\";\nimport type { FieldBuilder } from \"../orm/field-builders\";\n\n// Helper type to extract defaultSelect from an FMTable\n// Since TypeScript can't extract Symbol-indexed properties at the type level,\n// we simplify to return keyof InferSchemaFromFMTable<O> when O is an FMTable.\n// The actual defaultSelect logic is handled at runtime.\ntype ExtractDefaultSelect<O> =\n O extends FMTable<any, any> ? keyof InferSchemaOutputFromFMTable<O> : never;\n\n/**\n * Helper type to extract properly-typed columns from an FMTable.\n * This preserves the specific column types instead of widening to `any`.\n */\ntype ExtractColumnsFromOcc<T> =\n T extends FMTable<infer TFields, infer TName, any>\n ? TFields extends Record<string, FieldBuilder<any, any, any, any>>\n ? { [K in keyof TFields]: Column<InferFieldOutput<TFields[K]>, TName> }\n : never\n : never;\n\nexport class EntitySet<Occ extends FMTable<any, any>> {\n private occurrence: Occ;\n private databaseName: string;\n private context: ExecutionContext;\n private database: Database; // Database instance for accessing occurrences\n private isNavigateFromEntitySet?: boolean;\n private navigateRelation?: string;\n private navigateSourceTableName?: string;\n private navigateBasePath?: string; // Full base path for chained navigations\n private databaseUseEntityIds: boolean;\n\n constructor(config: {\n occurrence: Occ;\n databaseName: string;\n context: ExecutionContext;\n database?: any;\n }) {\n this.occurrence = config.occurrence;\n this.databaseName = config.databaseName;\n this.context = config.context;\n this.database = config.database;\n // Get useEntityIds from database if available, otherwise default to false\n this.databaseUseEntityIds =\n (config.database as any)?._useEntityIds ?? false;\n }\n\n // Type-only method to help TypeScript infer the schema from table\n static create<Occ extends FMTable<any, any>>(config: {\n occurrence: Occ;\n databaseName: string;\n context: ExecutionContext;\n database: Database;\n }): EntitySet<Occ> {\n return new EntitySet<Occ>({\n occurrence: config.occurrence,\n databaseName: config.databaseName,\n context: config.context,\n database: config.database,\n });\n }\n\n list() {\n const builder = new QueryBuilder<Occ>({\n occurrence: this.occurrence as Occ,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n\n // Apply defaultSelect if occurrence exists and select hasn't been called\n if (this.occurrence) {\n // FMTable - access via helper functions\n const defaultSelectValue = getDefaultSelect(this.occurrence);\n const tableSchema = (this.occurrence as any)[FMTableClass.Symbol.Schema];\n let schema: Record<string, StandardSchemaV1> | undefined;\n\n if (tableSchema) {\n // Extract schema from StandardSchemaV1\n const zodSchema = tableSchema[\"~standard\"]?.schema;\n if (\n zodSchema &&\n typeof zodSchema === \"object\" &&\n \"shape\" in zodSchema\n ) {\n schema = zodSchema.shape as Record<string, StandardSchemaV1>;\n }\n }\n\n if (defaultSelectValue === \"schema\") {\n // Use getTableColumns to get all columns and select them\n // This is equivalent to select(getTableColumns(occurrence))\n // Use ExtractColumnsFromOcc to preserve the properly-typed column types\n const allColumns = getTableColumns(\n this.occurrence as any,\n ) as ExtractColumnsFromOcc<Occ>;\n return builder.select(allColumns).top(1000);\n } else if (typeof defaultSelectValue === \"object\") {\n // defaultSelectValue is a select object (Record<string, Column>)\n // Use it directly with select()\n // Use ExtractColumnsFromOcc to preserve the properly-typed column types\n return builder\n .select(defaultSelectValue as ExtractColumnsFromOcc<Occ>)\n .top(1000);\n }\n // If defaultSelect is \"all\", no changes needed (current behavior)\n }\n\n // Propagate navigation context if present\n if (\n this.isNavigateFromEntitySet &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n (builder as any).navigation = {\n relation: this.navigateRelation,\n sourceTableName: this.navigateSourceTableName,\n basePath: this.navigateBasePath,\n // recordId is intentionally not set (undefined) to indicate navigation from EntitySet\n };\n }\n\n // Apply default pagination limit of 1000 records to prevent stack overflow\n // with large datasets. Users can override with .top() if needed.\n return builder.top(1000);\n }\n\n get(\n id: string | number,\n ): RecordBuilder<\n Occ,\n false,\n keyof InferSchemaOutputFromFMTable<Occ>,\n keyof InferSchemaOutputFromFMTable<Occ>,\n {}\n > {\n const builder = new RecordBuilder<Occ>({\n occurrence: this.occurrence,\n databaseName: this.databaseName,\n context: this.context,\n recordId: id,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n\n // Apply defaultSelect if occurrence exists\n if (this.occurrence) {\n // FMTable - access via helper functions\n const defaultSelectValue = getDefaultSelect(this.occurrence);\n const tableSchema = (this.occurrence as any)[FMTableClass.Symbol.Schema];\n let schema: Record<string, StandardSchemaV1> | undefined;\n\n if (tableSchema) {\n // Extract schema from StandardSchemaV1\n const zodSchema = tableSchema[\"~standard\"]?.schema;\n if (\n zodSchema &&\n typeof zodSchema === \"object\" &&\n \"shape\" in zodSchema\n ) {\n schema = zodSchema.shape as Record<string, StandardSchemaV1>;\n }\n }\n\n if (defaultSelectValue === \"schema\") {\n // Use getTableColumns to get all columns and select them\n // This is equivalent to select(getTableColumns(occurrence))\n // Use ExtractColumnsFromOcc to preserve the properly-typed column types\n const allColumns = getTableColumns(\n this.occurrence as any,\n ) as ExtractColumnsFromOcc<Occ>;\n const selectedBuilder = builder.select(allColumns);\n // Propagate navigation context if present\n if (\n this.isNavigateFromEntitySet &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n (selectedBuilder as any).navigation = {\n relation: this.navigateRelation,\n sourceTableName: this.navigateSourceTableName,\n basePath: this.navigateBasePath,\n };\n }\n return selectedBuilder as any;\n } else if (\n typeof defaultSelectValue === \"object\" &&\n defaultSelectValue !== null &&\n !Array.isArray(defaultSelectValue)\n ) {\n // defaultSelectValue is a select object (Record<string, Column>)\n // Use it directly with select()\n // Use ExtractColumnsFromOcc to preserve the properly-typed column types\n const selectedBuilder = builder.select(\n defaultSelectValue as ExtractColumnsFromOcc<Occ>,\n );\n // Propagate navigation context if present\n if (\n this.isNavigateFromEntitySet &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n (selectedBuilder as any).navigation = {\n relation: this.navigateRelation,\n sourceTableName: this.navigateSourceTableName,\n basePath: this.navigateBasePath,\n };\n }\n return selectedBuilder as any;\n }\n // If defaultSelect is \"all\", no changes needed (current behavior)\n }\n\n // Propagate navigation context if present\n if (\n this.isNavigateFromEntitySet &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n (builder as any).navigation = {\n relation: this.navigateRelation,\n sourceTableName: this.navigateSourceTableName,\n basePath: this.navigateBasePath,\n };\n }\n return builder as any;\n }\n\n // Overload: when returnFullRecord is false\n insert(\n data: InsertDataFromFMTable<Occ>,\n options: { returnFullRecord: false },\n ): InsertBuilder<Occ, \"minimal\">;\n\n // Overload: when returnFullRecord is true or omitted (default)\n insert(\n data: InsertDataFromFMTable<Occ>,\n options?: { returnFullRecord?: true },\n ): InsertBuilder<Occ, \"representation\">;\n\n // Implementation\n insert(\n data: InsertDataFromFMTable<Occ>,\n options?: { returnFullRecord?: boolean },\n ): InsertBuilder<Occ, \"minimal\" | \"representation\"> {\n const returnPreference =\n options?.returnFullRecord === false ? \"minimal\" : \"representation\";\n\n return new InsertBuilder<Occ, typeof returnPreference>({\n occurrence: this.occurrence,\n databaseName: this.databaseName,\n context: this.context,\n data: data as any, // Input type is validated/transformed at runtime\n returnPreference: returnPreference as any,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n }\n\n // Overload: when returnFullRecord is explicitly true\n update(\n data: UpdateDataFromFMTable<Occ>,\n options: { returnFullRecord: true },\n ): UpdateBuilder<Occ, \"representation\">;\n\n // Overload: when returnFullRecord is false or omitted (default)\n update(\n data: UpdateDataFromFMTable<Occ>,\n options?: { returnFullRecord?: false },\n ): UpdateBuilder<Occ, \"minimal\">;\n\n // Implementation\n update(\n data: UpdateDataFromFMTable<Occ>,\n options?: { returnFullRecord?: boolean },\n ): UpdateBuilder<Occ, \"minimal\" | \"representation\"> {\n const returnPreference =\n options?.returnFullRecord === true ? \"representation\" : \"minimal\";\n\n return new UpdateBuilder<Occ, typeof returnPreference>({\n occurrence: this.occurrence,\n databaseName: this.databaseName,\n context: this.context,\n data: data as any, // Input type is validated/transformed at runtime\n returnPreference: returnPreference as any,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n }\n\n delete(): DeleteBuilder<Occ> {\n return new DeleteBuilder<Occ>({\n occurrence: this.occurrence,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n }) as any;\n }\n\n // Implementation\n navigate<TargetTable extends FMTable<any, any>>(\n targetTable: ValidExpandTarget<Occ, TargetTable>,\n ): EntitySet<TargetTable extends FMTable<any, any> ? TargetTable : never> {\n // Check if it's an FMTable object or a string\n let relationName: string;\n\n // FMTable object - extract name and validate\n relationName = getTableName(targetTable);\n\n // Runtime validation: Check if relation name is in navigationPaths\n if (\n this.occurrence &&\n FMTableClass.Symbol.NavigationPaths in this.occurrence\n ) {\n const navigationPaths = (this.occurrence as any)[\n FMTableClass.Symbol.NavigationPaths\n ] as readonly string[];\n if (navigationPaths && !navigationPaths.includes(relationName)) {\n console.warn(\n `Cannot navigate to \"${relationName}\". Valid navigation paths: ${navigationPaths.length > 0 ? navigationPaths.join(\", \") : \"none\"}`,\n );\n }\n }\n\n // Create EntitySet with target table\n const entitySet = new EntitySet<any>({\n occurrence: targetTable,\n databaseName: this.databaseName,\n context: this.context,\n database: this.database,\n });\n // Store the navigation info in the EntitySet\n (entitySet as any).isNavigateFromEntitySet = true;\n (entitySet as any).navigateRelation = relationName;\n\n // Build the full base path for chained navigations\n if (this.isNavigateFromEntitySet && this.navigateBasePath) {\n // Already have a base path from previous navigation - extend it with current relation\n (entitySet as any).navigateBasePath =\n `${this.navigateBasePath}/${this.navigateRelation}`;\n (entitySet as any).navigateSourceTableName = this.navigateSourceTableName;\n } else if (this.isNavigateFromEntitySet && this.navigateRelation) {\n // First chained navigation - create base path from source/relation\n (entitySet as any).navigateBasePath =\n `${this.navigateSourceTableName}/${this.navigateRelation}`;\n (entitySet as any).navigateSourceTableName = this.navigateSourceTableName;\n } else {\n // Initial navigation - source is just the table name\n (entitySet as any).navigateSourceTableName = getTableName(\n this.occurrence,\n );\n }\n return entitySet;\n }\n}\n"],"names":["FMTableClass"],"mappings":";;;;;;;;;AAgDO,MAAM,UAAyC;AAAA,EAWpD,YAAY,QAKT;AAfK;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;;AAQN,SAAK,aAAa,OAAO;AACzB,SAAK,eAAe,OAAO;AAC3B,SAAK,UAAU,OAAO;AACtB,SAAK,WAAW,OAAO;AAElB,SAAA,yBACF,YAAO,aAAP,mBAAyB,kBAAiB;AAAA,EAAA;AAAA;AAAA,EAI/C,OAAO,OAAsC,QAK1B;AACjB,WAAO,IAAI,UAAe;AAAA,MACxB,YAAY,OAAO;AAAA,MACnB,cAAc,OAAO;AAAA,MACrB,SAAS,OAAO;AAAA,MAChB,UAAU,OAAO;AAAA,IAAA,CAClB;AAAA,EAAA;AAAA,EAGH,OAAO;;AACC,UAAA,UAAU,IAAI,aAAkB;AAAA,MACpC,YAAY,KAAK;AAAA,MACjB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd,sBAAsB,KAAK;AAAA,IAAA,CAC5B;AAGD,QAAI,KAAK,YAAY;AAEb,YAAA,qBAAqB,iBAAiB,KAAK,UAAU;AAC3D,YAAM,cAAe,KAAK,WAAmBA,QAAa,OAAO,MAAM;AAGvE,UAAI,aAAa;AAET,cAAA,aAAY,iBAAY,WAAW,MAAvB,mBAA0B;AAC5C,YACE,aACA,OAAO,cAAc,YACrB,WAAW,WACX;AACS,oBAAU;AAAA,QAAA;AAAA,MACrB;AAGF,UAAI,uBAAuB,UAAU;AAInC,cAAM,aAAa;AAAA,UACjB,KAAK;AAAA,QACP;AACA,eAAO,QAAQ,OAAO,UAAU,EAAE,IAAI,GAAI;AAAA,MAAA,WACjC,OAAO,uBAAuB,UAAU;AAIjD,eAAO,QACJ,OAAO,kBAAgD,EACvD,IAAI,GAAI;AAAA,MAAA;AAAA,IACb;AAKF,QACE,KAAK,2BACL,KAAK,oBACL,KAAK,yBACL;AACC,cAAgB,aAAa;AAAA,QAC5B,UAAU,KAAK;AAAA,QACf,iBAAiB,KAAK;AAAA,QACtB,UAAU,KAAK;AAAA;AAAA,MAEjB;AAAA,IAAA;AAKK,WAAA,QAAQ,IAAI,GAAI;AAAA,EAAA;AAAA,EAGzB,IACE,IAOA;;AACM,UAAA,UAAU,IAAI,cAAmB;AAAA,MACrC,YAAY,KAAK;AAAA,MACjB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd,UAAU;AAAA,MACV,sBAAsB,KAAK;AAAA,IAAA,CAC5B;AAGD,QAAI,KAAK,YAAY;AAEb,YAAA,qBAAqB,iBAAiB,KAAK,UAAU;AAC3D,YAAM,cAAe,KAAK,WAAmBA,QAAa,OAAO,MAAM;AAGvE,UAAI,aAAa;AAET,cAAA,aAAY,iBAAY,WAAW,MAAvB,mBAA0B;AAC5C,YACE,aACA,OAAO,cAAc,YACrB,WAAW,WACX;AACS,oBAAU;AAAA,QAAA;AAAA,MACrB;AAGF,UAAI,uBAAuB,UAAU;AAInC,cAAM,aAAa;AAAA,UACjB,KAAK;AAAA,QACP;AACM,cAAA,kBAAkB,QAAQ,OAAO,UAAU;AAEjD,YACE,KAAK,2BACL,KAAK,oBACL,KAAK,yBACL;AACC,0BAAwB,aAAa;AAAA,YACpC,UAAU,KAAK;AAAA,YACf,iBAAiB,KAAK;AAAA,YACtB,UAAU,KAAK;AAAA,UACjB;AAAA,QAAA;AAEK,eAAA;AAAA,MAAA,WAEP,OAAO,uBAAuB,YAC9B,uBAAuB,QACvB,CAAC,MAAM,QAAQ,kBAAkB,GACjC;AAIA,cAAM,kBAAkB,QAAQ;AAAA,UAC9B;AAAA,QACF;AAEA,YACE,KAAK,2BACL,KAAK,oBACL,KAAK,yBACL;AACC,0BAAwB,aAAa;AAAA,YACpC,UAAU,KAAK;AAAA,YACf,iBAAiB,KAAK;AAAA,YACtB,UAAU,KAAK;AAAA,UACjB;AAAA,QAAA;AAEK,eAAA;AAAA,MAAA;AAAA,IACT;AAKF,QACE,KAAK,2BACL,KAAK,oBACL,KAAK,yBACL;AACC,cAAgB,aAAa;AAAA,QAC5B,UAAU,KAAK;AAAA,QACf,iBAAiB,KAAK;AAAA,QACtB,UAAU,KAAK;AAAA,MACjB;AAAA,IAAA;AAEK,WAAA;AAAA,EAAA;AAAA;AAAA,EAgBT,OACE,MACA,SACkD;AAClD,UAAM,oBACJ,mCAAS,sBAAqB,QAAQ,YAAY;AAEpD,WAAO,IAAI,cAA4C;AAAA,MACrD,YAAY,KAAK;AAAA,MACjB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd;AAAA;AAAA,MACA;AAAA,MACA,sBAAsB,KAAK;AAAA,IAAA,CAC5B;AAAA,EAAA;AAAA;AAAA,EAgBH,OACE,MACA,SACkD;AAClD,UAAM,oBACJ,mCAAS,sBAAqB,OAAO,mBAAmB;AAE1D,WAAO,IAAI,cAA4C;AAAA,MACrD,YAAY,KAAK;AAAA,MACjB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd;AAAA;AAAA,MACA;AAAA,MACA,sBAAsB,KAAK;AAAA,IAAA,CAC5B;AAAA,EAAA;AAAA,EAGH,SAA6B;AAC3B,WAAO,IAAI,cAAmB;AAAA,MAC5B,YAAY,KAAK;AAAA,MACjB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd,sBAAsB,KAAK;AAAA,IAAA,CAC5B;AAAA,EAAA;AAAA;AAAA,EAIH,SACE,aACwE;AAEpE,QAAA;AAGJ,mBAAe,aAAa,WAAW;AAGvC,QACE,KAAK,cACLA,QAAa,OAAO,mBAAmB,KAAK,YAC5C;AACA,YAAM,kBAAmB,KAAK,WAC5BA,QAAa,OAAO,eACtB;AACA,UAAI,mBAAmB,CAAC,gBAAgB,SAAS,YAAY,GAAG;AACtD,gBAAA;AAAA,UACN,uBAAuB,YAAY,8BAA8B,gBAAgB,SAAS,IAAI,gBAAgB,KAAK,IAAI,IAAI,MAAM;AAAA,QACnI;AAAA,MAAA;AAAA,IACF;AAII,UAAA,YAAY,IAAI,UAAe;AAAA,MACnC,YAAY;AAAA,MACZ,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,IAAA,CAChB;AAEA,cAAkB,0BAA0B;AAC5C,cAAkB,mBAAmB;AAGlC,QAAA,KAAK,2BAA2B,KAAK,kBAAkB;AAExD,gBAAkB,mBACjB,GAAG,KAAK,gBAAgB,IAAI,KAAK,gBAAgB;AAClD,gBAAkB,0BAA0B,KAAK;AAAA,IACzC,WAAA,KAAK,2BAA2B,KAAK,kBAAkB;AAE/D,gBAAkB,mBACjB,GAAG,KAAK,uBAAuB,IAAI,KAAK,gBAAgB;AACzD,gBAAkB,0BAA0B,KAAK;AAAA,IAAA,OAC7C;AAEJ,gBAAkB,0BAA0B;AAAA,QAC3C,KAAK;AAAA,MACP;AAAA,IAAA;AAEK,WAAA;AAAA,EAAA;AAEX;"}
@@ -0,0 +1,12 @@
1
+ import { FMODataErrorType } from '../errors.js';
2
+ /**
3
+ * Parses an error response and returns an appropriate error object.
4
+ * This helper is used by builder processResponse methods to handle error responses
5
+ * consistently, particularly important for batch operations where errors need to be
6
+ * properly parsed from the response body.
7
+ *
8
+ * @param response - The Response object (may be from batch or direct request)
9
+ * @param url - The URL that was requested (for error context)
10
+ * @returns An appropriate error object (ODataError, SchemaLockedError, or HTTPError)
11
+ */
12
+ export declare function parseErrorResponse(response: Response, url: string): Promise<FMODataErrorType>;
@@ -0,0 +1,30 @@
1
+ import { SchemaLockedError, ODataError, HTTPError } from "../errors.js";
2
+ import { safeJsonParse } from "./sanitize-json.js";
3
+ async function parseErrorResponse(response, url) {
4
+ var _a;
5
+ let errorBody;
6
+ try {
7
+ if ((_a = response.headers.get("content-type")) == null ? void 0 : _a.includes("application/json")) {
8
+ errorBody = await safeJsonParse(response);
9
+ }
10
+ } catch {
11
+ }
12
+ if (errorBody == null ? void 0 : errorBody.error) {
13
+ const errorCode = errorBody.error.code;
14
+ const errorMessage = errorBody.error.message || response.statusText;
15
+ if (errorCode === "303" || errorCode === 303) {
16
+ return new SchemaLockedError(url, errorMessage, errorBody.error);
17
+ }
18
+ return new ODataError(
19
+ url,
20
+ errorMessage,
21
+ String(errorCode),
22
+ errorBody.error
23
+ );
24
+ }
25
+ return new HTTPError(url, response.status, response.statusText, errorBody);
26
+ }
27
+ export {
28
+ parseErrorResponse
29
+ };
30
+ //# sourceMappingURL=error-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-parser.js","sources":["../../../src/client/error-parser.ts"],"sourcesContent":["import {\n HTTPError,\n ODataError,\n SchemaLockedError,\n FMODataErrorType,\n} from \"../errors\";\nimport { safeJsonParse } from \"./sanitize-json\";\n\n/**\n * Parses an error response and returns an appropriate error object.\n * This helper is used by builder processResponse methods to handle error responses\n * consistently, particularly important for batch operations where errors need to be\n * properly parsed from the response body.\n *\n * @param response - The Response object (may be from batch or direct request)\n * @param url - The URL that was requested (for error context)\n * @returns An appropriate error object (ODataError, SchemaLockedError, or HTTPError)\n */\nexport async function parseErrorResponse(\n response: Response,\n url: string,\n): Promise<FMODataErrorType> {\n // Try to parse error body if it's JSON\n let errorBody: { error?: { code?: string | number; message?: string } } | undefined;\n \n try {\n if (response.headers.get(\"content-type\")?.includes(\"application/json\")) {\n errorBody = await safeJsonParse<typeof errorBody>(response);\n }\n } catch {\n // Ignore JSON parse errors - we'll fall back to HTTPError\n }\n\n // Check if it's an OData error response\n if (errorBody?.error) {\n const errorCode = errorBody.error.code;\n const errorMessage = errorBody.error.message || response.statusText;\n\n // Check for schema locked error (code 303)\n if (errorCode === \"303\" || errorCode === 303) {\n return new SchemaLockedError(url, errorMessage, errorBody.error);\n }\n\n return new ODataError(\n url,\n errorMessage,\n String(errorCode),\n errorBody.error,\n );\n }\n\n // Fall back to generic HTTPError\n return new HTTPError(url, response.status, response.statusText, errorBody);\n}\n\n\n\n\n\n"],"names":[],"mappings":";;AAkBsB,eAAA,mBACpB,UACA,KAC2B;;AAEvB,MAAA;AAEA,MAAA;AACF,SAAI,cAAS,QAAQ,IAAI,cAAc,MAAnC,mBAAsC,SAAS,qBAAqB;AAC1D,kBAAA,MAAM,cAAgC,QAAQ;AAAA,IAAA;AAAA,EAC5D,QACM;AAAA,EAAA;AAKR,MAAI,uCAAW,OAAO;AACd,UAAA,YAAY,UAAU,MAAM;AAClC,UAAM,eAAe,UAAU,MAAM,WAAW,SAAS;AAGrD,QAAA,cAAc,SAAS,cAAc,KAAK;AAC5C,aAAO,IAAI,kBAAkB,KAAK,cAAc,UAAU,KAAK;AAAA,IAAA;AAGjE,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,UAAU;AAAA,IACZ;AAAA,EAAA;AAIF,SAAO,IAAI,UAAU,KAAK,SAAS,QAAQ,SAAS,YAAY,SAAS;AAC3E;"}
@@ -1,7 +1,6 @@
1
1
  import { FFetchOptions } from '@fetchkit/ffetch';
2
2
  import { Auth, ExecutionContext, Result } from '../types.js';
3
3
  import { Database } from './database.js';
4
- import { TableOccurrence } from './table-occurrence.js';
5
4
  export declare class FMServerConnection implements ExecutionContext {
6
5
  private fetchClient;
7
6
  private serverUrl;
@@ -33,10 +32,9 @@ export declare class FMServerConnection implements ExecutionContext {
33
32
  _makeRequest<T>(url: string, options?: RequestInit & FFetchOptions & {
34
33
  useEntityIds?: boolean;
35
34
  }): Promise<Result<T>>;
36
- database<const Occurrences extends readonly TableOccurrence<any, any, any, any>[]>(name: string, config?: {
37
- occurrences?: Occurrences | undefined;
35
+ database(name: string, config?: {
38
36
  useEntityIds?: boolean;
39
- }): Database<Occurrences>;
37
+ }): Database;
40
38
  /**
41
39
  * Lists all available databases from the FileMaker OData service.
42
40
  * @returns Promise resolving to an array of database names
@@ -74,11 +74,7 @@ class FMServerConnection {
74
74
  ...restOptions,
75
75
  headers
76
76
  };
77
- const resp = url.includes("/$batch") ? await fetch(fullUrl, {
78
- method: finalOptions.method,
79
- headers: finalOptions.headers,
80
- body: finalOptions.body
81
- }) : await clientToUse(fullUrl, finalOptions);
77
+ const resp = await clientToUse(fullUrl, finalOptions);
82
78
  if (!resp.ok) {
83
79
  let errorBody;
84
80
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"filemaker-odata.js","sources":["../../../src/client/filemaker-odata.ts"],"sourcesContent":["import createClient, {\n FFetchOptions,\n TimeoutError,\n AbortError,\n NetworkError,\n RetryLimitError,\n CircuitOpenError,\n} from \"@fetchkit/ffetch\";\nimport type { Auth, ExecutionContext, Result } from \"../types\";\nimport { getAcceptHeader } from \"../types\";\nimport {\n HTTPError,\n ODataError,\n SchemaLockedError,\n ResponseParseError,\n} from \"../errors\";\nimport { Database } from \"./database\";\nimport { TableOccurrence } from \"./table-occurrence\";\nimport { safeJsonParse } from \"./sanitize-json\";\nimport { get } from \"es-toolkit/compat\";\n\nexport class FMServerConnection implements ExecutionContext {\n private fetchClient: ReturnType<typeof createClient>;\n private serverUrl: string;\n private auth: Auth;\n private useEntityIds: boolean = false;\n constructor(config: {\n serverUrl: string;\n auth: Auth;\n fetchClientOptions?: FFetchOptions;\n }) {\n this.fetchClient = createClient({\n retries: 0,\n ...config.fetchClientOptions,\n });\n // Ensure the URL uses https://, is valid, and has no trailing slash\n const url = new URL(config.serverUrl);\n if (url.protocol !== \"https:\") {\n url.protocol = \"https:\";\n }\n // Remove any trailing slash from pathname\n url.pathname = url.pathname.replace(/\\/+$/, \"\");\n this.serverUrl = url.toString().replace(/\\/+$/, \"\");\n this.auth = config.auth;\n }\n\n /**\n * @internal\n * Sets whether to use FileMaker entity IDs (FMFID/FMTID) in requests\n */\n _setUseEntityIds(useEntityIds: boolean): void {\n this.useEntityIds = useEntityIds;\n }\n\n /**\n * @internal\n * Gets whether to use FileMaker entity IDs (FMFID/FMTID) in requests\n */\n _getUseEntityIds(): boolean {\n return this.useEntityIds;\n }\n\n /**\n * @internal\n * Gets the base URL for OData requests\n */\n _getBaseUrl(): string {\n return `${this.serverUrl}${\"apiKey\" in this.auth ? `/otto` : \"\"}/fmi/odata/v4`;\n }\n\n /**\n * @internal\n */\n async _makeRequest<T>(\n url: string,\n options?: RequestInit & FFetchOptions & { useEntityIds?: boolean },\n ): Promise<Result<T>> {\n const baseUrl = `${this.serverUrl}${\"apiKey\" in this.auth ? `/otto` : \"\"}/fmi/odata/v4`;\n const fullUrl = baseUrl + url;\n\n // Use per-request override if provided, otherwise use the database-level setting\n const useEntityIds = options?.useEntityIds ?? this.useEntityIds;\n\n // Get includeODataAnnotations from options (it's passed through from execute options)\n const includeODataAnnotations = (options as any)?.includeODataAnnotations;\n\n const headers = {\n Authorization:\n \"apiKey\" in this.auth\n ? `Bearer ${this.auth.apiKey}`\n : `Basic ${btoa(`${this.auth.username}:${this.auth.password}`)}`,\n \"Content-Type\": \"application/json\",\n Accept: getAcceptHeader(includeODataAnnotations),\n ...(useEntityIds ? { Prefer: \"fmodata.entity-ids\" } : {}),\n ...(options?.headers || {}),\n };\n\n // TEMPORARY WORKAROUND: Hopefully this feature will be fixed in the ffetch library\n // Extract fetchHandler and headers separately, only for tests where we're overriding the fetch handler per-request\n const fetchHandler = options?.fetchHandler;\n const {\n headers: _headers,\n fetchHandler: _fetchHandler,\n ...restOptions\n } = options || {};\n\n // If fetchHandler is provided, create a temporary client with it\n // Otherwise use the existing client\n const clientToUse = fetchHandler\n ? createClient({ retries: 0, fetchHandler })\n : this.fetchClient;\n\n try {\n const finalOptions = {\n ...restOptions,\n headers,\n };\n\n // For batch requests, use native fetch to avoid any potential serialization issues with ffetch\n const resp = url.includes(\"/$batch\")\n ? await fetch(fullUrl, {\n method: finalOptions.method,\n headers: finalOptions.headers,\n body: finalOptions.body,\n })\n : await clientToUse(fullUrl, finalOptions);\n\n // Handle HTTP errors\n if (!resp.ok) {\n // Try to parse error body if it's JSON\n let errorBody:\n | { error?: { code?: string | number; message?: string } }\n | undefined;\n try {\n if (resp.headers.get(\"content-type\")?.includes(\"application/json\")) {\n errorBody = await safeJsonParse<typeof errorBody>(resp);\n }\n } catch {\n // Ignore JSON parse errors\n }\n\n // Check if it's an OData error response\n if (errorBody?.error) {\n const errorCode = errorBody.error.code;\n const errorMessage = errorBody.error.message || resp.statusText;\n\n // Check for schema locked error (code 303)\n if (errorCode === \"303\" || errorCode === 303) {\n return {\n data: undefined,\n error: new SchemaLockedError(\n fullUrl,\n errorMessage,\n errorBody.error,\n ),\n };\n }\n\n return {\n data: undefined,\n error: new ODataError(\n fullUrl,\n errorMessage,\n String(errorCode),\n errorBody.error,\n ),\n };\n }\n\n return {\n data: undefined,\n error: new HTTPError(\n fullUrl,\n resp.status,\n resp.statusText,\n errorBody,\n ),\n };\n }\n\n // Check for affected rows header (for DELETE and bulk PATCH operations)\n // FileMaker may return this with 204 No Content or 200 OK\n const affectedRows = resp.headers.get(\"fmodata.affected_rows\");\n if (affectedRows !== null) {\n return { data: parseInt(affectedRows, 10) as T, error: undefined };\n }\n\n // Handle 204 No Content with no body\n if (resp.status === 204) {\n // Check for Location header (used for insert with return=minimal)\n // Use optional chaining for safety with mocks that might not have proper headers\n const locationHeader =\n resp.headers?.get?.(\"Location\") || resp.headers?.get?.(\"location\");\n if (locationHeader) {\n // Return the location header so InsertBuilder can extract ROWID\n return { data: { _location: locationHeader } as T, error: undefined };\n }\n return { data: 0 as T, error: undefined };\n }\n\n // Parse response\n if (resp.headers.get(\"content-type\")?.includes(\"application/json\")) {\n const data = await safeJsonParse<\n T & { error?: { code?: string | number; message?: string } }\n >(resp);\n\n // Check for embedded OData errors\n if (get(data, \"error\", null)) {\n const errorCode = get(data, \"error.code\", null);\n const errorMessage = get(\n data,\n \"error.message\",\n \"Unknown OData error\",\n );\n\n // Check for schema locked error (code 303)\n if (errorCode === \"303\" || errorCode === 303) {\n return {\n data: undefined,\n error: new SchemaLockedError(fullUrl, errorMessage, data.error),\n };\n }\n\n return {\n data: undefined,\n error: new ODataError(\n fullUrl,\n errorMessage,\n String(errorCode),\n data.error,\n ),\n };\n }\n\n return { data: data as T, error: undefined };\n }\n\n return { data: (await resp.text()) as T, error: undefined };\n } catch (err) {\n // Map ffetch errors - return them directly (no re-wrapping)\n if (\n err instanceof TimeoutError ||\n err instanceof AbortError ||\n err instanceof NetworkError ||\n err instanceof RetryLimitError ||\n err instanceof CircuitOpenError\n ) {\n return { data: undefined, error: err };\n }\n\n // Handle JSON parse errors (ResponseParseError from safeJsonParse)\n if (err instanceof ResponseParseError) {\n return { data: undefined, error: err };\n }\n\n // Unknown error - wrap it as NetworkError\n return {\n data: undefined,\n error: new NetworkError(fullUrl, err),\n };\n }\n }\n\n database<\n const Occurrences extends readonly TableOccurrence<any, any, any, any>[],\n >(\n name: string,\n config?: {\n occurrences?: Occurrences | undefined;\n useEntityIds?: boolean;\n },\n ): Database<Occurrences> {\n return new Database(name, this, config);\n }\n\n /**\n * Lists all available databases from the FileMaker OData service.\n * @returns Promise resolving to an array of database names\n */\n async listDatabaseNames(): Promise<string[]> {\n const result = await this._makeRequest<{\n value?: Array<{ name: string }>;\n }>(\"/\");\n if (result.error) {\n throw result.error;\n }\n if (result.data.value && Array.isArray(result.data.value)) {\n return result.data.value.map((item) => item.name);\n }\n return [];\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"filemaker-odata.js","sources":["../../../src/client/filemaker-odata.ts"],"sourcesContent":["import createClient, {\n FFetchOptions,\n TimeoutError,\n AbortError,\n NetworkError,\n RetryLimitError,\n CircuitOpenError,\n} from \"@fetchkit/ffetch\";\nimport type { Auth, ExecutionContext, Result } from \"../types\";\nimport { getAcceptHeader } from \"../types\";\nimport {\n HTTPError,\n ODataError,\n SchemaLockedError,\n ResponseParseError,\n} from \"../errors\";\nimport { Database } from \"./database\";\nimport { safeJsonParse } from \"./sanitize-json\";\nimport { get } from \"es-toolkit/compat\";\n\nexport class FMServerConnection implements ExecutionContext {\n private fetchClient: ReturnType<typeof createClient>;\n private serverUrl: string;\n private auth: Auth;\n private useEntityIds: boolean = false;\n constructor(config: {\n serverUrl: string;\n auth: Auth;\n fetchClientOptions?: FFetchOptions;\n }) {\n this.fetchClient = createClient({\n retries: 0,\n ...config.fetchClientOptions,\n });\n // Ensure the URL uses https://, is valid, and has no trailing slash\n const url = new URL(config.serverUrl);\n if (url.protocol !== \"https:\") {\n url.protocol = \"https:\";\n }\n // Remove any trailing slash from pathname\n url.pathname = url.pathname.replace(/\\/+$/, \"\");\n this.serverUrl = url.toString().replace(/\\/+$/, \"\");\n this.auth = config.auth;\n }\n\n /**\n * @internal\n * Sets whether to use FileMaker entity IDs (FMFID/FMTID) in requests\n */\n _setUseEntityIds(useEntityIds: boolean): void {\n this.useEntityIds = useEntityIds;\n }\n\n /**\n * @internal\n * Gets whether to use FileMaker entity IDs (FMFID/FMTID) in requests\n */\n _getUseEntityIds(): boolean {\n return this.useEntityIds;\n }\n\n /**\n * @internal\n * Gets the base URL for OData requests\n */\n _getBaseUrl(): string {\n return `${this.serverUrl}${\"apiKey\" in this.auth ? `/otto` : \"\"}/fmi/odata/v4`;\n }\n\n /**\n * @internal\n */\n async _makeRequest<T>(\n url: string,\n options?: RequestInit & FFetchOptions & { useEntityIds?: boolean },\n ): Promise<Result<T>> {\n const baseUrl = `${this.serverUrl}${\"apiKey\" in this.auth ? `/otto` : \"\"}/fmi/odata/v4`;\n const fullUrl = baseUrl + url;\n\n // Use per-request override if provided, otherwise use the database-level setting\n const useEntityIds = options?.useEntityIds ?? this.useEntityIds;\n\n // Get includeODataAnnotations from options (it's passed through from execute options)\n const includeODataAnnotations = (options as any)?.includeODataAnnotations;\n\n const headers = {\n Authorization:\n \"apiKey\" in this.auth\n ? `Bearer ${this.auth.apiKey}`\n : `Basic ${btoa(`${this.auth.username}:${this.auth.password}`)}`,\n \"Content-Type\": \"application/json\",\n Accept: getAcceptHeader(includeODataAnnotations),\n ...(useEntityIds ? { Prefer: \"fmodata.entity-ids\" } : {}),\n ...(options?.headers || {}),\n };\n\n // TEMPORARY WORKAROUND: Hopefully this feature will be fixed in the ffetch library\n // Extract fetchHandler and headers separately, only for tests where we're overriding the fetch handler per-request\n const fetchHandler = options?.fetchHandler;\n const {\n headers: _headers,\n fetchHandler: _fetchHandler,\n ...restOptions\n } = options || {};\n\n // If fetchHandler is provided, create a temporary client with it\n // Otherwise use the existing client\n const clientToUse = fetchHandler\n ? createClient({ retries: 0, fetchHandler })\n : this.fetchClient;\n\n try {\n const finalOptions = {\n ...restOptions,\n headers,\n };\n\n const resp = await clientToUse(fullUrl, finalOptions);\n\n // Handle HTTP errors\n if (!resp.ok) {\n // Try to parse error body if it's JSON\n let errorBody:\n | { error?: { code?: string | number; message?: string } }\n | undefined;\n try {\n if (resp.headers.get(\"content-type\")?.includes(\"application/json\")) {\n errorBody = await safeJsonParse<typeof errorBody>(resp);\n }\n } catch {\n // Ignore JSON parse errors\n }\n\n // Check if it's an OData error response\n if (errorBody?.error) {\n const errorCode = errorBody.error.code;\n const errorMessage = errorBody.error.message || resp.statusText;\n\n // Check for schema locked error (code 303)\n if (errorCode === \"303\" || errorCode === 303) {\n return {\n data: undefined,\n error: new SchemaLockedError(\n fullUrl,\n errorMessage,\n errorBody.error,\n ),\n };\n }\n\n return {\n data: undefined,\n error: new ODataError(\n fullUrl,\n errorMessage,\n String(errorCode),\n errorBody.error,\n ),\n };\n }\n\n return {\n data: undefined,\n error: new HTTPError(\n fullUrl,\n resp.status,\n resp.statusText,\n errorBody,\n ),\n };\n }\n\n // Check for affected rows header (for DELETE and bulk PATCH operations)\n // FileMaker may return this with 204 No Content or 200 OK\n const affectedRows = resp.headers.get(\"fmodata.affected_rows\");\n if (affectedRows !== null) {\n return { data: parseInt(affectedRows, 10) as T, error: undefined };\n }\n\n // Handle 204 No Content with no body\n if (resp.status === 204) {\n // Check for Location header (used for insert with return=minimal)\n // Use optional chaining for safety with mocks that might not have proper headers\n const locationHeader =\n resp.headers?.get?.(\"Location\") || resp.headers?.get?.(\"location\");\n if (locationHeader) {\n // Return the location header so InsertBuilder can extract ROWID\n return { data: { _location: locationHeader } as T, error: undefined };\n }\n return { data: 0 as T, error: undefined };\n }\n\n // Parse response\n if (resp.headers.get(\"content-type\")?.includes(\"application/json\")) {\n const data = await safeJsonParse<\n T & { error?: { code?: string | number; message?: string } }\n >(resp);\n\n // Check for embedded OData errors\n if (get(data, \"error\", null)) {\n const errorCode = get(data, \"error.code\", null);\n const errorMessage = get(\n data,\n \"error.message\",\n \"Unknown OData error\",\n );\n\n // Check for schema locked error (code 303)\n if (errorCode === \"303\" || errorCode === 303) {\n return {\n data: undefined,\n error: new SchemaLockedError(fullUrl, errorMessage, data.error),\n };\n }\n\n return {\n data: undefined,\n error: new ODataError(\n fullUrl,\n errorMessage,\n String(errorCode),\n data.error,\n ),\n };\n }\n\n return { data: data as T, error: undefined };\n }\n\n return { data: (await resp.text()) as T, error: undefined };\n } catch (err) {\n // Map ffetch errors - return them directly (no re-wrapping)\n if (\n err instanceof TimeoutError ||\n err instanceof AbortError ||\n err instanceof NetworkError ||\n err instanceof RetryLimitError ||\n err instanceof CircuitOpenError\n ) {\n return { data: undefined, error: err };\n }\n\n // Handle JSON parse errors (ResponseParseError from safeJsonParse)\n if (err instanceof ResponseParseError) {\n return { data: undefined, error: err };\n }\n\n // Unknown error - wrap it as NetworkError\n return {\n data: undefined,\n error: new NetworkError(fullUrl, err),\n };\n }\n }\n\n database(\n name: string,\n config?: {\n useEntityIds?: boolean;\n },\n ): Database {\n return new Database(name, this, config);\n }\n\n /**\n * Lists all available databases from the FileMaker OData service.\n * @returns Promise resolving to an array of database names\n */\n async listDatabaseNames(): Promise<string[]> {\n const result = await this._makeRequest<{\n value?: Array<{ name: string }>;\n }>(\"/\");\n if (result.error) {\n throw result.error;\n }\n if (result.data.value && Array.isArray(result.data.value)) {\n return result.data.value.map((item) => item.name);\n }\n return [];\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,14 +1,13 @@
1
1
  import { ExecutionContext, ExecutableBuilder, Result, ExecuteOptions, ConditionallyWithODataAnnotations } from '../types.js';
2
- import { TableOccurrence } from './table-occurrence.js';
2
+ import { FMTable, InferSchemaOutputFromFMTable } from '../orm/table.js';
3
3
  import { FFetchOptions } from '@fetchkit/ffetch';
4
4
  export type InsertOptions = {
5
5
  return?: "minimal" | "representation";
6
6
  };
7
- export declare class InsertBuilder<T extends Record<string, any>, Occ extends TableOccurrence<any, any, any, any> | undefined = undefined, ReturnPreference extends "minimal" | "representation" = "representation"> implements ExecutableBuilder<ReturnPreference extends "minimal" ? {
7
+ export declare class InsertBuilder<Occ extends FMTable<any, any> | undefined = undefined, ReturnPreference extends "minimal" | "representation" = "representation"> implements ExecutableBuilder<ReturnPreference extends "minimal" ? {
8
8
  ROWID: number;
9
- } : T> {
10
- private occurrence?;
11
- private tableName;
9
+ } : InferSchemaOutputFromFMTable<NonNullable<Occ>>> {
10
+ private table?;
12
11
  private databaseName;
13
12
  private context;
14
13
  private data;
@@ -16,10 +15,9 @@ export declare class InsertBuilder<T extends Record<string, any>, Occ extends Ta
16
15
  private databaseUseEntityIds;
17
16
  constructor(config: {
18
17
  occurrence?: Occ;
19
- tableName: string;
20
18
  databaseName: string;
21
19
  context: ExecutionContext;
22
- data: Partial<T>;
20
+ data: Partial<InferSchemaOutputFromFMTable<NonNullable<Occ>>>;
23
21
  returnPreference?: ReturnPreference;
24
22
  databaseUseEntityIds?: boolean;
25
23
  });
@@ -41,7 +39,7 @@ export declare class InsertBuilder<T extends Record<string, any>, Occ extends Ta
41
39
  private getTableId;
42
40
  execute<EO extends ExecuteOptions>(options?: RequestInit & FFetchOptions & EO): Promise<Result<ReturnPreference extends "minimal" ? {
43
41
  ROWID: number;
44
- } : ConditionallyWithODataAnnotations<T, EO["includeODataAnnotations"] extends true ? true : false>>>;
42
+ } : ConditionallyWithODataAnnotations<InferSchemaOutputFromFMTable<NonNullable<Occ>>, EO["includeODataAnnotations"] extends true ? true : false>>>;
45
43
  getRequestConfig(): {
46
44
  method: string;
47
45
  url: string;
@@ -50,5 +48,5 @@ export declare class InsertBuilder<T extends Record<string, any>, Occ extends Ta
50
48
  toRequest(baseUrl: string, options?: ExecuteOptions): Request;
51
49
  processResponse(response: Response, options?: ExecuteOptions): Promise<Result<ReturnPreference extends "minimal" ? {
52
50
  ROWID: number;
53
- } : T>>;
51
+ } : InferSchemaOutputFromFMTable<NonNullable<Occ>>>>;
54
52
  }