UNPKG

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