@loopback/repository 4.1.2 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/invalid-polymorphism.error.d.ts +5 -0
- package/dist/errors/invalid-polymorphism.error.js +22 -0
- package/dist/errors/invalid-polymorphism.error.js.map +1 -0
- package/dist/model.d.ts +7 -1
- package/dist/model.js +14 -0
- package/dist/model.js.map +1 -1
- package/dist/relations/belongs-to/belongs-to.accessor.d.ts +6 -2
- package/dist/relations/belongs-to/belongs-to.accessor.js +18 -5
- package/dist/relations/belongs-to/belongs-to.accessor.js.map +1 -1
- package/dist/relations/belongs-to/belongs-to.helpers.d.ts +3 -0
- package/dist/relations/belongs-to/belongs-to.helpers.js +32 -8
- package/dist/relations/belongs-to/belongs-to.helpers.js.map +1 -1
- package/dist/relations/belongs-to/belongs-to.inclusion-resolver.d.ts +5 -2
- package/dist/relations/belongs-to/belongs-to.inclusion-resolver.js +81 -8
- package/dist/relations/belongs-to/belongs-to.inclusion-resolver.js.map +1 -1
- package/dist/relations/belongs-to/belongs-to.repository.d.ts +28 -5
- package/dist/relations/belongs-to/belongs-to.repository.js +49 -10
- package/dist/relations/belongs-to/belongs-to.repository.js.map +1 -1
- package/dist/relations/has-many/has-many-through.helpers.d.ts +3 -0
- package/dist/relations/has-many/has-many-through.helpers.js +25 -1
- package/dist/relations/has-many/has-many-through.helpers.js.map +1 -1
- package/dist/relations/has-many/has-many-through.inclusion-resolver.d.ts +3 -1
- package/dist/relations/has-many/has-many-through.inclusion-resolver.js +92 -21
- package/dist/relations/has-many/has-many-through.inclusion-resolver.js.map +1 -1
- package/dist/relations/has-many/has-many-through.repository-factory.d.ts +3 -1
- package/dist/relations/has-many/has-many-through.repository-factory.js +7 -1
- package/dist/relations/has-many/has-many-through.repository-factory.js.map +1 -1
- package/dist/relations/has-many/has-many-through.repository.d.ts +66 -11
- package/dist/relations/has-many/has-many-through.repository.js +211 -35
- package/dist/relations/has-many/has-many-through.repository.js.map +1 -1
- package/dist/relations/has-one/has-one.helpers.d.ts +3 -0
- package/dist/relations/has-one/has-one.helpers.js +34 -8
- package/dist/relations/has-one/has-one.helpers.js.map +1 -1
- package/dist/relations/has-one/has-one.inclusion-resolver.d.ts +6 -3
- package/dist/relations/has-one/has-one.inclusion-resolver.js +82 -7
- package/dist/relations/has-one/has-one.inclusion-resolver.js.map +1 -1
- package/dist/relations/has-one/has-one.repository-factory.d.ts +9 -3
- package/dist/relations/has-one/has-one.repository-factory.js +13 -3
- package/dist/relations/has-one/has-one.repository-factory.js.map +1 -1
- package/dist/relations/has-one/has-one.repository.d.ts +58 -11
- package/dist/relations/has-one/has-one.repository.js +118 -15
- package/dist/relations/has-one/has-one.repository.js.map +1 -1
- package/dist/relations/index.d.ts +2 -0
- package/dist/relations/index.js +2 -0
- package/dist/relations/index.js.map +1 -1
- package/dist/relations/references-many/index.d.ts +4 -0
- package/dist/relations/references-many/index.js +12 -0
- package/dist/relations/references-many/index.js.map +1 -0
- package/dist/relations/references-many/references-many.accessor.d.ts +17 -0
- package/dist/relations/references-many/references-many.accessor.js +40 -0
- package/dist/relations/references-many/references-many.accessor.js.map +1 -0
- package/dist/relations/references-many/references-many.decorator.d.ts +11 -0
- package/dist/relations/references-many/references-many.decorator.js +73 -0
- package/dist/relations/references-many/references-many.decorator.js.map +1 -0
- package/dist/relations/references-many/references-many.helpers.d.ts +17 -0
- package/dist/relations/references-many/references-many.helpers.js +63 -0
- package/dist/relations/references-many/references-many.helpers.js.map +1 -0
- package/dist/relations/references-many/references-many.inclusion-resolver.d.ts +14 -0
- package/dist/relations/references-many/references-many.inclusion-resolver.js +42 -0
- package/dist/relations/references-many/references-many.inclusion-resolver.js.map +1 -0
- package/dist/relations/references-many/references-many.repository.d.ts +28 -0
- package/dist/relations/references-many/references-many.repository.js +33 -0
- package/dist/relations/references-many/references-many.repository.js.map +1 -0
- package/dist/relations/relation.decorator.d.ts +0 -6
- package/dist/relations/relation.decorator.js +1 -13
- package/dist/relations/relation.decorator.js.map +1 -1
- package/dist/relations/relation.filter.solver.d.ts +2 -0
- package/dist/relations/relation.filter.solver.js +57 -0
- package/dist/relations/relation.filter.solver.js.map +1 -0
- package/dist/relations/relation.helpers.js +16 -1
- package/dist/relations/relation.helpers.js.map +1 -1
- package/dist/relations/relation.types.d.ts +52 -1
- package/dist/relations/relation.types.js.map +1 -1
- package/dist/repositories/legacy-juggler-bridge.d.ts +35 -8
- package/dist/repositories/legacy-juggler-bridge.js +36 -14
- package/dist/repositories/legacy-juggler-bridge.js.map +1 -1
- package/package.json +13 -13
- package/src/errors/index.ts +1 -0
- package/src/errors/invalid-polymorphism.error.ts +28 -0
- package/src/model.ts +19 -0
- package/src/relations/belongs-to/belongs-to.accessor.ts +35 -6
- package/src/relations/belongs-to/belongs-to.helpers.ts +36 -9
- package/src/relations/belongs-to/belongs-to.inclusion-resolver.ts +108 -17
- package/src/relations/belongs-to/belongs-to.repository.ts +77 -17
- package/src/relations/has-many/has-many-through.helpers.ts +27 -1
- package/src/relations/has-many/has-many-through.inclusion-resolver.ts +117 -26
- package/src/relations/has-many/has-many-through.repository-factory.ts +21 -3
- package/src/relations/has-many/has-many-through.repository.ts +343 -76
- package/src/relations/has-one/has-one.helpers.ts +40 -13
- package/src/relations/has-one/has-one.inclusion-resolver.ts +109 -15
- package/src/relations/has-one/has-one.repository-factory.ts +34 -6
- package/src/relations/has-one/has-one.repository.ts +188 -35
- package/src/relations/index.ts +2 -0
- package/src/relations/references-many/index.ts +9 -0
- package/src/relations/references-many/references-many.accessor.ts +76 -0
- package/src/relations/references-many/references-many.decorator.ts +100 -0
- package/src/relations/references-many/references-many.helpers.ts +82 -0
- package/src/relations/references-many/references-many.inclusion-resolver.ts +80 -0
- package/src/relations/references-many/references-many.repository.ts +55 -0
- package/src/relations/relation.decorator.ts +0 -12
- package/src/relations/relation.filter.solver.ts +56 -0
- package/src/relations/relation.helpers.ts +16 -1
- package/src/relations/relation.types.ts +51 -0
- package/src/repositories/legacy-juggler-bridge.ts +78 -14
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import {Filter, InclusionFilter} from '@loopback/filter';
|
|
7
7
|
import debugFactory from 'debug';
|
|
8
|
+
import {InvalidPolymorphismError} from '../..';
|
|
8
9
|
import {AnyObject, Options} from '../../common-types';
|
|
9
10
|
import {Entity} from '../../model';
|
|
10
11
|
import {EntityCrudRepository} from '../../repositories';
|
|
@@ -14,7 +15,7 @@ import {
|
|
|
14
15
|
StringKeyOf,
|
|
15
16
|
} from '../relation.helpers';
|
|
16
17
|
import {Getter, HasManyDefinition, InclusionResolver} from '../relation.types';
|
|
17
|
-
import {
|
|
18
|
+
import {resolveHasManyThroughMetadata} from './has-many-through.helpers';
|
|
18
19
|
|
|
19
20
|
const debug = debugFactory(
|
|
20
21
|
'loopback:repository:relations:has-many-through:inclusion-resolver',
|
|
@@ -44,17 +45,25 @@ export function createHasManyThroughInclusionResolver<
|
|
|
44
45
|
getThroughRepo: Getter<
|
|
45
46
|
EntityCrudRepository<Through, ThroughID, ThroughRelations>
|
|
46
47
|
>,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
getTargetRepoDict: {
|
|
49
|
+
[repoType: string]: Getter<
|
|
50
|
+
EntityCrudRepository<Target, TargetID, TargetRelations>
|
|
51
|
+
>;
|
|
52
|
+
},
|
|
50
53
|
): InclusionResolver<Entity, Target> {
|
|
51
|
-
const relationMeta =
|
|
54
|
+
const relationMeta = resolveHasManyThroughMetadata(meta);
|
|
52
55
|
|
|
53
56
|
return async function fetchHasManyThroughModels(
|
|
54
57
|
entities: Entity[],
|
|
55
58
|
inclusion: InclusionFilter,
|
|
56
59
|
options?: Options,
|
|
57
60
|
): Promise<((Target & TargetRelations)[] | undefined)[]> {
|
|
61
|
+
if (!relationMeta.through) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`relationMeta.through must be defined on ${relationMeta}`,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
if (!entities.length) return [];
|
|
59
68
|
|
|
60
69
|
debug('Fetching target models for entities:', entities);
|
|
@@ -85,7 +94,6 @@ export function createHasManyThroughInclusionResolver<
|
|
|
85
94
|
);
|
|
86
95
|
|
|
87
96
|
const throughRepo = await getThroughRepo();
|
|
88
|
-
const targetRepo = await getTargetRepo();
|
|
89
97
|
|
|
90
98
|
// find through models
|
|
91
99
|
const throughFound = await findByForeignKeys(
|
|
@@ -102,34 +110,117 @@ export function createHasManyThroughInclusionResolver<
|
|
|
102
110
|
throughKeyFrom,
|
|
103
111
|
);
|
|
104
112
|
|
|
105
|
-
const result = [];
|
|
106
|
-
|
|
107
113
|
const scope =
|
|
108
114
|
typeof inclusion === 'string' ? {} : (inclusion.scope as Filter<Target>);
|
|
109
115
|
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
// whether the polymorphism is configured
|
|
117
|
+
const targetDiscriminator: keyof (Through & ThroughRelations) | undefined =
|
|
118
|
+
relationMeta.through!.polymorphic
|
|
119
|
+
? (relationMeta.through!.polymorphic.discriminator as keyof (Through &
|
|
120
|
+
ThroughRelations))
|
|
121
|
+
: undefined;
|
|
122
|
+
if (targetDiscriminator) {
|
|
123
|
+
// put through results into arrays based on the target polymorphic types
|
|
124
|
+
const throughArrayByTargetType: {
|
|
125
|
+
[targetType: string]: (Through & ThroughRelations)[];
|
|
126
|
+
} = {};
|
|
127
|
+
for (const throughArray of throughResult) {
|
|
128
|
+
if (throughArray) {
|
|
129
|
+
for (const throughItem of throughArray) {
|
|
130
|
+
const targetType = String(throughItem[targetDiscriminator]);
|
|
131
|
+
if (!getTargetRepoDict[targetType]) {
|
|
132
|
+
throw new InvalidPolymorphismError(
|
|
133
|
+
targetType,
|
|
134
|
+
String(targetDiscriminator),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
if (!throughArrayByTargetType[targetType]) {
|
|
138
|
+
throughArrayByTargetType[targetType] = [];
|
|
139
|
+
}
|
|
140
|
+
throughArrayByTargetType[targetType].push(throughItem);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// get targets based on their polymorphic types
|
|
145
|
+
const targetOfTypes: {
|
|
146
|
+
[targetType: string]: (Target & TargetRelations)[];
|
|
147
|
+
} = {};
|
|
148
|
+
for (const targetType of Object.keys(throughArrayByTargetType)) {
|
|
149
|
+
const targetIds = throughArrayByTargetType[targetType].map(
|
|
150
|
+
throughItem => throughItem[throughKeyTo],
|
|
151
|
+
);
|
|
152
|
+
const targetRepo = await getTargetRepoDict[targetType]();
|
|
117
153
|
const targetEntityList = await findByForeignKeys<
|
|
118
154
|
Target,
|
|
119
155
|
TargetRelations,
|
|
120
156
|
StringKeyOf<Target>
|
|
121
|
-
>(targetRepo, targetKey, targetIds as unknown as [], scope,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
157
|
+
>(targetRepo, targetKey, targetIds as unknown as [], scope, options);
|
|
158
|
+
targetOfTypes[targetType] = targetEntityList;
|
|
159
|
+
}
|
|
160
|
+
// put targets into arrays reflecting their throughs
|
|
161
|
+
// Why the order is correct:
|
|
162
|
+
// e.g. through model = T(target instance), target model 1 = a, target model 2 = b
|
|
163
|
+
// all entities: [S1, S2, S2]
|
|
164
|
+
// through-result: [[T(b-11), T(a-12), T(b-13), T(b-14)], [T(a-21), T(a-22), T(b-23)], [T(b-31), T(b-32), T(a-33)]]
|
|
165
|
+
// through-array-by-target-type: {a:[T(a-12), T(a-21), T(a-22), T(a-33)] b: [T(b-11), T(b-13), T(b-14), T(b-23), T(b-31), T(b-32)]}
|
|
166
|
+
// target-array-by-target-type: {a:[a-12, a-21, a-22, a-33] b: [b-11, b-13, b-14, b-23, b-31, b-32]}
|
|
167
|
+
// merged:
|
|
168
|
+
// through-result[0][0]->b => targets: [[b-11 from b.shift()]]
|
|
169
|
+
// through-result[0][1]->a => targets: [[b-11, a-12 from a.shift()]]
|
|
170
|
+
// through-result[0][2]->b => targets: [[b-11, a-12, b-13 from b.shift()]]
|
|
171
|
+
// through-result[0][3]->b => targets: [[b-11, a-12, b-13, b-14 from b.shift()]]
|
|
172
|
+
// through-result[1][0]->a => targets: [[b-11, a-12, b-13, b-14], [a-21, from a.shift()]]
|
|
173
|
+
// through-result[1][1]->a => targets: [[b-11, a-12, b-13, b-14], [a-21, a-22 from a.shift()]]
|
|
174
|
+
// through-result[1][2]->b => targets: [[b-11, a-12, b-13, b-14], [a-21, a-22, b-23 from b.shift()]]
|
|
175
|
+
// through-result[2][0]->b => targets: [[b-11, a-12, b-13, b-14], [a-21, a-22, b-23], [b-31, from b.shift()]]
|
|
176
|
+
// through-result[2][1]->b => targets: [[b-11, a-12, b-13, b-14], [a-21, a-22, b-23], [b-31, b-32 from b.shift()]]
|
|
177
|
+
// through-result[2][1]->b => targets: [[b-11, a-12, b-13, b-14], [a-21, a-22, b-23], [b-31, b-32, a-33 from a.shift()]]
|
|
178
|
+
const allTargetsOfThrough: ((Target & TargetRelations)[] | undefined)[] =
|
|
179
|
+
[];
|
|
180
|
+
for (const throughArray of throughResult) {
|
|
181
|
+
if (throughArray && throughArray.length > 0) {
|
|
182
|
+
const currentTargetThroughArray: (Target & TargetRelations)[] = [];
|
|
183
|
+
for (const throughItem of throughArray) {
|
|
184
|
+
const itemToAdd =
|
|
185
|
+
targetOfTypes[String(throughItem[targetDiscriminator])].shift();
|
|
186
|
+
if (itemToAdd) {
|
|
187
|
+
currentTargetThroughArray.push(itemToAdd);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
allTargetsOfThrough.push(currentTargetThroughArray);
|
|
191
|
+
} else {
|
|
192
|
+
allTargetsOfThrough.push(undefined);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return allTargetsOfThrough;
|
|
196
|
+
} else {
|
|
197
|
+
const targetRepo = await getTargetRepoDict[relationMeta.target().name]();
|
|
198
|
+
const result = [];
|
|
199
|
+
|
|
200
|
+
// convert from through entities to the target entities
|
|
201
|
+
for (const entityList of throughResult) {
|
|
202
|
+
if (entityList) {
|
|
203
|
+
// get target ids from the through entities by foreign key
|
|
204
|
+
const targetIds = entityList.map(entity => entity[throughKeyTo]);
|
|
205
|
+
|
|
206
|
+
// the explicit types and casts are needed
|
|
207
|
+
const targetEntityList = await findByForeignKeys<
|
|
208
|
+
Target,
|
|
209
|
+
TargetRelations,
|
|
210
|
+
StringKeyOf<Target>
|
|
211
|
+
>(targetRepo, targetKey, targetIds as unknown as [], scope, {
|
|
212
|
+
...options,
|
|
213
|
+
isThroughModelInclude: true,
|
|
214
|
+
});
|
|
215
|
+
result.push(targetEntityList);
|
|
216
|
+
} else {
|
|
217
|
+
// no entities found, add undefined to results
|
|
218
|
+
result.push(entityList);
|
|
219
|
+
}
|
|
129
220
|
}
|
|
130
|
-
}
|
|
131
221
|
|
|
132
|
-
|
|
133
|
-
|
|
222
|
+
debug('fetchHasManyThroughModels result', result);
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
134
225
|
};
|
|
135
226
|
}
|
|
@@ -59,10 +59,22 @@ export function createHasManyThroughRepositoryFactory<
|
|
|
59
59
|
SourceID,
|
|
60
60
|
>(
|
|
61
61
|
relationMetadata: HasManyDefinition,
|
|
62
|
-
targetRepositoryGetter:
|
|
62
|
+
targetRepositoryGetter:
|
|
63
|
+
| Getter<EntityCrudRepository<Target, TargetID>>
|
|
64
|
+
| {
|
|
65
|
+
[repoType: string]: Getter<EntityCrudRepository<Target, TargetID>>;
|
|
66
|
+
},
|
|
63
67
|
throughRepositoryGetter: Getter<EntityCrudRepository<Through, ThroughID>>,
|
|
64
68
|
): HasManyThroughRepositoryFactory<Target, TargetID, Through, SourceID> {
|
|
65
69
|
const meta = resolveHasManyThroughMetadata(relationMetadata);
|
|
70
|
+
// resolve the repositoryGetter into a dictionary
|
|
71
|
+
if (typeof targetRepositoryGetter === 'function') {
|
|
72
|
+
targetRepositoryGetter = {
|
|
73
|
+
[meta.target().name]: targetRepositoryGetter as Getter<
|
|
74
|
+
EntityCrudRepository<Target, TargetID>
|
|
75
|
+
>,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
66
78
|
const result = function (fkValue: SourceID) {
|
|
67
79
|
function getTargetConstraintFromThroughModels(
|
|
68
80
|
throughInstances: Through[],
|
|
@@ -103,19 +115,25 @@ export function createHasManyThroughRepositoryFactory<
|
|
|
103
115
|
ThroughID,
|
|
104
116
|
EntityCrudRepository<Through, ThroughID>
|
|
105
117
|
>(
|
|
106
|
-
targetRepositoryGetter
|
|
118
|
+
targetRepositoryGetter as {
|
|
119
|
+
[repoType: string]: Getter<EntityCrudRepository<Target, TargetID>>;
|
|
120
|
+
},
|
|
107
121
|
throughRepositoryGetter,
|
|
108
122
|
getTargetConstraintFromThroughModels,
|
|
109
123
|
getTargetKeys,
|
|
110
124
|
getThroughConstraintFromSource,
|
|
111
125
|
getTargetIds,
|
|
112
126
|
getThroughConstraintFromTarget,
|
|
127
|
+
relationMetadata.target,
|
|
128
|
+
relationMetadata.through!.model,
|
|
113
129
|
);
|
|
114
130
|
};
|
|
115
131
|
result.inclusionResolver = createHasManyThroughInclusionResolver(
|
|
116
132
|
meta,
|
|
117
133
|
throughRepositoryGetter,
|
|
118
|
-
targetRepositoryGetter
|
|
134
|
+
targetRepositoryGetter as {
|
|
135
|
+
[repoType: string]: Getter<EntityCrudRepository<Target, TargetID>>;
|
|
136
|
+
},
|
|
119
137
|
);
|
|
120
138
|
return result;
|
|
121
139
|
}
|