UNPKG

2.7 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 debugFactory from 'debug';
8import {AnyObject, Options} from '../../common-types';
9import {Entity} from '../../model';
10import {EntityCrudRepository} from '../../repositories';
11import {
12 findByForeignKeys,
13 flattenTargetsOfOneToManyRelation,
14 StringKeyOf,
15} from '../relation.helpers';
16import {Getter, HasManyDefinition, InclusionResolver} from '../relation.types';
17import {resolveHasManyMetadata} from './has-many.helpers';
18
19const debug = debugFactory(
20 'loopback:repository:relations:has-many:inclusion-resolver',
21);
22
23/**
24 * Creates InclusionResolver for HasMany 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 metadata of the hasMany relation
31 * @param getTargetRepo - target repository i.e where related instances are
32 */
33export function createHasManyInclusionResolver<
34 Target extends Entity,
35 TargetID,
36 TargetRelations extends object,
37>(
38 meta: HasManyDefinition,
39 getTargetRepo: Getter<
40 EntityCrudRepository<Target, TargetID, TargetRelations>
41 >,
42): InclusionResolver<Entity, Target> {
43 const relationMeta = resolveHasManyMetadata(meta);
44
45 return async function fetchHasManyModels(
46 entities: Entity[],
47 inclusion: InclusionFilter,
48 options?: Options,
49 ): Promise<((Target & TargetRelations)[] | undefined)[]> {
50 if (!entities.length) return [];
51
52 debug('Fetching target models for entities:', entities);
53 debug('Relation metadata:', relationMeta);
54
55 const sourceKey = relationMeta.keyFrom;
56 const sourceIds = entities.map(e => (e as AnyObject)[sourceKey]);
57 const targetKey = relationMeta.keyTo as StringKeyOf<Target>;
58
59 debug('Parameters:', {sourceKey, sourceIds, targetKey});
60 debug(
61 'sourceId types',
62 sourceIds.map(i => typeof i),
63 );
64
65 const scope =
66 typeof inclusion === 'string' ? {} : (inclusion.scope as Filter<Target>);
67
68 const targetRepo = await getTargetRepo();
69 const targetsFound = await findByForeignKeys(
70 targetRepo,
71 targetKey,
72 sourceIds,
73 scope,
74 options,
75 );
76
77 debug('Targets found:', targetsFound);
78
79 const result = flattenTargetsOfOneToManyRelation(
80 sourceIds,
81 targetsFound,
82 targetKey,
83 );
84
85 debug('fetchHasManyModels result', result);
86 return result;
87 };
88}