1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | import {Filter, InclusionFilter} from '@loopback/filter';
|
7 | import {AnyObject, Options} from '../../common-types';
|
8 | import {Entity} from '../../model';
|
9 | import {EntityCrudRepository} from '../../repositories';
|
10 | import {
|
11 | deduplicate,
|
12 | findByForeignKeys,
|
13 | flattenTargetsOfOneToOneRelation,
|
14 | StringKeyOf,
|
15 | } from '../relation.helpers';
|
16 | import {
|
17 | Getter,
|
18 | InclusionResolver,
|
19 | ReferencesManyDefinition,
|
20 | } from '../relation.types';
|
21 | import {resolveReferencesManyMetadata} from './references-many.helpers';
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 | export 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 | }
|