1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | import {DecoratorFactory, MetadataInspector} from '@loopback/core';
|
7 | import {property} from '../../decorators';
|
8 | import {Entity, EntityResolver, PropertyDefinition} from '../../model';
|
9 | import {relation} from '../relation.decorator';
|
10 | import {ReferencesManyDefinition, RelationType} from '../relation.types';
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | export function referencesMany<T extends Entity>(
|
21 | targetResolver: EntityResolver<T>,
|
22 | definition?: Partial<ReferencesManyDefinition>,
|
23 | propertyDefinition?: Partial<PropertyDefinition>,
|
24 | ) {
|
25 | return function (decoratedTarget: Entity, decoratedKey: string) {
|
26 | const propType =
|
27 | MetadataInspector.getDesignTypeForProperty(
|
28 | decoratedTarget,
|
29 | decoratedKey,
|
30 | ) ?? propertyDefinition?.type;
|
31 |
|
32 | if (!propType) {
|
33 | const fullPropName = DecoratorFactory.getTargetName(
|
34 | decoratedTarget,
|
35 | decoratedKey,
|
36 | );
|
37 | throw new Error(
|
38 | `Cannot infer type of model property ${fullPropName} because ` +
|
39 | 'TypeScript compiler option `emitDecoratorMetadata` is not set. ' +
|
40 | 'Please enable `emitDecoratorMetadata` or use the third argument of ' +
|
41 | '`@referencesMany` decorator to specify the property type explicitly.',
|
42 | );
|
43 | }
|
44 |
|
45 | const sourceKeyType = MetadataInspector.getDesignTypeForProperty(
|
46 | targetResolver().prototype,
|
47 | definition?.keyTo ?? 'id',
|
48 | );
|
49 |
|
50 | if (!sourceKeyType) {
|
51 | const fullPropName = DecoratorFactory.getTargetName(
|
52 | targetResolver().prototype,
|
53 | definition?.keyTo ?? 'id',
|
54 | );
|
55 | throw new Error(
|
56 | `Cannot infer type of model property ${fullPropName} because ` +
|
57 | 'TypeScript compiler option `emitDecoratorMetadata` is not set. ' +
|
58 | 'Please enable `emitDecoratorMetadata` or use the second argument of ' +
|
59 | '`@referencesMany` decorator to specify the property type explicitly.',
|
60 | );
|
61 | }
|
62 |
|
63 | const propMeta: PropertyDefinition = Object.assign(
|
64 | {},
|
65 |
|
66 | propertyDefinition,
|
67 |
|
68 | {
|
69 | type: propType,
|
70 | itemType: sourceKeyType,
|
71 |
|
72 |
|
73 |
|
74 | },
|
75 | );
|
76 | property(propMeta)(decoratedTarget, decoratedKey);
|
77 |
|
78 |
|
79 |
|
80 | const relationName = decoratedKey.replace(/Ids$/, 's');
|
81 |
|
82 | const meta: ReferencesManyDefinition = Object.assign(
|
83 |
|
84 | {
|
85 | keyFrom: decoratedKey,
|
86 | name: relationName,
|
87 | },
|
88 |
|
89 | definition,
|
90 |
|
91 | {
|
92 | type: RelationType.referencesMany,
|
93 | targetsMany: true,
|
94 | source: decoratedTarget.constructor,
|
95 | target: targetResolver,
|
96 | },
|
97 | );
|
98 | relation(meta)(decoratedTarget, decoratedKey);
|
99 | };
|
100 | }
|