@acmekit/orchestration 2.13.1
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/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/joiner/helpers.d.ts +3 -0
- package/dist/joiner/helpers.d.ts.map +1 -0
- package/dist/joiner/helpers.js +69 -0
- package/dist/joiner/helpers.js.map +1 -0
- package/dist/joiner/index.d.ts +3 -0
- package/dist/joiner/index.d.ts.map +1 -0
- package/dist/joiner/index.js +19 -0
- package/dist/joiner/index.js.map +1 -0
- package/dist/joiner/remote-joiner.d.ts +43 -0
- package/dist/joiner/remote-joiner.d.ts.map +1 -0
- package/dist/joiner/remote-joiner.js +1279 -0
- package/dist/joiner/remote-joiner.js.map +1 -0
- package/dist/transaction/datastore/abstract-storage.d.ts +44 -0
- package/dist/transaction/datastore/abstract-storage.d.ts.map +1 -0
- package/dist/transaction/datastore/abstract-storage.js +52 -0
- package/dist/transaction/datastore/abstract-storage.js.map +1 -0
- package/dist/transaction/datastore/base-in-memory-storage.d.ts +12 -0
- package/dist/transaction/datastore/base-in-memory-storage.d.ts.map +1 -0
- package/dist/transaction/datastore/base-in-memory-storage.js +35 -0
- package/dist/transaction/datastore/base-in-memory-storage.js.map +1 -0
- package/dist/transaction/distributed-transaction.d.ts +116 -0
- package/dist/transaction/distributed-transaction.d.ts.map +1 -0
- package/dist/transaction/distributed-transaction.js +488 -0
- package/dist/transaction/distributed-transaction.js.map +1 -0
- package/dist/transaction/errors.d.ts +41 -0
- package/dist/transaction/errors.d.ts.map +1 -0
- package/dist/transaction/errors.js +117 -0
- package/dist/transaction/errors.js.map +1 -0
- package/dist/transaction/index.d.ts +8 -0
- package/dist/transaction/index.d.ts.map +1 -0
- package/dist/transaction/index.js +24 -0
- package/dist/transaction/index.js.map +1 -0
- package/dist/transaction/orchestrator-builder.d.ts +36 -0
- package/dist/transaction/orchestrator-builder.d.ts.map +1 -0
- package/dist/transaction/orchestrator-builder.js +300 -0
- package/dist/transaction/orchestrator-builder.js.map +1 -0
- package/dist/transaction/transaction-orchestrator.d.ts +207 -0
- package/dist/transaction/transaction-orchestrator.d.ts.map +1 -0
- package/dist/transaction/transaction-orchestrator.js +1292 -0
- package/dist/transaction/transaction-orchestrator.js.map +1 -0
- package/dist/transaction/transaction-step.d.ts +69 -0
- package/dist/transaction/transaction-step.d.ts.map +1 -0
- package/dist/transaction/transaction-step.js +153 -0
- package/dist/transaction/transaction-step.js.map +1 -0
- package/dist/transaction/types.d.ts +264 -0
- package/dist/transaction/types.d.ts.map +1 -0
- package/dist/transaction/types.js +23 -0
- package/dist/transaction/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/workflow/global-workflow.d.ts +14 -0
- package/dist/workflow/global-workflow.d.ts.map +1 -0
- package/dist/workflow/global-workflow.js +105 -0
- package/dist/workflow/global-workflow.js.map +1 -0
- package/dist/workflow/index.d.ts +5 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +21 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/local-workflow.d.ts +47 -0
- package/dist/workflow/local-workflow.d.ts.map +1 -0
- package/dist/workflow/local-workflow.js +390 -0
- package/dist/workflow/local-workflow.js.map +1 -0
- package/dist/workflow/scheduler.d.ts +12 -0
- package/dist/workflow/scheduler.d.ts.map +1 -0
- package/dist/workflow/scheduler.js +35 -0
- package/dist/workflow/scheduler.js.map +1 -0
- package/dist/workflow/workflow-manager.d.ts +38 -0
- package/dist/workflow/workflow-manager.d.ts.map +1 -0
- package/dist/workflow/workflow-manager.js +124 -0
- package/dist/workflow/workflow-manager.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,1279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RemoteJoiner = void 0;
|
|
4
|
+
const utils_1 = require("@acmekit/utils");
|
|
5
|
+
const BASE_PATH = "_root";
|
|
6
|
+
class RemoteJoiner {
|
|
7
|
+
static filterFields(data, fields, expands) {
|
|
8
|
+
if (!fields || !data) {
|
|
9
|
+
return data;
|
|
10
|
+
}
|
|
11
|
+
let filteredData = {};
|
|
12
|
+
if (fields.includes("*")) {
|
|
13
|
+
// select all fields
|
|
14
|
+
filteredData = data;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
filteredData = fields.reduce((acc, field) => {
|
|
18
|
+
const fieldValue = data?.[field];
|
|
19
|
+
if ((0, utils_1.isDefined)(fieldValue)) {
|
|
20
|
+
acc[field] = data?.[field];
|
|
21
|
+
}
|
|
22
|
+
return acc;
|
|
23
|
+
}, {});
|
|
24
|
+
}
|
|
25
|
+
if (expands) {
|
|
26
|
+
for (const key of Object.keys(expands ?? {})) {
|
|
27
|
+
const expand = expands[key];
|
|
28
|
+
if (expand) {
|
|
29
|
+
if (Array.isArray(data[key])) {
|
|
30
|
+
filteredData[key] = data[key].map((item) => RemoteJoiner.filterFields(item, expand.fields, expand.expands));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const filteredFields = RemoteJoiner.filterFields(data[key], expand.fields, expand.expands);
|
|
34
|
+
if ((0, utils_1.isDefined)(filteredFields)) {
|
|
35
|
+
filteredData[key] = RemoteJoiner.filterFields(data[key], expand.fields, expand.expands);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return (Object.keys(filteredData).length && filteredData) || undefined;
|
|
42
|
+
}
|
|
43
|
+
static getNestedItems(items, property) {
|
|
44
|
+
const result = [];
|
|
45
|
+
for (const item of items) {
|
|
46
|
+
const allValues = item?.[property] ?? [];
|
|
47
|
+
const values = Array.isArray(allValues) ? allValues : [allValues];
|
|
48
|
+
for (const value of values) {
|
|
49
|
+
if ((0, utils_1.isDefined)(value)) {
|
|
50
|
+
result.push(value);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
static createRelatedDataMap(relatedDataArray, joinFields) {
|
|
57
|
+
return relatedDataArray.reduce((acc, data) => {
|
|
58
|
+
const joinValues = joinFields.map((field) => data[field]);
|
|
59
|
+
const key = joinValues.length === 1 ? joinValues[0] : joinValues.join(",");
|
|
60
|
+
let isArray = Array.isArray(acc[key]);
|
|
61
|
+
if ((0, utils_1.isDefined)(acc[key]) && !isArray) {
|
|
62
|
+
acc[key] = [acc[key]];
|
|
63
|
+
isArray = true;
|
|
64
|
+
}
|
|
65
|
+
if (isArray) {
|
|
66
|
+
acc[key].push(data);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
acc[key] = data;
|
|
70
|
+
}
|
|
71
|
+
return acc;
|
|
72
|
+
}, {});
|
|
73
|
+
}
|
|
74
|
+
// compute ids to fetch for a relationship
|
|
75
|
+
computeIdsForRelationship(items, relationship) {
|
|
76
|
+
const field = relationship.inverse
|
|
77
|
+
? relationship.primaryKey
|
|
78
|
+
: relationship.foreignKey.split(".").pop();
|
|
79
|
+
const fieldsArray = relationship.inverse
|
|
80
|
+
? relationship.primaryKeyArr
|
|
81
|
+
: relationship.foreignKeyArr;
|
|
82
|
+
const idsToFetch = new Set();
|
|
83
|
+
for (let i = 0; i < items.length; i++) {
|
|
84
|
+
const item = items[i];
|
|
85
|
+
if (!item) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const values = fieldsArray.map((f) => item?.[f]);
|
|
89
|
+
if (values.length !== fieldsArray.length) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (fieldsArray.length === 1) {
|
|
93
|
+
const val = values[0];
|
|
94
|
+
if (Array.isArray(val)) {
|
|
95
|
+
for (let x = 0; x < val.length; x++) {
|
|
96
|
+
idsToFetch.add(val[x]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
idsToFetch.add(val);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
idsToFetch.add(values);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { field, fieldsArray, idsToFetch };
|
|
108
|
+
}
|
|
109
|
+
// assign fetched related data to items
|
|
110
|
+
assignRelatedToItems(params) {
|
|
111
|
+
const { items, relationship, relatedDataMap, field, fieldsArray } = params;
|
|
112
|
+
items.forEach((item) => {
|
|
113
|
+
if (!item) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const itemKey = fieldsArray.map((f) => item[f]).join(",");
|
|
117
|
+
if (item[relationship.alias]) {
|
|
118
|
+
if (Array.isArray(item[field])) {
|
|
119
|
+
for (let i = 0; i < item[relationship.alias].length; i++) {
|
|
120
|
+
const it = item[relationship.alias][i];
|
|
121
|
+
item[relationship.alias][i] = Object.assign(it, relatedDataMap[it[relationship.primaryKey]]);
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
item[relationship.alias] = Object.assign(item[relationship.alias], relatedDataMap[itemKey]);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (Array.isArray(item[field])) {
|
|
129
|
+
item[relationship.alias] = item[field].map((id) => {
|
|
130
|
+
if (relationship.isList && !Array.isArray(relatedDataMap[id])) {
|
|
131
|
+
relatedDataMap[id] = (0, utils_1.isDefined)(relatedDataMap[id])
|
|
132
|
+
? [relatedDataMap[id]]
|
|
133
|
+
: [];
|
|
134
|
+
}
|
|
135
|
+
return relatedDataMap[id];
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (relationship.isList && !Array.isArray(relatedDataMap[itemKey])) {
|
|
140
|
+
relatedDataMap[itemKey] = (0, utils_1.isDefined)(relatedDataMap[itemKey])
|
|
141
|
+
? [relatedDataMap[itemKey]]
|
|
142
|
+
: [];
|
|
143
|
+
}
|
|
144
|
+
item[relationship.alias] = relatedDataMap[itemKey];
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
static parseQuery(graphqlQuery, variables) {
|
|
149
|
+
const parser = new utils_1.GraphQLUtils.GraphQLParser(graphqlQuery, variables);
|
|
150
|
+
return parser.parseQuery();
|
|
151
|
+
}
|
|
152
|
+
constructor(serviceConfigs, remoteFetchData, options = {}) {
|
|
153
|
+
this.remoteFetchData = remoteFetchData;
|
|
154
|
+
this.options = options;
|
|
155
|
+
this.serviceConfigCache = new Map();
|
|
156
|
+
this.entityMap = new Map();
|
|
157
|
+
this.options.autoCreateServiceNameAlias ??= true;
|
|
158
|
+
if (this.options.entitiesMap) {
|
|
159
|
+
this.entityMap = utils_1.GraphQLUtils.extractRelationsFromGQL(this.options.entitiesMap);
|
|
160
|
+
}
|
|
161
|
+
this.buildReferences(JSON.parse(JSON.stringify(serviceConfigs), (key, value) => {
|
|
162
|
+
if (key === "schema") {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
return value;
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
setFetchDataCallback(remoteFetchData) {
|
|
169
|
+
this.remoteFetchData = remoteFetchData;
|
|
170
|
+
}
|
|
171
|
+
buildReferences(serviceConfigs) {
|
|
172
|
+
const expandedRelationships = new Map();
|
|
173
|
+
for (const service of serviceConfigs) {
|
|
174
|
+
const service_ = service;
|
|
175
|
+
if (this.serviceConfigCache.has(service_.serviceName)) {
|
|
176
|
+
throw new Error(`Service "${service_.serviceName}" is already defined.`);
|
|
177
|
+
}
|
|
178
|
+
service_.fieldAlias ??= {};
|
|
179
|
+
service_.extends ??= [];
|
|
180
|
+
service_.relationships ??= new Map();
|
|
181
|
+
if (Array.isArray(service_.relationships)) {
|
|
182
|
+
const relationships = new Map();
|
|
183
|
+
for (const relationship of service_.relationships) {
|
|
184
|
+
relationships.set(relationship.alias, relationship);
|
|
185
|
+
}
|
|
186
|
+
service_.relationships = relationships;
|
|
187
|
+
}
|
|
188
|
+
// Precompute key arrays for all existing relationships on the service
|
|
189
|
+
if (service_.relationships?.size) {
|
|
190
|
+
for (const [, relVal] of service_.relationships.entries()) {
|
|
191
|
+
if (Array.isArray(relVal)) {
|
|
192
|
+
for (let i = 0; i < relVal.length; i++) {
|
|
193
|
+
const rel = relVal[i];
|
|
194
|
+
rel.primaryKeyArr = rel.primaryKey.split(",");
|
|
195
|
+
rel.foreignKeyArr = rel.foreignKey
|
|
196
|
+
.split(",")
|
|
197
|
+
.map((fk) => fk.split(".").pop());
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else if (relVal) {
|
|
201
|
+
const rel = relVal;
|
|
202
|
+
rel.primaryKeyArr = rel.primaryKey.split(",");
|
|
203
|
+
rel.foreignKeyArr = rel.foreignKey
|
|
204
|
+
.split(",")
|
|
205
|
+
.map((fk) => fk.split(".").pop());
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// add aliases
|
|
210
|
+
const isReadOnlyDefinition = !(0, utils_1.isDefined)(service_.serviceName) || service_.isReadOnlyLink;
|
|
211
|
+
if (!isReadOnlyDefinition) {
|
|
212
|
+
service_.alias ??= [];
|
|
213
|
+
if (!Array.isArray(service_.alias)) {
|
|
214
|
+
service_.alias = [service_.alias];
|
|
215
|
+
}
|
|
216
|
+
if (this.options.autoCreateServiceNameAlias) {
|
|
217
|
+
service_.alias.push({ name: service_.serviceName });
|
|
218
|
+
}
|
|
219
|
+
// handle alias.name as array
|
|
220
|
+
for (let idx = 0; idx < service_.alias.length; idx++) {
|
|
221
|
+
const alias = service_.alias[idx];
|
|
222
|
+
if (!Array.isArray(alias.name)) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
for (const name of alias.name) {
|
|
226
|
+
service_.alias.push({
|
|
227
|
+
name,
|
|
228
|
+
entity: alias.entity,
|
|
229
|
+
args: alias.args,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
service_.alias.splice(idx, 1);
|
|
233
|
+
idx--;
|
|
234
|
+
}
|
|
235
|
+
// self-reference
|
|
236
|
+
for (const alias of service_.alias) {
|
|
237
|
+
if (this.serviceConfigCache.has(`alias_${alias.name}`)) {
|
|
238
|
+
const defined = this.serviceConfigCache.get(`alias_${alias.name}`);
|
|
239
|
+
if (service_.serviceName === defined?.serviceName) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
throw new Error(`Cannot add alias "${alias.name}" for "${service_.serviceName}". It is already defined for Service "${defined?.serviceName}".`);
|
|
243
|
+
}
|
|
244
|
+
const args = service_.args || alias.args
|
|
245
|
+
? { ...service_.args, ...alias.args }
|
|
246
|
+
: undefined;
|
|
247
|
+
const aliasName = alias.name;
|
|
248
|
+
const rel = {
|
|
249
|
+
alias: aliasName,
|
|
250
|
+
entity: alias.entity,
|
|
251
|
+
foreignKey: alias.name + "_id",
|
|
252
|
+
primaryKey: "id",
|
|
253
|
+
serviceName: service_.serviceName,
|
|
254
|
+
args,
|
|
255
|
+
};
|
|
256
|
+
if (service_.relationships?.has(aliasName)) {
|
|
257
|
+
const existing = service_.relationships.get(aliasName);
|
|
258
|
+
const newRelation = Array.isArray(existing)
|
|
259
|
+
? existing.concat(rel)
|
|
260
|
+
: [existing, rel];
|
|
261
|
+
service_.relationships?.set(aliasName, newRelation);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
service_.relationships?.set(aliasName, rel);
|
|
265
|
+
}
|
|
266
|
+
this.cacheServiceConfig(serviceConfigs, { serviceAlias: alias });
|
|
267
|
+
}
|
|
268
|
+
this.cacheServiceConfig(serviceConfigs, {
|
|
269
|
+
serviceName: service_.serviceName,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
for (const extend of service_.extends) {
|
|
273
|
+
if (!expandedRelationships.has(extend.serviceName)) {
|
|
274
|
+
expandedRelationships.set(extend.serviceName, {
|
|
275
|
+
fieldAlias: {},
|
|
276
|
+
relationships: new Map(),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
const service_ = expandedRelationships.get(extend.serviceName);
|
|
280
|
+
const aliasName = extend.relationship.alias;
|
|
281
|
+
const rel = extend.relationship;
|
|
282
|
+
rel.primaryKeyArr = rel.primaryKey.split(",");
|
|
283
|
+
rel.foreignKeyArr = rel.foreignKey
|
|
284
|
+
.split(",")
|
|
285
|
+
.map((fk) => fk.split(".").pop());
|
|
286
|
+
if (service_.relationships?.has(aliasName)) {
|
|
287
|
+
const existing = service_.relationships.get(aliasName);
|
|
288
|
+
const newRelation = Array.isArray(existing)
|
|
289
|
+
? existing.concat(rel)
|
|
290
|
+
: [existing, rel];
|
|
291
|
+
service_.relationships?.set(aliasName, newRelation);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
service_.relationships?.set(aliasName, rel);
|
|
295
|
+
}
|
|
296
|
+
// Multiple "fieldAlias" w/ same name need the entity to handle different paths
|
|
297
|
+
this.mergeFieldAlias(service_, extend);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
for (const [serviceName, { fieldAlias, relationships },] of expandedRelationships) {
|
|
301
|
+
if (!this.serviceConfigCache.has(serviceName)) {
|
|
302
|
+
throw new Error(`Service "${serviceName}" was not found`);
|
|
303
|
+
}
|
|
304
|
+
const service_ = this.serviceConfigCache.get(serviceName);
|
|
305
|
+
relationships.forEach((relationship, alias) => {
|
|
306
|
+
const rel = relationship;
|
|
307
|
+
if (service_.relationships?.has(alias)) {
|
|
308
|
+
const existing = service_.relationships.get(alias);
|
|
309
|
+
const newRelation = Array.isArray(existing)
|
|
310
|
+
? existing.concat(rel)
|
|
311
|
+
: [existing, rel];
|
|
312
|
+
service_.relationships?.set(alias, newRelation);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
service_.relationships?.set(alias, rel);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
Object.assign(service_.fieldAlias, fieldAlias ?? {});
|
|
319
|
+
if (Object.keys(service_.fieldAlias).length) {
|
|
320
|
+
const conflictAliases = Array.from(service_.relationships.keys()).filter((alias) => fieldAlias[alias]);
|
|
321
|
+
if (conflictAliases.length) {
|
|
322
|
+
throw new Error(`Conflict configuration for service "${serviceName}". The following aliases are already defined as relationships: ${conflictAliases.join(", ")}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return serviceConfigs;
|
|
327
|
+
}
|
|
328
|
+
mergeFieldAlias(service_, extend) {
|
|
329
|
+
for (const [alias, fieldAlias] of Object.entries(extend.fieldAlias ?? {})) {
|
|
330
|
+
const objAlias = (0, utils_1.isString)(fieldAlias)
|
|
331
|
+
? { path: fieldAlias }
|
|
332
|
+
: fieldAlias;
|
|
333
|
+
if (service_.fieldAlias[alias]) {
|
|
334
|
+
if (!Array.isArray(service_.fieldAlias[alias])) {
|
|
335
|
+
service_.fieldAlias[alias] = [service_.fieldAlias[alias]];
|
|
336
|
+
}
|
|
337
|
+
if (service_.fieldAlias[alias].some((f) => f.entity === extend.entity)) {
|
|
338
|
+
throw new Error(`Cannot add alias "${alias}" for "${extend.serviceName}". It is already defined for Entity "${extend.entity}".`);
|
|
339
|
+
}
|
|
340
|
+
service_.fieldAlias[alias].push({
|
|
341
|
+
...objAlias,
|
|
342
|
+
entity: extend.entity,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
service_.fieldAlias[alias] = {
|
|
347
|
+
...objAlias,
|
|
348
|
+
entity: extend.entity,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
getServiceConfig({ serviceName, serviceAlias, entity, }) {
|
|
354
|
+
if (entity) {
|
|
355
|
+
const name = `entity_${entity}`;
|
|
356
|
+
const serviceConfig = this.serviceConfigCache.get(name);
|
|
357
|
+
if (serviceConfig) {
|
|
358
|
+
return serviceConfig;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (serviceAlias) {
|
|
362
|
+
const name = `alias_${serviceAlias}`;
|
|
363
|
+
return this.serviceConfigCache.get(name);
|
|
364
|
+
}
|
|
365
|
+
return this.serviceConfigCache.get(serviceName);
|
|
366
|
+
}
|
|
367
|
+
cacheServiceConfig(serviceConfigs, params) {
|
|
368
|
+
const { serviceName, serviceAlias } = params;
|
|
369
|
+
if (serviceAlias) {
|
|
370
|
+
const name = `alias_${serviceAlias.name}`;
|
|
371
|
+
if (!this.serviceConfigCache.has(name)) {
|
|
372
|
+
let aliasConfig;
|
|
373
|
+
const config = serviceConfigs.find((conf) => {
|
|
374
|
+
const aliases = conf.alias;
|
|
375
|
+
const hasArgs = aliases?.find((alias) => alias.name === serviceAlias.name);
|
|
376
|
+
aliasConfig = hasArgs;
|
|
377
|
+
return hasArgs;
|
|
378
|
+
});
|
|
379
|
+
if (config) {
|
|
380
|
+
const serviceConfig = { ...config, entity: serviceAlias.entity };
|
|
381
|
+
if (aliasConfig) {
|
|
382
|
+
serviceConfig.args = { ...config?.args, ...aliasConfig?.args };
|
|
383
|
+
}
|
|
384
|
+
this.serviceConfigCache.set(name, serviceConfig);
|
|
385
|
+
const entity = serviceAlias.entity;
|
|
386
|
+
if (entity) {
|
|
387
|
+
const name = `entity_${entity}`;
|
|
388
|
+
this.serviceConfigCache.set(name, serviceConfig);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const config = serviceConfigs.find((config) => config.serviceName === serviceName);
|
|
395
|
+
this.serviceConfigCache.set(serviceName, config);
|
|
396
|
+
}
|
|
397
|
+
async fetchData(params) {
|
|
398
|
+
const { expand, pkField, ids, relationship, options } = params;
|
|
399
|
+
let uniqueIds;
|
|
400
|
+
if (ids != null) {
|
|
401
|
+
const isIdsUsingOperatorMap = (0, utils_1.isObject)(ids) &&
|
|
402
|
+
Object.keys(ids).some((key) => !!utils_1.FilterOperatorMap[key]);
|
|
403
|
+
uniqueIds = isIdsUsingOperatorMap ? ids : Array.isArray(ids) ? ids : [ids];
|
|
404
|
+
uniqueIds = Array.isArray(uniqueIds)
|
|
405
|
+
? uniqueIds.filter((id) => id != null)
|
|
406
|
+
: uniqueIds;
|
|
407
|
+
}
|
|
408
|
+
if (uniqueIds && Array.isArray(uniqueIds)) {
|
|
409
|
+
const isCompositeKey = Array.isArray(uniqueIds[0]);
|
|
410
|
+
if (isCompositeKey) {
|
|
411
|
+
const seen = new Set();
|
|
412
|
+
uniqueIds = uniqueIds.filter((idArray) => {
|
|
413
|
+
const key = JSON.stringify(idArray);
|
|
414
|
+
const isNew = !seen.has(key);
|
|
415
|
+
seen.add(key);
|
|
416
|
+
return isNew;
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
uniqueIds = Array.from(new Set(uniqueIds.flat()));
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
let pkFieldAdjusted = pkField;
|
|
424
|
+
if (relationship) {
|
|
425
|
+
pkFieldAdjusted = relationship.inverse
|
|
426
|
+
? relationship.foreignKey.split(".").pop()
|
|
427
|
+
: relationship.primaryKey;
|
|
428
|
+
}
|
|
429
|
+
const response = await this.remoteFetchData(expand, pkFieldAdjusted, uniqueIds, relationship);
|
|
430
|
+
const isObj = (0, utils_1.isDefined)(response.path);
|
|
431
|
+
let resData = isObj ? response.data[response.path] : response.data;
|
|
432
|
+
resData = (0, utils_1.isDefined)(resData)
|
|
433
|
+
? Array.isArray(resData)
|
|
434
|
+
? resData
|
|
435
|
+
: [resData]
|
|
436
|
+
: [];
|
|
437
|
+
this.checkIfKeysExist({
|
|
438
|
+
uniqueIds,
|
|
439
|
+
resData,
|
|
440
|
+
expand,
|
|
441
|
+
pkField: pkFieldAdjusted,
|
|
442
|
+
relationship,
|
|
443
|
+
options,
|
|
444
|
+
});
|
|
445
|
+
const filteredDataArray = resData.map((data) => RemoteJoiner.filterFields(data, expand.fields, expand.expands));
|
|
446
|
+
if (isObj) {
|
|
447
|
+
response.data[response.path] = filteredDataArray;
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
response.data = filteredDataArray;
|
|
451
|
+
}
|
|
452
|
+
return response;
|
|
453
|
+
}
|
|
454
|
+
checkIfKeysExist(params) {
|
|
455
|
+
const { uniqueIds, resData, expand, pkField, relationship, options } = params;
|
|
456
|
+
if (!((0, utils_1.isDefined)(uniqueIds) &&
|
|
457
|
+
((options?.throwIfKeyNotFound && !(0, utils_1.isDefined)(relationship)) ||
|
|
458
|
+
(options?.throwIfRelationNotFound && (0, utils_1.isDefined)(relationship))))) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if ((0, utils_1.isDefined)(relationship)) {
|
|
462
|
+
if (Array.isArray(options?.throwIfRelationNotFound) &&
|
|
463
|
+
!options?.throwIfRelationNotFound.includes(relationship.serviceName)) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const notFound = new Set(uniqueIds);
|
|
468
|
+
resData.forEach((data) => {
|
|
469
|
+
notFound.delete(data[pkField]);
|
|
470
|
+
});
|
|
471
|
+
if (notFound.size > 0) {
|
|
472
|
+
const entityName = expand.serviceConfig.entity ??
|
|
473
|
+
expand.serviceConfig.args?.methodSuffix ??
|
|
474
|
+
expand.serviceConfig.serviceName;
|
|
475
|
+
throw new utils_1.AcmeKitError(utils_1.AcmeKitError.Types.NOT_FOUND, `${entityName} ${pkField} not found: ` + Array.from(notFound).join(", "));
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
handleFieldAliases(params) {
|
|
479
|
+
const { items, parsedExpands, implodeMapping } = params;
|
|
480
|
+
const getChildren = (item, prop) => {
|
|
481
|
+
if (Array.isArray(item)) {
|
|
482
|
+
return item.flatMap((currentItem) => currentItem[prop]);
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
return item[prop];
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
const removeChildren = (item, prop) => {
|
|
489
|
+
if (Array.isArray(item)) {
|
|
490
|
+
for (let i = 0; i < item.length; i++) {
|
|
491
|
+
Object.defineProperty(item[i], prop, {
|
|
492
|
+
value: undefined,
|
|
493
|
+
enumerable: false,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
Object.defineProperty(item, prop, {
|
|
499
|
+
value: undefined,
|
|
500
|
+
enumerable: false,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
const cleanup = [];
|
|
505
|
+
for (const alias of implodeMapping) {
|
|
506
|
+
const propPath = alias.path;
|
|
507
|
+
let itemsLocation = items;
|
|
508
|
+
for (const locationProp of alias.location) {
|
|
509
|
+
propPath.shift();
|
|
510
|
+
itemsLocation = RemoteJoiner.getNestedItems(itemsLocation, locationProp);
|
|
511
|
+
}
|
|
512
|
+
itemsLocation.forEach((locationItem) => {
|
|
513
|
+
if (!locationItem) {
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
let currentItems = locationItem;
|
|
517
|
+
let parentRemoveItems = null;
|
|
518
|
+
const curPath = [BASE_PATH].concat(alias.location);
|
|
519
|
+
for (const prop of propPath) {
|
|
520
|
+
if (!(0, utils_1.isDefined)(currentItems)) {
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
curPath.push(prop);
|
|
524
|
+
const config = parsedExpands.get(curPath.join("."));
|
|
525
|
+
if (config?.isAliasMapping && parentRemoveItems === null) {
|
|
526
|
+
parentRemoveItems = [currentItems, prop];
|
|
527
|
+
}
|
|
528
|
+
currentItems = getChildren(currentItems, prop);
|
|
529
|
+
}
|
|
530
|
+
if (Array.isArray(currentItems)) {
|
|
531
|
+
if (currentItems.length < 2 && !alias.isList) {
|
|
532
|
+
locationItem[alias.property] = currentItems.shift();
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
locationItem[alias.property] = currentItems;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
locationItem[alias.property] = alias.isList
|
|
540
|
+
? (0, utils_1.isDefined)(currentItems)
|
|
541
|
+
? [currentItems]
|
|
542
|
+
: []
|
|
543
|
+
: currentItems;
|
|
544
|
+
}
|
|
545
|
+
if (parentRemoveItems !== null) {
|
|
546
|
+
cleanup.push(parentRemoveItems);
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
for (const parentRemoveItems of cleanup) {
|
|
551
|
+
const [remItems, path] = parentRemoveItems;
|
|
552
|
+
removeChildren(remItems, path);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
async handleExpands(params) {
|
|
556
|
+
const { items, parsedExpands, implodeMapping = [], options } = params;
|
|
557
|
+
if (parsedExpands.size === 0) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
const getItemsForPath = (rootItems, fullPath) => {
|
|
561
|
+
let nestedItems = rootItems;
|
|
562
|
+
const expandedPathLevels = fullPath.split(".");
|
|
563
|
+
for (let idx = 1; idx < expandedPathLevels.length - 1; idx++) {
|
|
564
|
+
nestedItems = RemoteJoiner.getNestedItems(nestedItems, expandedPathLevels[idx]);
|
|
565
|
+
}
|
|
566
|
+
return nestedItems;
|
|
567
|
+
};
|
|
568
|
+
const root = parsedExpands.get(BASE_PATH);
|
|
569
|
+
const executionStages = root?.executionStages;
|
|
570
|
+
// remove root
|
|
571
|
+
root?.executionStages.shift();
|
|
572
|
+
for (const stage of executionStages) {
|
|
573
|
+
const stageFetchGroups = [];
|
|
574
|
+
for (const { paths } of stage) {
|
|
575
|
+
const pathCtx = [];
|
|
576
|
+
for (const path of paths) {
|
|
577
|
+
const expand = parsedExpands.get(path);
|
|
578
|
+
const nestedItems = getItemsForPath(items, path);
|
|
579
|
+
if (!nestedItems?.length || !expand) {
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
const relationship = this.getEntityRelationship({
|
|
583
|
+
parentServiceConfig: expand.parentConfig,
|
|
584
|
+
property: expand.property,
|
|
585
|
+
entity: expand.entity,
|
|
586
|
+
});
|
|
587
|
+
if (!relationship) {
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
const { field, fieldsArray, idsToFetch } = this.computeIdsForRelationship(nestedItems, relationship);
|
|
591
|
+
pathCtx.push({
|
|
592
|
+
path,
|
|
593
|
+
expand,
|
|
594
|
+
relationship,
|
|
595
|
+
nestedItems,
|
|
596
|
+
field,
|
|
597
|
+
fieldsArray,
|
|
598
|
+
args: expand.args,
|
|
599
|
+
ids: idsToFetch,
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
if (!pathCtx.length) {
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
// Group by pkField
|
|
606
|
+
const byPkField = new Map();
|
|
607
|
+
for (const ctx of pathCtx) {
|
|
608
|
+
const key = ctx.field;
|
|
609
|
+
if (!byPkField.has(key)) {
|
|
610
|
+
byPkField.set(key, []);
|
|
611
|
+
}
|
|
612
|
+
byPkField.get(key).push(ctx);
|
|
613
|
+
}
|
|
614
|
+
for (const [pkField, ctxs] of byPkField.entries()) {
|
|
615
|
+
const unionIds = Array.from(new Set(ctxs.flatMap((c) => Array.from(c.ids))));
|
|
616
|
+
const unionFields = Array.from(new Set(ctxs.flatMap((c) => c.expand.fields ?? [])));
|
|
617
|
+
const unionArgs = ctxs.flatMap((c) => c.expand.args ?? []);
|
|
618
|
+
const base = ctxs[0].expand;
|
|
619
|
+
const aggExpand = {
|
|
620
|
+
...base,
|
|
621
|
+
fields: unionFields,
|
|
622
|
+
};
|
|
623
|
+
if (unionArgs.length) {
|
|
624
|
+
aggExpand.args = unionArgs;
|
|
625
|
+
}
|
|
626
|
+
const relationship = ctxs[0].relationship;
|
|
627
|
+
const promise = this.fetchData({
|
|
628
|
+
expand: aggExpand,
|
|
629
|
+
pkField,
|
|
630
|
+
ids: unionIds,
|
|
631
|
+
relationship,
|
|
632
|
+
options,
|
|
633
|
+
});
|
|
634
|
+
stageFetchGroups.push({ ctxs, relationship, promise });
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
const stageResults = await Promise.all(stageFetchGroups.map((g) => g.promise));
|
|
638
|
+
for (let i = 0; i < stageFetchGroups.length; i++) {
|
|
639
|
+
const { ctxs, relationship } = stageFetchGroups[i];
|
|
640
|
+
const relatedDataArray = stageResults[i];
|
|
641
|
+
const joinFields = relationship.inverse
|
|
642
|
+
? relationship.foreignKeyArr
|
|
643
|
+
: relationship.primaryKeyArr;
|
|
644
|
+
const relData = relatedDataArray.path
|
|
645
|
+
? relatedDataArray.data[relatedDataArray.path]
|
|
646
|
+
: relatedDataArray.data;
|
|
647
|
+
const relatedDataMap = RemoteJoiner.createRelatedDataMap(relData, joinFields);
|
|
648
|
+
for (let ci = 0; ci < ctxs.length; ci++) {
|
|
649
|
+
const ctx = ctxs[ci];
|
|
650
|
+
this.assignRelatedToItems({
|
|
651
|
+
items: ctx.nestedItems,
|
|
652
|
+
relationship: ctx.relationship,
|
|
653
|
+
relatedDataMap,
|
|
654
|
+
field: ctx.field,
|
|
655
|
+
fieldsArray: ctx.fieldsArray,
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (implodeMapping.length > 0) {
|
|
661
|
+
this.handleFieldAliases({
|
|
662
|
+
items,
|
|
663
|
+
parsedExpands,
|
|
664
|
+
implodeMapping,
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
getEntityRelationship(params) {
|
|
669
|
+
const { parentServiceConfig, property, entity } = params;
|
|
670
|
+
const propEntity = entity ?? parentServiceConfig?.entity;
|
|
671
|
+
const rel = parentServiceConfig?.relationships?.get(property);
|
|
672
|
+
if (Array.isArray(rel)) {
|
|
673
|
+
if (!propEntity) {
|
|
674
|
+
return rel[0];
|
|
675
|
+
}
|
|
676
|
+
const entityRel = rel.find((r) => r.entity === propEntity);
|
|
677
|
+
if (entityRel) {
|
|
678
|
+
return entityRel;
|
|
679
|
+
}
|
|
680
|
+
// If entity is not found, return the relationship where the primary key matches
|
|
681
|
+
const serviceEntity = this.getServiceConfig({
|
|
682
|
+
entity: propEntity,
|
|
683
|
+
});
|
|
684
|
+
return rel.find((r) => serviceEntity.primaryKeys.includes(r.primaryKey));
|
|
685
|
+
}
|
|
686
|
+
return rel;
|
|
687
|
+
}
|
|
688
|
+
parseExpands(params) {
|
|
689
|
+
const { initialService, query, serviceConfig, expands, implodeMapping, options, initialData, initialDataOnly, } = params;
|
|
690
|
+
const { parsedExpands, aliasRealPathMap } = this.parseProperties({
|
|
691
|
+
initialService,
|
|
692
|
+
query,
|
|
693
|
+
serviceConfig,
|
|
694
|
+
expands,
|
|
695
|
+
implodeMapping,
|
|
696
|
+
});
|
|
697
|
+
if (initialData?.length && initialDataOnly) {
|
|
698
|
+
this.createFilterFromInitialData({
|
|
699
|
+
initialData: options?.initialData,
|
|
700
|
+
parsedExpands,
|
|
701
|
+
aliasRealPathMap,
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
const groupedExpands = this.groupExpands(parsedExpands);
|
|
705
|
+
this.buildQueryPlan(parsedExpands, groupedExpands);
|
|
706
|
+
return groupedExpands;
|
|
707
|
+
}
|
|
708
|
+
buildQueryPlan(fullParsedExpands, groupedExpands) {
|
|
709
|
+
const stages = [];
|
|
710
|
+
// Root stage
|
|
711
|
+
const rootExp = groupedExpands.get(BASE_PATH);
|
|
712
|
+
const rootService = rootExp.serviceConfig.serviceName;
|
|
713
|
+
stages.push([
|
|
714
|
+
{
|
|
715
|
+
service: rootService,
|
|
716
|
+
entity: rootExp.entity,
|
|
717
|
+
paths: [],
|
|
718
|
+
depth: 0,
|
|
719
|
+
},
|
|
720
|
+
]);
|
|
721
|
+
// Build service sequence for each path
|
|
722
|
+
const getServiceSequence = (path) => {
|
|
723
|
+
const sequence = [];
|
|
724
|
+
let currentPath = path;
|
|
725
|
+
while (currentPath && currentPath !== BASE_PATH) {
|
|
726
|
+
const expand = fullParsedExpands.get(currentPath);
|
|
727
|
+
if (!expand) {
|
|
728
|
+
break;
|
|
729
|
+
}
|
|
730
|
+
sequence.unshift(expand.serviceConfig.serviceName);
|
|
731
|
+
currentPath = expand.parent;
|
|
732
|
+
}
|
|
733
|
+
return sequence;
|
|
734
|
+
};
|
|
735
|
+
// Group paths by their service sequence length and last service in sequence
|
|
736
|
+
const pathsBySequenceDepth = new Map();
|
|
737
|
+
for (const [path, expand] of groupedExpands.entries()) {
|
|
738
|
+
if (path === BASE_PATH) {
|
|
739
|
+
continue;
|
|
740
|
+
}
|
|
741
|
+
const serviceSequence = getServiceSequence(path);
|
|
742
|
+
const sequenceDepth = serviceSequence.length;
|
|
743
|
+
const lastService = expand.serviceConfig.serviceName;
|
|
744
|
+
if (!pathsBySequenceDepth.has(sequenceDepth)) {
|
|
745
|
+
pathsBySequenceDepth.set(sequenceDepth, new Map());
|
|
746
|
+
}
|
|
747
|
+
const depthMap = pathsBySequenceDepth.get(sequenceDepth);
|
|
748
|
+
if (!depthMap.has(lastService)) {
|
|
749
|
+
depthMap.set(lastService, []);
|
|
750
|
+
}
|
|
751
|
+
depthMap.get(lastService).push(path);
|
|
752
|
+
}
|
|
753
|
+
const maxDepth = Math.max(...Array.from(pathsBySequenceDepth.keys()));
|
|
754
|
+
for (let depth = 1; depth <= maxDepth; depth++) {
|
|
755
|
+
const serviceMap = pathsBySequenceDepth.get(depth);
|
|
756
|
+
if (!serviceMap) {
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
const stageGroups = [];
|
|
760
|
+
for (const [service, paths] of serviceMap.entries()) {
|
|
761
|
+
stageGroups.push({
|
|
762
|
+
service,
|
|
763
|
+
paths,
|
|
764
|
+
depth: depth,
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
if (stageGroups.length > 0) {
|
|
768
|
+
stages.push(stageGroups);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
const root = groupedExpands.get(BASE_PATH);
|
|
772
|
+
root.executionStages = stages;
|
|
773
|
+
}
|
|
774
|
+
parseProperties(params) {
|
|
775
|
+
const { initialService, query, serviceConfig, expands, implodeMapping } = params;
|
|
776
|
+
const aliasRealPathMap = new Map();
|
|
777
|
+
const parsedExpands = new Map();
|
|
778
|
+
parsedExpands.set(BASE_PATH, initialService);
|
|
779
|
+
const forwardArgumentsOnPath = [];
|
|
780
|
+
for (const expand of expands || []) {
|
|
781
|
+
const properties = expand.property.split(".");
|
|
782
|
+
const currentPath = [];
|
|
783
|
+
const currentAliasPath = [];
|
|
784
|
+
let currentServiceConfig = serviceConfig;
|
|
785
|
+
for (const prop of properties) {
|
|
786
|
+
const fieldAlias = currentServiceConfig.fieldAlias ?? {};
|
|
787
|
+
if (fieldAlias[prop]) {
|
|
788
|
+
const aliasPath = [BASE_PATH, ...currentPath, prop].join(".");
|
|
789
|
+
const lastServiceConfig = this.parseAlias({
|
|
790
|
+
aliasPath,
|
|
791
|
+
aliasRealPathMap,
|
|
792
|
+
expands,
|
|
793
|
+
expand,
|
|
794
|
+
property: prop,
|
|
795
|
+
parsedExpands,
|
|
796
|
+
currentServiceConfig,
|
|
797
|
+
currentPath,
|
|
798
|
+
implodeMapping,
|
|
799
|
+
forwardArgumentsOnPath,
|
|
800
|
+
});
|
|
801
|
+
currentAliasPath.push(prop);
|
|
802
|
+
currentServiceConfig = lastServiceConfig;
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
const fullPath = [BASE_PATH, ...currentPath, prop].join(".");
|
|
806
|
+
const fullAliasPath = [BASE_PATH, ...currentAliasPath, prop].join(".");
|
|
807
|
+
let entity = currentServiceConfig.entity;
|
|
808
|
+
if (entity) {
|
|
809
|
+
const completePath = fullPath.split(".");
|
|
810
|
+
for (let i = 1; i < completePath.length; i++) {
|
|
811
|
+
entity = this.getEntity({ entity, prop: completePath[i] }) ?? entity;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
const relationship = this.getEntityRelationship({
|
|
815
|
+
parentServiceConfig: currentServiceConfig,
|
|
816
|
+
property: prop,
|
|
817
|
+
entity,
|
|
818
|
+
});
|
|
819
|
+
const isCurrentProp = fullPath === BASE_PATH + "." + expand.property ||
|
|
820
|
+
fullAliasPath == BASE_PATH + "." + expand.property;
|
|
821
|
+
let fields = isCurrentProp ? expand.fields ?? [] : [];
|
|
822
|
+
const args = isCurrentProp ? expand.args : [];
|
|
823
|
+
if (relationship) {
|
|
824
|
+
const parentExpand = parsedExpands.get([BASE_PATH, ...currentPath].join(".")) || query;
|
|
825
|
+
if (parentExpand) {
|
|
826
|
+
const parRelField = relationship.inverse
|
|
827
|
+
? relationship.primaryKey
|
|
828
|
+
: relationship.foreignKey.split(".").pop();
|
|
829
|
+
parentExpand.fields ??= [];
|
|
830
|
+
parentExpand.fields = parentExpand.fields
|
|
831
|
+
.concat(parRelField.split(","))
|
|
832
|
+
.filter((field) => field !== relationship.alias);
|
|
833
|
+
parentExpand.fields = (0, utils_1.deduplicate)(parentExpand.fields);
|
|
834
|
+
const relField = relationship.inverse
|
|
835
|
+
? relationship.foreignKey.split(".").pop()
|
|
836
|
+
: relationship.primaryKey;
|
|
837
|
+
fields = fields.concat(relField.split(","));
|
|
838
|
+
}
|
|
839
|
+
currentServiceConfig = this.getServiceConfig({
|
|
840
|
+
serviceName: relationship.serviceName,
|
|
841
|
+
entity: relationship.entity,
|
|
842
|
+
});
|
|
843
|
+
if (!currentServiceConfig) {
|
|
844
|
+
throw new Error(`Target service not found: ${relationship.serviceName}`);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
const isAliasMapping = expand.isAliasMapping;
|
|
848
|
+
if (!parsedExpands.has(fullPath)) {
|
|
849
|
+
let parentPath = [BASE_PATH, ...currentPath].join(".");
|
|
850
|
+
if (aliasRealPathMap.has(parentPath)) {
|
|
851
|
+
parentPath = aliasRealPathMap
|
|
852
|
+
.get(parentPath)
|
|
853
|
+
.slice(0, -1)
|
|
854
|
+
.join(".");
|
|
855
|
+
}
|
|
856
|
+
parsedExpands.set(fullPath, {
|
|
857
|
+
property: prop,
|
|
858
|
+
serviceConfig: currentServiceConfig,
|
|
859
|
+
entity: entity,
|
|
860
|
+
fields,
|
|
861
|
+
args: isAliasMapping
|
|
862
|
+
? forwardArgumentsOnPath.includes(fullPath)
|
|
863
|
+
? args
|
|
864
|
+
: undefined
|
|
865
|
+
: args,
|
|
866
|
+
isAliasMapping: isAliasMapping,
|
|
867
|
+
parent: parentPath,
|
|
868
|
+
parentConfig: parsedExpands.get(parentPath).serviceConfig,
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
else {
|
|
872
|
+
const exp = parsedExpands.get(fullPath);
|
|
873
|
+
if (forwardArgumentsOnPath.includes(fullPath) && args) {
|
|
874
|
+
exp.args = (exp.args || []).concat(args);
|
|
875
|
+
}
|
|
876
|
+
exp.isAliasMapping ??= isAliasMapping;
|
|
877
|
+
if (fields) {
|
|
878
|
+
exp.fields = (0, utils_1.deduplicate)((exp.fields ?? []).concat(fields));
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
currentPath.push(prop);
|
|
882
|
+
currentAliasPath.push(prop);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return { parsedExpands, aliasRealPathMap };
|
|
886
|
+
}
|
|
887
|
+
getEntity({ entity, prop }) {
|
|
888
|
+
return this.entityMap.get(entity)?.get(prop);
|
|
889
|
+
}
|
|
890
|
+
parseAlias({ aliasPath, aliasRealPathMap, expands, expand, property, parsedExpands, currentServiceConfig, currentPath, implodeMapping, forwardArgumentsOnPath, }) {
|
|
891
|
+
const serviceConfig = currentServiceConfig;
|
|
892
|
+
const fieldAlias = currentServiceConfig.fieldAlias ?? {};
|
|
893
|
+
let alias = fieldAlias[property];
|
|
894
|
+
// Handle multiple shortcuts for the same property
|
|
895
|
+
if (Array.isArray(alias)) {
|
|
896
|
+
const currentPathEntity = parsedExpands.get([BASE_PATH, ...currentPath].join("."))?.entity;
|
|
897
|
+
alias = alias.find((a) => a.entity == currentPathEntity);
|
|
898
|
+
if (!alias) {
|
|
899
|
+
throw new Error(`Cannot resolve alias path "${currentPath.join(".")}" that matches entity ${currentPathEntity}.`);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
const path = (0, utils_1.isString)(alias) ? alias : alias.path;
|
|
903
|
+
const fieldAliasIsList = (0, utils_1.isString)(alias) ? false : !!alias.isList;
|
|
904
|
+
const fullPath = [...currentPath.concat(path.split("."))];
|
|
905
|
+
if (aliasRealPathMap.has(aliasPath)) {
|
|
906
|
+
currentPath.push(...path.split("."));
|
|
907
|
+
const fullPath = [BASE_PATH, ...currentPath].join(".");
|
|
908
|
+
return parsedExpands.get(fullPath).serviceConfig;
|
|
909
|
+
}
|
|
910
|
+
const parentPath = [BASE_PATH, ...currentPath].join(".");
|
|
911
|
+
const parentExpands = parsedExpands.get(parentPath);
|
|
912
|
+
parentExpands.fields = parentExpands.fields?.filter((field) => field !== property);
|
|
913
|
+
forwardArgumentsOnPath.push(...(alias?.forwardArgumentsOnPath || []).map((forPath) => BASE_PATH + "." + currentPath.concat(forPath).join(".")));
|
|
914
|
+
const parentFieldAlias = fullPath[Math.max(fullPath.length - 2, 0)];
|
|
915
|
+
implodeMapping.push({
|
|
916
|
+
location: [...currentPath],
|
|
917
|
+
property,
|
|
918
|
+
path: fullPath,
|
|
919
|
+
isList: fieldAliasIsList ||
|
|
920
|
+
!!serviceConfig.relationships?.get(parentFieldAlias)?.isList,
|
|
921
|
+
});
|
|
922
|
+
const extMapping = expands;
|
|
923
|
+
const fullAliasProp = fullPath.join(".");
|
|
924
|
+
const middlePath = path.split(".");
|
|
925
|
+
let curMiddlePath = currentPath;
|
|
926
|
+
for (const path of middlePath) {
|
|
927
|
+
curMiddlePath = curMiddlePath.concat(path);
|
|
928
|
+
const midProp = curMiddlePath.join(".");
|
|
929
|
+
const existingExpand = expands.find((exp) => exp.property === midProp);
|
|
930
|
+
const extraExtends = {
|
|
931
|
+
fields: existingExpand?.fields,
|
|
932
|
+
args: existingExpand?.args,
|
|
933
|
+
...(midProp === fullAliasProp ? expand : {}),
|
|
934
|
+
property: midProp,
|
|
935
|
+
isAliasMapping: !existingExpand,
|
|
936
|
+
};
|
|
937
|
+
if (forwardArgumentsOnPath.includes(BASE_PATH + "." + midProp)) {
|
|
938
|
+
const forwarded = (existingExpand?.args ?? []).concat(expand?.args ?? []);
|
|
939
|
+
if (forwarded.length) {
|
|
940
|
+
extraExtends.args = forwarded;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
extMapping.push(extraExtends);
|
|
944
|
+
}
|
|
945
|
+
const partialPath = [];
|
|
946
|
+
for (const partial of path.split(".")) {
|
|
947
|
+
const completePath = [
|
|
948
|
+
BASE_PATH,
|
|
949
|
+
...currentPath.concat(partialPath),
|
|
950
|
+
partial,
|
|
951
|
+
];
|
|
952
|
+
const parentPath = completePath.slice(0, -1).join(".");
|
|
953
|
+
let entity = serviceConfig.entity;
|
|
954
|
+
if (entity) {
|
|
955
|
+
for (let i = 1; i < completePath.length; i++) {
|
|
956
|
+
entity = this.getEntity({ entity, prop: completePath[i] }) ?? entity;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
const relationship = this.getEntityRelationship({
|
|
960
|
+
parentServiceConfig: currentServiceConfig,
|
|
961
|
+
property: partial,
|
|
962
|
+
entity,
|
|
963
|
+
});
|
|
964
|
+
if (relationship) {
|
|
965
|
+
currentServiceConfig = this.getServiceConfig({
|
|
966
|
+
serviceName: relationship.serviceName,
|
|
967
|
+
entity: relationship.entity,
|
|
968
|
+
});
|
|
969
|
+
if (!currentServiceConfig) {
|
|
970
|
+
throw new Error(`Target service not found: ${relationship.serviceName}`);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
partialPath.push(partial);
|
|
974
|
+
parsedExpands.set(completePath.join("."), {
|
|
975
|
+
property: partial,
|
|
976
|
+
serviceConfig: currentServiceConfig,
|
|
977
|
+
entity: entity,
|
|
978
|
+
parent: parentPath,
|
|
979
|
+
parentConfig: parsedExpands.get(parentPath).serviceConfig,
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
currentPath.push(...path.split("."));
|
|
983
|
+
aliasRealPathMap.set(aliasPath, [BASE_PATH, ...currentPath]);
|
|
984
|
+
return currentServiceConfig;
|
|
985
|
+
}
|
|
986
|
+
groupExpands(parsedExpands) {
|
|
987
|
+
const mergedExpands = new Map(parsedExpands);
|
|
988
|
+
const mergedPaths = new Map();
|
|
989
|
+
for (const [path, expand] of mergedExpands.entries()) {
|
|
990
|
+
const currentServiceName = expand.serviceConfig.serviceName;
|
|
991
|
+
let parentPath = expand.parent;
|
|
992
|
+
while (parentPath) {
|
|
993
|
+
const parentExpand = mergedExpands.get(parentPath) ?? mergedPaths.get(parentPath);
|
|
994
|
+
if (!parentExpand ||
|
|
995
|
+
parentExpand.serviceConfig.serviceName !== currentServiceName) {
|
|
996
|
+
break;
|
|
997
|
+
}
|
|
998
|
+
const nestedKeys = path.split(".").slice(parentPath.split(".").length);
|
|
999
|
+
let targetExpand = parentExpand;
|
|
1000
|
+
for (const key of nestedKeys) {
|
|
1001
|
+
targetExpand.expands ??= {};
|
|
1002
|
+
targetExpand = targetExpand.expands[key] ??= {};
|
|
1003
|
+
}
|
|
1004
|
+
const nextFields = [
|
|
1005
|
+
...new Set([
|
|
1006
|
+
...(targetExpand.fields ?? []),
|
|
1007
|
+
...(expand.fields ?? []),
|
|
1008
|
+
]),
|
|
1009
|
+
];
|
|
1010
|
+
targetExpand.fields = nextFields;
|
|
1011
|
+
if (expand.args?.length) {
|
|
1012
|
+
const existingArgs = targetExpand.args;
|
|
1013
|
+
targetExpand.args = existingArgs
|
|
1014
|
+
? existingArgs.concat(expand.args)
|
|
1015
|
+
: expand.args;
|
|
1016
|
+
}
|
|
1017
|
+
mergedExpands.delete(path);
|
|
1018
|
+
mergedPaths.set(path, expand);
|
|
1019
|
+
parentPath = parentExpand.parent;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
return mergedExpands;
|
|
1023
|
+
}
|
|
1024
|
+
createFilterFromInitialData({ initialData, parsedExpands, aliasRealPathMap, }) {
|
|
1025
|
+
if (!initialData.length) {
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
const getPkValues = ({ initialData, serviceConfig, relationship, }) => {
|
|
1029
|
+
if (!initialData.length || !relationship || !serviceConfig) {
|
|
1030
|
+
return {};
|
|
1031
|
+
}
|
|
1032
|
+
const primaryKeys = relationship.primaryKey
|
|
1033
|
+
? relationship.primaryKey.split(",")
|
|
1034
|
+
: serviceConfig.primaryKeys;
|
|
1035
|
+
const filter = {};
|
|
1036
|
+
// Collect IDs for the current level, considering composed keys
|
|
1037
|
+
primaryKeys.forEach((key) => {
|
|
1038
|
+
filter[key] = Array.from(new Set(initialData.map((dt) => dt[key]).filter(utils_1.isDefined)));
|
|
1039
|
+
});
|
|
1040
|
+
return filter;
|
|
1041
|
+
};
|
|
1042
|
+
const parsedSegment = new Map();
|
|
1043
|
+
const aliasReversePathMap = new Map(Array.from(aliasRealPathMap).map(([path, realPath]) => [
|
|
1044
|
+
realPath.join("."),
|
|
1045
|
+
path,
|
|
1046
|
+
]));
|
|
1047
|
+
for (let [path, expand] of parsedExpands.entries()) {
|
|
1048
|
+
const serviceConfig = expand.serviceConfig;
|
|
1049
|
+
const relationship = this.getEntityRelationship({
|
|
1050
|
+
parentServiceConfig: expand.parentConfig,
|
|
1051
|
+
property: expand.property,
|
|
1052
|
+
}) ?? serviceConfig.relationships?.get(serviceConfig.serviceName);
|
|
1053
|
+
if (!serviceConfig || !relationship) {
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
let aliasToPath = null;
|
|
1057
|
+
if (aliasReversePathMap.has(path)) {
|
|
1058
|
+
aliasToPath = path;
|
|
1059
|
+
path = aliasReversePathMap.get(path);
|
|
1060
|
+
}
|
|
1061
|
+
const pathSegments = path.split(".");
|
|
1062
|
+
let relevantInitialData = initialData;
|
|
1063
|
+
let fullPath = [];
|
|
1064
|
+
for (const segment of pathSegments) {
|
|
1065
|
+
fullPath.push(segment);
|
|
1066
|
+
if (segment === BASE_PATH) {
|
|
1067
|
+
continue;
|
|
1068
|
+
}
|
|
1069
|
+
const pathStr = fullPath.join(".");
|
|
1070
|
+
if (parsedSegment.has(pathStr)) {
|
|
1071
|
+
relevantInitialData = parsedSegment.get(pathStr);
|
|
1072
|
+
continue;
|
|
1073
|
+
}
|
|
1074
|
+
relevantInitialData =
|
|
1075
|
+
RemoteJoiner.getNestedItems(relevantInitialData, segment) ?? [];
|
|
1076
|
+
parsedSegment.set(pathStr, relevantInitialData);
|
|
1077
|
+
if (!relevantInitialData.length) {
|
|
1078
|
+
break;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
if (!relevantInitialData.length) {
|
|
1082
|
+
continue;
|
|
1083
|
+
}
|
|
1084
|
+
const queryPath = expand.parent === "" ? BASE_PATH : aliasToPath ?? path;
|
|
1085
|
+
const filter = getPkValues({
|
|
1086
|
+
initialData: relevantInitialData,
|
|
1087
|
+
serviceConfig,
|
|
1088
|
+
relationship,
|
|
1089
|
+
});
|
|
1090
|
+
if (!Object.keys(filter).length) {
|
|
1091
|
+
continue;
|
|
1092
|
+
}
|
|
1093
|
+
const parsed = parsedExpands.get(queryPath);
|
|
1094
|
+
parsed.args ??= [];
|
|
1095
|
+
parsed.args.push({
|
|
1096
|
+
name: "filters",
|
|
1097
|
+
value: filter,
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
mergeInitialData({ items, initialData, serviceConfig, path, expands, relationship, }) {
|
|
1102
|
+
if (!initialData.length || !relationship) {
|
|
1103
|
+
return items;
|
|
1104
|
+
}
|
|
1105
|
+
const primaryKeys = relationship?.primaryKey.split(",") || [
|
|
1106
|
+
serviceConfig.primaryKeys[0],
|
|
1107
|
+
];
|
|
1108
|
+
const expandKeys = Object.keys(expands ?? {});
|
|
1109
|
+
const initialDataIndexMap = new Map(initialData.map((dt, index) => [
|
|
1110
|
+
primaryKeys.map((key) => dt[key]).join(","),
|
|
1111
|
+
index,
|
|
1112
|
+
]));
|
|
1113
|
+
const itemMap = new Map(items.map((item) => [primaryKeys.map((key) => item[key]).join(","), item]));
|
|
1114
|
+
const orderedMergedItems = new Array(initialData.length);
|
|
1115
|
+
for (const [key, index] of initialDataIndexMap.entries()) {
|
|
1116
|
+
const iniData = initialData[index];
|
|
1117
|
+
const item = itemMap.get(key);
|
|
1118
|
+
if (!item) {
|
|
1119
|
+
orderedMergedItems[index] = iniData;
|
|
1120
|
+
continue;
|
|
1121
|
+
}
|
|
1122
|
+
// Only merge properties that are not relations
|
|
1123
|
+
const shallowProperty = { ...iniData };
|
|
1124
|
+
for (const key of expandKeys) {
|
|
1125
|
+
const isRel = !!this.getEntityRelationship({
|
|
1126
|
+
parentServiceConfig: serviceConfig,
|
|
1127
|
+
property: key,
|
|
1128
|
+
});
|
|
1129
|
+
if (isRel) {
|
|
1130
|
+
Object.defineProperty(shallowProperty, key, {
|
|
1131
|
+
value: undefined,
|
|
1132
|
+
enumerable: false,
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
Object.assign(item, shallowProperty);
|
|
1137
|
+
orderedMergedItems[index] = item;
|
|
1138
|
+
}
|
|
1139
|
+
if (expands) {
|
|
1140
|
+
for (const expand of expandKeys) {
|
|
1141
|
+
this.mergeInitialData({
|
|
1142
|
+
items: items.flatMap((dt) => dt[expand] ?? []),
|
|
1143
|
+
initialData: initialData
|
|
1144
|
+
.flatMap((dt) => dt[expand] ?? [])
|
|
1145
|
+
.filter(utils_1.isDefined),
|
|
1146
|
+
serviceConfig,
|
|
1147
|
+
path: `${path}.${expand}`,
|
|
1148
|
+
expands: expands[expand]?.expands,
|
|
1149
|
+
relationship: this.getEntityRelationship({
|
|
1150
|
+
parentServiceConfig: serviceConfig,
|
|
1151
|
+
property: expand,
|
|
1152
|
+
}),
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return orderedMergedItems;
|
|
1157
|
+
}
|
|
1158
|
+
async query(queryObj, options) {
|
|
1159
|
+
const serviceConfig = this.getServiceConfig({
|
|
1160
|
+
serviceName: queryObj.service,
|
|
1161
|
+
serviceAlias: queryObj.alias,
|
|
1162
|
+
});
|
|
1163
|
+
if (!serviceConfig) {
|
|
1164
|
+
if (queryObj.alias) {
|
|
1165
|
+
throw new Error(`Service with alias "${queryObj.alias}" was not found.`);
|
|
1166
|
+
}
|
|
1167
|
+
throw new Error(`Service "${queryObj.service}" was not found.`);
|
|
1168
|
+
}
|
|
1169
|
+
const iniDataArray = options?.initialData
|
|
1170
|
+
? Array.isArray(options.initialData)
|
|
1171
|
+
? options.initialData
|
|
1172
|
+
: [options.initialData]
|
|
1173
|
+
: [];
|
|
1174
|
+
const implodeMapping = [];
|
|
1175
|
+
const parseExpandsConfig = {
|
|
1176
|
+
initialService: {
|
|
1177
|
+
property: "",
|
|
1178
|
+
parent: "",
|
|
1179
|
+
serviceConfig,
|
|
1180
|
+
entity: serviceConfig.entity,
|
|
1181
|
+
fields: queryObj.fields,
|
|
1182
|
+
},
|
|
1183
|
+
query: queryObj,
|
|
1184
|
+
serviceConfig,
|
|
1185
|
+
expands: queryObj.expands,
|
|
1186
|
+
implodeMapping,
|
|
1187
|
+
options,
|
|
1188
|
+
initialData: iniDataArray,
|
|
1189
|
+
initialDataOnly: options?.initialDataOnly,
|
|
1190
|
+
};
|
|
1191
|
+
const parsedExpands = this.parseExpands(parseExpandsConfig);
|
|
1192
|
+
const root = parsedExpands.get(BASE_PATH);
|
|
1193
|
+
const { primaryKeyArg, otherArgs, pkName } = gerPrimaryKeysAndOtherFilters({
|
|
1194
|
+
serviceConfig,
|
|
1195
|
+
queryObj,
|
|
1196
|
+
});
|
|
1197
|
+
if (otherArgs) {
|
|
1198
|
+
parseExpandsConfig.initialService.args = otherArgs;
|
|
1199
|
+
}
|
|
1200
|
+
if (options?.throwIfKeyNotFound) {
|
|
1201
|
+
if (primaryKeyArg?.value == undefined) {
|
|
1202
|
+
if (!primaryKeyArg) {
|
|
1203
|
+
throw new utils_1.AcmeKitError(utils_1.AcmeKitError.Types.NOT_FOUND, `${serviceConfig.entity ?? serviceConfig.serviceName}: Primary key(s) [${serviceConfig.primaryKeys.join(", ")}] not found in filters`);
|
|
1204
|
+
}
|
|
1205
|
+
throw new utils_1.AcmeKitError(utils_1.AcmeKitError.Types.NOT_FOUND, `${serviceConfig.entity ?? serviceConfig.serviceName}: Value for primary key ${primaryKeyArg.name} not found in filters`);
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
const response = await this.fetchData({
|
|
1209
|
+
expand: root,
|
|
1210
|
+
pkField: pkName,
|
|
1211
|
+
ids: primaryKeyArg?.value,
|
|
1212
|
+
options,
|
|
1213
|
+
});
|
|
1214
|
+
let data = response.path ? response.data[response.path] : response.data;
|
|
1215
|
+
const isDataArray = Array.isArray(data);
|
|
1216
|
+
data = isDataArray ? data : [data];
|
|
1217
|
+
if (options?.initialData) {
|
|
1218
|
+
data = this.mergeInitialData({
|
|
1219
|
+
items: data,
|
|
1220
|
+
initialData: iniDataArray,
|
|
1221
|
+
serviceConfig,
|
|
1222
|
+
path: BASE_PATH,
|
|
1223
|
+
expands: parsedExpands.get(BASE_PATH)?.expands,
|
|
1224
|
+
relationship: serviceConfig.relationships?.get(serviceConfig.serviceName),
|
|
1225
|
+
});
|
|
1226
|
+
delete options?.initialData;
|
|
1227
|
+
}
|
|
1228
|
+
await this.handleExpands({
|
|
1229
|
+
items: data,
|
|
1230
|
+
parsedExpands,
|
|
1231
|
+
implodeMapping,
|
|
1232
|
+
options,
|
|
1233
|
+
});
|
|
1234
|
+
const retData = isDataArray ? data : data[0];
|
|
1235
|
+
if (response.path) {
|
|
1236
|
+
response.data[response.path] = retData;
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
response.data = retData;
|
|
1240
|
+
}
|
|
1241
|
+
return response.data;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
exports.RemoteJoiner = RemoteJoiner;
|
|
1245
|
+
function gerPrimaryKeysAndOtherFilters({ serviceConfig, queryObj }) {
|
|
1246
|
+
let pkName = serviceConfig.primaryKeys[0];
|
|
1247
|
+
let primaryKeyArg = queryObj.args?.find((arg) => {
|
|
1248
|
+
const include = serviceConfig.primaryKeys.includes(arg.name);
|
|
1249
|
+
if (include) {
|
|
1250
|
+
pkName = arg.name;
|
|
1251
|
+
}
|
|
1252
|
+
return include;
|
|
1253
|
+
});
|
|
1254
|
+
let otherArgs = queryObj.args?.filter((arg) => !serviceConfig.primaryKeys.includes(arg.name));
|
|
1255
|
+
if (!primaryKeyArg) {
|
|
1256
|
+
const filters = queryObj.args?.find((arg) => arg.name === "filters")?.value ?? {};
|
|
1257
|
+
const primaryKeyFilter = Object.keys(filters).find((key) => {
|
|
1258
|
+
return serviceConfig.primaryKeys.includes(key);
|
|
1259
|
+
});
|
|
1260
|
+
if (primaryKeyFilter) {
|
|
1261
|
+
pkName = primaryKeyFilter;
|
|
1262
|
+
primaryKeyArg = {
|
|
1263
|
+
name: primaryKeyFilter,
|
|
1264
|
+
value: filters[primaryKeyFilter],
|
|
1265
|
+
};
|
|
1266
|
+
Object.defineProperty(filters, primaryKeyFilter, {
|
|
1267
|
+
value: undefined,
|
|
1268
|
+
enumerable: false,
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
otherArgs = otherArgs?.length ? otherArgs : undefined;
|
|
1273
|
+
return {
|
|
1274
|
+
primaryKeyArg,
|
|
1275
|
+
otherArgs,
|
|
1276
|
+
pkName,
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
//# sourceMappingURL=remote-joiner.js.map
|