@medusajs/orchestration 3.0.0-preview-20250410180148 → 3.0.0-preview-20251201152819
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/joiner/remote-joiner.d.ts +3 -2
- package/dist/joiner/remote-joiner.d.ts.map +1 -1
- package/dist/joiner/remote-joiner.js +312 -141
- package/dist/joiner/remote-joiner.js.map +1 -1
- package/dist/transaction/datastore/abstract-storage.d.ts +7 -5
- package/dist/transaction/datastore/abstract-storage.d.ts.map +1 -1
- package/dist/transaction/datastore/abstract-storage.js +3 -3
- package/dist/transaction/datastore/abstract-storage.js.map +1 -1
- package/dist/transaction/datastore/base-in-memory-storage.d.ts +2 -1
- package/dist/transaction/datastore/base-in-memory-storage.d.ts.map +1 -1
- package/dist/transaction/datastore/base-in-memory-storage.js +2 -0
- package/dist/transaction/datastore/base-in-memory-storage.js.map +1 -1
- package/dist/transaction/distributed-transaction.d.ts +23 -6
- package/dist/transaction/distributed-transaction.d.ts.map +1 -1
- package/dist/transaction/distributed-transaction.js +284 -54
- package/dist/transaction/distributed-transaction.js.map +1 -1
- package/dist/transaction/errors.d.ts +11 -0
- package/dist/transaction/errors.d.ts.map +1 -1
- package/dist/transaction/errors.js +34 -2
- package/dist/transaction/errors.js.map +1 -1
- package/dist/transaction/transaction-orchestrator.d.ts +99 -10
- package/dist/transaction/transaction-orchestrator.d.ts.map +1 -1
- package/dist/transaction/transaction-orchestrator.js +599 -274
- package/dist/transaction/transaction-orchestrator.js.map +1 -1
- package/dist/transaction/transaction-step.d.ts +2 -0
- package/dist/transaction/transaction-step.d.ts.map +1 -1
- package/dist/transaction/transaction-step.js +10 -3
- package/dist/transaction/transaction-step.js.map +1 -1
- package/dist/transaction/types.d.ts +31 -1
- package/dist/transaction/types.d.ts.map +1 -1
- package/dist/transaction/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/workflow/global-workflow.d.ts.map +1 -1
- package/dist/workflow/global-workflow.js +16 -4
- package/dist/workflow/global-workflow.js.map +1 -1
- package/dist/workflow/local-workflow.d.ts +3 -1
- package/dist/workflow/local-workflow.d.ts.map +1 -1
- package/dist/workflow/local-workflow.js +71 -9
- package/dist/workflow/local-workflow.js.map +1 -1
- package/package.json +8 -26
|
@@ -13,6 +13,8 @@ export declare class RemoteJoiner {
|
|
|
13
13
|
private static filterFields;
|
|
14
14
|
private static getNestedItems;
|
|
15
15
|
private static createRelatedDataMap;
|
|
16
|
+
private computeIdsForRelationship;
|
|
17
|
+
private assignRelatedToItems;
|
|
16
18
|
static parseQuery(graphqlQuery: string, variables?: Record<string, unknown>): RemoteJoinerQuery;
|
|
17
19
|
constructor(serviceConfigs: ModuleJoinerConfig[], remoteFetchData: RemoteFetchDataCallback, options?: {
|
|
18
20
|
autoCreateServiceNameAlias?: boolean;
|
|
@@ -28,9 +30,8 @@ export declare class RemoteJoiner {
|
|
|
28
30
|
private handleFieldAliases;
|
|
29
31
|
private handleExpands;
|
|
30
32
|
private getEntityRelationship;
|
|
31
|
-
private expandProperty;
|
|
32
|
-
private expandRelationshipProperty;
|
|
33
33
|
private parseExpands;
|
|
34
|
+
private buildQueryPlan;
|
|
34
35
|
private parseProperties;
|
|
35
36
|
private getEntity;
|
|
36
37
|
private parseAlias;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-joiner.d.ts","sourceRoot":"","sources":["../../src/joiner/remote-joiner.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"remote-joiner.d.ts","sourceRoot":"","sources":["../../src/joiner/remote-joiner.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EAElB,MAAM,iBAAiB,CAAA;AAaxB,MAAM,MAAM,uBAAuB,GAAG,CACpC,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,OAAO,EAAE,CAAC,EAAE,EAC7B,YAAY,CAAC,EAAE,GAAG,KACf,OAAO,CAAC;IACX,IAAI,EAAE,OAAO,EAAE,GAAG;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAC,CAAA;AAoBF,qBAAa,YAAY;IAiNrB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,OAAO;IAjNjB,OAAO,CAAC,kBAAkB,CACf;IAEX,OAAO,CAAC,SAAS,CAA8C;IAE/D,OAAO,CAAC,MAAM,CAAC,YAAY;IAwD3B,OAAO,CAAC,MAAM,CAAC,cAAc;IAe7B,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAwBnC,OAAO,CAAC,yBAAyB;IAyCjC,OAAO,CAAC,oBAAoB;IAyD5B,MAAM,CAAC,UAAU,CACf,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,iBAAiB;gBAMlB,cAAc,EAAE,kBAAkB,EAAE,EAC5B,eAAe,EAAE,uBAAuB,EACxC,OAAO,GAAE;QACf,0BAA0B,CAAC,EAAE,OAAO,CAAA;QACpC,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAC1B;IAmBD,oBAAoB,CAAC,eAAe,EAAE,uBAAuB,GAAG,IAAI;IAI3E,OAAO,CAAC,eAAe;IAgNvB,OAAO,CAAC,eAAe;IAgCvB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,kBAAkB;YAmDZ,SAAS;IAmFvB,OAAO,CAAC,gBAAgB;IAgDxB,OAAO,CAAC,kBAAkB;YA0FZ,aAAa;IA4K3B,OAAO,CAAC,qBAAqB;IAiC7B,OAAO,CAAC,YAAY;IAqCpB,OAAO,CAAC,cAAc;IAuFtB,OAAO,CAAC,eAAe;IAuJvB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,UAAU;IAoJlB,OAAO,CAAC,YAAY;IAuDpB,OAAO,CAAC,2BAA2B;IAuHnC,OAAO,CAAC,gBAAgB;IAoFlB,KAAK,CACT,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,GAAG,CAAC;CAmHhB"}
|
|
@@ -71,6 +71,80 @@ class RemoteJoiner {
|
|
|
71
71
|
return acc;
|
|
72
72
|
}, {});
|
|
73
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
|
+
}
|
|
74
148
|
static parseQuery(graphqlQuery, variables) {
|
|
75
149
|
const parser = new utils_1.GraphQLUtils.GraphQLParser(graphqlQuery, variables);
|
|
76
150
|
return parser.parseQuery();
|
|
@@ -111,6 +185,27 @@ class RemoteJoiner {
|
|
|
111
185
|
}
|
|
112
186
|
service_.relationships = relationships;
|
|
113
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
|
+
}
|
|
114
209
|
// add aliases
|
|
115
210
|
const isReadOnlyDefinition = !(0, utils_1.isDefined)(service_.serviceName) || service_.isReadOnlyLink;
|
|
116
211
|
if (!isReadOnlyDefinition) {
|
|
@@ -184,6 +279,10 @@ class RemoteJoiner {
|
|
|
184
279
|
const service_ = expandedRelationships.get(extend.serviceName);
|
|
185
280
|
const aliasName = extend.relationship.alias;
|
|
186
281
|
const rel = extend.relationship;
|
|
282
|
+
rel.primaryKeyArr = rel.primaryKey.split(",");
|
|
283
|
+
rel.foreignKeyArr = rel.foreignKey
|
|
284
|
+
.split(",")
|
|
285
|
+
.map((fk) => fk.split(".").pop());
|
|
187
286
|
if (service_.relationships?.has(aliasName)) {
|
|
188
287
|
const existing = service_.relationships.get(aliasName);
|
|
189
288
|
const newRelation = Array.isArray(existing)
|
|
@@ -302,6 +401,9 @@ class RemoteJoiner {
|
|
|
302
401
|
const isIdsUsingOperatorMap = (0, utils_1.isObject)(ids) &&
|
|
303
402
|
Object.keys(ids).some((key) => !!utils_1.FilterOperatorMap[key]);
|
|
304
403
|
uniqueIds = isIdsUsingOperatorMap ? ids : Array.isArray(ids) ? ids : [ids];
|
|
404
|
+
uniqueIds = Array.isArray(uniqueIds)
|
|
405
|
+
? uniqueIds.filter((id) => id != null)
|
|
406
|
+
: uniqueIds;
|
|
305
407
|
}
|
|
306
408
|
if (uniqueIds && Array.isArray(uniqueIds)) {
|
|
307
409
|
const isCompositeKey = Array.isArray(uniqueIds[0]);
|
|
@@ -317,7 +419,6 @@ class RemoteJoiner {
|
|
|
317
419
|
else {
|
|
318
420
|
uniqueIds = Array.from(new Set(uniqueIds.flat()));
|
|
319
421
|
}
|
|
320
|
-
uniqueIds = uniqueIds.filter((id) => (0, utils_1.isDefined)(id));
|
|
321
422
|
}
|
|
322
423
|
let pkFieldAdjusted = pkField;
|
|
323
424
|
if (relationship) {
|
|
@@ -386,10 +487,18 @@ class RemoteJoiner {
|
|
|
386
487
|
};
|
|
387
488
|
const removeChildren = (item, prop) => {
|
|
388
489
|
if (Array.isArray(item)) {
|
|
389
|
-
|
|
490
|
+
for (let i = 0; i < item.length; i++) {
|
|
491
|
+
Object.defineProperty(item[i], prop, {
|
|
492
|
+
value: undefined,
|
|
493
|
+
enumerable: false,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
390
496
|
}
|
|
391
497
|
else {
|
|
392
|
-
|
|
498
|
+
Object.defineProperty(item, prop, {
|
|
499
|
+
value: undefined,
|
|
500
|
+
enumerable: false,
|
|
501
|
+
});
|
|
393
502
|
}
|
|
394
503
|
};
|
|
395
504
|
const cleanup = [];
|
|
@@ -445,28 +554,116 @@ class RemoteJoiner {
|
|
|
445
554
|
}
|
|
446
555
|
async handleExpands(params) {
|
|
447
556
|
const { items, parsedExpands, implodeMapping = [], options } = params;
|
|
448
|
-
if (
|
|
557
|
+
if (parsedExpands.size === 0) {
|
|
449
558
|
return;
|
|
450
559
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
let nestedItems = items;
|
|
456
|
-
const expandedPathLevels = expandedPath.split(".");
|
|
560
|
+
const getItemsForPath = (rootItems, fullPath) => {
|
|
561
|
+
let nestedItems = rootItems;
|
|
562
|
+
const expandedPathLevels = fullPath.split(".");
|
|
457
563
|
for (let idx = 1; idx < expandedPathLevels.length - 1; idx++) {
|
|
458
564
|
nestedItems = RemoteJoiner.getNestedItems(nestedItems, expandedPathLevels[idx]);
|
|
459
565
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
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
|
+
}
|
|
467
658
|
}
|
|
468
659
|
}
|
|
469
|
-
|
|
660
|
+
if (implodeMapping.length > 0) {
|
|
661
|
+
this.handleFieldAliases({
|
|
662
|
+
items,
|
|
663
|
+
parsedExpands,
|
|
664
|
+
implodeMapping,
|
|
665
|
+
});
|
|
666
|
+
}
|
|
470
667
|
}
|
|
471
668
|
getEntityRelationship(params) {
|
|
472
669
|
const { parentServiceConfig, property, entity } = params;
|
|
@@ -488,124 +685,8 @@ class RemoteJoiner {
|
|
|
488
685
|
}
|
|
489
686
|
return rel;
|
|
490
687
|
}
|
|
491
|
-
async expandProperty(params) {
|
|
492
|
-
const { items, parentServiceConfig, expand, options } = params;
|
|
493
|
-
if (!expand) {
|
|
494
|
-
return;
|
|
495
|
-
}
|
|
496
|
-
const relationship = this.getEntityRelationship({
|
|
497
|
-
parentServiceConfig,
|
|
498
|
-
property: expand.property,
|
|
499
|
-
entity: expand.entity,
|
|
500
|
-
});
|
|
501
|
-
if (!relationship) {
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
await this.expandRelationshipProperty({
|
|
505
|
-
items,
|
|
506
|
-
expand,
|
|
507
|
-
relationship,
|
|
508
|
-
options,
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
async expandRelationshipProperty(params) {
|
|
512
|
-
const { items, expand, relationship, options } = params;
|
|
513
|
-
const field = relationship.inverse
|
|
514
|
-
? relationship.primaryKey
|
|
515
|
-
: relationship.foreignKey.split(".").pop();
|
|
516
|
-
const fieldsArray = field.split(",");
|
|
517
|
-
const idsToFetch = new Set();
|
|
518
|
-
const requestedFields = new Set(expand.fields ?? []);
|
|
519
|
-
const fieldsById = new Map();
|
|
520
|
-
items.forEach((item) => {
|
|
521
|
-
const values = fieldsArray.map((field) => item?.[field]);
|
|
522
|
-
if (values.length === fieldsArray.length) {
|
|
523
|
-
if (item?.[relationship.alias]) {
|
|
524
|
-
for (const field of requestedFields.values()) {
|
|
525
|
-
if (field in item[relationship.alias]) {
|
|
526
|
-
requestedFields.delete(field);
|
|
527
|
-
fieldsById.delete(field);
|
|
528
|
-
}
|
|
529
|
-
else {
|
|
530
|
-
if (!fieldsById.has(field)) {
|
|
531
|
-
fieldsById.set(field, []);
|
|
532
|
-
}
|
|
533
|
-
fieldsById
|
|
534
|
-
.get(field)
|
|
535
|
-
.push(fieldsArray.length === 1 ? values[0] : values);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
else {
|
|
540
|
-
if (fieldsArray.length === 1) {
|
|
541
|
-
idsToFetch.add(values[0]);
|
|
542
|
-
}
|
|
543
|
-
else {
|
|
544
|
-
idsToFetch.add(values);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
});
|
|
549
|
-
for (const values of fieldsById.values()) {
|
|
550
|
-
values.forEach((val) => {
|
|
551
|
-
idsToFetch.add(val);
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
if (idsToFetch.size === 0) {
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
|
-
const relatedDataArray = await this.fetchData({
|
|
558
|
-
expand,
|
|
559
|
-
pkField: field,
|
|
560
|
-
ids: Array.from(idsToFetch),
|
|
561
|
-
relationship,
|
|
562
|
-
options,
|
|
563
|
-
});
|
|
564
|
-
const joinFields = relationship.inverse
|
|
565
|
-
? relationship.foreignKey.split(",")
|
|
566
|
-
: relationship.primaryKey.split(",");
|
|
567
|
-
const relData = relatedDataArray.path
|
|
568
|
-
? relatedDataArray.data[relatedDataArray.path]
|
|
569
|
-
: relatedDataArray.data;
|
|
570
|
-
const relatedDataMap = RemoteJoiner.createRelatedDataMap(relData, joinFields);
|
|
571
|
-
items.forEach((item) => {
|
|
572
|
-
if (!item) {
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
const itemKey = fieldsArray.map((field) => item[field]).join(",");
|
|
576
|
-
if (item[relationship.alias]) {
|
|
577
|
-
if (Array.isArray(item[field])) {
|
|
578
|
-
for (let i = 0; i < item[relationship.alias].length; i++) {
|
|
579
|
-
const it = item[relationship.alias][i];
|
|
580
|
-
item[relationship.alias][i] = Object.assign(it, relatedDataMap[it[relationship.primaryKey]]);
|
|
581
|
-
}
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
item[relationship.alias] = Object.assign(item[relationship.alias], relatedDataMap[itemKey]);
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
if (Array.isArray(item[field])) {
|
|
588
|
-
item[relationship.alias] = item[field].map((id) => {
|
|
589
|
-
if (relationship.isList && !Array.isArray(relatedDataMap[id])) {
|
|
590
|
-
relatedDataMap[id] = (0, utils_1.isDefined)(relatedDataMap[id])
|
|
591
|
-
? [relatedDataMap[id]]
|
|
592
|
-
: [];
|
|
593
|
-
}
|
|
594
|
-
return relatedDataMap[id];
|
|
595
|
-
});
|
|
596
|
-
}
|
|
597
|
-
else {
|
|
598
|
-
if (relationship.isList && !Array.isArray(relatedDataMap[itemKey])) {
|
|
599
|
-
relatedDataMap[itemKey] = (0, utils_1.isDefined)(relatedDataMap[itemKey])
|
|
600
|
-
? [relatedDataMap[itemKey]]
|
|
601
|
-
: [];
|
|
602
|
-
}
|
|
603
|
-
item[relationship.alias] = relatedDataMap[itemKey];
|
|
604
|
-
}
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
688
|
parseExpands(params) {
|
|
608
|
-
const { initialService, query, serviceConfig, expands, implodeMapping, options, initialData, } = params;
|
|
689
|
+
const { initialService, query, serviceConfig, expands, implodeMapping, options, initialData, initialDataOnly, } = params;
|
|
609
690
|
const { parsedExpands, aliasRealPathMap } = this.parseProperties({
|
|
610
691
|
initialService,
|
|
611
692
|
query,
|
|
@@ -613,7 +694,7 @@ class RemoteJoiner {
|
|
|
613
694
|
expands,
|
|
614
695
|
implodeMapping,
|
|
615
696
|
});
|
|
616
|
-
if (initialData?.length) {
|
|
697
|
+
if (initialData?.length && initialDataOnly) {
|
|
617
698
|
this.createFilterFromInitialData({
|
|
618
699
|
initialData: options?.initialData,
|
|
619
700
|
parsedExpands,
|
|
@@ -621,8 +702,75 @@ class RemoteJoiner {
|
|
|
621
702
|
});
|
|
622
703
|
}
|
|
623
704
|
const groupedExpands = this.groupExpands(parsedExpands);
|
|
705
|
+
this.buildQueryPlan(parsedExpands, groupedExpands);
|
|
624
706
|
return groupedExpands;
|
|
625
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
|
+
}
|
|
626
774
|
parseProperties(params) {
|
|
627
775
|
const { initialService, query, serviceConfig, expands, implodeMapping } = params;
|
|
628
776
|
const aliasRealPathMap = new Map();
|
|
@@ -780,12 +928,17 @@ class RemoteJoiner {
|
|
|
780
928
|
const midProp = curMiddlePath.join(".");
|
|
781
929
|
const existingExpand = expands.find((exp) => exp.property === midProp);
|
|
782
930
|
const extraExtends = {
|
|
931
|
+
fields: existingExpand?.fields,
|
|
932
|
+
args: existingExpand?.args,
|
|
783
933
|
...(midProp === fullAliasProp ? expand : {}),
|
|
784
934
|
property: midProp,
|
|
785
935
|
isAliasMapping: !existingExpand,
|
|
786
936
|
};
|
|
787
937
|
if (forwardArgumentsOnPath.includes(BASE_PATH + "." + midProp)) {
|
|
788
|
-
|
|
938
|
+
const forwarded = (existingExpand?.args ?? []).concat(expand?.args ?? []);
|
|
939
|
+
if (forwarded.length) {
|
|
940
|
+
extraExtends.args = forwarded;
|
|
941
|
+
}
|
|
789
942
|
}
|
|
790
943
|
extMapping.push(extraExtends);
|
|
791
944
|
}
|
|
@@ -848,8 +1001,19 @@ class RemoteJoiner {
|
|
|
848
1001
|
targetExpand.expands ??= {};
|
|
849
1002
|
targetExpand = targetExpand.expands[key] ??= {};
|
|
850
1003
|
}
|
|
851
|
-
|
|
852
|
-
|
|
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
|
+
}
|
|
853
1017
|
mergedExpands.delete(path);
|
|
854
1018
|
mergedPaths.set(path, expand);
|
|
855
1019
|
parentPath = parentExpand.parent;
|
|
@@ -963,7 +1127,10 @@ class RemoteJoiner {
|
|
|
963
1127
|
property: key,
|
|
964
1128
|
});
|
|
965
1129
|
if (isRel) {
|
|
966
|
-
|
|
1130
|
+
Object.defineProperty(shallowProperty, key, {
|
|
1131
|
+
value: undefined,
|
|
1132
|
+
enumerable: false,
|
|
1133
|
+
});
|
|
967
1134
|
}
|
|
968
1135
|
}
|
|
969
1136
|
Object.assign(item, shallowProperty);
|
|
@@ -1019,6 +1186,7 @@ class RemoteJoiner {
|
|
|
1019
1186
|
implodeMapping,
|
|
1020
1187
|
options,
|
|
1021
1188
|
initialData: iniDataArray,
|
|
1189
|
+
initialDataOnly: options?.initialDataOnly,
|
|
1022
1190
|
};
|
|
1023
1191
|
const parsedExpands = this.parseExpands(parseExpandsConfig);
|
|
1024
1192
|
const root = parsedExpands.get(BASE_PATH);
|
|
@@ -1095,7 +1263,10 @@ function gerPrimaryKeysAndOtherFilters({ serviceConfig, queryObj }) {
|
|
|
1095
1263
|
name: primaryKeyFilter,
|
|
1096
1264
|
value: filters[primaryKeyFilter],
|
|
1097
1265
|
};
|
|
1098
|
-
|
|
1266
|
+
Object.defineProperty(filters, primaryKeyFilter, {
|
|
1267
|
+
value: undefined,
|
|
1268
|
+
enumerable: false,
|
|
1269
|
+
});
|
|
1099
1270
|
}
|
|
1100
1271
|
}
|
|
1101
1272
|
otherArgs = otherArgs?.length ? otherArgs : undefined;
|