@etohq/orchestration 1.0.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/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 +39 -0
- package/dist/joiner/remote-joiner.d.ts.map +1 -0
- package/dist/joiner/remote-joiner.js +872 -0
- package/dist/joiner/remote-joiner.js.map +1 -0
- package/dist/transaction/datastore/abstract-storage.d.ts +42 -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 +11 -0
- package/dist/transaction/datastore/base-in-memory-storage.d.ts.map +1 -0
- package/dist/transaction/datastore/base-in-memory-storage.js +33 -0
- package/dist/transaction/datastore/base-in-memory-storage.js.map +1 -0
- package/dist/transaction/distributed-transaction.d.ts +99 -0
- package/dist/transaction/distributed-transaction.d.ts.map +1 -0
- package/dist/transaction/distributed-transaction.js +260 -0
- package/dist/transaction/distributed-transaction.js.map +1 -0
- package/dist/transaction/errors.d.ts +27 -0
- package/dist/transaction/errors.d.ts.map +1 -0
- package/dist/transaction/errors.js +78 -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 +118 -0
- package/dist/transaction/transaction-orchestrator.d.ts.map +1 -0
- package/dist/transaction/transaction-orchestrator.js +924 -0
- package/dist/transaction/transaction-orchestrator.js.map +1 -0
- package/dist/transaction/transaction-step.d.ts +67 -0
- package/dist/transaction/transaction-step.d.ts.map +1 -0
- package/dist/transaction/transaction-step.js +146 -0
- package/dist/transaction/transaction-step.js.map +1 -0
- package/dist/transaction/types.d.ts +223 -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 +93 -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 +44 -0
- package/dist/workflow/local-workflow.d.ts.map +1 -0
- package/dist/workflow/local-workflow.js +327 -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 +36 -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 +52 -0
|
@@ -0,0 +1,872 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RemoteJoiner = void 0;
|
|
4
|
+
const utils_1 = require("@etohq/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
|
+
static parseQuery(graphqlQuery, variables) {
|
|
75
|
+
const parser = new utils_1.GraphQLUtils.GraphQLParser(graphqlQuery, variables);
|
|
76
|
+
return parser.parseQuery();
|
|
77
|
+
}
|
|
78
|
+
constructor(serviceConfigs, remoteFetchData, options = {}) {
|
|
79
|
+
this.remoteFetchData = remoteFetchData;
|
|
80
|
+
this.options = options;
|
|
81
|
+
this.serviceConfigCache = new Map();
|
|
82
|
+
this.entityMap = new Map();
|
|
83
|
+
this.options.autoCreateServiceNameAlias ??= true;
|
|
84
|
+
if (this.options.entitiesMap) {
|
|
85
|
+
this.entityMap = utils_1.GraphQLUtils.extractRelationsFromGQL(this.options.entitiesMap);
|
|
86
|
+
}
|
|
87
|
+
this.buildReferences(JSON.parse(JSON.stringify(serviceConfigs), (key, value) => {
|
|
88
|
+
if (key === "schema") {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
return value;
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
setFetchDataCallback(remoteFetchData) {
|
|
95
|
+
this.remoteFetchData = remoteFetchData;
|
|
96
|
+
}
|
|
97
|
+
buildReferences(serviceConfigs) {
|
|
98
|
+
const expandedRelationships = new Map();
|
|
99
|
+
for (const service of serviceConfigs) {
|
|
100
|
+
const service_ = service;
|
|
101
|
+
if (this.serviceConfigCache.has(service_.serviceName)) {
|
|
102
|
+
throw new Error(`Service "${service_.serviceName}" is already defined.`);
|
|
103
|
+
}
|
|
104
|
+
service_.fieldAlias ??= {};
|
|
105
|
+
service_.extends ??= [];
|
|
106
|
+
service_.relationships ??= new Map();
|
|
107
|
+
if (Array.isArray(service_.relationships)) {
|
|
108
|
+
const relationships = new Map();
|
|
109
|
+
for (const relationship of service_.relationships) {
|
|
110
|
+
relationships.set(relationship.alias, relationship);
|
|
111
|
+
}
|
|
112
|
+
service_.relationships = relationships;
|
|
113
|
+
}
|
|
114
|
+
// add aliases
|
|
115
|
+
const isReadOnlyDefinition = !(0, utils_1.isDefined)(service_.serviceName) || service_.isReadOnlyLink;
|
|
116
|
+
if (!isReadOnlyDefinition) {
|
|
117
|
+
service_.alias ??= [];
|
|
118
|
+
if (!Array.isArray(service_.alias)) {
|
|
119
|
+
service_.alias = [service_.alias];
|
|
120
|
+
}
|
|
121
|
+
if (this.options.autoCreateServiceNameAlias) {
|
|
122
|
+
service_.alias.push({ name: service_.serviceName });
|
|
123
|
+
}
|
|
124
|
+
// handle alias.name as array
|
|
125
|
+
for (let idx = 0; idx < service_.alias.length; idx++) {
|
|
126
|
+
const alias = service_.alias[idx];
|
|
127
|
+
if (!Array.isArray(alias.name)) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
for (const name of alias.name) {
|
|
131
|
+
service_.alias.push({
|
|
132
|
+
name,
|
|
133
|
+
entity: alias.entity,
|
|
134
|
+
args: alias.args,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
service_.alias.splice(idx, 1);
|
|
138
|
+
idx--;
|
|
139
|
+
}
|
|
140
|
+
// self-reference
|
|
141
|
+
for (const alias of service_.alias) {
|
|
142
|
+
if (this.serviceConfigCache.has(`alias_${alias.name}`)) {
|
|
143
|
+
const defined = this.serviceConfigCache.get(`alias_${alias.name}`);
|
|
144
|
+
if (service_.serviceName === defined?.serviceName) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
throw new Error(`Cannot add alias "${alias.name}" for "${service_.serviceName}". It is already defined for Service "${defined?.serviceName}".`);
|
|
148
|
+
}
|
|
149
|
+
const args = service_.args || alias.args
|
|
150
|
+
? { ...service_.args, ...alias.args }
|
|
151
|
+
: undefined;
|
|
152
|
+
const aliasName = alias.name;
|
|
153
|
+
const rel = {
|
|
154
|
+
alias: aliasName,
|
|
155
|
+
entity: alias.entity,
|
|
156
|
+
foreignKey: alias.name + "_id",
|
|
157
|
+
primaryKey: "id",
|
|
158
|
+
serviceName: service_.serviceName,
|
|
159
|
+
args,
|
|
160
|
+
};
|
|
161
|
+
if (service_.relationships?.has(aliasName)) {
|
|
162
|
+
const existing = service_.relationships.get(aliasName);
|
|
163
|
+
const newRelation = Array.isArray(existing)
|
|
164
|
+
? existing.concat(rel)
|
|
165
|
+
: [existing, rel];
|
|
166
|
+
service_.relationships?.set(aliasName, newRelation);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
service_.relationships?.set(aliasName, rel);
|
|
170
|
+
}
|
|
171
|
+
this.cacheServiceConfig(serviceConfigs, { serviceAlias: alias });
|
|
172
|
+
}
|
|
173
|
+
this.cacheServiceConfig(serviceConfigs, {
|
|
174
|
+
serviceName: service_.serviceName,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
for (const extend of service_.extends) {
|
|
178
|
+
if (!expandedRelationships.has(extend.serviceName)) {
|
|
179
|
+
expandedRelationships.set(extend.serviceName, {
|
|
180
|
+
fieldAlias: {},
|
|
181
|
+
relationships: new Map(),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
const service_ = expandedRelationships.get(extend.serviceName);
|
|
185
|
+
const aliasName = extend.relationship.alias;
|
|
186
|
+
const rel = extend.relationship;
|
|
187
|
+
if (service_.relationships?.has(aliasName)) {
|
|
188
|
+
const existing = service_.relationships.get(aliasName);
|
|
189
|
+
const newRelation = Array.isArray(existing)
|
|
190
|
+
? existing.concat(rel)
|
|
191
|
+
: [existing, rel];
|
|
192
|
+
service_.relationships?.set(aliasName, newRelation);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
service_.relationships?.set(aliasName, rel);
|
|
196
|
+
}
|
|
197
|
+
Object.assign(service_.fieldAlias ?? {}, extend.fieldAlias);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (const [serviceName, { fieldAlias, relationships },] of expandedRelationships) {
|
|
201
|
+
if (!this.serviceConfigCache.has(serviceName)) {
|
|
202
|
+
throw new Error(`Service "${serviceName}" was not found`);
|
|
203
|
+
}
|
|
204
|
+
const service_ = this.serviceConfigCache.get(serviceName);
|
|
205
|
+
relationships.forEach((relationship, alias) => {
|
|
206
|
+
const rel = relationship;
|
|
207
|
+
if (service_.relationships?.has(alias)) {
|
|
208
|
+
const existing = service_.relationships.get(alias);
|
|
209
|
+
const newRelation = Array.isArray(existing)
|
|
210
|
+
? existing.concat(rel)
|
|
211
|
+
: [existing, rel];
|
|
212
|
+
service_.relationships?.set(alias, newRelation);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
service_.relationships?.set(alias, rel);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
Object.assign(service_.fieldAlias, fieldAlias ?? {});
|
|
219
|
+
if (Object.keys(service_.fieldAlias).length) {
|
|
220
|
+
const conflictAliases = Array.from(service_.relationships.keys()).filter((alias) => fieldAlias[alias]);
|
|
221
|
+
if (conflictAliases.length) {
|
|
222
|
+
throw new Error(`Conflict configuration for service "${serviceName}". The following aliases are already defined as relationships: ${conflictAliases.join(", ")}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return serviceConfigs;
|
|
227
|
+
}
|
|
228
|
+
getServiceConfig({ serviceName, serviceAlias, entity, }) {
|
|
229
|
+
if (entity) {
|
|
230
|
+
const name = `entity_${entity}`;
|
|
231
|
+
const serviceConfig = this.serviceConfigCache.get(name);
|
|
232
|
+
if (serviceConfig) {
|
|
233
|
+
return serviceConfig;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (serviceAlias) {
|
|
237
|
+
const name = `alias_${serviceAlias}`;
|
|
238
|
+
return this.serviceConfigCache.get(name);
|
|
239
|
+
}
|
|
240
|
+
return this.serviceConfigCache.get(serviceName);
|
|
241
|
+
}
|
|
242
|
+
cacheServiceConfig(serviceConfigs, params) {
|
|
243
|
+
const { serviceName, serviceAlias } = params;
|
|
244
|
+
if (serviceAlias) {
|
|
245
|
+
const name = `alias_${serviceAlias.name}`;
|
|
246
|
+
if (!this.serviceConfigCache.has(name)) {
|
|
247
|
+
let aliasConfig;
|
|
248
|
+
const config = serviceConfigs.find((conf) => {
|
|
249
|
+
const aliases = conf.alias;
|
|
250
|
+
const hasArgs = aliases?.find((alias) => alias.name === serviceAlias.name);
|
|
251
|
+
aliasConfig = hasArgs;
|
|
252
|
+
return hasArgs;
|
|
253
|
+
});
|
|
254
|
+
if (config) {
|
|
255
|
+
const serviceConfig = { ...config, entity: serviceAlias.entity };
|
|
256
|
+
if (aliasConfig) {
|
|
257
|
+
serviceConfig.args = { ...config?.args, ...aliasConfig?.args };
|
|
258
|
+
}
|
|
259
|
+
this.serviceConfigCache.set(name, serviceConfig);
|
|
260
|
+
const entity = serviceAlias.entity;
|
|
261
|
+
if (entity) {
|
|
262
|
+
const name = `entity_${entity}`;
|
|
263
|
+
this.serviceConfigCache.set(name, serviceConfig);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const config = serviceConfigs.find((config) => config.serviceName === serviceName);
|
|
270
|
+
this.serviceConfigCache.set(serviceName, config);
|
|
271
|
+
}
|
|
272
|
+
async fetchData(params) {
|
|
273
|
+
const { expand, pkField, ids, relationship, options } = params;
|
|
274
|
+
let uniqueIds;
|
|
275
|
+
if (ids != null) {
|
|
276
|
+
const isIdsUsingOperatorMap = (0, utils_1.isObject)(ids) &&
|
|
277
|
+
Object.keys(ids).some((key) => !!utils_1.FilterOperatorMap[key]);
|
|
278
|
+
uniqueIds = isIdsUsingOperatorMap ? ids : Array.isArray(ids) ? ids : [ids];
|
|
279
|
+
}
|
|
280
|
+
if (uniqueIds && Array.isArray(uniqueIds)) {
|
|
281
|
+
const isCompositeKey = Array.isArray(uniqueIds[0]);
|
|
282
|
+
if (isCompositeKey) {
|
|
283
|
+
const seen = new Set();
|
|
284
|
+
uniqueIds = uniqueIds.filter((idArray) => {
|
|
285
|
+
const key = JSON.stringify(idArray);
|
|
286
|
+
const isNew = !seen.has(key);
|
|
287
|
+
seen.add(key);
|
|
288
|
+
return isNew;
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
uniqueIds = Array.from(new Set(uniqueIds.flat()));
|
|
293
|
+
}
|
|
294
|
+
uniqueIds = uniqueIds.filter((id) => (0, utils_1.isDefined)(id));
|
|
295
|
+
}
|
|
296
|
+
let pkFieldAdjusted = pkField;
|
|
297
|
+
if (relationship) {
|
|
298
|
+
pkFieldAdjusted = relationship.inverse
|
|
299
|
+
? relationship.foreignKey.split(".").pop()
|
|
300
|
+
: relationship.primaryKey;
|
|
301
|
+
}
|
|
302
|
+
const response = await this.remoteFetchData(expand, pkFieldAdjusted, uniqueIds, relationship);
|
|
303
|
+
const isObj = (0, utils_1.isDefined)(response.path);
|
|
304
|
+
let resData = isObj ? response.data[response.path] : response.data;
|
|
305
|
+
resData = (0, utils_1.isDefined)(resData)
|
|
306
|
+
? Array.isArray(resData)
|
|
307
|
+
? resData
|
|
308
|
+
: [resData]
|
|
309
|
+
: [];
|
|
310
|
+
this.checkIfKeysExist({
|
|
311
|
+
uniqueIds,
|
|
312
|
+
resData,
|
|
313
|
+
expand,
|
|
314
|
+
pkField: pkFieldAdjusted,
|
|
315
|
+
relationship,
|
|
316
|
+
options,
|
|
317
|
+
});
|
|
318
|
+
const filteredDataArray = resData.map((data) => RemoteJoiner.filterFields(data, expand.fields, expand.expands));
|
|
319
|
+
if (isObj) {
|
|
320
|
+
response.data[response.path] = filteredDataArray;
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
response.data = filteredDataArray;
|
|
324
|
+
}
|
|
325
|
+
return response;
|
|
326
|
+
}
|
|
327
|
+
checkIfKeysExist(params) {
|
|
328
|
+
const { uniqueIds, resData, expand, pkField, relationship, options } = params;
|
|
329
|
+
if (!((0, utils_1.isDefined)(uniqueIds) &&
|
|
330
|
+
((options?.throwIfKeyNotFound && !(0, utils_1.isDefined)(relationship)) ||
|
|
331
|
+
(options?.throwIfRelationNotFound && (0, utils_1.isDefined)(relationship))))) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if ((0, utils_1.isDefined)(relationship)) {
|
|
335
|
+
if (Array.isArray(options?.throwIfRelationNotFound) &&
|
|
336
|
+
!options?.throwIfRelationNotFound.includes(relationship.serviceName)) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const notFound = new Set(uniqueIds);
|
|
341
|
+
resData.forEach((data) => {
|
|
342
|
+
notFound.delete(data[pkField]);
|
|
343
|
+
});
|
|
344
|
+
if (notFound.size > 0) {
|
|
345
|
+
const entityName = expand.serviceConfig.entity ??
|
|
346
|
+
expand.serviceConfig.args?.methodSuffix ??
|
|
347
|
+
expand.serviceConfig.serviceName;
|
|
348
|
+
throw new utils_1.EtoError(utils_1.EtoError.Types.NOT_FOUND, `${entityName} ${pkField} not found: ` + Array.from(notFound).join(", "));
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
handleFieldAliases(params) {
|
|
352
|
+
const { items, parsedExpands, implodeMapping } = params;
|
|
353
|
+
const getChildren = (item, prop) => {
|
|
354
|
+
if (Array.isArray(item)) {
|
|
355
|
+
return item.flatMap((currentItem) => currentItem[prop]);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
return item[prop];
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
const removeChildren = (item, prop) => {
|
|
362
|
+
if (Array.isArray(item)) {
|
|
363
|
+
item.forEach((currentItem) => delete currentItem[prop]);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
delete item[prop];
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
const cleanup = [];
|
|
370
|
+
for (const alias of implodeMapping) {
|
|
371
|
+
const propPath = alias.path;
|
|
372
|
+
let itemsLocation = items;
|
|
373
|
+
for (const locationProp of alias.location) {
|
|
374
|
+
propPath.shift();
|
|
375
|
+
itemsLocation = RemoteJoiner.getNestedItems(itemsLocation, locationProp);
|
|
376
|
+
}
|
|
377
|
+
itemsLocation.forEach((locationItem) => {
|
|
378
|
+
if (!locationItem) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
let currentItems = locationItem;
|
|
382
|
+
let parentRemoveItems = null;
|
|
383
|
+
const curPath = [BASE_PATH].concat(alias.location);
|
|
384
|
+
for (const prop of propPath) {
|
|
385
|
+
if (!(0, utils_1.isDefined)(currentItems)) {
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
curPath.push(prop);
|
|
389
|
+
const config = parsedExpands.get(curPath.join("."));
|
|
390
|
+
if (config?.isAliasMapping && parentRemoveItems === null) {
|
|
391
|
+
parentRemoveItems = [currentItems, prop];
|
|
392
|
+
}
|
|
393
|
+
currentItems = getChildren(currentItems, prop);
|
|
394
|
+
}
|
|
395
|
+
if (Array.isArray(currentItems)) {
|
|
396
|
+
if (currentItems.length < 2 && !alias.isList) {
|
|
397
|
+
locationItem[alias.property] = currentItems.shift();
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
locationItem[alias.property] = currentItems;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
locationItem[alias.property] = alias.isList
|
|
405
|
+
? (0, utils_1.isDefined)(currentItems)
|
|
406
|
+
? [currentItems]
|
|
407
|
+
: []
|
|
408
|
+
: currentItems;
|
|
409
|
+
}
|
|
410
|
+
if (parentRemoveItems !== null) {
|
|
411
|
+
cleanup.push(parentRemoveItems);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
for (const parentRemoveItems of cleanup) {
|
|
416
|
+
const [remItems, path] = parentRemoveItems;
|
|
417
|
+
removeChildren(remItems, path);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async handleExpands(params) {
|
|
421
|
+
const { items, parsedExpands, implodeMapping = [], options } = params;
|
|
422
|
+
if (!parsedExpands) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
for (const [expandedPath, expand] of parsedExpands.entries()) {
|
|
426
|
+
if (expandedPath === BASE_PATH) {
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
let nestedItems = items;
|
|
430
|
+
const expandedPathLevels = expandedPath.split(".");
|
|
431
|
+
for (let idx = 1; idx < expandedPathLevels.length - 1; idx++) {
|
|
432
|
+
nestedItems = RemoteJoiner.getNestedItems(nestedItems, expandedPathLevels[idx]);
|
|
433
|
+
}
|
|
434
|
+
if (nestedItems.length > 0) {
|
|
435
|
+
await this.expandProperty({
|
|
436
|
+
items: nestedItems,
|
|
437
|
+
parentServiceConfig: expand.parentConfig,
|
|
438
|
+
expand,
|
|
439
|
+
options,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
this.handleFieldAliases({ items, parsedExpands, implodeMapping });
|
|
444
|
+
}
|
|
445
|
+
getEntityRelationship(params) {
|
|
446
|
+
const { parentServiceConfig, property, entity } = params;
|
|
447
|
+
const propEntity = entity ?? parentServiceConfig?.entity;
|
|
448
|
+
const rel = parentServiceConfig?.relationships?.get(property);
|
|
449
|
+
if (Array.isArray(rel)) {
|
|
450
|
+
if (!propEntity) {
|
|
451
|
+
return rel[0];
|
|
452
|
+
}
|
|
453
|
+
const entityRel = rel.find((r) => r.entity === propEntity);
|
|
454
|
+
if (entityRel) {
|
|
455
|
+
return entityRel;
|
|
456
|
+
}
|
|
457
|
+
// If entity is not found, return the relationship where the primary key matches
|
|
458
|
+
const serviceEntity = this.getServiceConfig({
|
|
459
|
+
entity: propEntity,
|
|
460
|
+
});
|
|
461
|
+
return rel.find((r) => serviceEntity.primaryKeys.includes(r.primaryKey));
|
|
462
|
+
}
|
|
463
|
+
return rel;
|
|
464
|
+
}
|
|
465
|
+
async expandProperty(params) {
|
|
466
|
+
const { items, parentServiceConfig, expand, options } = params;
|
|
467
|
+
if (!expand) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const relationship = this.getEntityRelationship({
|
|
471
|
+
parentServiceConfig,
|
|
472
|
+
property: expand.property,
|
|
473
|
+
entity: expand.entity,
|
|
474
|
+
});
|
|
475
|
+
if (!relationship) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
await this.expandRelationshipProperty({
|
|
479
|
+
items,
|
|
480
|
+
expand,
|
|
481
|
+
relationship,
|
|
482
|
+
options,
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
async expandRelationshipProperty(params) {
|
|
486
|
+
const { items, expand, relationship, options } = params;
|
|
487
|
+
const field = relationship.inverse
|
|
488
|
+
? relationship.primaryKey
|
|
489
|
+
: relationship.foreignKey.split(".").pop();
|
|
490
|
+
const fieldsArray = field.split(",");
|
|
491
|
+
const idsToFetch = [];
|
|
492
|
+
items.forEach((item) => {
|
|
493
|
+
const values = fieldsArray.map((field) => item?.[field]);
|
|
494
|
+
if (values.length === fieldsArray.length && !item?.[relationship.alias]) {
|
|
495
|
+
if (fieldsArray.length === 1) {
|
|
496
|
+
if (!idsToFetch.includes(values[0])) {
|
|
497
|
+
idsToFetch.push(values[0]);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
// composite key
|
|
502
|
+
const valuesString = values.join(",");
|
|
503
|
+
if (!idsToFetch.some((id) => id.join(",") === valuesString)) {
|
|
504
|
+
idsToFetch.push(values);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
if (idsToFetch.length === 0) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
const relatedDataArray = await this.fetchData({
|
|
513
|
+
expand,
|
|
514
|
+
pkField: field,
|
|
515
|
+
ids: idsToFetch,
|
|
516
|
+
relationship,
|
|
517
|
+
options,
|
|
518
|
+
});
|
|
519
|
+
const joinFields = relationship.inverse
|
|
520
|
+
? relationship.foreignKey.split(",")
|
|
521
|
+
: relationship.primaryKey.split(",");
|
|
522
|
+
const relData = relatedDataArray.path
|
|
523
|
+
? relatedDataArray.data[relatedDataArray.path]
|
|
524
|
+
: relatedDataArray.data;
|
|
525
|
+
const relatedDataMap = RemoteJoiner.createRelatedDataMap(relData, joinFields);
|
|
526
|
+
items.forEach((item) => {
|
|
527
|
+
if (!item || item[relationship.alias]) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
const itemKey = fieldsArray.map((field) => item[field]).join(",");
|
|
531
|
+
if (Array.isArray(item[field])) {
|
|
532
|
+
item[relationship.alias] = item[field].map((id) => {
|
|
533
|
+
if (relationship.isList && !Array.isArray(relatedDataMap[id])) {
|
|
534
|
+
relatedDataMap[id] = (0, utils_1.isDefined)(relatedDataMap[id])
|
|
535
|
+
? [relatedDataMap[id]]
|
|
536
|
+
: [];
|
|
537
|
+
}
|
|
538
|
+
return relatedDataMap[id];
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
if (relationship.isList && !Array.isArray(relatedDataMap[itemKey])) {
|
|
543
|
+
relatedDataMap[itemKey] = (0, utils_1.isDefined)(relatedDataMap[itemKey])
|
|
544
|
+
? [relatedDataMap[itemKey]]
|
|
545
|
+
: [];
|
|
546
|
+
}
|
|
547
|
+
item[relationship.alias] = relatedDataMap[itemKey];
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
parseExpands(params) {
|
|
552
|
+
const { initialService, query, serviceConfig, expands, implodeMapping } = params;
|
|
553
|
+
const parsedExpands = this.parseProperties({
|
|
554
|
+
initialService,
|
|
555
|
+
query,
|
|
556
|
+
serviceConfig,
|
|
557
|
+
expands,
|
|
558
|
+
implodeMapping,
|
|
559
|
+
});
|
|
560
|
+
const groupedExpands = this.groupExpands(parsedExpands);
|
|
561
|
+
return groupedExpands;
|
|
562
|
+
}
|
|
563
|
+
parseProperties(params) {
|
|
564
|
+
const { initialService, query, serviceConfig, expands, implodeMapping } = params;
|
|
565
|
+
const aliasRealPathMap = new Map();
|
|
566
|
+
const parsedExpands = new Map();
|
|
567
|
+
parsedExpands.set(BASE_PATH, initialService);
|
|
568
|
+
const forwardArgumentsOnPath = [];
|
|
569
|
+
for (const expand of expands || []) {
|
|
570
|
+
const properties = expand.property.split(".");
|
|
571
|
+
const currentPath = [];
|
|
572
|
+
const currentAliasPath = [];
|
|
573
|
+
let currentServiceConfig = serviceConfig;
|
|
574
|
+
for (const prop of properties) {
|
|
575
|
+
const fieldAlias = currentServiceConfig.fieldAlias ?? {};
|
|
576
|
+
if (fieldAlias[prop]) {
|
|
577
|
+
const aliasPath = [BASE_PATH, ...currentPath, prop].join(".");
|
|
578
|
+
const lastServiceConfig = this.parseAlias({
|
|
579
|
+
aliasPath,
|
|
580
|
+
aliasRealPathMap,
|
|
581
|
+
expands,
|
|
582
|
+
expand,
|
|
583
|
+
property: prop,
|
|
584
|
+
parsedExpands,
|
|
585
|
+
currentServiceConfig,
|
|
586
|
+
currentPath,
|
|
587
|
+
implodeMapping,
|
|
588
|
+
forwardArgumentsOnPath,
|
|
589
|
+
});
|
|
590
|
+
currentAliasPath.push(prop);
|
|
591
|
+
currentServiceConfig = lastServiceConfig;
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
const fullPath = [BASE_PATH, ...currentPath, prop].join(".");
|
|
595
|
+
const fullAliasPath = [BASE_PATH, ...currentAliasPath, prop].join(".");
|
|
596
|
+
let entity = currentServiceConfig.entity;
|
|
597
|
+
if (entity) {
|
|
598
|
+
const completePath = fullPath.split(".");
|
|
599
|
+
for (let i = 1; i < completePath.length; i++) {
|
|
600
|
+
entity = this.getEntity({ entity, prop: completePath[i] }) ?? entity;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
const relationship = this.getEntityRelationship({
|
|
604
|
+
parentServiceConfig: currentServiceConfig,
|
|
605
|
+
property: prop,
|
|
606
|
+
entity,
|
|
607
|
+
});
|
|
608
|
+
const isCurrentProp = fullPath === BASE_PATH + "." + expand.property ||
|
|
609
|
+
fullAliasPath == BASE_PATH + "." + expand.property;
|
|
610
|
+
let fields = isCurrentProp ? expand.fields ?? [] : [];
|
|
611
|
+
const args = isCurrentProp ? expand.args : [];
|
|
612
|
+
if (relationship) {
|
|
613
|
+
const parentExpand = parsedExpands.get([BASE_PATH, ...currentPath].join(".")) || query;
|
|
614
|
+
if (parentExpand) {
|
|
615
|
+
const parRelField = relationship.inverse
|
|
616
|
+
? relationship.primaryKey
|
|
617
|
+
: relationship.foreignKey.split(".").pop();
|
|
618
|
+
parentExpand.fields ??= [];
|
|
619
|
+
parentExpand.fields = parentExpand.fields
|
|
620
|
+
.concat(parRelField.split(","))
|
|
621
|
+
.filter((field) => field !== relationship.alias);
|
|
622
|
+
parentExpand.fields = (0, utils_1.deduplicate)(parentExpand.fields);
|
|
623
|
+
const relField = relationship.inverse
|
|
624
|
+
? relationship.foreignKey.split(".").pop()
|
|
625
|
+
: relationship.primaryKey;
|
|
626
|
+
fields = fields.concat(relField.split(","));
|
|
627
|
+
}
|
|
628
|
+
currentServiceConfig = this.getServiceConfig({
|
|
629
|
+
serviceName: relationship.serviceName,
|
|
630
|
+
entity: relationship.entity,
|
|
631
|
+
});
|
|
632
|
+
if (!currentServiceConfig) {
|
|
633
|
+
throw new Error(`Target service not found: ${relationship.serviceName}`);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
const isAliasMapping = expand.isAliasMapping;
|
|
637
|
+
if (!parsedExpands.has(fullPath)) {
|
|
638
|
+
let parentPath = [BASE_PATH, ...currentPath].join(".");
|
|
639
|
+
if (aliasRealPathMap.has(parentPath)) {
|
|
640
|
+
parentPath = aliasRealPathMap
|
|
641
|
+
.get(parentPath)
|
|
642
|
+
.slice(0, -1)
|
|
643
|
+
.join(".");
|
|
644
|
+
}
|
|
645
|
+
parsedExpands.set(fullPath, {
|
|
646
|
+
property: prop,
|
|
647
|
+
serviceConfig: currentServiceConfig,
|
|
648
|
+
entity: entity,
|
|
649
|
+
fields,
|
|
650
|
+
args: isAliasMapping
|
|
651
|
+
? forwardArgumentsOnPath.includes(fullPath)
|
|
652
|
+
? args
|
|
653
|
+
: undefined
|
|
654
|
+
: args,
|
|
655
|
+
isAliasMapping: isAliasMapping,
|
|
656
|
+
parent: parentPath,
|
|
657
|
+
parentConfig: parsedExpands.get(parentPath).serviceConfig,
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
const exp = parsedExpands.get(fullPath);
|
|
662
|
+
if (forwardArgumentsOnPath.includes(fullPath) && args) {
|
|
663
|
+
exp.args = (exp.args || []).concat(args);
|
|
664
|
+
}
|
|
665
|
+
exp.isAliasMapping ??= isAliasMapping;
|
|
666
|
+
if (fields) {
|
|
667
|
+
exp.fields = (0, utils_1.deduplicate)((exp.fields ?? []).concat(fields));
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
currentPath.push(prop);
|
|
671
|
+
currentAliasPath.push(prop);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return parsedExpands;
|
|
675
|
+
}
|
|
676
|
+
getEntity({ entity, prop }) {
|
|
677
|
+
return this.entityMap.get(entity)?.get(prop);
|
|
678
|
+
}
|
|
679
|
+
parseAlias({ aliasPath, aliasRealPathMap, expands, expand, property, parsedExpands, currentServiceConfig, currentPath, implodeMapping, forwardArgumentsOnPath, }) {
|
|
680
|
+
const serviceConfig = currentServiceConfig;
|
|
681
|
+
const fieldAlias = currentServiceConfig.fieldAlias ?? {};
|
|
682
|
+
const alias = fieldAlias[property];
|
|
683
|
+
const path = (0, utils_1.isString)(alias) ? alias : alias.path;
|
|
684
|
+
const fieldAliasIsList = (0, utils_1.isString)(alias) ? false : !!alias.isList;
|
|
685
|
+
const fullPath = [...currentPath.concat(path.split("."))];
|
|
686
|
+
if (aliasRealPathMap.has(aliasPath)) {
|
|
687
|
+
currentPath.push(...path.split("."));
|
|
688
|
+
const fullPath = [BASE_PATH, ...currentPath].join(".");
|
|
689
|
+
return parsedExpands.get(fullPath).serviceConfig;
|
|
690
|
+
}
|
|
691
|
+
const parentPath = [BASE_PATH, ...currentPath].join(".");
|
|
692
|
+
const parentExpands = parsedExpands.get(parentPath);
|
|
693
|
+
parentExpands.fields = parentExpands.fields?.filter((field) => field !== property);
|
|
694
|
+
forwardArgumentsOnPath.push(...(alias?.forwardArgumentsOnPath || []).map((forPath) => BASE_PATH + "." + currentPath.concat(forPath).join(".")));
|
|
695
|
+
const parentFieldAlias = fullPath[Math.max(fullPath.length - 2, 0)];
|
|
696
|
+
implodeMapping.push({
|
|
697
|
+
location: [...currentPath],
|
|
698
|
+
property,
|
|
699
|
+
path: fullPath,
|
|
700
|
+
isList: fieldAliasIsList ||
|
|
701
|
+
!!serviceConfig.relationships?.get(parentFieldAlias)?.isList,
|
|
702
|
+
});
|
|
703
|
+
const extMapping = expands;
|
|
704
|
+
const fullAliasProp = fullPath.join(".");
|
|
705
|
+
const middlePath = path.split(".");
|
|
706
|
+
let curMiddlePath = currentPath;
|
|
707
|
+
for (const path of middlePath) {
|
|
708
|
+
curMiddlePath = curMiddlePath.concat(path);
|
|
709
|
+
const midProp = curMiddlePath.join(".");
|
|
710
|
+
const existingExpand = expands.find((exp) => exp.property === midProp);
|
|
711
|
+
const extraExtends = {
|
|
712
|
+
...(midProp === fullAliasProp ? expand : {}),
|
|
713
|
+
property: midProp,
|
|
714
|
+
isAliasMapping: !existingExpand,
|
|
715
|
+
};
|
|
716
|
+
if (forwardArgumentsOnPath.includes(BASE_PATH + "." + midProp)) {
|
|
717
|
+
extraExtends.args = (existingExpand?.args ?? []).concat(expand?.args ?? []);
|
|
718
|
+
}
|
|
719
|
+
extMapping.push(extraExtends);
|
|
720
|
+
}
|
|
721
|
+
const partialPath = [];
|
|
722
|
+
for (const partial of path.split(".")) {
|
|
723
|
+
const completePath = [
|
|
724
|
+
BASE_PATH,
|
|
725
|
+
...currentPath.concat(partialPath),
|
|
726
|
+
partial,
|
|
727
|
+
];
|
|
728
|
+
const parentPath = completePath.slice(0, -1).join(".");
|
|
729
|
+
let entity = serviceConfig.entity;
|
|
730
|
+
if (entity) {
|
|
731
|
+
for (let i = 1; i < completePath.length; i++) {
|
|
732
|
+
entity = this.getEntity({ entity, prop: completePath[i] }) ?? entity;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
const relationship = this.getEntityRelationship({
|
|
736
|
+
parentServiceConfig: currentServiceConfig,
|
|
737
|
+
property: partial,
|
|
738
|
+
entity,
|
|
739
|
+
});
|
|
740
|
+
if (relationship) {
|
|
741
|
+
currentServiceConfig = this.getServiceConfig({
|
|
742
|
+
serviceName: relationship.serviceName,
|
|
743
|
+
entity: relationship.entity,
|
|
744
|
+
});
|
|
745
|
+
if (!currentServiceConfig) {
|
|
746
|
+
throw new Error(`Target service not found: ${relationship.serviceName}`);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
partialPath.push(partial);
|
|
750
|
+
parsedExpands.set(completePath.join("."), {
|
|
751
|
+
property: partial,
|
|
752
|
+
serviceConfig: currentServiceConfig,
|
|
753
|
+
entity: entity,
|
|
754
|
+
parent: parentPath,
|
|
755
|
+
parentConfig: parsedExpands.get(parentPath).serviceConfig,
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
currentPath.push(...path.split("."));
|
|
759
|
+
aliasRealPathMap.set(aliasPath, [BASE_PATH, ...currentPath]);
|
|
760
|
+
return currentServiceConfig;
|
|
761
|
+
}
|
|
762
|
+
groupExpands(parsedExpands) {
|
|
763
|
+
const mergedExpands = new Map(parsedExpands);
|
|
764
|
+
const mergedPaths = new Map();
|
|
765
|
+
for (const [path, expand] of mergedExpands.entries()) {
|
|
766
|
+
const currentServiceName = expand.serviceConfig.serviceName;
|
|
767
|
+
let parentPath = expand.parent;
|
|
768
|
+
while (parentPath) {
|
|
769
|
+
const parentExpand = mergedExpands.get(parentPath) ?? mergedPaths.get(parentPath);
|
|
770
|
+
if (!parentExpand ||
|
|
771
|
+
parentExpand.serviceConfig.serviceName !== currentServiceName) {
|
|
772
|
+
break;
|
|
773
|
+
}
|
|
774
|
+
const nestedKeys = path.split(".").slice(parentPath.split(".").length);
|
|
775
|
+
let targetExpand = parentExpand;
|
|
776
|
+
for (const key of nestedKeys) {
|
|
777
|
+
targetExpand.expands ??= {};
|
|
778
|
+
targetExpand = targetExpand.expands[key] ??= {};
|
|
779
|
+
}
|
|
780
|
+
targetExpand.fields = [...new Set(expand.fields)];
|
|
781
|
+
targetExpand.args = expand.args;
|
|
782
|
+
mergedExpands.delete(path);
|
|
783
|
+
mergedPaths.set(path, expand);
|
|
784
|
+
parentPath = parentExpand.parent;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
return mergedExpands;
|
|
788
|
+
}
|
|
789
|
+
async query(queryObj, options) {
|
|
790
|
+
const serviceConfig = this.getServiceConfig({
|
|
791
|
+
serviceName: queryObj.service,
|
|
792
|
+
serviceAlias: queryObj.alias,
|
|
793
|
+
});
|
|
794
|
+
if (!serviceConfig) {
|
|
795
|
+
if (queryObj.alias) {
|
|
796
|
+
throw new Error(`Service with alias "${queryObj.alias}" was not found.`);
|
|
797
|
+
}
|
|
798
|
+
throw new Error(`Service "${queryObj.service}" was not found.`);
|
|
799
|
+
}
|
|
800
|
+
const { primaryKeyArg, otherArgs, pkName } = gerPrimaryKeysAndOtherFilters({
|
|
801
|
+
serviceConfig,
|
|
802
|
+
queryObj,
|
|
803
|
+
});
|
|
804
|
+
const implodeMapping = [];
|
|
805
|
+
const parseExpandsConfig = {
|
|
806
|
+
initialService: {
|
|
807
|
+
property: "",
|
|
808
|
+
parent: "",
|
|
809
|
+
serviceConfig,
|
|
810
|
+
entity: serviceConfig.entity,
|
|
811
|
+
fields: queryObj.fields,
|
|
812
|
+
},
|
|
813
|
+
query: queryObj,
|
|
814
|
+
serviceConfig,
|
|
815
|
+
expands: queryObj.expands,
|
|
816
|
+
implodeMapping,
|
|
817
|
+
options,
|
|
818
|
+
};
|
|
819
|
+
if (otherArgs) {
|
|
820
|
+
parseExpandsConfig.initialService.args = otherArgs;
|
|
821
|
+
}
|
|
822
|
+
const parsedExpands = this.parseExpands(parseExpandsConfig);
|
|
823
|
+
const root = parsedExpands.get(BASE_PATH);
|
|
824
|
+
const response = await this.fetchData({
|
|
825
|
+
expand: root,
|
|
826
|
+
pkField: pkName,
|
|
827
|
+
ids: primaryKeyArg?.value,
|
|
828
|
+
options,
|
|
829
|
+
});
|
|
830
|
+
const data = response.path ? response.data[response.path] : response.data;
|
|
831
|
+
await this.handleExpands({
|
|
832
|
+
items: Array.isArray(data) ? data : [data],
|
|
833
|
+
parsedExpands,
|
|
834
|
+
implodeMapping,
|
|
835
|
+
options,
|
|
836
|
+
});
|
|
837
|
+
return response.data;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
exports.RemoteJoiner = RemoteJoiner;
|
|
841
|
+
function gerPrimaryKeysAndOtherFilters({ serviceConfig, queryObj }) {
|
|
842
|
+
let pkName = serviceConfig.primaryKeys[0];
|
|
843
|
+
let primaryKeyArg = queryObj.args?.find((arg) => {
|
|
844
|
+
const include = serviceConfig.primaryKeys.includes(arg.name);
|
|
845
|
+
if (include) {
|
|
846
|
+
pkName = arg.name;
|
|
847
|
+
}
|
|
848
|
+
return include;
|
|
849
|
+
});
|
|
850
|
+
let otherArgs = queryObj.args?.filter((arg) => !serviceConfig.primaryKeys.includes(arg.name));
|
|
851
|
+
const filters = queryObj.args?.find((arg) => arg.name === "filters")?.value ?? {};
|
|
852
|
+
if (!primaryKeyArg) {
|
|
853
|
+
const primaryKeyFilter = Object.keys(filters).find((key) => {
|
|
854
|
+
return serviceConfig.primaryKeys.includes(key);
|
|
855
|
+
});
|
|
856
|
+
if (primaryKeyFilter) {
|
|
857
|
+
pkName = primaryKeyFilter;
|
|
858
|
+
primaryKeyArg = {
|
|
859
|
+
name: primaryKeyFilter,
|
|
860
|
+
value: filters[primaryKeyFilter],
|
|
861
|
+
};
|
|
862
|
+
delete filters[primaryKeyFilter];
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
otherArgs = otherArgs?.length ? otherArgs : undefined;
|
|
866
|
+
return {
|
|
867
|
+
primaryKeyArg,
|
|
868
|
+
otherArgs,
|
|
869
|
+
pkName,
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
//# sourceMappingURL=remote-joiner.js.map
|