@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.
- package/README.md +489 -334
- package/dist/esm/client/batch-builder.d.ts +7 -4
- package/dist/esm/client/batch-builder.js +84 -25
- package/dist/esm/client/batch-builder.js.map +1 -1
- package/dist/esm/client/builders/default-select.d.ts +7 -0
- package/dist/esm/client/builders/default-select.js +42 -0
- package/dist/esm/client/builders/default-select.js.map +1 -0
- package/dist/esm/client/builders/expand-builder.d.ts +43 -0
- package/dist/esm/client/builders/expand-builder.js +173 -0
- package/dist/esm/client/builders/expand-builder.js.map +1 -0
- package/dist/esm/client/builders/index.d.ts +8 -0
- package/dist/esm/client/builders/query-string-builder.d.ts +15 -0
- package/dist/esm/client/builders/query-string-builder.js +25 -0
- package/dist/esm/client/builders/query-string-builder.js.map +1 -0
- package/dist/esm/client/builders/response-processor.d.ts +39 -0
- package/dist/esm/client/builders/response-processor.js +170 -0
- package/dist/esm/client/builders/response-processor.js.map +1 -0
- package/dist/esm/client/builders/select-mixin.d.ts +31 -0
- package/dist/esm/client/builders/select-mixin.js +30 -0
- package/dist/esm/client/builders/select-mixin.js.map +1 -0
- package/dist/esm/client/builders/select-utils.d.ts +8 -0
- package/dist/esm/client/builders/select-utils.js +15 -0
- package/dist/esm/client/builders/select-utils.js.map +1 -0
- package/dist/esm/client/builders/shared-types.d.ts +39 -0
- package/dist/esm/client/builders/table-utils.d.ts +35 -0
- package/dist/esm/client/builders/table-utils.js +45 -0
- package/dist/esm/client/builders/table-utils.js.map +1 -0
- package/dist/esm/client/database.d.ts +3 -22
- package/dist/esm/client/database.js +14 -76
- package/dist/esm/client/database.js.map +1 -1
- package/dist/esm/client/delete-builder.d.ts +11 -15
- package/dist/esm/client/delete-builder.js +26 -26
- package/dist/esm/client/delete-builder.js.map +1 -1
- package/dist/esm/client/entity-set.d.ts +32 -32
- package/dist/esm/client/entity-set.js +92 -69
- package/dist/esm/client/entity-set.js.map +1 -1
- package/dist/esm/client/error-parser.d.ts +12 -0
- package/dist/esm/client/error-parser.js +30 -0
- package/dist/esm/client/error-parser.js.map +1 -0
- package/dist/esm/client/filemaker-odata.d.ts +2 -4
- package/dist/esm/client/filemaker-odata.js +1 -5
- package/dist/esm/client/filemaker-odata.js.map +1 -1
- package/dist/esm/client/insert-builder.d.ts +7 -9
- package/dist/esm/client/insert-builder.js +70 -24
- package/dist/esm/client/insert-builder.js.map +1 -1
- package/dist/esm/client/query/expand-builder.d.ts +35 -0
- package/dist/esm/client/query/index.d.ts +3 -0
- package/dist/esm/client/query/query-builder.d.ts +134 -0
- package/dist/esm/client/query/query-builder.js +505 -0
- package/dist/esm/client/query/query-builder.js.map +1 -0
- package/dist/esm/client/query/response-processor.d.ts +22 -0
- package/dist/esm/client/query/types.d.ts +52 -0
- package/dist/esm/client/query/url-builder.d.ts +71 -0
- package/dist/esm/client/query/url-builder.js +107 -0
- package/dist/esm/client/query/url-builder.js.map +1 -0
- package/dist/esm/client/query-builder.d.ts +1 -111
- package/dist/esm/client/record-builder.d.ts +56 -63
- package/dist/esm/client/record-builder.js +158 -296
- package/dist/esm/client/record-builder.js.map +1 -1
- package/dist/esm/client/response-processor.d.ts +3 -3
- package/dist/esm/client/update-builder.d.ts +16 -21
- package/dist/esm/client/update-builder.js +56 -30
- package/dist/esm/client/update-builder.js.map +1 -1
- package/dist/esm/errors.d.ts +8 -1
- package/dist/esm/errors.js +17 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +3 -7
- package/dist/esm/index.js +37 -8
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/orm/column.d.ts +45 -0
- package/dist/esm/orm/column.js +59 -0
- package/dist/esm/orm/column.js.map +1 -0
- package/dist/esm/orm/field-builders.d.ts +154 -0
- package/dist/esm/orm/field-builders.js +152 -0
- package/dist/esm/orm/field-builders.js.map +1 -0
- package/dist/esm/orm/index.d.ts +4 -0
- package/dist/esm/orm/operators.d.ts +175 -0
- package/dist/esm/orm/operators.js +221 -0
- package/dist/esm/orm/operators.js.map +1 -0
- package/dist/esm/orm/table.d.ts +341 -0
- package/dist/esm/orm/table.js +211 -0
- package/dist/esm/orm/table.js.map +1 -0
- package/dist/esm/transform.d.ts +20 -21
- package/dist/esm/transform.js +34 -34
- package/dist/esm/transform.js.map +1 -1
- package/dist/esm/types.d.ts +16 -13
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/validation.d.ts +14 -4
- package/dist/esm/validation.js +45 -1
- package/dist/esm/validation.js.map +1 -1
- package/package.json +5 -2
- package/src/client/batch-builder.ts +100 -32
- package/src/client/builders/default-select.ts +69 -0
- package/src/client/builders/expand-builder.ts +236 -0
- package/src/client/builders/index.ts +11 -0
- package/src/client/builders/query-string-builder.ts +41 -0
- package/src/client/builders/response-processor.ts +273 -0
- package/src/client/builders/select-mixin.ts +74 -0
- package/src/client/builders/select-utils.ts +34 -0
- package/src/client/builders/shared-types.ts +41 -0
- package/src/client/builders/table-utils.ts +87 -0
- package/src/client/database.ts +19 -160
- package/src/client/delete-builder.ts +46 -51
- package/src/client/entity-set.ts +227 -302
- package/src/client/error-parser.ts +59 -0
- package/src/client/filemaker-odata.ts +3 -14
- package/src/client/insert-builder.ts +124 -43
- package/src/client/query/expand-builder.ts +164 -0
- package/src/client/query/index.ts +13 -0
- package/src/client/query/query-builder.ts +816 -0
- package/src/client/query/response-processor.ts +244 -0
- package/src/client/query/types.ts +102 -0
- package/src/client/query/url-builder.ts +179 -0
- package/src/client/query-builder.ts +8 -1447
- package/src/client/record-builder.ts +325 -583
- package/src/client/response-processor.ts +4 -5
- package/src/client/update-builder.ts +102 -73
- package/src/errors.ts +22 -1
- package/src/index.ts +55 -5
- package/src/orm/column.ts +78 -0
- package/src/orm/field-builders.ts +296 -0
- package/src/orm/index.ts +60 -0
- package/src/orm/operators.ts +428 -0
- package/src/orm/table.ts +759 -0
- package/src/transform.ts +62 -48
- package/src/types.ts +20 -63
- package/src/validation.ts +76 -4
- package/dist/esm/client/base-table.d.ts +0 -128
- package/dist/esm/client/base-table.js +0 -57
- package/dist/esm/client/base-table.js.map +0 -1
- package/dist/esm/client/build-occurrences.d.ts +0 -74
- package/dist/esm/client/build-occurrences.js +0 -31
- package/dist/esm/client/build-occurrences.js.map +0 -1
- package/dist/esm/client/query-builder.js +0 -897
- package/dist/esm/client/query-builder.js.map +0 -1
- package/dist/esm/client/table-occurrence.d.ts +0 -86
- package/dist/esm/client/table-occurrence.js +0 -58
- package/dist/esm/client/table-occurrence.js.map +0 -1
- package/src/client/base-table.ts +0 -178
- package/src/client/build-occurrences.ts +0 -155
- package/src/client/query-builder.ts.bak +0 -1457
- package/src/client/table-occurrence.ts +0 -156
|
@@ -1,16 +1,18 @@
|
|
|
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 {
|
|
5
|
-
import { getTableIdentifiers, transformTableName, transformFieldNamesArray, transformResponseFields } from "../transform.js";
|
|
4
|
+
import { getTableName, getNavigationPaths } from "../orm/table.js";
|
|
6
5
|
import { safeJsonParse } from "./sanitize-json.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
6
|
+
import { parseErrorResponse } from "./error-parser.js";
|
|
7
|
+
import { QueryBuilder } from "./query/query-builder.js";
|
|
8
|
+
import { mergeExecuteOptions, resolveTableId, createODataRequest } from "./builders/table-utils.js";
|
|
9
|
+
import { processSelectWithRenames } from "./builders/select-mixin.js";
|
|
10
|
+
import { ExpandBuilder } from "./builders/expand-builder.js";
|
|
11
|
+
import { processODataResponse, getSchemaFromTable } from "./builders/response-processor.js";
|
|
12
|
+
import { buildSelectExpandQueryString } from "./builders/query-string-builder.js";
|
|
10
13
|
class RecordBuilder {
|
|
11
14
|
constructor(config) {
|
|
12
|
-
__publicField(this, "
|
|
13
|
-
__publicField(this, "tableName");
|
|
15
|
+
__publicField(this, "table");
|
|
14
16
|
__publicField(this, "databaseName");
|
|
15
17
|
__publicField(this, "context");
|
|
16
18
|
__publicField(this, "recordId");
|
|
@@ -20,11 +22,12 @@ class RecordBuilder {
|
|
|
20
22
|
__publicField(this, "navigateRelation");
|
|
21
23
|
__publicField(this, "navigateSourceTableName");
|
|
22
24
|
__publicField(this, "databaseUseEntityIds");
|
|
23
|
-
//
|
|
25
|
+
// Properties for select/expand support
|
|
24
26
|
__publicField(this, "selectedFields");
|
|
25
27
|
__publicField(this, "expandConfigs", []);
|
|
26
|
-
|
|
27
|
-
this
|
|
28
|
+
// Mapping from field names to output keys (for renamed fields in select)
|
|
29
|
+
__publicField(this, "fieldMapping");
|
|
30
|
+
this.table = config.occurrence;
|
|
28
31
|
this.databaseName = config.databaseName;
|
|
29
32
|
this.context = config.context;
|
|
30
33
|
this.recordId = config.recordId;
|
|
@@ -34,306 +37,180 @@ class RecordBuilder {
|
|
|
34
37
|
* Helper to merge database-level useEntityIds with per-request options
|
|
35
38
|
*/
|
|
36
39
|
mergeExecuteOptions(options) {
|
|
37
|
-
return
|
|
38
|
-
...options,
|
|
39
|
-
useEntityIds: (options == null ? void 0 : options.useEntityIds) ?? this.databaseUseEntityIds
|
|
40
|
-
};
|
|
40
|
+
return mergeExecuteOptions(options, this.databaseUseEntityIds);
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* Gets the table ID (FMTID) if using entity IDs, otherwise returns the table name
|
|
44
44
|
* @param useEntityIds - Optional override for entity ID usage
|
|
45
45
|
*/
|
|
46
46
|
getTableId(useEntityIds) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return this.tableName;
|
|
50
|
-
}
|
|
51
|
-
const contextDefault = ((_b = (_a = this.context)._getUseEntityIds) == null ? void 0 : _b.call(_a)) ?? false;
|
|
52
|
-
const shouldUseIds = useEntityIds ?? contextDefault;
|
|
53
|
-
if (shouldUseIds) {
|
|
54
|
-
const identifiers = getTableIdentifiers(this.occurrence);
|
|
55
|
-
if (!identifiers.id) {
|
|
56
|
-
throw new Error(
|
|
57
|
-
`useEntityIds is true but TableOccurrence "${identifiers.name}" does not have an fmtId defined`
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
return identifiers.id;
|
|
47
|
+
if (!this.table) {
|
|
48
|
+
throw new Error("Table occurrence is required");
|
|
61
49
|
}
|
|
62
|
-
return
|
|
50
|
+
return resolveTableId(
|
|
51
|
+
this.table,
|
|
52
|
+
getTableName(this.table),
|
|
53
|
+
this.context,
|
|
54
|
+
useEntityIds
|
|
55
|
+
);
|
|
63
56
|
}
|
|
64
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Creates a new RecordBuilder with modified configuration.
|
|
59
|
+
* Used by select() to create new instances.
|
|
60
|
+
*/
|
|
61
|
+
cloneWithChanges(changes) {
|
|
65
62
|
const newBuilder = new RecordBuilder({
|
|
66
|
-
occurrence: this.
|
|
67
|
-
tableName: this.tableName,
|
|
63
|
+
occurrence: this.table,
|
|
68
64
|
databaseName: this.databaseName,
|
|
69
65
|
context: this.context,
|
|
70
66
|
recordId: this.recordId,
|
|
71
67
|
databaseUseEntityIds: this.databaseUseEntityIds
|
|
72
68
|
});
|
|
73
|
-
newBuilder.
|
|
74
|
-
newBuilder.
|
|
69
|
+
newBuilder.selectedFields = changes.selectedFields ?? this.selectedFields;
|
|
70
|
+
newBuilder.fieldMapping = changes.fieldMapping ?? this.fieldMapping;
|
|
71
|
+
newBuilder.expandConfigs = [...this.expandConfigs];
|
|
75
72
|
newBuilder.isNavigateFromEntitySet = this.isNavigateFromEntitySet;
|
|
76
73
|
newBuilder.navigateRelation = this.navigateRelation;
|
|
77
74
|
newBuilder.navigateSourceTableName = this.navigateSourceTableName;
|
|
78
75
|
return newBuilder;
|
|
79
76
|
}
|
|
80
|
-
|
|
81
|
-
* Select specific fields to retrieve from the record.
|
|
82
|
-
* Only the selected fields will be returned in the response.
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* ```typescript
|
|
86
|
-
* const contact = await db.from("contacts").get("uuid").select("name", "email").execute();
|
|
87
|
-
* // contact.data has type { name: string; email: string }
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
select(...fields) {
|
|
91
|
-
const uniqueFields = [...new Set(fields)];
|
|
77
|
+
getSingleField(field) {
|
|
92
78
|
const newBuilder = new RecordBuilder({
|
|
93
|
-
occurrence: this.
|
|
94
|
-
tableName: this.tableName,
|
|
79
|
+
occurrence: this.table,
|
|
95
80
|
databaseName: this.databaseName,
|
|
96
81
|
context: this.context,
|
|
97
82
|
recordId: this.recordId,
|
|
98
83
|
databaseUseEntityIds: this.databaseUseEntityIds
|
|
99
84
|
});
|
|
100
|
-
newBuilder.
|
|
101
|
-
newBuilder.
|
|
85
|
+
newBuilder.operation = "getSingleField";
|
|
86
|
+
newBuilder.operationParam = field.toString();
|
|
102
87
|
newBuilder.isNavigateFromEntitySet = this.isNavigateFromEntitySet;
|
|
103
88
|
newBuilder.navigateRelation = this.navigateRelation;
|
|
104
89
|
newBuilder.navigateSourceTableName = this.navigateSourceTableName;
|
|
105
90
|
return newBuilder;
|
|
106
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Select fields using column references.
|
|
94
|
+
* Allows renaming fields by using different keys in the object.
|
|
95
|
+
* Container fields cannot be selected and will cause a type error.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* db.from(contacts).get("uuid").select({
|
|
99
|
+
* name: contacts.name,
|
|
100
|
+
* userEmail: contacts.email // renamed!
|
|
101
|
+
* })
|
|
102
|
+
*
|
|
103
|
+
* @param fields - Object mapping output keys to column references (container fields excluded)
|
|
104
|
+
* @returns RecordBuilder with updated selected fields
|
|
105
|
+
*/
|
|
106
|
+
select(fields) {
|
|
107
|
+
const tableName = getTableName(this.table);
|
|
108
|
+
const { selectedFields, fieldMapping } = processSelectWithRenames(
|
|
109
|
+
fields,
|
|
110
|
+
tableName
|
|
111
|
+
);
|
|
112
|
+
return this.cloneWithChanges({
|
|
113
|
+
selectedFields,
|
|
114
|
+
fieldMapping: Object.keys(fieldMapping).length > 0 ? fieldMapping : void 0
|
|
115
|
+
});
|
|
116
|
+
}
|
|
107
117
|
/**
|
|
108
118
|
* Expand a navigation property to include related records.
|
|
109
119
|
* Supports nested select, filter, orderBy, and expand operations.
|
|
110
120
|
*
|
|
111
121
|
* @example
|
|
112
122
|
* ```typescript
|
|
113
|
-
* // Simple expand
|
|
114
|
-
* const contact = await db.from(
|
|
123
|
+
* // Simple expand with FMTable object
|
|
124
|
+
* const contact = await db.from(contacts).get("uuid").expand(users).execute();
|
|
115
125
|
*
|
|
116
126
|
* // Expand with select
|
|
117
|
-
* const contact = await db.from(
|
|
118
|
-
* .expand(
|
|
127
|
+
* const contact = await db.from(contacts).get("uuid")
|
|
128
|
+
* .expand(users, b => b.select({ username: users.username, email: users.email }))
|
|
119
129
|
* .execute();
|
|
120
130
|
* ```
|
|
121
131
|
*/
|
|
122
|
-
expand(
|
|
123
|
-
var _a, _b;
|
|
124
|
-
const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[relation];
|
|
125
|
-
const getDefaultSelectFields = () => {
|
|
126
|
-
var _a2;
|
|
127
|
-
if (!targetOccurrence) return void 0;
|
|
128
|
-
const defaultSelect = targetOccurrence.defaultSelect;
|
|
129
|
-
if (defaultSelect === "schema") {
|
|
130
|
-
const schema = (_a2 = targetOccurrence.baseTable) == null ? void 0 : _a2.schema;
|
|
131
|
-
if (schema) {
|
|
132
|
-
return [...new Set(Object.keys(schema))];
|
|
133
|
-
}
|
|
134
|
-
} else if (Array.isArray(defaultSelect)) {
|
|
135
|
-
return [...new Set(defaultSelect)];
|
|
136
|
-
}
|
|
137
|
-
return void 0;
|
|
138
|
-
};
|
|
132
|
+
expand(targetTable, callback) {
|
|
139
133
|
const newBuilder = new RecordBuilder({
|
|
140
|
-
occurrence: this.
|
|
141
|
-
tableName: this.tableName,
|
|
134
|
+
occurrence: this.table,
|
|
142
135
|
databaseName: this.databaseName,
|
|
143
136
|
context: this.context,
|
|
144
137
|
recordId: this.recordId,
|
|
145
138
|
databaseUseEntityIds: this.databaseUseEntityIds
|
|
146
139
|
});
|
|
147
140
|
newBuilder.selectedFields = this.selectedFields;
|
|
141
|
+
newBuilder.fieldMapping = this.fieldMapping;
|
|
148
142
|
newBuilder.expandConfigs = [...this.expandConfigs];
|
|
149
143
|
newBuilder.isNavigateFromEntitySet = this.isNavigateFromEntitySet;
|
|
150
144
|
newBuilder.navigateRelation = this.navigateRelation;
|
|
151
145
|
newBuilder.navigateSourceTableName = this.navigateSourceTableName;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
146
|
+
const expandBuilder = new ExpandBuilder(this.databaseUseEntityIds);
|
|
147
|
+
const expandConfig = expandBuilder.processExpand(
|
|
148
|
+
targetTable,
|
|
149
|
+
this.table ?? void 0,
|
|
150
|
+
callback,
|
|
151
|
+
() => new QueryBuilder({
|
|
152
|
+
occurrence: targetTable,
|
|
156
153
|
databaseName: this.databaseName,
|
|
157
154
|
context: this.context,
|
|
158
155
|
databaseUseEntityIds: this.databaseUseEntityIds
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (((_b = configuredBuilder.expandConfigs) == null ? void 0 : _b.length) > 0) {
|
|
172
|
-
const nestedExpandString = this.buildExpandString(
|
|
173
|
-
configuredBuilder.expandConfigs
|
|
156
|
+
})
|
|
157
|
+
);
|
|
158
|
+
newBuilder.expandConfigs.push(expandConfig);
|
|
159
|
+
return newBuilder;
|
|
160
|
+
}
|
|
161
|
+
navigate(targetTable) {
|
|
162
|
+
const relationName = getTableName(targetTable);
|
|
163
|
+
if (this.table) {
|
|
164
|
+
const navigationPaths = getNavigationPaths(this.table);
|
|
165
|
+
if (navigationPaths && !navigationPaths.includes(relationName)) {
|
|
166
|
+
console.warn(
|
|
167
|
+
`Cannot navigate to "${relationName}". Valid navigation paths: ${navigationPaths.length > 0 ? navigationPaths.join(", ") : "none"}`
|
|
174
168
|
);
|
|
175
|
-
if (nestedExpandString) {
|
|
176
|
-
expandOptions.expand = nestedExpandString;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
const expandConfig = {
|
|
180
|
-
relation,
|
|
181
|
-
options: expandOptions
|
|
182
|
-
};
|
|
183
|
-
newBuilder.expandConfigs.push(expandConfig);
|
|
184
|
-
} else {
|
|
185
|
-
const defaultFields = getDefaultSelectFields();
|
|
186
|
-
if (defaultFields) {
|
|
187
|
-
newBuilder.expandConfigs.push({
|
|
188
|
-
relation,
|
|
189
|
-
options: { select: defaultFields }
|
|
190
|
-
});
|
|
191
|
-
} else {
|
|
192
|
-
newBuilder.expandConfigs.push({ relation });
|
|
193
169
|
}
|
|
194
170
|
}
|
|
195
|
-
return newBuilder;
|
|
196
|
-
}
|
|
197
|
-
// Implementation
|
|
198
|
-
navigate(relationName) {
|
|
199
|
-
var _a;
|
|
200
|
-
const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[relationName];
|
|
201
171
|
const builder = new QueryBuilder({
|
|
202
|
-
occurrence:
|
|
203
|
-
tableName: (targetOccurrence == null ? void 0 : targetOccurrence.name) ?? relationName,
|
|
172
|
+
occurrence: targetTable,
|
|
204
173
|
databaseName: this.databaseName,
|
|
205
|
-
context: this.context
|
|
174
|
+
context: this.context,
|
|
175
|
+
databaseUseEntityIds: this.databaseUseEntityIds
|
|
206
176
|
});
|
|
207
|
-
const relationId =
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
builder.navigateRelation = relationId;
|
|
177
|
+
const relationId = relationName;
|
|
178
|
+
let sourceTableName;
|
|
179
|
+
let baseRelation;
|
|
211
180
|
if (this.isNavigateFromEntitySet && this.navigateSourceTableName && this.navigateRelation) {
|
|
212
|
-
|
|
213
|
-
|
|
181
|
+
sourceTableName = this.navigateSourceTableName;
|
|
182
|
+
baseRelation = this.navigateRelation;
|
|
214
183
|
} else {
|
|
215
|
-
|
|
216
|
-
|
|
184
|
+
if (!this.table) {
|
|
185
|
+
throw new Error("Table occurrence is required for navigation");
|
|
186
|
+
}
|
|
187
|
+
sourceTableName = resolveTableId(
|
|
188
|
+
this.table,
|
|
189
|
+
getTableName(this.table),
|
|
190
|
+
this.context,
|
|
191
|
+
this.databaseUseEntityIds
|
|
192
|
+
);
|
|
217
193
|
}
|
|
194
|
+
builder.navigation = {
|
|
195
|
+
recordId: this.recordId,
|
|
196
|
+
relation: relationId,
|
|
197
|
+
sourceTableName,
|
|
198
|
+
baseRelation
|
|
199
|
+
};
|
|
218
200
|
return builder;
|
|
219
201
|
}
|
|
220
|
-
/**
|
|
221
|
-
* Formats select fields for use in query strings.
|
|
222
|
-
* - Transforms field names to FMFIDs if using entity IDs
|
|
223
|
-
* - Wraps "id" fields in double quotes
|
|
224
|
-
* - URL-encodes special characters but preserves spaces
|
|
225
|
-
*/
|
|
226
|
-
formatSelectFields(select, baseTable) {
|
|
227
|
-
if (!select || select.length === 0) return "";
|
|
228
|
-
const transformedFields = baseTable ? transformFieldNamesArray(select, baseTable) : select;
|
|
229
|
-
return transformedFields.map((field) => {
|
|
230
|
-
if (field === "id") return `"id"`;
|
|
231
|
-
const encodedField = encodeURIComponent(String(field));
|
|
232
|
-
return encodedField.replace(/%20/g, " ");
|
|
233
|
-
}).join(",");
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Builds expand validation configs from internal expand configurations.
|
|
237
|
-
* These are used to validate expanded navigation properties.
|
|
238
|
-
*/
|
|
239
|
-
buildExpandValidationConfigs(configs) {
|
|
240
|
-
return configs.map((config) => {
|
|
241
|
-
var _a, _b, _c;
|
|
242
|
-
const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[config.relation];
|
|
243
|
-
const targetSchema = (_b = targetOccurrence == null ? void 0 : targetOccurrence.baseTable) == null ? void 0 : _b.schema;
|
|
244
|
-
const selectedFields = ((_c = config.options) == null ? void 0 : _c.select) ? Array.isArray(config.options.select) ? config.options.select.map((f) => String(f)) : [String(config.options.select)] : void 0;
|
|
245
|
-
return {
|
|
246
|
-
relation: config.relation,
|
|
247
|
-
targetSchema,
|
|
248
|
-
targetOccurrence,
|
|
249
|
-
targetBaseTable: targetOccurrence == null ? void 0 : targetOccurrence.baseTable,
|
|
250
|
-
occurrence: targetOccurrence,
|
|
251
|
-
// For transformation
|
|
252
|
-
selectedFields,
|
|
253
|
-
nestedExpands: void 0
|
|
254
|
-
// TODO: Handle nested expands if needed
|
|
255
|
-
};
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Builds OData expand query string from expand configurations.
|
|
260
|
-
* Handles nested expands recursively.
|
|
261
|
-
* Transforms relation names to FMTIDs if using entity IDs.
|
|
262
|
-
*/
|
|
263
|
-
buildExpandString(configs) {
|
|
264
|
-
if (configs.length === 0) {
|
|
265
|
-
return "";
|
|
266
|
-
}
|
|
267
|
-
return configs.map((config) => {
|
|
268
|
-
var _a, _b;
|
|
269
|
-
const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[config.relation];
|
|
270
|
-
const relationName = targetOccurrence && ((_b = targetOccurrence.isUsingTableId) == null ? void 0 : _b.call(targetOccurrence)) ? targetOccurrence.getTableId() : config.relation;
|
|
271
|
-
if (!config.options || Object.keys(config.options).length === 0) {
|
|
272
|
-
return relationName;
|
|
273
|
-
}
|
|
274
|
-
const parts = [];
|
|
275
|
-
if (config.options.select) {
|
|
276
|
-
const selectFields = this.formatSelectFields(
|
|
277
|
-
Array.isArray(config.options.select) ? config.options.select.map((f) => String(f)) : [String(config.options.select)],
|
|
278
|
-
targetOccurrence == null ? void 0 : targetOccurrence.baseTable
|
|
279
|
-
);
|
|
280
|
-
parts.push(`$select=${selectFields}`);
|
|
281
|
-
}
|
|
282
|
-
if (config.options.filter) {
|
|
283
|
-
const filterQuery = buildQuery({ filter: config.options.filter });
|
|
284
|
-
const filterMatch = filterQuery.match(/\$filter=([^&]+)/);
|
|
285
|
-
if (filterMatch) {
|
|
286
|
-
parts.push(`$filter=${filterMatch[1]}`);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
if (config.options.orderBy) {
|
|
290
|
-
const orderByQuery = buildQuery({ orderBy: config.options.orderBy });
|
|
291
|
-
const orderByMatch = orderByQuery.match(/\$orderby=([^&]+)/);
|
|
292
|
-
if (orderByMatch) {
|
|
293
|
-
parts.push(`$orderby=${orderByMatch[1]}`);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
if (config.options.top !== void 0) {
|
|
297
|
-
parts.push(`$top=${config.options.top}`);
|
|
298
|
-
}
|
|
299
|
-
if (config.options.skip !== void 0) {
|
|
300
|
-
parts.push(`$skip=${config.options.skip}`);
|
|
301
|
-
}
|
|
302
|
-
if (config.options.expand) {
|
|
303
|
-
parts.push(`$expand=${String(config.options.expand)}`);
|
|
304
|
-
}
|
|
305
|
-
if (parts.length === 0) {
|
|
306
|
-
return relationName;
|
|
307
|
-
}
|
|
308
|
-
return `${relationName}(${parts.join(";")})`;
|
|
309
|
-
}).join(",");
|
|
310
|
-
}
|
|
311
202
|
/**
|
|
312
203
|
* Builds the complete query string including $select and $expand parameters.
|
|
313
204
|
*/
|
|
314
205
|
buildQueryString() {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
);
|
|
322
|
-
if (selectString) {
|
|
323
|
-
parts.push(`$select=${selectString}`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
const expandString = this.buildExpandString(this.expandConfigs);
|
|
327
|
-
if (expandString) {
|
|
328
|
-
parts.push(`$expand=${expandString}`);
|
|
329
|
-
}
|
|
330
|
-
if (parts.length === 0) {
|
|
331
|
-
return "";
|
|
332
|
-
}
|
|
333
|
-
return `?${parts.join("&")}`;
|
|
206
|
+
return buildSelectExpandQueryString({
|
|
207
|
+
selectedFields: this.selectedFields,
|
|
208
|
+
expandConfigs: this.expandConfigs,
|
|
209
|
+
table: this.table,
|
|
210
|
+
useEntityIds: this.databaseUseEntityIds
|
|
211
|
+
});
|
|
334
212
|
}
|
|
335
213
|
async execute(options) {
|
|
336
|
-
var _a, _b, _c;
|
|
337
214
|
let url;
|
|
338
215
|
if (this.isNavigateFromEntitySet && this.navigateSourceTableName && this.navigateRelation) {
|
|
339
216
|
url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}('${this.recordId}')`;
|
|
@@ -359,31 +236,22 @@ class RecordBuilder {
|
|
|
359
236
|
const fieldResponse = response;
|
|
360
237
|
return { data: fieldResponse.value, error: void 0 };
|
|
361
238
|
}
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
if (((_a = this.occurrence) == null ? void 0 : _a.baseTable) && shouldUseIds) {
|
|
365
|
-
response = transformResponseFields(
|
|
366
|
-
response,
|
|
367
|
-
this.occurrence.baseTable,
|
|
368
|
-
expandValidationConfigs
|
|
369
|
-
);
|
|
370
|
-
}
|
|
371
|
-
const schema = (_c = (_b = this.occurrence) == null ? void 0 : _b.baseTable) == null ? void 0 : _c.schema;
|
|
372
|
-
const validation = await validateSingleResponse(
|
|
373
|
-
response,
|
|
374
|
-
schema,
|
|
375
|
-
this.selectedFields,
|
|
376
|
-
expandValidationConfigs,
|
|
377
|
-
"exact"
|
|
378
|
-
// Expect exactly one record
|
|
239
|
+
const expandBuilder = new ExpandBuilder(
|
|
240
|
+
mergedOptions.useEntityIds ?? false
|
|
379
241
|
);
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
242
|
+
const expandValidationConfigs = expandBuilder.buildValidationConfigs(
|
|
243
|
+
this.expandConfigs
|
|
244
|
+
);
|
|
245
|
+
return processODataResponse(response, {
|
|
246
|
+
table: this.table,
|
|
247
|
+
schema: getSchemaFromTable(this.table),
|
|
248
|
+
singleMode: "exact",
|
|
249
|
+
selectedFields: this.selectedFields,
|
|
250
|
+
expandValidationConfigs,
|
|
251
|
+
skipValidation: options == null ? void 0 : options.skipValidation,
|
|
252
|
+
useEntityIds: mergedOptions.useEntityIds,
|
|
253
|
+
fieldMapping: this.fieldMapping
|
|
254
|
+
});
|
|
387
255
|
}
|
|
388
256
|
getRequestConfig() {
|
|
389
257
|
let url;
|
|
@@ -423,48 +291,42 @@ class RecordBuilder {
|
|
|
423
291
|
}
|
|
424
292
|
toRequest(baseUrl, options) {
|
|
425
293
|
const config = this.getRequestConfig();
|
|
426
|
-
|
|
427
|
-
return new Request(fullUrl, {
|
|
428
|
-
method: config.method,
|
|
429
|
-
headers: {
|
|
430
|
-
"Content-Type": "application/json",
|
|
431
|
-
Accept: getAcceptHeader(options == null ? void 0 : options.includeODataAnnotations)
|
|
432
|
-
}
|
|
433
|
-
});
|
|
294
|
+
return createODataRequest(baseUrl, config, options);
|
|
434
295
|
}
|
|
435
296
|
async processResponse(response, options) {
|
|
436
|
-
|
|
297
|
+
if (!response.ok) {
|
|
298
|
+
const tableName = this.table ? getTableName(this.table) : "unknown";
|
|
299
|
+
const error = await parseErrorResponse(
|
|
300
|
+
response,
|
|
301
|
+
response.url || `/${this.databaseName}/${tableName}`
|
|
302
|
+
);
|
|
303
|
+
return { data: void 0, error };
|
|
304
|
+
}
|
|
437
305
|
const rawResponse = await safeJsonParse(response);
|
|
438
306
|
if (this.operation === "getSingleField") {
|
|
439
307
|
const fieldResponse = rawResponse;
|
|
440
308
|
return { data: fieldResponse.value, error: void 0 };
|
|
441
309
|
}
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
if (((_a = this.occurrence) == null ? void 0 : _a.baseTable) && shouldUseIds) {
|
|
446
|
-
transformedResponse = transformResponseFields(
|
|
447
|
-
rawResponse,
|
|
448
|
-
this.occurrence.baseTable,
|
|
449
|
-
expandValidationConfigs
|
|
450
|
-
);
|
|
451
|
-
}
|
|
452
|
-
const schema = (_c = (_b = this.occurrence) == null ? void 0 : _b.baseTable) == null ? void 0 : _c.schema;
|
|
453
|
-
const validation = await validateSingleResponse(
|
|
454
|
-
transformedResponse,
|
|
455
|
-
schema,
|
|
456
|
-
this.selectedFields,
|
|
457
|
-
expandValidationConfigs,
|
|
458
|
-
"exact"
|
|
459
|
-
// Expect exactly one record
|
|
310
|
+
const mergedOptions = mergeExecuteOptions(
|
|
311
|
+
options,
|
|
312
|
+
this.databaseUseEntityIds
|
|
460
313
|
);
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
return
|
|
314
|
+
const expandBuilder = new ExpandBuilder(
|
|
315
|
+
mergedOptions.useEntityIds ?? false
|
|
316
|
+
);
|
|
317
|
+
const expandValidationConfigs = expandBuilder.buildValidationConfigs(
|
|
318
|
+
this.expandConfigs
|
|
319
|
+
);
|
|
320
|
+
return processODataResponse(rawResponse, {
|
|
321
|
+
table: this.table,
|
|
322
|
+
schema: getSchemaFromTable(this.table),
|
|
323
|
+
singleMode: "exact",
|
|
324
|
+
selectedFields: this.selectedFields,
|
|
325
|
+
expandValidationConfigs,
|
|
326
|
+
skipValidation: options == null ? void 0 : options.skipValidation,
|
|
327
|
+
useEntityIds: mergedOptions.useEntityIds,
|
|
328
|
+
fieldMapping: this.fieldMapping
|
|
329
|
+
});
|
|
468
330
|
}
|
|
469
331
|
}
|
|
470
332
|
export {
|