@loopback/repository 4.1.1 → 5.0.1
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/LICENSE +1 -1
- package/dist/connectors/connector.js +1 -1
- package/dist/connectors/connector.js.map +1 -1
- package/dist/connectors/crud.connector.js +1 -1
- package/dist/connectors/crud.connector.js.map +1 -1
- package/dist/connectors/index.js +4 -4
- package/dist/connectors/index.js.map +1 -1
- package/dist/connectors/kv.connector.js +1 -1
- package/dist/connectors/kv.connector.js.map +1 -1
- package/dist/datasource.js +1 -1
- package/dist/datasource.js.map +1 -1
- package/dist/decorators/index.js +4 -4
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/metadata.js +1 -1
- package/dist/decorators/metadata.js.map +1 -1
- package/dist/decorators/model.decorator.js +1 -1
- package/dist/decorators/model.decorator.js.map +1 -1
- package/dist/decorators/repository.decorator.js +2 -2
- package/dist/decorators/repository.decorator.js.map +1 -1
- package/dist/define-model-class.js +2 -2
- package/dist/define-model-class.js.map +1 -1
- package/dist/define-repository-class.js +2 -2
- package/dist/define-repository-class.js.map +1 -1
- package/dist/errors/entity-not-found.error.js +1 -1
- package/dist/errors/entity-not-found.error.js.map +1 -1
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +4 -3
- 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/errors/invalid-relation.error.d.ts +1 -1
- package/dist/errors/invalid-relation.error.js +1 -1
- package/dist/errors/invalid-relation.error.js.map +1 -1
- package/dist/index.js +17 -17
- package/dist/index.js.map +1 -1
- package/dist/mixins/index.js +2 -2
- package/dist/mixins/index.js.map +1 -1
- package/dist/mixins/repository.mixin.d.ts +49 -50
- package/dist/mixins/repository.mixin.js +2 -2
- package/dist/mixins/repository.mixin.js.map +1 -1
- package/dist/model.d.ts +7 -1
- package/dist/model.js +15 -1
- 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 +20 -7
- package/dist/relations/belongs-to/belongs-to.accessor.js.map +1 -1
- package/dist/relations/belongs-to/belongs-to.decorator.js +1 -1
- package/dist/relations/belongs-to/belongs-to.decorator.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 +34 -10
- 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 +82 -9
- 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 +50 -11
- package/dist/relations/belongs-to/belongs-to.repository.js.map +1 -1
- package/dist/relations/belongs-to/index.d.ts +2 -2
- package/dist/relations/belongs-to/index.js +5 -5
- package/dist/relations/belongs-to/index.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 +27 -3
- 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 +94 -23
- 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 +8 -2
- 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 +212 -36
- package/dist/relations/has-many/has-many-through.repository.js.map +1 -1
- package/dist/relations/has-many/has-many.decorator.js +1 -1
- package/dist/relations/has-many/has-many.decorator.js.map +1 -1
- package/dist/relations/has-many/has-many.helpers.js +2 -2
- package/dist/relations/has-many/has-many.helpers.js.map +1 -1
- package/dist/relations/has-many/has-many.inclusion-resolver.js +2 -2
- package/dist/relations/has-many/has-many.inclusion-resolver.js.map +1 -1
- package/dist/relations/has-many/has-many.repository-factory.js +2 -2
- package/dist/relations/has-many/has-many.repository-factory.js.map +1 -1
- package/dist/relations/has-many/has-many.repository.js +1 -1
- package/dist/relations/has-many/has-many.repository.js.map +1 -1
- package/dist/relations/has-many/index.d.ts +2 -2
- package/dist/relations/has-many/index.js +7 -7
- package/dist/relations/has-many/index.js.map +1 -1
- package/dist/relations/has-one/has-one.decorator.js +1 -1
- package/dist/relations/has-one/has-one.decorator.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 +36 -10
- 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 +83 -8
- 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 +15 -5
- 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 +119 -16
- package/dist/relations/has-one/has-one.repository.js.map +1 -1
- package/dist/relations/has-one/index.js +4 -4
- package/dist/relations/has-one/index.js.map +1 -1
- package/dist/relations/index.d.ts +2 -0
- package/dist/relations/index.js +9 -7
- 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 +2 -14
- 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 +20 -5
- package/dist/relations/relation.helpers.js.map +1 -1
- package/dist/relations/relation.types.d.ts +52 -1
- package/dist/relations/relation.types.js +1 -1
- package/dist/relations/relation.types.js.map +1 -1
- package/dist/repositories/constraint-utils.js +1 -1
- package/dist/repositories/constraint-utils.js.map +1 -1
- package/dist/repositories/index.d.ts +2 -2
- package/dist/repositories/index.js +6 -6
- package/dist/repositories/index.js.map +1 -1
- package/dist/repositories/kv.repository.bridge.js +1 -1
- package/dist/repositories/kv.repository.bridge.js.map +1 -1
- package/dist/repositories/kv.repository.d.ts +2 -2
- package/dist/repositories/kv.repository.js +1 -1
- package/dist/repositories/kv.repository.js.map +1 -1
- package/dist/repositories/legacy-juggler-bridge.d.ts +35 -8
- package/dist/repositories/legacy-juggler-bridge.js +39 -17
- package/dist/repositories/legacy-juggler-bridge.js.map +1 -1
- package/dist/repositories/repository.js +1 -1
- package/dist/repositories/repository.js.map +1 -1
- package/dist/type-resolver.js +1 -1
- package/dist/type-resolver.js.map +1 -1
- package/dist/types/any.js +1 -1
- package/dist/types/any.js.map +1 -1
- package/dist/types/array.js +2 -2
- package/dist/types/array.js.map +1 -1
- package/dist/types/boolean.js +1 -1
- package/dist/types/boolean.js.map +1 -1
- package/dist/types/buffer.js +2 -2
- package/dist/types/buffer.js.map +1 -1
- package/dist/types/date.js +2 -2
- package/dist/types/date.js.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/model.js +1 -1
- package/dist/types/model.js.map +1 -1
- package/dist/types/null.js +1 -1
- package/dist/types/null.js.map +1 -1
- package/dist/types/number.js +2 -2
- package/dist/types/number.js.map +1 -1
- package/dist/types/object.js +2 -2
- package/dist/types/object.js.map +1 -1
- package/dist/types/string.js +1 -1
- package/dist/types/string.js.map +1 -1
- package/dist/types/type.js +1 -1
- package/dist/types/type.js.map +1 -1
- package/dist/types/union.js +2 -2
- package/dist/types/union.js.map +1 -1
- package/package.json +17 -17
- package/src/connectors/connector.ts +1 -1
- package/src/connectors/crud.connector.ts +1 -1
- package/src/connectors/index.ts +1 -1
- package/src/connectors/kv.connector.ts +1 -1
- package/src/datasource.ts +1 -1
- package/src/decorators/index.ts +1 -1
- package/src/decorators/metadata.ts +1 -1
- package/src/decorators/model.decorator.ts +1 -1
- package/src/decorators/repository.decorator.ts +1 -1
- package/src/define-model-class.ts +1 -1
- package/src/define-repository-class.ts +1 -1
- package/src/errors/entity-not-found.error.ts +1 -1
- package/src/errors/index.ts +2 -1
- package/src/errors/invalid-polymorphism.error.ts +28 -0
- package/src/errors/invalid-relation.error.ts +2 -2
- package/src/index.ts +1 -1
- package/src/mixins/index.ts +1 -1
- package/src/mixins/repository.mixin.ts +1 -6
- package/src/model.ts +20 -1
- package/src/relations/belongs-to/belongs-to.accessor.ts +36 -7
- package/src/relations/belongs-to/belongs-to.decorator.ts +2 -2
- package/src/relations/belongs-to/belongs-to.helpers.ts +37 -10
- package/src/relations/belongs-to/belongs-to.inclusion-resolver.ts +109 -18
- package/src/relations/belongs-to/belongs-to.repository.ts +78 -18
- package/src/relations/belongs-to/index.ts +3 -3
- package/src/relations/has-many/has-many-through.helpers.ts +28 -2
- package/src/relations/has-many/has-many-through.inclusion-resolver.ts +118 -27
- package/src/relations/has-many/has-many-through.repository-factory.ts +22 -4
- package/src/relations/has-many/has-many-through.repository.ts +344 -77
- package/src/relations/has-many/has-many.decorator.ts +1 -1
- package/src/relations/has-many/has-many.helpers.ts +1 -1
- package/src/relations/has-many/has-many.inclusion-resolver.ts +1 -1
- package/src/relations/has-many/has-many.repository-factory.ts +1 -1
- package/src/relations/has-many/has-many.repository.ts +1 -1
- package/src/relations/has-many/index.ts +3 -3
- package/src/relations/has-one/has-one.decorator.ts +1 -1
- package/src/relations/has-one/has-one.helpers.ts +41 -14
- package/src/relations/has-one/has-one.inclusion-resolver.ts +110 -16
- package/src/relations/has-one/has-one.repository-factory.ts +35 -7
- package/src/relations/has-one/has-one.repository.ts +189 -36
- package/src/relations/has-one/index.ts +1 -1
- package/src/relations/index.ts +3 -1
- 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 +1 -13
- package/src/relations/relation.filter.solver.ts +56 -0
- package/src/relations/relation.helpers.ts +17 -2
- package/src/relations/relation.types.ts +52 -1
- package/src/repositories/constraint-utils.ts +1 -1
- package/src/repositories/index.ts +3 -3
- package/src/repositories/kv.repository.bridge.ts +1 -1
- package/src/repositories/kv.repository.ts +3 -3
- package/src/repositories/legacy-juggler-bridge.ts +79 -15
- package/src/repositories/repository.ts +1 -1
- package/src/type-resolver.ts +1 -1
- package/src/types/any.ts +1 -1
- package/src/types/array.ts +1 -1
- package/src/types/boolean.ts +1 -1
- package/src/types/buffer.ts +1 -1
- package/src/types/date.ts +1 -1
- package/src/types/index.ts +1 -1
- package/src/types/model.ts +1 -1
- package/src/types/null.ts +1 -1
- package/src/types/number.ts +1 -1
- package/src/types/object.ts +1 -1
- package/src/types/string.ts +1 -1
- package/src/types/type.ts +1 -1
- package/src/types/union.ts +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2019,2020. All Rights Reserved.
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/repository
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
@@ -18,6 +18,7 @@ const debug = debugFactory('loopback:repository:relations:has-one:helpers');
|
|
|
18
18
|
export type HasOneResolvedDefinition = HasOneDefinition & {
|
|
19
19
|
keyFrom: string;
|
|
20
20
|
keyTo: string;
|
|
21
|
+
polymorphic: false | {discriminator: string};
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -60,25 +61,51 @@ export function resolveHasOneMetadata(
|
|
|
60
61
|
keyFrom = sourceModel.getIdProperties()[0];
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
let keyTo;
|
|
63
65
|
// Make sure that if it already keys to the foreign key property,
|
|
64
66
|
// the key exists in the target model
|
|
65
67
|
if (relationMeta.keyTo && targetModelProperties[relationMeta.keyTo]) {
|
|
66
68
|
// The explicit cast is needed because of a limitation of type inference
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
+
keyTo = relationMeta.keyTo;
|
|
70
|
+
} else {
|
|
71
|
+
debug(
|
|
72
|
+
'Resolved model %s from given metadata: %o',
|
|
73
|
+
targetModel.modelName,
|
|
74
|
+
targetModel,
|
|
75
|
+
);
|
|
76
|
+
keyTo = camelCase(sourceModel.modelName + '_id');
|
|
77
|
+
const hasDefaultFkProperty = targetModelProperties[keyTo];
|
|
69
78
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const defaultFkName = camelCase(sourceModel.modelName + '_id');
|
|
76
|
-
const hasDefaultFkProperty = targetModelProperties[defaultFkName];
|
|
79
|
+
if (!hasDefaultFkProperty) {
|
|
80
|
+
const reason = `target model ${targetModel.name} is missing definition of foreign key ${keyTo}`;
|
|
81
|
+
throw new InvalidRelationError(reason, relationMeta);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
77
84
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
let polymorphic: false | {discriminator: string};
|
|
86
|
+
if (
|
|
87
|
+
relationMeta.polymorphic === undefined ||
|
|
88
|
+
relationMeta.polymorphic === false ||
|
|
89
|
+
!relationMeta.polymorphic
|
|
90
|
+
) {
|
|
91
|
+
const polymorphicFalse = false as const;
|
|
92
|
+
polymorphic = polymorphicFalse;
|
|
93
|
+
} else {
|
|
94
|
+
if (relationMeta.polymorphic === true) {
|
|
95
|
+
const polymorphicObject: {discriminator: string} = {
|
|
96
|
+
discriminator: camelCase(relationMeta.target().name + '_type'),
|
|
97
|
+
};
|
|
98
|
+
polymorphic = polymorphicObject;
|
|
99
|
+
} else {
|
|
100
|
+
const polymorphicObject: {discriminator: string} =
|
|
101
|
+
relationMeta.polymorphic as {discriminator: string};
|
|
102
|
+
polymorphic = polymorphicObject;
|
|
103
|
+
}
|
|
81
104
|
}
|
|
82
105
|
|
|
83
|
-
return Object.assign(relationMeta, {
|
|
106
|
+
return Object.assign(relationMeta, {
|
|
107
|
+
keyFrom: keyFrom,
|
|
108
|
+
keyTo: keyTo,
|
|
109
|
+
polymorphic: polymorphic,
|
|
110
|
+
});
|
|
84
111
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2019,2020. All Rights Reserved.
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/repository
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
6
|
import {Filter, InclusionFilter} from '@loopback/filter';
|
|
7
|
+
import {cloneDeep} from 'lodash';
|
|
8
|
+
import {includeFieldIfNot, InvalidPolymorphismError} from '../../';
|
|
7
9
|
import {AnyObject, Options} from '../../common-types';
|
|
8
10
|
import {Entity} from '../../model';
|
|
9
11
|
import {EntityCrudRepository} from '../../repositories';
|
|
@@ -22,18 +24,22 @@ import {resolveHasOneMetadata} from './has-one.helpers';
|
|
|
22
24
|
*
|
|
23
25
|
* Notice: scope field for inclusion is not supported yet.
|
|
24
26
|
*
|
|
25
|
-
* @param meta
|
|
26
|
-
* @param
|
|
27
|
+
* @param meta - resolved HasOneMetadata
|
|
28
|
+
* @param getTargetRepoDict - dictionary of target model type - target repository
|
|
29
|
+
* i.e where related instances for different types are
|
|
27
30
|
*/
|
|
31
|
+
|
|
28
32
|
export function createHasOneInclusionResolver<
|
|
29
33
|
Target extends Entity,
|
|
30
34
|
TargetID,
|
|
31
35
|
TargetRelations extends object,
|
|
32
36
|
>(
|
|
33
37
|
meta: HasOneDefinition,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
getTargetRepoDict: {
|
|
39
|
+
[repoType: string]: Getter<
|
|
40
|
+
EntityCrudRepository<Target, TargetID, TargetRelations>
|
|
41
|
+
>;
|
|
42
|
+
},
|
|
37
43
|
): InclusionResolver<Entity, Target> {
|
|
38
44
|
const relationMeta = resolveHasOneMetadata(meta);
|
|
39
45
|
|
|
@@ -44,22 +50,110 @@ export function createHasOneInclusionResolver<
|
|
|
44
50
|
): Promise<((Target & TargetRelations) | undefined)[]> {
|
|
45
51
|
if (!entities.length) return [];
|
|
46
52
|
|
|
53
|
+
// Source ids are grouped by their target polymorphic types
|
|
54
|
+
// Each type search for target instances and then merge together in a merge-sort-like manner
|
|
55
|
+
|
|
47
56
|
const sourceKey = relationMeta.keyFrom;
|
|
48
|
-
const sourceIds = entities.map(e => (e as AnyObject)[sourceKey]);
|
|
49
57
|
const targetKey = relationMeta.keyTo as StringKeyOf<Target>;
|
|
58
|
+
const targetDiscriminator: keyof Entity | undefined =
|
|
59
|
+
relationMeta.polymorphic
|
|
60
|
+
? (relationMeta.polymorphic.discriminator as keyof Entity)
|
|
61
|
+
: undefined;
|
|
50
62
|
|
|
51
63
|
const scope =
|
|
52
64
|
typeof inclusion === 'string' ? {} : (inclusion.scope as Filter<Target>);
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
// sourceIds in {targetType -> sourceId}
|
|
67
|
+
const sourceIdsCategorized: {
|
|
68
|
+
[concreteItemType: string]: Target[StringKeyOf<Target>][];
|
|
69
|
+
} = {};
|
|
70
|
+
if (targetDiscriminator) {
|
|
71
|
+
entities.forEach((value, index, allEntites) => {
|
|
72
|
+
const concreteType = String(value[targetDiscriminator]);
|
|
73
|
+
if (!getTargetRepoDict[concreteType]) {
|
|
74
|
+
throw new InvalidPolymorphismError(concreteType, targetDiscriminator);
|
|
75
|
+
}
|
|
76
|
+
if (!sourceIdsCategorized[concreteType]) {
|
|
77
|
+
sourceIdsCategorized[concreteType] = [];
|
|
78
|
+
}
|
|
79
|
+
sourceIdsCategorized[concreteType].push(
|
|
80
|
+
(value as AnyObject)[sourceKey],
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
} else {
|
|
84
|
+
const concreteType = relationMeta.target().name;
|
|
85
|
+
if (!getTargetRepoDict[concreteType]) {
|
|
86
|
+
throw new InvalidPolymorphismError(concreteType);
|
|
87
|
+
}
|
|
88
|
+
entities.forEach((value, index, allEntites) => {
|
|
89
|
+
if (!sourceIdsCategorized[concreteType]) {
|
|
90
|
+
sourceIdsCategorized[concreteType] = [];
|
|
91
|
+
}
|
|
92
|
+
sourceIdsCategorized[concreteType].push(
|
|
93
|
+
(value as AnyObject)[sourceKey],
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Ensure targetKey is included otherwise flatten function cannot work
|
|
99
|
+
const changedTargetKeyField = includeFieldIfNot(scope?.fields, targetKey);
|
|
100
|
+
let needToRemoveTargetKeyFieldLater = false;
|
|
101
|
+
if (changedTargetKeyField !== false) {
|
|
102
|
+
scope.fields = changedTargetKeyField;
|
|
103
|
+
needToRemoveTargetKeyFieldLater = true;
|
|
104
|
+
}
|
|
105
|
+
// Each sourceIds array with same target type extract target instances
|
|
106
|
+
const targetCategorized: {
|
|
107
|
+
[concreteItemType: string]: ((Target & TargetRelations) | undefined)[];
|
|
108
|
+
} = {};
|
|
109
|
+
for (const k of Object.keys(sourceIdsCategorized)) {
|
|
110
|
+
const targetRepo = await getTargetRepoDict[k]();
|
|
111
|
+
const targetsFound = await findByForeignKeys(
|
|
112
|
+
targetRepo,
|
|
113
|
+
targetKey,
|
|
114
|
+
sourceIdsCategorized[k],
|
|
115
|
+
scope,
|
|
116
|
+
Object.assign(cloneDeep(options ?? {}), {polymorphicType: k}),
|
|
117
|
+
);
|
|
118
|
+
targetCategorized[k] = flattenTargetsOfOneToOneRelation(
|
|
119
|
+
sourceIdsCategorized[k],
|
|
120
|
+
targetsFound,
|
|
121
|
+
targetKey,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Remove targetKey if should be excluded but included above
|
|
125
|
+
if (needToRemoveTargetKeyFieldLater) {
|
|
126
|
+
targetCategorized[k] = targetCategorized[k].map(e => {
|
|
127
|
+
if (e) {
|
|
128
|
+
delete e[targetKey];
|
|
129
|
+
}
|
|
130
|
+
return e;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
62
134
|
|
|
63
|
-
|
|
135
|
+
// Merge
|
|
136
|
+
// Why the order is correct:
|
|
137
|
+
// e.g. target model 1 = a, target model 2 = b
|
|
138
|
+
// all entities: [S(a-1), S(a-2), S(b-3), S(a-4), S(b-5)]
|
|
139
|
+
// a-result: [a-1, a-2, a-4]
|
|
140
|
+
// b-result: [b-3, b-4]
|
|
141
|
+
// merged:
|
|
142
|
+
// entities[1]->a => targets: [a-1 from a-result.shift()]
|
|
143
|
+
// entities[2]->a => targets: [a-1, a-2 from a-result.shift()]
|
|
144
|
+
// entities[3]->b => targets: [a-1, a-2, b-3 from b-result.shift()]
|
|
145
|
+
// entities[4]->a => targets: [a-1, a-2, b-3, a-4 from a-result.shift()]
|
|
146
|
+
// entities[5]->b => targets: [a-1, a-2, b-3, a-4, b-5 from b-result.shift()]
|
|
147
|
+
if (targetDiscriminator) {
|
|
148
|
+
const allTargets: ((Target & TargetRelations) | undefined)[] = [];
|
|
149
|
+
entities.forEach((value, index, allEntites) => {
|
|
150
|
+
allTargets.push(
|
|
151
|
+
targetCategorized[String(value[targetDiscriminator])].shift(),
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
return allTargets;
|
|
155
|
+
} else {
|
|
156
|
+
return targetCategorized[relationMeta.target().name];
|
|
157
|
+
}
|
|
64
158
|
};
|
|
65
159
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/repository
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
@@ -36,10 +36,14 @@ export interface HasOneRepositoryFactory<
|
|
|
36
36
|
* via a HasOne relation, then, the relational repository returned by the
|
|
37
37
|
* factory function would be constrained by a Customer model instance's id(s).
|
|
38
38
|
*
|
|
39
|
+
* If the target model is polymorphic, i.e. stored within different repositories,
|
|
40
|
+
* supply the targetRepositoryGetter with a dictionary in the form of {[typeName: string]: repositoryGetter}
|
|
41
|
+
*
|
|
39
42
|
* @param relationMetadata - The relation metadata used to describe the
|
|
40
43
|
* relationship and determine how to apply the constraint.
|
|
41
|
-
* @param targetRepositoryGetter - The repository
|
|
42
|
-
* relation attached to a datasource.
|
|
44
|
+
* @param targetRepositoryGetter - The repository or a dictionary of classname - repository,
|
|
45
|
+
* which represents the target model of a relation attached to a datasource.
|
|
46
|
+
* For the dictionary, the key is the class name of the concrete class the the polymorphic model.
|
|
43
47
|
* @returns The factory function which accepts a foreign key value to constrain
|
|
44
48
|
* the given target repository
|
|
45
49
|
*/
|
|
@@ -49,9 +53,21 @@ export function createHasOneRepositoryFactory<
|
|
|
49
53
|
ForeignKeyType,
|
|
50
54
|
>(
|
|
51
55
|
relationMetadata: HasOneDefinition,
|
|
52
|
-
targetRepositoryGetter:
|
|
56
|
+
targetRepositoryGetter:
|
|
57
|
+
| Getter<EntityCrudRepository<Target, TargetID>>
|
|
58
|
+
| {
|
|
59
|
+
[repoType: string]: Getter<EntityCrudRepository<Target, TargetID>>;
|
|
60
|
+
},
|
|
53
61
|
): HasOneRepositoryFactory<Target, ForeignKeyType> {
|
|
54
62
|
const meta = resolveHasOneMetadata(relationMetadata);
|
|
63
|
+
// resolve the repositoryGetter into a dictionary
|
|
64
|
+
if (typeof targetRepositoryGetter === 'function') {
|
|
65
|
+
targetRepositoryGetter = {
|
|
66
|
+
[meta.target().name]: targetRepositoryGetter as Getter<
|
|
67
|
+
EntityCrudRepository<Target, TargetID>
|
|
68
|
+
>,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
55
71
|
debug('Resolved HasOne relation metadata: %o', meta);
|
|
56
72
|
const result: HasOneRepositoryFactory<Target, ForeignKeyType> = function (
|
|
57
73
|
fkValue: ForeignKeyType,
|
|
@@ -62,11 +78,23 @@ export function createHasOneRepositoryFactory<
|
|
|
62
78
|
Target,
|
|
63
79
|
TargetID,
|
|
64
80
|
EntityCrudRepository<Target, TargetID>
|
|
65
|
-
>(
|
|
81
|
+
>(
|
|
82
|
+
targetRepositoryGetter as {
|
|
83
|
+
[repoType: string]: Getter<EntityCrudRepository<Target, TargetID>>;
|
|
84
|
+
},
|
|
85
|
+
constraint as DataObject<Target>,
|
|
86
|
+
relationMetadata.target,
|
|
87
|
+
);
|
|
66
88
|
};
|
|
67
|
-
result.inclusionResolver = createHasOneInclusionResolver
|
|
89
|
+
result.inclusionResolver = createHasOneInclusionResolver<
|
|
90
|
+
Target,
|
|
91
|
+
TargetID,
|
|
92
|
+
object
|
|
93
|
+
>(
|
|
68
94
|
meta,
|
|
69
|
-
targetRepositoryGetter
|
|
95
|
+
targetRepositoryGetter as {
|
|
96
|
+
[repoType: string]: Getter<EntityCrudRepository<Target, TargetID>>;
|
|
97
|
+
},
|
|
70
98
|
);
|
|
71
99
|
return result;
|
|
72
100
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/repository
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
6
|
import {Getter} from '@loopback/core';
|
|
7
7
|
import {Filter} from '@loopback/filter';
|
|
8
|
+
import {cloneDeep} from 'lodash';
|
|
9
|
+
import {TypeResolver} from '../../';
|
|
8
10
|
import {Count, DataObject, Options} from '../../common-types';
|
|
9
|
-
import {EntityNotFoundError} from '../../errors';
|
|
11
|
+
import {EntityNotFoundError, InvalidPolymorphismError} from '../../errors';
|
|
10
12
|
import {Entity} from '../../model';
|
|
11
13
|
import {
|
|
12
14
|
constrainDataObject,
|
|
@@ -23,39 +25,58 @@ export interface HasOneRepository<Target extends Entity> {
|
|
|
23
25
|
* Create a target model instance
|
|
24
26
|
* @param targetModelData - The target model data
|
|
25
27
|
* @param options - Options for the operation
|
|
28
|
+
* options.polymorphicType - If polymorphic target model,
|
|
29
|
+
* specify of which concrete model the created instance should be
|
|
26
30
|
* @returns A promise which resolves to the newly created target model instance
|
|
27
31
|
*/
|
|
28
32
|
create(
|
|
29
33
|
targetModelData: DataObject<Target>,
|
|
30
|
-
options?: Options,
|
|
34
|
+
options?: Options & {polymorphicType?: string},
|
|
31
35
|
): Promise<Target>;
|
|
32
36
|
|
|
33
37
|
/**
|
|
34
38
|
* Find the only target model instance that belongs to the declaring model.
|
|
35
39
|
* @param filter - Query filter without a Where condition
|
|
36
40
|
* @param options - Options for the operations
|
|
41
|
+
* options.polymorphicType - a string or a string array of polymorphic type names
|
|
42
|
+
* to specify which repositories should are expected to be searched
|
|
43
|
+
* It is highly recommended to contain this param especially for
|
|
44
|
+
* datasources using deplicated ids across tables
|
|
37
45
|
* @returns A promise resolved with the target object or rejected
|
|
38
46
|
* with an EntityNotFoundError when target model instance was not found.
|
|
39
47
|
*/
|
|
40
48
|
get(
|
|
41
49
|
filter?: Pick<Filter<Target>, Exclude<keyof Filter<Target>, 'where'>>,
|
|
42
|
-
options?: Options,
|
|
50
|
+
options?: Options & {polymorphicType?: string | string[]},
|
|
43
51
|
): Promise<Target>;
|
|
44
52
|
|
|
45
53
|
/**
|
|
46
54
|
* Delete the related target model instance
|
|
47
55
|
* @param options
|
|
56
|
+
* options.polymorphicType - a string or a string array of polymorphic type names
|
|
57
|
+
* to specify which repositories should are expected to be searched
|
|
58
|
+
* It is highly recommended to contain this param especially for
|
|
59
|
+
* datasources using deplicated ids across tables
|
|
48
60
|
* @returns A promise which resolves the deleted target model instances
|
|
49
61
|
*/
|
|
50
|
-
delete(
|
|
62
|
+
delete(
|
|
63
|
+
options?: Options & {polymorphicType?: string | string[]},
|
|
64
|
+
): Promise<Count>;
|
|
51
65
|
|
|
52
66
|
/**
|
|
53
67
|
* Patch the related target model instance
|
|
54
68
|
* @param dataObject - The target model fields and their new values to patch
|
|
69
|
+
* If the target models are of different types, this should be a dictionary
|
|
55
70
|
* @param options
|
|
71
|
+
* options.isPolymorphic - whether dataObject is a dictionary
|
|
56
72
|
* @returns A promise which resolves the patched target model instances
|
|
57
73
|
*/
|
|
58
|
-
patch(
|
|
74
|
+
patch(
|
|
75
|
+
dataObject:
|
|
76
|
+
| DataObject<Target>
|
|
77
|
+
| {[polymorphicType: string]: DataObject<Target>},
|
|
78
|
+
options?: Options & {isPolymorphic?: boolean},
|
|
79
|
+
): Promise<Count>;
|
|
59
80
|
}
|
|
60
81
|
|
|
61
82
|
export class DefaultHasOneRepository<
|
|
@@ -66,20 +87,65 @@ export class DefaultHasOneRepository<
|
|
|
66
87
|
{
|
|
67
88
|
/**
|
|
68
89
|
* Constructor of DefaultHasOneEntityCrudRepository
|
|
69
|
-
* @param getTargetRepository
|
|
90
|
+
* @param getTargetRepository - either a dictionary of target model type - target repository instance
|
|
91
|
+
* or a single target repository instance
|
|
92
|
+
* e.g. if the target is of a non-polymorphic type "Student", put the studentRepositoryGetterInstance
|
|
93
|
+
* if the target is of a polymorphic type "Person" which can be either a "Student" or a "Teacher"
|
|
94
|
+
* then put "{Student: studentRepositoryGetterInstance, Teacher: teacherRepositoryGetterInstance}"
|
|
70
95
|
* @param constraint - the key value pair representing foreign key name to constrain
|
|
71
96
|
* the target repository instance
|
|
97
|
+
* @param targetResolver - () => Target to resolve the target class
|
|
98
|
+
* e.g. if the target is of type "Student", then put "() => Student"
|
|
72
99
|
*/
|
|
100
|
+
|
|
73
101
|
constructor(
|
|
74
|
-
public getTargetRepository:
|
|
102
|
+
public getTargetRepository:
|
|
103
|
+
| Getter<TargetRepository>
|
|
104
|
+
| {
|
|
105
|
+
[repoType: string]: Getter<TargetRepository>;
|
|
106
|
+
},
|
|
75
107
|
public constraint: DataObject<TargetEntity>,
|
|
76
|
-
|
|
108
|
+
public targetResolver: TypeResolver<Entity, typeof Entity>,
|
|
109
|
+
) {
|
|
110
|
+
if (typeof getTargetRepository === 'function') {
|
|
111
|
+
this.getTargetRepositoryDict = {
|
|
112
|
+
[targetResolver().name]:
|
|
113
|
+
getTargetRepository as Getter<TargetRepository>,
|
|
114
|
+
};
|
|
115
|
+
} else {
|
|
116
|
+
this.getTargetRepositoryDict = getTargetRepository as {
|
|
117
|
+
[repoType: string]: Getter<TargetRepository>;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public getTargetRepositoryDict: {
|
|
123
|
+
[repoType: string]: Getter<TargetRepository>;
|
|
124
|
+
};
|
|
77
125
|
|
|
78
126
|
async create(
|
|
79
127
|
targetModelData: DataObject<TargetEntity>,
|
|
80
|
-
options?: Options,
|
|
128
|
+
options?: Options & {polymorphicType?: string},
|
|
81
129
|
): Promise<TargetEntity> {
|
|
82
|
-
|
|
130
|
+
let polymorphicTypeName = options?.polymorphicType;
|
|
131
|
+
if (polymorphicTypeName) {
|
|
132
|
+
if (!this.getTargetRepositoryDict[polymorphicTypeName]) {
|
|
133
|
+
throw new InvalidPolymorphismError(polymorphicTypeName);
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
if (Object.keys(this.getTargetRepositoryDict).length > 1) {
|
|
137
|
+
console.warn(
|
|
138
|
+
'It is highly recommended to specify the polymorphicType param when using polymorphic types.',
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
polymorphicTypeName = this.targetResolver().name;
|
|
142
|
+
if (!this.getTargetRepositoryDict[polymorphicTypeName]) {
|
|
143
|
+
throw new InvalidPolymorphismError(polymorphicTypeName);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const targetRepository = await this.getTargetRepositoryDict[
|
|
147
|
+
polymorphicTypeName
|
|
148
|
+
]();
|
|
83
149
|
return targetRepository.create(
|
|
84
150
|
constrainDataObject(targetModelData, this.constraint),
|
|
85
151
|
options,
|
|
@@ -91,37 +157,124 @@ export class DefaultHasOneRepository<
|
|
|
91
157
|
Filter<TargetEntity>,
|
|
92
158
|
Exclude<keyof Filter<TargetEntity>, 'where'>
|
|
93
159
|
>,
|
|
94
|
-
options?: Options,
|
|
160
|
+
options?: Options & {polymorphicType?: string | string[]},
|
|
95
161
|
): Promise<TargetEntity> {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
162
|
+
let polymorphicTypes = options?.polymorphicType;
|
|
163
|
+
let allKeys: string[];
|
|
164
|
+
if (Object.keys(this.getTargetRepositoryDict).length <= 1) {
|
|
165
|
+
allKeys = Object.keys(this.getTargetRepositoryDict);
|
|
166
|
+
} else if (!polymorphicTypes || polymorphicTypes.length === 0) {
|
|
167
|
+
console.warn(
|
|
168
|
+
'It is highly recommended to specify the polymorphicType param when using polymorphic types.',
|
|
169
|
+
);
|
|
170
|
+
allKeys = Object.keys(this.getTargetRepositoryDict);
|
|
171
|
+
} else {
|
|
172
|
+
if (typeof polymorphicTypes === 'string') {
|
|
173
|
+
polymorphicTypes = [polymorphicTypes];
|
|
174
|
+
}
|
|
175
|
+
allKeys = [];
|
|
176
|
+
new Set(polymorphicTypes!).forEach(element => {
|
|
177
|
+
if (Object.keys(this.getTargetRepositoryDict).includes(element)) {
|
|
178
|
+
allKeys.push(element);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
105
181
|
}
|
|
106
|
-
|
|
182
|
+
for (const key of allKeys) {
|
|
183
|
+
const targetRepository = await this.getTargetRepositoryDict[key]();
|
|
184
|
+
const found = await targetRepository.find(
|
|
185
|
+
Object.assign({limit: 1}, constrainFilter(filter, this.constraint)),
|
|
186
|
+
Object.assign(cloneDeep(options ?? {}), {polymorphicType: key}),
|
|
187
|
+
);
|
|
188
|
+
if (found.length >= 1) {
|
|
189
|
+
return found[0];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// We don't have a direct access to the foreign key value here :(
|
|
193
|
+
const id = 'constraint ' + JSON.stringify(this.constraint);
|
|
194
|
+
throw new EntityNotFoundError(this.targetResolver().name, id);
|
|
107
195
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
196
|
+
|
|
197
|
+
async delete(
|
|
198
|
+
options?: Options & {polymorphicType?: string | string[]},
|
|
199
|
+
): Promise<Count> {
|
|
200
|
+
let polymorphicTypes = options?.polymorphicType;
|
|
201
|
+
let allKeys: string[];
|
|
202
|
+
if (Object.keys(this.getTargetRepositoryDict).length <= 1) {
|
|
203
|
+
allKeys = Object.keys(this.getTargetRepositoryDict);
|
|
204
|
+
} else if (!polymorphicTypes || polymorphicTypes.length === 0) {
|
|
205
|
+
console.warn(
|
|
206
|
+
'It is highly recommended to specify the polymorphicType param when using polymorphic types.',
|
|
207
|
+
);
|
|
208
|
+
allKeys = Object.keys(this.getTargetRepositoryDict);
|
|
209
|
+
} else {
|
|
210
|
+
if (typeof polymorphicTypes === 'string') {
|
|
211
|
+
polymorphicTypes = [polymorphicTypes];
|
|
212
|
+
}
|
|
213
|
+
allKeys = [];
|
|
214
|
+
new Set(polymorphicTypes!).forEach(element => {
|
|
215
|
+
if (Object.keys(this.getTargetRepositoryDict).includes(element)) {
|
|
216
|
+
allKeys.push(element);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
let total = 0;
|
|
221
|
+
for (const key of allKeys) {
|
|
222
|
+
const targetRepository = await this.getTargetRepositoryDict[key]();
|
|
223
|
+
total +=
|
|
224
|
+
(
|
|
225
|
+
await targetRepository.deleteAll(
|
|
226
|
+
constrainWhere({}, this.constraint),
|
|
227
|
+
options,
|
|
228
|
+
)
|
|
229
|
+
)?.count ?? 0;
|
|
230
|
+
}
|
|
231
|
+
return {count: total};
|
|
114
232
|
}
|
|
115
233
|
|
|
116
234
|
async patch(
|
|
117
|
-
dataObject:
|
|
118
|
-
|
|
235
|
+
dataObject:
|
|
236
|
+
| DataObject<TargetEntity>
|
|
237
|
+
| {[polymorphicType: string]: DataObject<TargetEntity>},
|
|
238
|
+
options?: Options & {isPolymorphic?: boolean},
|
|
119
239
|
): Promise<Count> {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
240
|
+
const isMultipleTypes = options?.isPolymorphic;
|
|
241
|
+
let allKeys: string[];
|
|
242
|
+
if (!isMultipleTypes) {
|
|
243
|
+
if (Object.keys(this.getTargetRepositoryDict).length > 1) {
|
|
244
|
+
console.warn(
|
|
245
|
+
'It is highly recommended to specify the isPolymorphic param and pass in a dictionary of dataobjects when using polymorphic types.',
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
allKeys = Object.keys(this.getTargetRepositoryDict);
|
|
249
|
+
} else {
|
|
250
|
+
allKeys = [];
|
|
251
|
+
new Set(Object.keys(dataObject)).forEach(element => {
|
|
252
|
+
if (Object.keys(this.getTargetRepositoryDict).includes(element)) {
|
|
253
|
+
allKeys.push(element);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
let total = 0;
|
|
258
|
+
for (const key of allKeys) {
|
|
259
|
+
const targetRepository = await this.getTargetRepositoryDict[key]();
|
|
260
|
+
total +=
|
|
261
|
+
(
|
|
262
|
+
await targetRepository.updateAll(
|
|
263
|
+
constrainDataObject(
|
|
264
|
+
isMultipleTypes
|
|
265
|
+
? (
|
|
266
|
+
dataObject as {
|
|
267
|
+
[polymorphicType: string]: DataObject<TargetEntity>;
|
|
268
|
+
}
|
|
269
|
+
)[key]
|
|
270
|
+
: (dataObject as DataObject<TargetEntity>),
|
|
271
|
+
this.constraint,
|
|
272
|
+
),
|
|
273
|
+
constrainWhere({}, this.constraint),
|
|
274
|
+
options,
|
|
275
|
+
)
|
|
276
|
+
)?.count ?? 0;
|
|
277
|
+
}
|
|
278
|
+
return {count: total};
|
|
126
279
|
}
|
|
127
280
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/repository
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
package/src/relations/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/repository
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
export * from './belongs-to';
|
|
7
7
|
export * from './has-many';
|
|
8
8
|
export * from './has-one';
|
|
9
|
+
export * from './references-many';
|
|
9
10
|
export * from './relation.decorator';
|
|
11
|
+
export * from './relation.filter.solver';
|
|
10
12
|
export * from './relation.helpers';
|
|
11
13
|
export * from './relation.types';
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
|
|
6
|
+
export * from './references-many.accessor';
|
|
7
|
+
export * from './references-many.decorator';
|
|
8
|
+
export * from './references-many.inclusion-resolver';
|
|
9
|
+
export * from './references-many.repository';
|