UNPKG

8.23 kBPlain TextView Raw
1// Copyright IBM Corp. and LoopBack contributors 2018,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 {InclusionFilter} from '@loopback/filter';
7import {Options} from '../common-types';
8import {Entity} from '../model';
9import {TypeResolver} from '../type-resolver';
10
11export enum RelationType {
12 belongsTo = 'belongsTo',
13 hasOne = 'hasOne',
14 hasMany = 'hasMany',
15 embedsOne = 'embedsOne',
16 embedsMany = 'embedsMany',
17 referencesOne = 'referencesOne',
18 referencesMany = 'referencesMany',
19}
20
21export interface RelationDefinitionBase {
22 /**
23 * The type of the relation, must be one of RelationType values.
24 */
25 type: RelationType;
26
27 /**
28 * True for relations targeting multiple instances (e.g. HasMany),
29 * false for relations with a single target (e.g. BelongsTo, HasOne).
30 * This property is needed by OpenAPI/JSON Schema generator.
31 */
32 targetsMany: boolean;
33
34 /**
35 * The relation name, typically matching the name of the accessor property
36 * defined on the source model. For example "orders" or "customer".
37 */
38 name: string;
39
40 /**
41 * The source model of this relation.
42 *
43 * E.g. when a Customer has many Order instances, then Customer is the source.
44 */
45 source: typeof Entity;
46
47 /**
48 * The target model of this relation.
49 *
50 * E.g. when a Customer has many Order instances, then Order is the target.
51 */
52 target: TypeResolver<Entity, typeof Entity>;
53}
54
55/**
56 * HasManyDefinition defines one-to-many relations and also possible defines
57 * many-to-many relations with through models.
58 */
59export interface HasManyDefinition extends RelationDefinitionBase {
60 type: RelationType.hasMany;
61 targetsMany: true;
62
63 /**
64 * keyTo: The foreign key used by the target model for this relation.
65 * keyFrom: The source key used by the source model for this relation.
66 *
67 * E.g. when a Customer has many Order instances, then keyTo is "customerId".
68 * Note that "customerId" is the default FK assumed by the framework, users
69 * can provide a custom FK name by setting "keyTo".
70 * And Customer.id is keyFrom. keyFrom defaults to the id property of a model.
71 * Users can provide a custom source key name by setting "keyTo".
72 *
73 */
74 keyTo?: string;
75 keyFrom?: string;
76
77 /**
78 * With current architecture design, polymorphic type cannot be supported without through
79 * Consider using Source-hasMany->Through->hasOne->Target(polymorphic) for one-to-many relations
80 */
81 // polymorphic?: boolean | {discriminator: string};
82
83 /**
84 * Description of the through model of the hasManyThrough relation.
85 *
86 * A `hasManyThrough` relation defines a many-to-many connection with another model.
87 * This relation indicates that the declaring model can be matched with zero or more
88 * instances of another model by proceeding through a third model.
89 *
90 * E.g a Category has many Products, and a Product can have many Categories.
91 * CategoryProductLink can be the through model.
92 * Such a through model has information of foreign keys of the source model(Category) and the target model(Product).
93 *
94 * Warning: The hasManyThrough interface is experimental and is subject to change.
95 * If backwards-incompatible changes are made, a new major version may not be
96 * released.
97 */
98 through?: {
99 /**
100 * The through model of this relation.
101 *
102 * E.g. when a Category has many CategoryProductLink instances and a Product has many CategoryProductLink instances,
103 * then CategoryProductLink is through.
104 */
105 model: TypeResolver<Entity, typeof Entity>;
106
107 /**
108 * The foreign key of the source model defined in the through model, e.g. CategoryProductLink#categoryId
109 */
110 keyFrom?: string;
111
112 /**
113 * The foreign key of the target model defined in the through model, e.g. CategoryProductLink#productId
114 */
115 keyTo?: string;
116
117 /**
118 * The polymorphism of the target model. The discriminator is a key of *through* model.
119 * If the target model is not polymorphic, then the value should be left undefined or false;
120 * If the key on through model indicating the concrete class of the through instance is default
121 * i.e. camelCase(classNameOf(targetModelInstance)) + "Id"
122 * then the discriminator field can be undefined
123 *
124 * With current architecture design, polymorphic type cannot be supported without through
125 * Consider using Source hasMany Through hasOne Target(polymorphic)
126 * or Source hasMany Through belongsTo Target(polymorphic) for one-to-many relations
127 */
128 polymorphic?: boolean | {discriminator: string};
129 };
130}
131
132export interface BelongsToDefinition extends RelationDefinitionBase {
133 type: RelationType.belongsTo;
134 targetsMany: false;
135
136 /*
137 * The foreign key in the source model, e.g. Order#customerId.
138 */
139 keyFrom?: string;
140
141 /*
142 * The primary key of the target model, e.g Customer#id.
143 */
144 keyTo?: string;
145 /**
146 * The polymorphism of the target model. The discriminator is a key of source model.
147 * If the target model is not polymorphic, then the value should be left undefined or false;
148 * If the key on source model indicating the concrete class of the target instance is default
149 * i.e. camelCase(classNameOf(throughModelInstance)) + "Id"
150 * Then the discriminator field can be undefined
151 */
152 polymorphic?: boolean | {discriminator: string};
153}
154
155export interface HasOneDefinition extends RelationDefinitionBase {
156 type: RelationType.hasOne;
157 targetsMany: false;
158
159 /**
160 * keyTo: The foreign key used by the target model for this relation.
161 * keyFrom: The source key used by the source model for this relation.
162 *
163 * E.g. when a Customer has one Address instance, then keyTo is "customerId".
164 * Note that "customerId" is the default FK assumed by the framework, users
165 * can provide a custom FK name by setting "keyTo".
166 * And Customer.id is keyFrom. keyFrom defaults to the id property of a model.
167 * Users can provide a custom source key name by setting "keyTo".
168 */
169 keyTo?: string;
170 keyFrom?: string;
171 /**
172 * The polymorphism of the target model. The discriminator is a key of source model.
173 * If the target model is not polymorphic, then the value should be left undefined or false;
174 * If the key on source model indicating the concrete class of the target instance is default
175 * i.e. camelCase(classNameOf(throughModelInstance)) + "Id"
176 * Then the discriminator field can be undefined
177 */
178 polymorphic?: boolean | {discriminator: string};
179}
180
181export interface ReferencesManyDefinition extends RelationDefinitionBase {
182 type: RelationType.referencesMany;
183 targetsMany: true;
184
185 /**
186 * keyTo: The foreign key used by the target model for this relation.
187 * keyFrom: The source key used by the source model for this relation.
188 *
189 * TODO(bajtos) Add relation description.
190 *
191 */
192 keyTo?: string;
193 keyFrom?: string;
194}
195
196/**
197 * A union type describing all possible Relation metadata objects.
198 */
199export type RelationMetadata =
200 | HasManyDefinition
201 | BelongsToDefinition
202 | HasOneDefinition
203 | ReferencesManyDefinition
204 // TODO(bajtos) add other relation types and remove RelationDefinitionBase once
205 // all relation types are covered.
206 | RelationDefinitionBase;
207
208// Re-export Getter so that users don't have to import from @loopback/context
209export {Getter} from '@loopback/core';
210
211/**
212 * @returns An array of resolved values, the items must be ordered in the same
213 * way as `sourceEntities`. The resolved value can be one of:
214 * - `undefined` when no target model(s) were found
215 * - `Entity` for relations targeting a single model
216 * - `Entity[]` for relations targeting multiple models
217 */
218export type InclusionResolver<S extends Entity, T extends Entity> = (
219 /**
220 * List of source models as returned by the first database query.
221 */
222 sourceEntities: S[],
223 /**
224 * Inclusion requested by the user (e.g. scope constraints to apply).
225 */
226 inclusion: InclusionFilter,
227 /**
228 * Generic options object, e.g. carrying the Transaction object.
229 */
230 options?: Options,
231) => Promise<(T | undefined)[] | (T[] | undefined)[]>;