@e22m4u/js-repository 0.8.4 → 0.8.6
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/README.md +37 -49
- package/dist/cjs/index.cjs +762 -353
- package/eslint.config.js +1 -0
- package/package.json +14 -14
- package/src/adapter/adapter-loader.js +9 -4
- package/src/adapter/adapter-registry.js +3 -1
- package/src/adapter/builtin/memory-adapter.js +29 -13
- package/src/adapter/decorator/data-sanitizing-decorator.js +2 -1
- package/src/adapter/decorator/default-values-decorator.js +2 -1
- package/src/adapter/decorator/fields-filtering-decorator.js +14 -7
- package/src/adapter/decorator/inclusion-decorator.js +14 -7
- package/src/adapter/decorator/property-uniqueness-decorator.js +2 -1
- package/src/adapter/decorator/required-property-decorator.js +2 -1
- package/src/definition/datasource/datasource-definition-validator.js +6 -3
- package/src/definition/definition-registry.js +8 -4
- package/src/definition/model/model-data-sanitizer.js +4 -2
- package/src/definition/model/model-definition-utils.js +74 -35
- package/src/definition/model/model-definition-utils.spec.js +2 -6
- package/src/definition/model/model-definition-validator.js +10 -5
- package/src/definition/model/properties/primary-keys-definition-validator.js +4 -2
- package/src/definition/model/properties/properties-definition-validator.js +36 -18
- package/src/definition/model/properties/property-uniqueness-validator.js +30 -18
- package/src/definition/model/properties/property-uniqueness-validator.spec.js +734 -74
- package/src/definition/model/properties/required-property-validator.js +7 -12
- package/src/definition/model/properties/required-property-validator.spec.js +7 -46
- package/src/definition/model/relations/relations-definition-validator.js +70 -33
- package/src/filter/fields-clause-tool.js +31 -12
- package/src/filter/include-clause-tool.js +38 -15
- package/src/filter/operator-clause-tool.js +55 -23
- package/src/filter/order-clause-tool.js +36 -13
- package/src/filter/slice-clause-tool.js +16 -7
- package/src/filter/where-clause-tool.js +24 -10
- package/src/relations/belongs-to-resolver.js +44 -20
- package/src/relations/has-many-resolver.js +52 -25
- package/src/relations/has-one-resolver.js +58 -27
- package/src/relations/references-many-resolver.js +24 -11
- package/src/repository/repository-registry.js +3 -1
- package/src/repository/repository.js +2 -1
- package/src/utils/capitalize.js +3 -1
- package/src/utils/clone-deep.js +6 -2
- package/src/utils/exclude-object-keys.js +2 -1
- package/src/utils/get-value-by-path.js +6 -2
- package/src/utils/is-deep-equal.js +21 -7
- package/src/utils/is-promise.js +6 -2
- package/src/utils/model-name-to-model-key.js +2 -1
- package/src/utils/select-object-keys.js +9 -4
- package/src/utils/singularize.js +3 -1
|
@@ -39,13 +39,16 @@ export class WhereClauseTool extends Service {
|
|
|
39
39
|
* @returns {object[]}
|
|
40
40
|
*/
|
|
41
41
|
filter(entities, where = undefined) {
|
|
42
|
-
if (!Array.isArray(entities))
|
|
42
|
+
if (!Array.isArray(entities)) {
|
|
43
43
|
throw new InvalidArgumentError(
|
|
44
44
|
'The first argument of WhereClauseTool.filter should be ' +
|
|
45
45
|
'an Array of Object, but %v was given.',
|
|
46
46
|
entities,
|
|
47
47
|
);
|
|
48
|
-
|
|
48
|
+
}
|
|
49
|
+
if (where == null) {
|
|
50
|
+
return entities;
|
|
51
|
+
}
|
|
49
52
|
return entities.filter(this._createFilter(where));
|
|
50
53
|
}
|
|
51
54
|
|
|
@@ -56,37 +59,43 @@ export class WhereClauseTool extends Service {
|
|
|
56
59
|
* @returns {Function}
|
|
57
60
|
*/
|
|
58
61
|
_createFilter(whereClause) {
|
|
59
|
-
if (typeof whereClause !== 'object' || Array.isArray(whereClause))
|
|
62
|
+
if (typeof whereClause !== 'object' || Array.isArray(whereClause)) {
|
|
60
63
|
throw new InvalidArgumentError(
|
|
61
64
|
'The provided option "where" should be an Object, but %v was given.',
|
|
62
65
|
whereClause,
|
|
63
66
|
);
|
|
67
|
+
}
|
|
64
68
|
const keys = Object.keys(whereClause);
|
|
65
69
|
return data => {
|
|
66
|
-
if (typeof data !== 'object')
|
|
70
|
+
if (typeof data !== 'object') {
|
|
67
71
|
throw new InvalidArgumentError(
|
|
68
72
|
'The first argument of WhereClauseTool.filter should be ' +
|
|
69
73
|
'an Array of Object, but %v was given.',
|
|
70
74
|
data,
|
|
71
75
|
);
|
|
76
|
+
}
|
|
72
77
|
return keys.every(key => {
|
|
73
78
|
// AndClause (recursion)
|
|
74
79
|
if (key === 'and' && key in whereClause) {
|
|
75
80
|
const andClause = whereClause[key];
|
|
76
|
-
if (Array.isArray(andClause))
|
|
81
|
+
if (Array.isArray(andClause)) {
|
|
77
82
|
return andClause.every(clause => this._createFilter(clause)(data));
|
|
83
|
+
}
|
|
78
84
|
}
|
|
79
85
|
// OrClause (recursion)
|
|
80
86
|
else if (key === 'or' && key in whereClause) {
|
|
81
87
|
const orClause = whereClause[key];
|
|
82
|
-
if (Array.isArray(orClause))
|
|
88
|
+
if (Array.isArray(orClause)) {
|
|
83
89
|
return orClause.some(clause => this._createFilter(clause)(data));
|
|
90
|
+
}
|
|
84
91
|
}
|
|
85
92
|
// PropertiesClause (properties)
|
|
86
93
|
const value = getValueByPath(data, key);
|
|
87
94
|
const matcher = whereClause[key];
|
|
88
95
|
// Test property value.
|
|
89
|
-
if (this._test(matcher, value))
|
|
96
|
+
if (this._test(matcher, value)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
90
99
|
});
|
|
91
100
|
};
|
|
92
101
|
}
|
|
@@ -145,7 +154,9 @@ export class WhereClauseTool extends Service {
|
|
|
145
154
|
// если один из элементов массива соответствует
|
|
146
155
|
// поиску, то возвращается true
|
|
147
156
|
const isElementMatched = value.some(el => isDeepEqual(el, example));
|
|
148
|
-
if (isElementMatched)
|
|
157
|
+
if (isElementMatched) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
149
160
|
}
|
|
150
161
|
return isDeepEqual(example, value);
|
|
151
162
|
}
|
|
@@ -156,11 +167,14 @@ export class WhereClauseTool extends Service {
|
|
|
156
167
|
* @param {WhereClause|undefined} clause
|
|
157
168
|
*/
|
|
158
169
|
static validateWhereClause(clause) {
|
|
159
|
-
if (clause == null || typeof clause === 'function')
|
|
160
|
-
|
|
170
|
+
if (clause == null || typeof clause === 'function') {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (typeof clause !== 'object' || Array.isArray(clause)) {
|
|
161
174
|
throw new InvalidArgumentError(
|
|
162
175
|
'The provided option "where" should be an Object, but %v was given.',
|
|
163
176
|
clause,
|
|
164
177
|
);
|
|
178
|
+
}
|
|
165
179
|
}
|
|
166
180
|
}
|
|
@@ -27,50 +27,59 @@ export class BelongsToResolver extends Service {
|
|
|
27
27
|
foreignKey = undefined,
|
|
28
28
|
scope = undefined,
|
|
29
29
|
) {
|
|
30
|
-
if (!entities || !Array.isArray(entities))
|
|
30
|
+
if (!entities || !Array.isArray(entities)) {
|
|
31
31
|
throw new InvalidArgumentError(
|
|
32
32
|
'The parameter "entities" of BelongsToResolver.includeTo requires ' +
|
|
33
33
|
'an Array of Object, but %v was given.',
|
|
34
34
|
entities,
|
|
35
35
|
);
|
|
36
|
-
|
|
36
|
+
}
|
|
37
|
+
if (!sourceName || typeof sourceName !== 'string') {
|
|
37
38
|
throw new InvalidArgumentError(
|
|
38
39
|
'The parameter "sourceName" of BelongsToResolver.includeTo requires ' +
|
|
39
40
|
'a non-empty String, but %v was given.',
|
|
40
41
|
sourceName,
|
|
41
42
|
);
|
|
42
|
-
|
|
43
|
+
}
|
|
44
|
+
if (!targetName || typeof targetName !== 'string') {
|
|
43
45
|
throw new InvalidArgumentError(
|
|
44
46
|
'The parameter "targetName" of BelongsToResolver.includeTo requires ' +
|
|
45
47
|
'a non-empty String, but %v was given.',
|
|
46
48
|
targetName,
|
|
47
49
|
);
|
|
48
|
-
|
|
50
|
+
}
|
|
51
|
+
if (!relationName || typeof relationName !== 'string') {
|
|
49
52
|
throw new InvalidArgumentError(
|
|
50
53
|
'The parameter "relationName" of BelongsToResolver.includeTo requires ' +
|
|
51
54
|
'a non-empty String, but %v was given.',
|
|
52
55
|
relationName,
|
|
53
56
|
);
|
|
54
|
-
|
|
57
|
+
}
|
|
58
|
+
if (foreignKey && typeof foreignKey !== 'string') {
|
|
55
59
|
throw new InvalidArgumentError(
|
|
56
60
|
'The provided parameter "foreignKey" of BelongsToResolver.includeTo ' +
|
|
57
61
|
'should be a String, but %v was given.',
|
|
58
62
|
foreignKey,
|
|
59
63
|
);
|
|
60
|
-
|
|
64
|
+
}
|
|
65
|
+
if (scope && (typeof scope !== 'object' || Array.isArray(scope))) {
|
|
61
66
|
throw new InvalidArgumentError(
|
|
62
67
|
'The provided parameter "scope" of BelongsToResolver.includeTo ' +
|
|
63
68
|
'should be an Object, but %v was given.',
|
|
64
69
|
scope,
|
|
65
70
|
);
|
|
66
|
-
|
|
71
|
+
}
|
|
72
|
+
if (foreignKey == null) {
|
|
73
|
+
foreignKey = `${relationName}Id`;
|
|
74
|
+
}
|
|
67
75
|
const targetIds = entities.reduce((acc, entity) => {
|
|
68
|
-
if (!entity || typeof entity !== 'object' || Array.isArray(entity))
|
|
76
|
+
if (!entity || typeof entity !== 'object' || Array.isArray(entity)) {
|
|
69
77
|
throw new InvalidArgumentError(
|
|
70
78
|
'The parameter "entities" of BelongsToResolver.includeTo requires ' +
|
|
71
79
|
'an Array of Object, but %v was given.',
|
|
72
80
|
entity,
|
|
73
81
|
);
|
|
82
|
+
}
|
|
74
83
|
const targetId = entity[foreignKey];
|
|
75
84
|
return targetId != null ? [...acc, targetId] : acc;
|
|
76
85
|
}, []);
|
|
@@ -93,7 +102,9 @@ export class BelongsToResolver extends Service {
|
|
|
93
102
|
const target = targets.find(
|
|
94
103
|
e => e[targetPkPropName] === entity[foreignKey],
|
|
95
104
|
);
|
|
96
|
-
if (target)
|
|
105
|
+
if (target) {
|
|
106
|
+
entity[relationName] = target;
|
|
107
|
+
}
|
|
97
108
|
});
|
|
98
109
|
}
|
|
99
110
|
|
|
@@ -116,42 +127,48 @@ export class BelongsToResolver extends Service {
|
|
|
116
127
|
discriminator = undefined,
|
|
117
128
|
scope = undefined,
|
|
118
129
|
) {
|
|
119
|
-
if (!entities || !Array.isArray(entities))
|
|
130
|
+
if (!entities || !Array.isArray(entities)) {
|
|
120
131
|
throw new InvalidArgumentError(
|
|
121
132
|
'The parameter "entities" of BelongsToResolver.includePolymorphicTo ' +
|
|
122
133
|
'requires an Array of Object, but %v was given.',
|
|
123
134
|
entities,
|
|
124
135
|
);
|
|
125
|
-
|
|
136
|
+
}
|
|
137
|
+
if (!sourceName || typeof sourceName !== 'string') {
|
|
126
138
|
throw new InvalidArgumentError(
|
|
127
139
|
'The parameter "sourceName" of BelongsToResolver.includePolymorphicTo ' +
|
|
128
140
|
'requires a non-empty String, but %v was given.',
|
|
129
141
|
sourceName,
|
|
130
142
|
);
|
|
131
|
-
|
|
143
|
+
}
|
|
144
|
+
if (!relationName || typeof relationName !== 'string') {
|
|
132
145
|
throw new InvalidArgumentError(
|
|
133
146
|
'The parameter "relationName" of BelongsToResolver.includePolymorphicTo ' +
|
|
134
147
|
'requires a non-empty String, but %v was given.',
|
|
135
148
|
relationName,
|
|
136
149
|
);
|
|
137
|
-
|
|
150
|
+
}
|
|
151
|
+
if (foreignKey && typeof foreignKey !== 'string') {
|
|
138
152
|
throw new InvalidArgumentError(
|
|
139
153
|
'The provided parameter "foreignKey" of BelongsToResolver.includePolymorphicTo ' +
|
|
140
154
|
'should be a String, but %v was given.',
|
|
141
155
|
foreignKey,
|
|
142
156
|
);
|
|
143
|
-
|
|
157
|
+
}
|
|
158
|
+
if (discriminator && typeof discriminator !== 'string') {
|
|
144
159
|
throw new InvalidArgumentError(
|
|
145
160
|
'The provided parameter "discriminator" of BelongsToResolver.includePolymorphicTo ' +
|
|
146
161
|
'should be a String, but %v was given.',
|
|
147
162
|
discriminator,
|
|
148
163
|
);
|
|
149
|
-
|
|
164
|
+
}
|
|
165
|
+
if (scope && (typeof scope !== 'object' || Array.isArray(scope))) {
|
|
150
166
|
throw new InvalidArgumentError(
|
|
151
167
|
'The provided parameter "scope" of BelongsToResolver.includePolymorphicTo ' +
|
|
152
168
|
'should be an Object, but %v was given.',
|
|
153
169
|
scope,
|
|
154
170
|
);
|
|
171
|
+
}
|
|
155
172
|
if (foreignKey == null) {
|
|
156
173
|
const singularRelationName = singularize(relationName);
|
|
157
174
|
foreignKey = `${singularRelationName}Id`;
|
|
@@ -162,19 +179,24 @@ export class BelongsToResolver extends Service {
|
|
|
162
179
|
}
|
|
163
180
|
const targetIdsByTargetName = {};
|
|
164
181
|
entities.forEach(entity => {
|
|
165
|
-
if (!entity || typeof entity !== 'object' || Array.isArray(entity))
|
|
182
|
+
if (!entity || typeof entity !== 'object' || Array.isArray(entity)) {
|
|
166
183
|
throw new InvalidArgumentError(
|
|
167
184
|
'The parameter "entities" of BelongsToResolver.includePolymorphicTo requires ' +
|
|
168
185
|
'an Array of Object, but %v was given.',
|
|
169
186
|
entity,
|
|
170
187
|
);
|
|
188
|
+
}
|
|
171
189
|
const targetId = entity[foreignKey];
|
|
172
190
|
const targetName = entity[discriminator];
|
|
173
|
-
if (targetId == null || targetName == null)
|
|
174
|
-
|
|
191
|
+
if (targetId == null || targetName == null) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (targetIdsByTargetName[targetName] == null) {
|
|
175
195
|
targetIdsByTargetName[targetName] = [];
|
|
176
|
-
|
|
196
|
+
}
|
|
197
|
+
if (!targetIdsByTargetName[targetName].includes(targetId)) {
|
|
177
198
|
targetIdsByTargetName[targetName].push(targetId);
|
|
199
|
+
}
|
|
178
200
|
});
|
|
179
201
|
const promises = [];
|
|
180
202
|
const targetNames = Object.keys(targetIdsByTargetName);
|
|
@@ -235,7 +257,9 @@ export class BelongsToResolver extends Service {
|
|
|
235
257
|
targetName,
|
|
236
258
|
);
|
|
237
259
|
const target = targetEntities.find(e => e[targetPkPropName] === targetId);
|
|
238
|
-
if (target)
|
|
260
|
+
if (target) {
|
|
261
|
+
entity[relationName] = target;
|
|
262
|
+
}
|
|
239
263
|
});
|
|
240
264
|
}
|
|
241
265
|
}
|
|
@@ -27,42 +27,48 @@ export class HasManyResolver extends Service {
|
|
|
27
27
|
foreignKey,
|
|
28
28
|
scope = undefined,
|
|
29
29
|
) {
|
|
30
|
-
if (!entities || !Array.isArray(entities))
|
|
30
|
+
if (!entities || !Array.isArray(entities)) {
|
|
31
31
|
throw new InvalidArgumentError(
|
|
32
32
|
'The parameter "entities" of HasManyResolver.includeTo requires ' +
|
|
33
33
|
'an Array of Object, but %v was given.',
|
|
34
34
|
entities,
|
|
35
35
|
);
|
|
36
|
-
|
|
36
|
+
}
|
|
37
|
+
if (!sourceName || typeof sourceName !== 'string') {
|
|
37
38
|
throw new InvalidArgumentError(
|
|
38
39
|
'The parameter "sourceName" of HasManyResolver.includeTo requires ' +
|
|
39
40
|
'a non-empty String, but %v was given.',
|
|
40
41
|
sourceName,
|
|
41
42
|
);
|
|
42
|
-
|
|
43
|
+
}
|
|
44
|
+
if (!targetName || typeof targetName !== 'string') {
|
|
43
45
|
throw new InvalidArgumentError(
|
|
44
46
|
'The parameter "targetName" of HasManyResolver.includeTo requires ' +
|
|
45
47
|
'a non-empty String, but %v was given.',
|
|
46
48
|
targetName,
|
|
47
49
|
);
|
|
48
|
-
|
|
50
|
+
}
|
|
51
|
+
if (!relationName || typeof relationName !== 'string') {
|
|
49
52
|
throw new InvalidArgumentError(
|
|
50
53
|
'The parameter "relationName" of HasManyResolver.includeTo requires ' +
|
|
51
54
|
'a non-empty String, but %v was given.',
|
|
52
55
|
relationName,
|
|
53
56
|
);
|
|
54
|
-
|
|
57
|
+
}
|
|
58
|
+
if (!foreignKey || typeof foreignKey !== 'string') {
|
|
55
59
|
throw new InvalidArgumentError(
|
|
56
60
|
'The parameter "foreignKey" of HasManyResolver.includeTo requires ' +
|
|
57
61
|
'a non-empty String, but %v was given.',
|
|
58
62
|
foreignKey,
|
|
59
63
|
);
|
|
60
|
-
|
|
64
|
+
}
|
|
65
|
+
if (scope && (typeof scope !== 'object' || Array.isArray(scope))) {
|
|
61
66
|
throw new InvalidArgumentError(
|
|
62
67
|
'The provided parameter "scope" of HasManyResolver.includeTo ' +
|
|
63
68
|
'should be an Object, but %v was given.',
|
|
64
69
|
scope,
|
|
65
70
|
);
|
|
71
|
+
}
|
|
66
72
|
|
|
67
73
|
const sourcePkPropName =
|
|
68
74
|
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
@@ -70,14 +76,17 @@ export class HasManyResolver extends Service {
|
|
|
70
76
|
);
|
|
71
77
|
const sourceIds = [];
|
|
72
78
|
entities.forEach(entity => {
|
|
73
|
-
if (!entity || typeof entity !== 'object' || Array.isArray(entity))
|
|
79
|
+
if (!entity || typeof entity !== 'object' || Array.isArray(entity)) {
|
|
74
80
|
throw new InvalidArgumentError(
|
|
75
81
|
'The parameter "entities" of HasManyResolver.includeTo requires ' +
|
|
76
82
|
'an Array of Object, but %v was given.',
|
|
77
83
|
entity,
|
|
78
84
|
);
|
|
85
|
+
}
|
|
79
86
|
const sourceId = entity[sourcePkPropName];
|
|
80
|
-
if (sourceIds.includes(sourceId))
|
|
87
|
+
if (sourceIds.includes(sourceId)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
81
90
|
sourceIds.push(sourceId);
|
|
82
91
|
});
|
|
83
92
|
|
|
@@ -130,48 +139,55 @@ export class HasManyResolver extends Service {
|
|
|
130
139
|
discriminator,
|
|
131
140
|
scope = undefined,
|
|
132
141
|
) {
|
|
133
|
-
if (!entities || !Array.isArray(entities))
|
|
142
|
+
if (!entities || !Array.isArray(entities)) {
|
|
134
143
|
throw new InvalidArgumentError(
|
|
135
144
|
'The parameter "entities" of HasManyResolver.includePolymorphicTo requires ' +
|
|
136
145
|
'an Array of Object, but %v was given.',
|
|
137
146
|
entities,
|
|
138
147
|
);
|
|
139
|
-
|
|
148
|
+
}
|
|
149
|
+
if (!sourceName || typeof sourceName !== 'string') {
|
|
140
150
|
throw new InvalidArgumentError(
|
|
141
151
|
'The parameter "sourceName" of HasManyResolver.includePolymorphicTo requires ' +
|
|
142
152
|
'a non-empty String, but %v was given.',
|
|
143
153
|
sourceName,
|
|
144
154
|
);
|
|
145
|
-
|
|
155
|
+
}
|
|
156
|
+
if (!targetName || typeof targetName !== 'string') {
|
|
146
157
|
throw new InvalidArgumentError(
|
|
147
158
|
'The parameter "targetName" of HasManyResolver.includePolymorphicTo requires ' +
|
|
148
159
|
'a non-empty String, but %v was given.',
|
|
149
160
|
targetName,
|
|
150
161
|
);
|
|
151
|
-
|
|
162
|
+
}
|
|
163
|
+
if (!relationName || typeof relationName !== 'string') {
|
|
152
164
|
throw new InvalidArgumentError(
|
|
153
165
|
'The parameter "relationName" of HasManyResolver.includePolymorphicTo requires ' +
|
|
154
166
|
'a non-empty String, but %v was given.',
|
|
155
167
|
relationName,
|
|
156
168
|
);
|
|
157
|
-
|
|
169
|
+
}
|
|
170
|
+
if (!foreignKey || typeof foreignKey !== 'string') {
|
|
158
171
|
throw new InvalidArgumentError(
|
|
159
172
|
'The parameter "foreignKey" of HasManyResolver.includePolymorphicTo requires ' +
|
|
160
173
|
'a non-empty String, but %v was given.',
|
|
161
174
|
foreignKey,
|
|
162
175
|
);
|
|
163
|
-
|
|
176
|
+
}
|
|
177
|
+
if (!discriminator || typeof discriminator !== 'string') {
|
|
164
178
|
throw new InvalidArgumentError(
|
|
165
179
|
'The parameter "discriminator" of HasManyResolver.includePolymorphicTo requires ' +
|
|
166
180
|
'a non-empty String, but %v was given.',
|
|
167
181
|
discriminator,
|
|
168
182
|
);
|
|
169
|
-
|
|
183
|
+
}
|
|
184
|
+
if (scope && (typeof scope !== 'object' || Array.isArray(scope))) {
|
|
170
185
|
throw new InvalidArgumentError(
|
|
171
186
|
'The provided parameter "scope" of HasManyResolver.includePolymorphicTo ' +
|
|
172
187
|
'should be an Object, but %v was given.',
|
|
173
188
|
scope,
|
|
174
189
|
);
|
|
190
|
+
}
|
|
175
191
|
|
|
176
192
|
const sourcePkPropName =
|
|
177
193
|
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
@@ -179,14 +195,17 @@ export class HasManyResolver extends Service {
|
|
|
179
195
|
);
|
|
180
196
|
const sourceIds = [];
|
|
181
197
|
entities.forEach(entity => {
|
|
182
|
-
if (!entity || typeof entity !== 'object' || Array.isArray(entity))
|
|
198
|
+
if (!entity || typeof entity !== 'object' || Array.isArray(entity)) {
|
|
183
199
|
throw new InvalidArgumentError(
|
|
184
200
|
'The parameter "entities" of HasManyResolver.includePolymorphicTo requires ' +
|
|
185
201
|
'an Array of Object, but %v was given.',
|
|
186
202
|
entity,
|
|
187
203
|
);
|
|
204
|
+
}
|
|
188
205
|
const sourceId = entity[sourcePkPropName];
|
|
189
|
-
if (sourceIds.includes(sourceId))
|
|
206
|
+
if (sourceIds.includes(sourceId)) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
190
209
|
sourceIds.push(sourceId);
|
|
191
210
|
});
|
|
192
211
|
|
|
@@ -240,47 +259,53 @@ export class HasManyResolver extends Service {
|
|
|
240
259
|
targetRelationName,
|
|
241
260
|
scope = undefined,
|
|
242
261
|
) {
|
|
243
|
-
if (!entities || !Array.isArray(entities))
|
|
262
|
+
if (!entities || !Array.isArray(entities)) {
|
|
244
263
|
throw new InvalidArgumentError(
|
|
245
264
|
'The parameter "entities" of HasManyResolver.includePolymorphicByRelationName requires ' +
|
|
246
265
|
'an Array of Object, but %v was given.',
|
|
247
266
|
entities,
|
|
248
267
|
);
|
|
249
|
-
|
|
268
|
+
}
|
|
269
|
+
if (!sourceName || typeof sourceName !== 'string') {
|
|
250
270
|
throw new InvalidArgumentError(
|
|
251
271
|
'The parameter "sourceName" of HasManyResolver.includePolymorphicByRelationName requires ' +
|
|
252
272
|
'a non-empty String, but %v was given.',
|
|
253
273
|
sourceName,
|
|
254
274
|
);
|
|
255
|
-
|
|
275
|
+
}
|
|
276
|
+
if (!targetName || typeof targetName !== 'string') {
|
|
256
277
|
throw new InvalidArgumentError(
|
|
257
278
|
'The parameter "targetName" of HasManyResolver.includePolymorphicByRelationName requires ' +
|
|
258
279
|
'a non-empty String, but %v was given.',
|
|
259
280
|
targetName,
|
|
260
281
|
);
|
|
261
|
-
|
|
282
|
+
}
|
|
283
|
+
if (!relationName || typeof relationName !== 'string') {
|
|
262
284
|
throw new InvalidArgumentError(
|
|
263
285
|
'The parameter "relationName" of HasManyResolver.includePolymorphicByRelationName requires ' +
|
|
264
286
|
'a non-empty String, but %v was given.',
|
|
265
287
|
relationName,
|
|
266
288
|
);
|
|
267
|
-
|
|
289
|
+
}
|
|
290
|
+
if (!targetRelationName || typeof targetRelationName !== 'string') {
|
|
268
291
|
throw new InvalidArgumentError(
|
|
269
292
|
'The parameter "targetRelationName" of HasManyResolver.includePolymorphicByRelationName requires ' +
|
|
270
293
|
'a non-empty String, but %v was given.',
|
|
271
294
|
targetRelationName,
|
|
272
295
|
);
|
|
273
|
-
|
|
296
|
+
}
|
|
297
|
+
if (scope && (typeof scope !== 'object' || Array.isArray(scope))) {
|
|
274
298
|
throw new InvalidArgumentError(
|
|
275
299
|
'The provided parameter "scope" of HasManyResolver.includePolymorphicByRelationName ' +
|
|
276
300
|
'should be an Object, but %v was given.',
|
|
277
301
|
scope,
|
|
278
302
|
);
|
|
303
|
+
}
|
|
279
304
|
|
|
280
305
|
const targetRelationDef = this.getService(
|
|
281
306
|
ModelDefinitionUtils,
|
|
282
307
|
).getRelationDefinitionByName(targetName, targetRelationName);
|
|
283
|
-
if (targetRelationDef.type !== RelationType.BELONGS_TO)
|
|
308
|
+
if (targetRelationDef.type !== RelationType.BELONGS_TO) {
|
|
284
309
|
throw new InvalidArgumentError(
|
|
285
310
|
'The relation %v of the model %v is a polymorphic "hasMany" relation, ' +
|
|
286
311
|
'so it requires the target relation %v to be a polymorphic "belongsTo", ' +
|
|
@@ -290,7 +315,8 @@ export class HasManyResolver extends Service {
|
|
|
290
315
|
targetRelationName,
|
|
291
316
|
targetRelationDef.type,
|
|
292
317
|
);
|
|
293
|
-
|
|
318
|
+
}
|
|
319
|
+
if (!targetRelationDef.polymorphic) {
|
|
294
320
|
throw new InvalidArgumentError(
|
|
295
321
|
'The relation %v of the model %v is a polymorphic "hasMany" relation, ' +
|
|
296
322
|
'so it requires the target relation %v to be a polymorphic too.',
|
|
@@ -298,6 +324,7 @@ export class HasManyResolver extends Service {
|
|
|
298
324
|
sourceName,
|
|
299
325
|
targetRelationName,
|
|
300
326
|
);
|
|
327
|
+
}
|
|
301
328
|
const foreignKey =
|
|
302
329
|
targetRelationDef.foreignKey || `${targetRelationName}Id`;
|
|
303
330
|
const discriminator =
|