UNPKG

5.41 kBJavaScriptView Raw
1"use strict";
2// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
3// Node module: @loopback/repository
4// This file is licensed under the MIT License.
5// License text available at https://opensource.org/licenses/MIT
6Object.defineProperty(exports, "__esModule", { value: true });
7exports.createBelongsToInclusionResolver = void 0;
8const __1 = require("../../");
9const relation_helpers_1 = require("../relation.helpers");
10const belongs_to_helpers_1 = require("./belongs-to.helpers");
11/**
12 * Creates InclusionResolver for BelongsTo relation.
13 * Notice that this function only generates the inclusionResolver.
14 * It doesn't register it for the source repository.
15 *
16 * Notice: scope field for inclusion is not supported yet
17 *
18 * @param meta - resolved BelongsToMetadata
19 * @param getTargetRepoDict - dictionary of target model type - target repository
20 * i.e where related instances for different types are
21 */
22function createBelongsToInclusionResolver(meta, getTargetRepoDict) {
23 const relationMeta = (0, belongs_to_helpers_1.resolveBelongsToMetadata)(meta);
24 return async function fetchBelongsToModel(entities, inclusion, options) {
25 if (!entities.length)
26 return [];
27 // Source ids are grouped by their target polymorphic types
28 // Each type search for target instances and then merge together in a merge-sort-like manner
29 const sourceKey = relationMeta.keyFrom;
30 const targetKey = relationMeta.keyTo;
31 const targetDiscriminator = relationMeta.polymorphic
32 ? relationMeta.polymorphic.discriminator
33 : undefined;
34 const scope = typeof inclusion === 'string' ? {} : inclusion.scope;
35 // sourceIds in {targetType -> sourceId}
36 const sourceIdsCategorized = {};
37 if (targetDiscriminator) {
38 entities.forEach((value, index, allEntites) => {
39 const concreteType = String(value[targetDiscriminator]);
40 if (!getTargetRepoDict[concreteType]) {
41 throw new __1.InvalidPolymorphismError(concreteType, targetDiscriminator);
42 }
43 if (!sourceIdsCategorized[concreteType]) {
44 sourceIdsCategorized[concreteType] = [];
45 }
46 sourceIdsCategorized[concreteType].push(value[sourceKey]);
47 });
48 }
49 else {
50 const concreteType = relationMeta.target().name;
51 if (!getTargetRepoDict[concreteType]) {
52 throw new __1.InvalidPolymorphismError(concreteType);
53 }
54 entities.forEach((value, index, allEntites) => {
55 if (!sourceIdsCategorized[concreteType]) {
56 sourceIdsCategorized[concreteType] = [];
57 }
58 sourceIdsCategorized[concreteType].push(value[sourceKey]);
59 });
60 }
61 // Ensure targetKey is included otherwise flatten function cannot work
62 const changedTargetKeyField = (0, __1.includeFieldIfNot)(scope === null || scope === void 0 ? void 0 : scope.fields, targetKey);
63 let needToRemoveTargetKeyFieldLater = false;
64 if (changedTargetKeyField !== false) {
65 scope.fields = changedTargetKeyField;
66 needToRemoveTargetKeyFieldLater = true;
67 }
68 // Each sourceIds array with same target type extract target instances
69 const targetCategorized = {};
70 for (const k of Object.keys(sourceIdsCategorized)) {
71 const targetRepo = await getTargetRepoDict[k]();
72 const targetsFound = await (0, relation_helpers_1.findByForeignKeys)(targetRepo, targetKey, (0, relation_helpers_1.deduplicate)(sourceIdsCategorized[k]).filter(e => e), scope, options);
73 targetCategorized[k] = (0, relation_helpers_1.flattenTargetsOfOneToOneRelation)(sourceIdsCategorized[k], targetsFound, targetKey);
74 // Remove targetKey if should be excluded but included above
75 if (needToRemoveTargetKeyFieldLater) {
76 targetCategorized[k] = targetCategorized[k].map(e => {
77 if (e) {
78 delete e[targetKey];
79 }
80 return e;
81 });
82 }
83 }
84 // Merge
85 // Why the order is correct:
86 // e.g. target model 1 = a, target model 2 = b
87 // all entities: [S(a-1), S(a-2), S(b-3), S(a-4), S(b-5)]
88 // a-result: [a-1, a-2, a-4]
89 // b-result: [b-3, b-4]
90 // merged:
91 // entities[1]->a => targets: [a-1 from a-result.shift()]
92 // entities[2]->a => targets: [a-1, a-2 from a-result.shift()]
93 // entities[3]->b => targets: [a-1, a-2, b-3 from b-result.shift()]
94 // entities[4]->a => targets: [a-1, a-2, b-3, a-4 from a-result.shift()]
95 // entities[5]->b => targets: [a-1, a-2, b-3, a-4, b-5 from b-result.shift()]
96 if (targetDiscriminator) {
97 const allTargets = [];
98 entities.forEach((value, index, allEntites) => {
99 allTargets.push(targetCategorized[String(value[targetDiscriminator])].shift());
100 });
101 return allTargets;
102 }
103 else {
104 return targetCategorized[relationMeta.target().name];
105 }
106 };
107}
108exports.createBelongsToInclusionResolver = createBelongsToInclusionResolver;
109//# sourceMappingURL=belongs-to.inclusion-resolver.js.map
\No newline at end of file