UNPKG

2.54 kBPlain TextView Raw
1// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
2// Node module: @loopback/repository
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6import {Filter, InclusionFilter} from '@loopback/filter';
7import {AnyObject, Options} from '../../common-types';
8import {Entity} from '../../model';
9import {EntityCrudRepository} from '../../repositories';
10import {
11 deduplicate,
12 findByForeignKeys,
13 flattenTargetsOfOneToOneRelation,
14 StringKeyOf,
15} from '../relation.helpers';
16import {
17 Getter,
18 InclusionResolver,
19 ReferencesManyDefinition,
20} from '../relation.types';
21import {resolveReferencesManyMetadata} from './references-many.helpers';
22
23/**
24 * Creates InclusionResolver for ReferencesMany relation.
25 * Notice that this function only generates the inclusionResolver.
26 * It doesn't register it for the source repository.
27 *
28 * Notice: scope field for inclusion is not supported yet
29 *
30 * @param meta - resolved ReferencesManyMetadata
31 * @param getTargetRepo - target repository i.e where related instances are
32 */
33export function createReferencesManyInclusionResolver<
34 Target extends Entity,
35 TargetIds,
36 TargetRelations extends object,
37>(
38 meta: ReferencesManyDefinition,
39 getTargetRepo: Getter<
40 EntityCrudRepository<Target, TargetIds, TargetRelations>
41 >,
42): InclusionResolver<Entity, Target> {
43 const relationMeta = resolveReferencesManyMetadata(meta);
44
45 return async function fetchIncludedModels(
46 entities: Entity[],
47 inclusion: InclusionFilter,
48 options?: Options,
49 ): Promise<(Target & TargetRelations)[][]> {
50 if (!entities.length) return [];
51
52 const sourceKey = relationMeta.keyFrom;
53 const sourceMap = entities.map(e => (e as AnyObject)[sourceKey]);
54 const sourceIds = sourceMap.flat();
55 const targetKey = relationMeta.keyTo as StringKeyOf<Target>;
56 const dedupedSourceIds = deduplicate(sourceIds);
57
58 const scope =
59 typeof inclusion === 'string' ? {} : (inclusion.scope as Filter<Target>);
60
61 const targetRepo = await getTargetRepo();
62 const targetsFound = await findByForeignKeys(
63 targetRepo,
64 targetKey,
65 dedupedSourceIds.filter(e => e),
66 scope,
67 options,
68 );
69
70 return sourceMap.map(chainIds => {
71 if (!chainIds) return [];
72 const targets = flattenTargetsOfOneToOneRelation(
73 chainIds,
74 targetsFound,
75 targetKey,
76 );
77 return targets.filter((v): v is Target & TargetRelations => v != null);
78 });
79 };
80}