@proofkit/fmodata 0.1.0-alpha.0
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 +37 -0
- package/dist/esm/client/base-table.d.ts +13 -0
- package/dist/esm/client/base-table.js +19 -0
- package/dist/esm/client/base-table.js.map +1 -0
- package/dist/esm/client/database.d.ts +49 -0
- package/dist/esm/client/database.js +90 -0
- package/dist/esm/client/database.js.map +1 -0
- package/dist/esm/client/delete-builder.d.ts +61 -0
- package/dist/esm/client/delete-builder.js +121 -0
- package/dist/esm/client/delete-builder.js.map +1 -0
- package/dist/esm/client/entity-set.d.ts +43 -0
- package/dist/esm/client/entity-set.js +120 -0
- package/dist/esm/client/entity-set.js.map +1 -0
- package/dist/esm/client/filemaker-odata.d.ts +26 -0
- package/dist/esm/client/filemaker-odata.js +85 -0
- package/dist/esm/client/filemaker-odata.js.map +1 -0
- package/dist/esm/client/insert-builder.d.ts +23 -0
- package/dist/esm/client/insert-builder.js +69 -0
- package/dist/esm/client/insert-builder.js.map +1 -0
- package/dist/esm/client/query-builder.d.ts +94 -0
- package/dist/esm/client/query-builder.js +649 -0
- package/dist/esm/client/query-builder.js.map +1 -0
- package/dist/esm/client/record-builder.d.ts +43 -0
- package/dist/esm/client/record-builder.js +121 -0
- package/dist/esm/client/record-builder.js.map +1 -0
- package/dist/esm/client/table-occurrence.d.ts +25 -0
- package/dist/esm/client/table-occurrence.js +47 -0
- package/dist/esm/client/table-occurrence.js.map +1 -0
- package/dist/esm/client/update-builder.d.ts +69 -0
- package/dist/esm/client/update-builder.js +134 -0
- package/dist/esm/client/update-builder.js.map +1 -0
- package/dist/esm/filter-types.d.ts +76 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/types.d.ts +67 -0
- package/dist/esm/validation.d.ts +41 -0
- package/dist/esm/validation.js +270 -0
- package/dist/esm/validation.js.map +1 -0
- package/package.json +68 -0
- package/src/client/base-table.ts +25 -0
- package/src/client/database.ts +177 -0
- package/src/client/delete-builder.ts +193 -0
- package/src/client/entity-set.ts +310 -0
- package/src/client/filemaker-odata.ts +119 -0
- package/src/client/insert-builder.ts +93 -0
- package/src/client/query-builder.ts +1076 -0
- package/src/client/record-builder.ts +240 -0
- package/src/client/table-occurrence.ts +100 -0
- package/src/client/update-builder.ts +212 -0
- package/src/filter-types.ts +97 -0
- package/src/index.ts +17 -0
- package/src/types.ts +123 -0
- package/src/validation.ts +397 -0
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import buildQuery from "odata-query";
|
|
5
|
+
import { validateSingleResponse, validateListResponse } from "../validation.js";
|
|
6
|
+
class QueryBuilder {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
__publicField(this, "queryOptions", {});
|
|
9
|
+
__publicField(this, "expandConfigs", []);
|
|
10
|
+
__publicField(this, "singleMode", false);
|
|
11
|
+
__publicField(this, "isCountMode", false);
|
|
12
|
+
__publicField(this, "occurrence");
|
|
13
|
+
__publicField(this, "tableName");
|
|
14
|
+
__publicField(this, "databaseName");
|
|
15
|
+
__publicField(this, "context");
|
|
16
|
+
__publicField(this, "isNavigate");
|
|
17
|
+
__publicField(this, "navigateRecordId");
|
|
18
|
+
__publicField(this, "navigateRelation");
|
|
19
|
+
__publicField(this, "navigateSourceTableName");
|
|
20
|
+
__publicField(this, "navigateBaseRelation");
|
|
21
|
+
this.occurrence = config.occurrence;
|
|
22
|
+
this.tableName = config.tableName;
|
|
23
|
+
this.databaseName = config.databaseName;
|
|
24
|
+
this.context = config.context;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Helper to conditionally strip OData annotations based on options
|
|
28
|
+
*/
|
|
29
|
+
stripODataAnnotationsIfNeeded(data, options) {
|
|
30
|
+
if ((options == null ? void 0 : options.includeODataAnnotations) === true) {
|
|
31
|
+
return data;
|
|
32
|
+
}
|
|
33
|
+
const { "@id": _id, "@editLink": _editLink, ...rest } = data;
|
|
34
|
+
return rest;
|
|
35
|
+
}
|
|
36
|
+
select(...fields) {
|
|
37
|
+
const uniqueFields = [...new Set(fields)];
|
|
38
|
+
const newBuilder = new QueryBuilder({
|
|
39
|
+
occurrence: this.occurrence,
|
|
40
|
+
tableName: this.tableName,
|
|
41
|
+
databaseName: this.databaseName,
|
|
42
|
+
context: this.context
|
|
43
|
+
});
|
|
44
|
+
newBuilder.queryOptions = {
|
|
45
|
+
...this.queryOptions,
|
|
46
|
+
select: uniqueFields
|
|
47
|
+
};
|
|
48
|
+
newBuilder.expandConfigs = [...this.expandConfigs];
|
|
49
|
+
newBuilder.singleMode = this.singleMode;
|
|
50
|
+
newBuilder.isCountMode = this.isCountMode;
|
|
51
|
+
newBuilder.isNavigate = this.isNavigate;
|
|
52
|
+
newBuilder.navigateRecordId = this.navigateRecordId;
|
|
53
|
+
newBuilder.navigateRelation = this.navigateRelation;
|
|
54
|
+
newBuilder.navigateSourceTableName = this.navigateSourceTableName;
|
|
55
|
+
newBuilder.navigateBaseRelation = this.navigateBaseRelation;
|
|
56
|
+
return newBuilder;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Transforms our filter format to odata-query's expected format
|
|
60
|
+
* - Arrays of operators are converted to AND conditions
|
|
61
|
+
* - Single operator objects pass through as-is
|
|
62
|
+
* - Shorthand values are handled by odata-query
|
|
63
|
+
*/
|
|
64
|
+
transformFilter(filter) {
|
|
65
|
+
if (typeof filter === "string") {
|
|
66
|
+
return filter;
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(filter)) {
|
|
69
|
+
return filter.map((f) => this.transformFilter(f));
|
|
70
|
+
}
|
|
71
|
+
if ("and" in filter || "or" in filter || "not" in filter) {
|
|
72
|
+
const result2 = {};
|
|
73
|
+
if ("and" in filter && Array.isArray(filter.and)) {
|
|
74
|
+
result2.and = filter.and.map((f) => this.transformFilter(f));
|
|
75
|
+
}
|
|
76
|
+
if ("or" in filter && Array.isArray(filter.or)) {
|
|
77
|
+
result2.or = filter.or.map((f) => this.transformFilter(f));
|
|
78
|
+
}
|
|
79
|
+
if ("not" in filter && filter.not) {
|
|
80
|
+
result2.not = this.transformFilter(filter.not);
|
|
81
|
+
}
|
|
82
|
+
return result2;
|
|
83
|
+
}
|
|
84
|
+
const result = {};
|
|
85
|
+
const andConditions = [];
|
|
86
|
+
for (const [field, value] of Object.entries(filter)) {
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
if (value.length === 1) {
|
|
89
|
+
result[field] = value[0];
|
|
90
|
+
} else {
|
|
91
|
+
for (const op of value) {
|
|
92
|
+
andConditions.push({ [field]: op });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} else if (value && typeof value === "object" && !(value instanceof Date) && !Array.isArray(value)) {
|
|
96
|
+
const operatorKeys = [
|
|
97
|
+
"eq",
|
|
98
|
+
"ne",
|
|
99
|
+
"gt",
|
|
100
|
+
"ge",
|
|
101
|
+
"lt",
|
|
102
|
+
"le",
|
|
103
|
+
"contains",
|
|
104
|
+
"startswith",
|
|
105
|
+
"endswith",
|
|
106
|
+
"in"
|
|
107
|
+
];
|
|
108
|
+
const isOperatorObject = operatorKeys.some((key) => key in value);
|
|
109
|
+
if (isOperatorObject) {
|
|
110
|
+
result[field] = value;
|
|
111
|
+
} else {
|
|
112
|
+
result[field] = value;
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
result[field] = value;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (andConditions.length > 0) {
|
|
119
|
+
if (Object.keys(result).length > 0) {
|
|
120
|
+
return { and: [...andConditions, result] };
|
|
121
|
+
} else {
|
|
122
|
+
return { and: andConditions };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
filter(filter) {
|
|
128
|
+
this.queryOptions.filter = this.transformFilter(filter);
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
orderBy(orderBy) {
|
|
132
|
+
this.queryOptions.orderBy = orderBy;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
top(count) {
|
|
136
|
+
this.queryOptions.top = count;
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
skip(count) {
|
|
140
|
+
this.queryOptions.skip = count;
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Formats select fields for use in query strings.
|
|
145
|
+
* - Wraps "id" fields in double quotes
|
|
146
|
+
* - URL-encodes special characters but preserves spaces
|
|
147
|
+
*/
|
|
148
|
+
formatSelectFields(select) {
|
|
149
|
+
if (!select) return "";
|
|
150
|
+
const selectFieldsArray = Array.isArray(select) ? select : [select];
|
|
151
|
+
return selectFieldsArray.map((field) => {
|
|
152
|
+
if (field === "id") return `"id"`;
|
|
153
|
+
const encodedField = encodeURIComponent(String(field));
|
|
154
|
+
return encodedField.replace(/%20/g, " ");
|
|
155
|
+
}).join(",");
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Builds expand validation configs from internal expand configurations.
|
|
159
|
+
* These are used to validate expanded navigation properties.
|
|
160
|
+
*/
|
|
161
|
+
buildExpandValidationConfigs(configs) {
|
|
162
|
+
return configs.map((config) => {
|
|
163
|
+
var _a, _b, _c;
|
|
164
|
+
const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[config.relation];
|
|
165
|
+
const targetSchema = (_b = targetOccurrence == null ? void 0 : targetOccurrence.baseTable) == null ? void 0 : _b.schema;
|
|
166
|
+
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;
|
|
167
|
+
return {
|
|
168
|
+
relation: config.relation,
|
|
169
|
+
targetSchema,
|
|
170
|
+
targetOccurrence,
|
|
171
|
+
selectedFields,
|
|
172
|
+
nestedExpands: void 0
|
|
173
|
+
// TODO: Handle nested expands if needed
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Builds OData expand query string from expand configurations.
|
|
179
|
+
* Handles nested expands recursively.
|
|
180
|
+
*/
|
|
181
|
+
buildExpandString(configs) {
|
|
182
|
+
if (configs.length === 0) {
|
|
183
|
+
return "";
|
|
184
|
+
}
|
|
185
|
+
return configs.map((config) => {
|
|
186
|
+
if (!config.options || Object.keys(config.options).length === 0) {
|
|
187
|
+
return config.relation;
|
|
188
|
+
}
|
|
189
|
+
const parts = [];
|
|
190
|
+
if (config.options.select) {
|
|
191
|
+
const selectFields = this.formatSelectFields(config.options.select);
|
|
192
|
+
parts.push(`$select=${selectFields}`);
|
|
193
|
+
}
|
|
194
|
+
if (config.options.filter) {
|
|
195
|
+
const filterQuery = buildQuery({ filter: config.options.filter });
|
|
196
|
+
const filterMatch = filterQuery.match(/\$filter=([^&]+)/);
|
|
197
|
+
if (filterMatch) {
|
|
198
|
+
parts.push(`$filter=${filterMatch[1]}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (config.options.orderBy) {
|
|
202
|
+
const orderByValue = Array.isArray(config.options.orderBy) ? config.options.orderBy.join(",") : config.options.orderBy;
|
|
203
|
+
parts.push(`$orderby=${String(orderByValue)}`);
|
|
204
|
+
}
|
|
205
|
+
if (config.options.top !== void 0) {
|
|
206
|
+
parts.push(`$top=${config.options.top}`);
|
|
207
|
+
}
|
|
208
|
+
if (config.options.skip !== void 0) {
|
|
209
|
+
parts.push(`$skip=${config.options.skip}`);
|
|
210
|
+
}
|
|
211
|
+
if (config.options.expand) {
|
|
212
|
+
if (typeof config.options.expand === "string") {
|
|
213
|
+
parts.push(`$expand=${config.options.expand}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (parts.length === 0) {
|
|
217
|
+
return config.relation;
|
|
218
|
+
}
|
|
219
|
+
return `${config.relation}(${parts.join(";")})`;
|
|
220
|
+
}).join(",");
|
|
221
|
+
}
|
|
222
|
+
expand(relation, callback) {
|
|
223
|
+
var _a;
|
|
224
|
+
const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[relation];
|
|
225
|
+
if (callback) {
|
|
226
|
+
const targetBuilder = new QueryBuilder({
|
|
227
|
+
occurrence: targetOccurrence,
|
|
228
|
+
tableName: (targetOccurrence == null ? void 0 : targetOccurrence.name) ?? relation,
|
|
229
|
+
databaseName: this.databaseName,
|
|
230
|
+
context: this.context
|
|
231
|
+
});
|
|
232
|
+
const typedBuilder = targetBuilder;
|
|
233
|
+
const configuredBuilder = callback(typedBuilder);
|
|
234
|
+
const expandOptions = {
|
|
235
|
+
...configuredBuilder.queryOptions
|
|
236
|
+
};
|
|
237
|
+
if (configuredBuilder.expandConfigs.length > 0) {
|
|
238
|
+
const nestedExpandString = this.buildExpandString(
|
|
239
|
+
configuredBuilder.expandConfigs
|
|
240
|
+
);
|
|
241
|
+
if (nestedExpandString) {
|
|
242
|
+
expandOptions.expand = nestedExpandString;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const expandConfig = {
|
|
246
|
+
relation,
|
|
247
|
+
options: expandOptions
|
|
248
|
+
};
|
|
249
|
+
this.expandConfigs.push(expandConfig);
|
|
250
|
+
} else {
|
|
251
|
+
this.expandConfigs.push({ relation });
|
|
252
|
+
}
|
|
253
|
+
return this;
|
|
254
|
+
}
|
|
255
|
+
single() {
|
|
256
|
+
const newBuilder = new QueryBuilder({
|
|
257
|
+
occurrence: this.occurrence,
|
|
258
|
+
tableName: this.tableName,
|
|
259
|
+
databaseName: this.databaseName,
|
|
260
|
+
context: this.context
|
|
261
|
+
});
|
|
262
|
+
newBuilder.queryOptions = { ...this.queryOptions };
|
|
263
|
+
newBuilder.expandConfigs = [...this.expandConfigs];
|
|
264
|
+
newBuilder.singleMode = "exact";
|
|
265
|
+
newBuilder.isCountMode = this.isCountMode;
|
|
266
|
+
newBuilder.isNavigate = this.isNavigate;
|
|
267
|
+
newBuilder.navigateRecordId = this.navigateRecordId;
|
|
268
|
+
newBuilder.navigateRelation = this.navigateRelation;
|
|
269
|
+
newBuilder.navigateSourceTableName = this.navigateSourceTableName;
|
|
270
|
+
newBuilder.navigateBaseRelation = this.navigateBaseRelation;
|
|
271
|
+
return newBuilder;
|
|
272
|
+
}
|
|
273
|
+
maybeSingle() {
|
|
274
|
+
const newBuilder = new QueryBuilder({
|
|
275
|
+
occurrence: this.occurrence,
|
|
276
|
+
tableName: this.tableName,
|
|
277
|
+
databaseName: this.databaseName,
|
|
278
|
+
context: this.context
|
|
279
|
+
});
|
|
280
|
+
newBuilder.queryOptions = { ...this.queryOptions };
|
|
281
|
+
newBuilder.expandConfigs = [...this.expandConfigs];
|
|
282
|
+
newBuilder.singleMode = "maybe";
|
|
283
|
+
newBuilder.isCountMode = this.isCountMode;
|
|
284
|
+
newBuilder.isNavigate = this.isNavigate;
|
|
285
|
+
newBuilder.navigateRecordId = this.navigateRecordId;
|
|
286
|
+
newBuilder.navigateRelation = this.navigateRelation;
|
|
287
|
+
newBuilder.navigateSourceTableName = this.navigateSourceTableName;
|
|
288
|
+
newBuilder.navigateBaseRelation = this.navigateBaseRelation;
|
|
289
|
+
return newBuilder;
|
|
290
|
+
}
|
|
291
|
+
count() {
|
|
292
|
+
const newBuilder = new QueryBuilder({
|
|
293
|
+
occurrence: this.occurrence,
|
|
294
|
+
tableName: this.tableName,
|
|
295
|
+
databaseName: this.databaseName,
|
|
296
|
+
context: this.context
|
|
297
|
+
});
|
|
298
|
+
newBuilder.queryOptions = { ...this.queryOptions, count: true };
|
|
299
|
+
newBuilder.expandConfigs = [...this.expandConfigs];
|
|
300
|
+
newBuilder.singleMode = this.singleMode;
|
|
301
|
+
newBuilder.isCountMode = true;
|
|
302
|
+
newBuilder.isNavigate = this.isNavigate;
|
|
303
|
+
newBuilder.navigateRecordId = this.navigateRecordId;
|
|
304
|
+
newBuilder.navigateRelation = this.navigateRelation;
|
|
305
|
+
newBuilder.navigateSourceTableName = this.navigateSourceTableName;
|
|
306
|
+
newBuilder.navigateBaseRelation = this.navigateBaseRelation;
|
|
307
|
+
return newBuilder;
|
|
308
|
+
}
|
|
309
|
+
async execute(options) {
|
|
310
|
+
var _a, _b, _c, _d, _e, _f;
|
|
311
|
+
try {
|
|
312
|
+
const queryOptionsWithoutExpand = { ...this.queryOptions };
|
|
313
|
+
delete queryOptionsWithoutExpand.expand;
|
|
314
|
+
if (queryOptionsWithoutExpand.select) {
|
|
315
|
+
queryOptionsWithoutExpand.select = this.formatSelectFields(
|
|
316
|
+
queryOptionsWithoutExpand.select
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
let queryString = buildQuery(queryOptionsWithoutExpand);
|
|
320
|
+
const expandString = this.buildExpandString(this.expandConfigs);
|
|
321
|
+
if (expandString) {
|
|
322
|
+
const separator = queryString.includes("?") ? "&" : "?";
|
|
323
|
+
queryString = `${queryString}${separator}$expand=${expandString}`;
|
|
324
|
+
}
|
|
325
|
+
if (this.isNavigate && this.navigateRecordId && this.navigateRelation && this.navigateSourceTableName) {
|
|
326
|
+
let url;
|
|
327
|
+
if (this.navigateBaseRelation) {
|
|
328
|
+
url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;
|
|
329
|
+
} else {
|
|
330
|
+
url = `/${this.databaseName}/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;
|
|
331
|
+
}
|
|
332
|
+
const response2 = await this.context._makeRequest(url, options);
|
|
333
|
+
if ((options == null ? void 0 : options.skipValidation) === true) {
|
|
334
|
+
const resp = response2;
|
|
335
|
+
if (this.singleMode !== false) {
|
|
336
|
+
const records = resp.value ?? [resp];
|
|
337
|
+
const count = Array.isArray(records) ? records.length : 1;
|
|
338
|
+
if (count > 1) {
|
|
339
|
+
return {
|
|
340
|
+
data: void 0,
|
|
341
|
+
error: new Error(
|
|
342
|
+
`Expected ${this.singleMode === "exact" ? "exactly one" : "at most one"} record, but received ${count}`
|
|
343
|
+
)
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
if (count === 0) {
|
|
347
|
+
if (this.singleMode === "exact") {
|
|
348
|
+
return {
|
|
349
|
+
data: void 0,
|
|
350
|
+
error: new Error(
|
|
351
|
+
"Expected exactly one record, but received none"
|
|
352
|
+
)
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
return { data: null, error: void 0 };
|
|
356
|
+
}
|
|
357
|
+
const record = Array.isArray(records) ? records[0] : records;
|
|
358
|
+
const stripped = this.stripODataAnnotationsIfNeeded(
|
|
359
|
+
record,
|
|
360
|
+
options
|
|
361
|
+
);
|
|
362
|
+
return { data: stripped, error: void 0 };
|
|
363
|
+
} else {
|
|
364
|
+
const records = resp.value ?? [];
|
|
365
|
+
const stripped = records.map(
|
|
366
|
+
(record) => this.stripODataAnnotationsIfNeeded(record, options)
|
|
367
|
+
);
|
|
368
|
+
return { data: stripped, error: void 0 };
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const schema2 = (_b = (_a = this.occurrence) == null ? void 0 : _a.baseTable) == null ? void 0 : _b.schema;
|
|
372
|
+
const selectedFields2 = this.queryOptions.select;
|
|
373
|
+
const expandValidationConfigs2 = this.buildExpandValidationConfigs(
|
|
374
|
+
this.expandConfigs
|
|
375
|
+
);
|
|
376
|
+
if (this.singleMode !== false) {
|
|
377
|
+
const validation = await validateSingleResponse(
|
|
378
|
+
response2,
|
|
379
|
+
schema2,
|
|
380
|
+
selectedFields2,
|
|
381
|
+
expandValidationConfigs2,
|
|
382
|
+
this.singleMode
|
|
383
|
+
);
|
|
384
|
+
if (!validation.valid) {
|
|
385
|
+
return { data: void 0, error: validation.error };
|
|
386
|
+
}
|
|
387
|
+
const stripped = validation.data ? this.stripODataAnnotationsIfNeeded(validation.data, options) : null;
|
|
388
|
+
return { data: stripped, error: void 0 };
|
|
389
|
+
} else {
|
|
390
|
+
const validation = await validateListResponse(
|
|
391
|
+
response2,
|
|
392
|
+
schema2,
|
|
393
|
+
selectedFields2,
|
|
394
|
+
expandValidationConfigs2
|
|
395
|
+
);
|
|
396
|
+
if (!validation.valid) {
|
|
397
|
+
return { data: void 0, error: validation.error };
|
|
398
|
+
}
|
|
399
|
+
const stripped = validation.data.map(
|
|
400
|
+
(record) => this.stripODataAnnotationsIfNeeded(record, options)
|
|
401
|
+
);
|
|
402
|
+
return { data: stripped, error: void 0 };
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (this.isNavigate && !this.navigateRecordId && this.navigateRelation && this.navigateSourceTableName) {
|
|
406
|
+
const response2 = await this.context._makeRequest(
|
|
407
|
+
`/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}${queryString}`,
|
|
408
|
+
options
|
|
409
|
+
);
|
|
410
|
+
if ((options == null ? void 0 : options.skipValidation) === true) {
|
|
411
|
+
const resp = response2;
|
|
412
|
+
if (this.singleMode !== false) {
|
|
413
|
+
const records = resp.value ?? [resp];
|
|
414
|
+
const count = Array.isArray(records) ? records.length : 1;
|
|
415
|
+
if (count > 1) {
|
|
416
|
+
return {
|
|
417
|
+
data: void 0,
|
|
418
|
+
error: new Error(
|
|
419
|
+
`Expected ${this.singleMode === "exact" ? "exactly one" : "at most one"} record, but received ${count}`
|
|
420
|
+
)
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
if (count === 0) {
|
|
424
|
+
if (this.singleMode === "exact") {
|
|
425
|
+
return {
|
|
426
|
+
data: void 0,
|
|
427
|
+
error: new Error(
|
|
428
|
+
"Expected exactly one record, but received none"
|
|
429
|
+
)
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
return { data: null, error: void 0 };
|
|
433
|
+
}
|
|
434
|
+
const record = Array.isArray(records) ? records[0] : records;
|
|
435
|
+
const stripped = this.stripODataAnnotationsIfNeeded(
|
|
436
|
+
record,
|
|
437
|
+
options
|
|
438
|
+
);
|
|
439
|
+
return { data: stripped, error: void 0 };
|
|
440
|
+
} else {
|
|
441
|
+
const records = resp.value ?? [];
|
|
442
|
+
const stripped = records.map(
|
|
443
|
+
(record) => this.stripODataAnnotationsIfNeeded(record, options)
|
|
444
|
+
);
|
|
445
|
+
return { data: stripped, error: void 0 };
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const schema2 = (_d = (_c = this.occurrence) == null ? void 0 : _c.baseTable) == null ? void 0 : _d.schema;
|
|
449
|
+
const selectedFields2 = this.queryOptions.select;
|
|
450
|
+
const expandValidationConfigs2 = this.buildExpandValidationConfigs(
|
|
451
|
+
this.expandConfigs
|
|
452
|
+
);
|
|
453
|
+
if (this.singleMode !== false) {
|
|
454
|
+
const validation = await validateSingleResponse(
|
|
455
|
+
response2,
|
|
456
|
+
schema2,
|
|
457
|
+
selectedFields2,
|
|
458
|
+
expandValidationConfigs2,
|
|
459
|
+
this.singleMode
|
|
460
|
+
);
|
|
461
|
+
if (!validation.valid) {
|
|
462
|
+
return { data: void 0, error: validation.error };
|
|
463
|
+
}
|
|
464
|
+
const stripped = validation.data ? this.stripODataAnnotationsIfNeeded(validation.data, options) : null;
|
|
465
|
+
return { data: stripped, error: void 0 };
|
|
466
|
+
} else {
|
|
467
|
+
const validation = await validateListResponse(
|
|
468
|
+
response2,
|
|
469
|
+
schema2,
|
|
470
|
+
selectedFields2,
|
|
471
|
+
expandValidationConfigs2
|
|
472
|
+
);
|
|
473
|
+
if (!validation.valid) {
|
|
474
|
+
return { data: void 0, error: validation.error };
|
|
475
|
+
}
|
|
476
|
+
const stripped = validation.data.map(
|
|
477
|
+
(record) => this.stripODataAnnotationsIfNeeded(record, options)
|
|
478
|
+
);
|
|
479
|
+
return { data: stripped, error: void 0 };
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
if (this.isCountMode) {
|
|
483
|
+
const result = await this.context._makeRequest(
|
|
484
|
+
`/${this.databaseName}/${this.tableName}/$count${queryString}`,
|
|
485
|
+
options
|
|
486
|
+
);
|
|
487
|
+
const count = typeof result === "string" ? Number(result) : result;
|
|
488
|
+
return { data: count, error: void 0 };
|
|
489
|
+
}
|
|
490
|
+
const response = await this.context._makeRequest(
|
|
491
|
+
`/${this.databaseName}/${this.tableName}${queryString}`,
|
|
492
|
+
options
|
|
493
|
+
);
|
|
494
|
+
if ((options == null ? void 0 : options.skipValidation) === true) {
|
|
495
|
+
const resp = response;
|
|
496
|
+
if (this.singleMode !== false) {
|
|
497
|
+
const records = resp.value ?? [resp];
|
|
498
|
+
const count = Array.isArray(records) ? records.length : 1;
|
|
499
|
+
if (count > 1) {
|
|
500
|
+
return {
|
|
501
|
+
data: void 0,
|
|
502
|
+
error: new Error(
|
|
503
|
+
`Expected ${this.singleMode === "exact" ? "exactly one" : "at most one"} record, but received ${count}`
|
|
504
|
+
)
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
if (count === 0) {
|
|
508
|
+
if (this.singleMode === "exact") {
|
|
509
|
+
return {
|
|
510
|
+
data: void 0,
|
|
511
|
+
error: new Error(
|
|
512
|
+
"Expected exactly one record, but received none"
|
|
513
|
+
)
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
return { data: null, error: void 0 };
|
|
517
|
+
}
|
|
518
|
+
const record = Array.isArray(records) ? records[0] : records;
|
|
519
|
+
const stripped = this.stripODataAnnotationsIfNeeded(record, options);
|
|
520
|
+
return { data: stripped, error: void 0 };
|
|
521
|
+
} else {
|
|
522
|
+
const records = resp.value ?? [];
|
|
523
|
+
const stripped = records.map(
|
|
524
|
+
(record) => this.stripODataAnnotationsIfNeeded(record, options)
|
|
525
|
+
);
|
|
526
|
+
return { data: stripped, error: void 0 };
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
const schema = (_f = (_e = this.occurrence) == null ? void 0 : _e.baseTable) == null ? void 0 : _f.schema;
|
|
530
|
+
const selectedFields = this.queryOptions.select;
|
|
531
|
+
const expandValidationConfigs = this.buildExpandValidationConfigs(
|
|
532
|
+
this.expandConfigs
|
|
533
|
+
);
|
|
534
|
+
if (this.singleMode !== false) {
|
|
535
|
+
const validation = await validateSingleResponse(
|
|
536
|
+
response,
|
|
537
|
+
schema,
|
|
538
|
+
selectedFields,
|
|
539
|
+
expandValidationConfigs,
|
|
540
|
+
this.singleMode
|
|
541
|
+
);
|
|
542
|
+
if (!validation.valid) {
|
|
543
|
+
return { data: void 0, error: validation.error };
|
|
544
|
+
}
|
|
545
|
+
const stripped = validation.data ? this.stripODataAnnotationsIfNeeded(validation.data, options) : null;
|
|
546
|
+
return {
|
|
547
|
+
data: stripped,
|
|
548
|
+
error: void 0
|
|
549
|
+
};
|
|
550
|
+
} else {
|
|
551
|
+
const validation = await validateListResponse(
|
|
552
|
+
response,
|
|
553
|
+
schema,
|
|
554
|
+
selectedFields,
|
|
555
|
+
expandValidationConfigs
|
|
556
|
+
);
|
|
557
|
+
if (!validation.valid) {
|
|
558
|
+
return { data: void 0, error: validation.error };
|
|
559
|
+
}
|
|
560
|
+
const stripped = validation.data.map(
|
|
561
|
+
(record) => this.stripODataAnnotationsIfNeeded(record, options)
|
|
562
|
+
);
|
|
563
|
+
return {
|
|
564
|
+
data: stripped,
|
|
565
|
+
error: void 0
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
} catch (error) {
|
|
569
|
+
return {
|
|
570
|
+
data: void 0,
|
|
571
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
getQueryString() {
|
|
576
|
+
const queryOptionsWithoutExpand = { ...this.queryOptions };
|
|
577
|
+
delete queryOptionsWithoutExpand.expand;
|
|
578
|
+
if (queryOptionsWithoutExpand.select) {
|
|
579
|
+
queryOptionsWithoutExpand.select = this.formatSelectFields(
|
|
580
|
+
queryOptionsWithoutExpand.select
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
let queryParams = buildQuery(queryOptionsWithoutExpand);
|
|
584
|
+
if (this.queryOptions.select) {
|
|
585
|
+
queryParams = queryParams.replace(
|
|
586
|
+
/\$select=([^&]*)/,
|
|
587
|
+
(match, selectValue) => {
|
|
588
|
+
return `$select=${selectValue.replace(/%20/g, " ")}`;
|
|
589
|
+
}
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
const expandString = this.buildExpandString(this.expandConfigs);
|
|
593
|
+
if (expandString) {
|
|
594
|
+
const separator = queryParams.includes("?") ? "&" : "?";
|
|
595
|
+
queryParams = `${queryParams}${separator}$expand=${expandString}`;
|
|
596
|
+
}
|
|
597
|
+
if (this.isNavigate && this.navigateRecordId && this.navigateRelation && this.navigateSourceTableName) {
|
|
598
|
+
let path;
|
|
599
|
+
if (this.navigateBaseRelation) {
|
|
600
|
+
path = `/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}`;
|
|
601
|
+
} else {
|
|
602
|
+
path = `/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}`;
|
|
603
|
+
}
|
|
604
|
+
return queryParams ? `${path}${queryParams}` : path;
|
|
605
|
+
}
|
|
606
|
+
if (this.isNavigate && !this.navigateRecordId && this.navigateRelation && this.navigateSourceTableName) {
|
|
607
|
+
const path = `/${this.navigateSourceTableName}/${this.navigateRelation}`;
|
|
608
|
+
return queryParams ? `${path}${queryParams}` : path;
|
|
609
|
+
}
|
|
610
|
+
return `/${this.tableName}${queryParams}`;
|
|
611
|
+
}
|
|
612
|
+
getRequestConfig() {
|
|
613
|
+
const queryOptionsWithoutExpand = { ...this.queryOptions };
|
|
614
|
+
delete queryOptionsWithoutExpand.expand;
|
|
615
|
+
if (queryOptionsWithoutExpand.select) {
|
|
616
|
+
queryOptionsWithoutExpand.select = this.formatSelectFields(
|
|
617
|
+
queryOptionsWithoutExpand.select
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
let queryString = buildQuery(queryOptionsWithoutExpand);
|
|
621
|
+
const expandString = this.buildExpandString(this.expandConfigs);
|
|
622
|
+
if (expandString) {
|
|
623
|
+
const separator = queryString.includes("?") ? "&" : "?";
|
|
624
|
+
queryString = `${queryString}${separator}$expand=${expandString}`;
|
|
625
|
+
}
|
|
626
|
+
let url;
|
|
627
|
+
if (this.isNavigate && this.navigateRecordId && this.navigateRelation && this.navigateSourceTableName) {
|
|
628
|
+
if (this.navigateBaseRelation) {
|
|
629
|
+
url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;
|
|
630
|
+
} else {
|
|
631
|
+
url = `/${this.databaseName}/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;
|
|
632
|
+
}
|
|
633
|
+
} else if (this.isNavigate && !this.navigateRecordId && this.navigateRelation && this.navigateSourceTableName) {
|
|
634
|
+
url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}${queryString}`;
|
|
635
|
+
} else if (this.isCountMode) {
|
|
636
|
+
url = `/${this.databaseName}/${this.tableName}/$count${queryString}`;
|
|
637
|
+
} else {
|
|
638
|
+
url = `/${this.databaseName}/${this.tableName}${queryString}`;
|
|
639
|
+
}
|
|
640
|
+
return {
|
|
641
|
+
method: "GET",
|
|
642
|
+
url
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
export {
|
|
647
|
+
QueryBuilder
|
|
648
|
+
};
|
|
649
|
+
//# sourceMappingURL=query-builder.js.map
|