@e22m4u/js-repository 0.8.5 → 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 +27 -23
- package/dist/cjs/index.cjs +746 -325
- package/eslint.config.js +1 -0
- package/package.json +14 -13
- 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 +68 -26
- 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 +26 -10
- package/src/definition/model/properties/property-uniqueness-validator.spec.js +500 -38
- 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
|
@@ -13,19 +13,21 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
13
13
|
* @param {object} relDefs
|
|
14
14
|
*/
|
|
15
15
|
validate(modelName, relDefs) {
|
|
16
|
-
if (!modelName || typeof modelName !== 'string')
|
|
16
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
17
17
|
throw new InvalidArgumentError(
|
|
18
18
|
'The first argument of RelationsDefinitionValidator.validate ' +
|
|
19
19
|
'should be a non-empty String, but %v was given.',
|
|
20
20
|
modelName,
|
|
21
21
|
);
|
|
22
|
-
|
|
22
|
+
}
|
|
23
|
+
if (!relDefs || typeof relDefs !== 'object' || Array.isArray(relDefs)) {
|
|
23
24
|
throw new InvalidArgumentError(
|
|
24
25
|
'The provided option "relations" of the model %v ' +
|
|
25
26
|
'should be an Object, but %v was given.',
|
|
26
27
|
modelName,
|
|
27
28
|
relDefs,
|
|
28
29
|
);
|
|
30
|
+
}
|
|
29
31
|
const relNames = Object.keys(relDefs);
|
|
30
32
|
relNames.forEach(relName => {
|
|
31
33
|
const relDef = relDefs[relName];
|
|
@@ -41,27 +43,30 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
41
43
|
* @param {object} relDef
|
|
42
44
|
*/
|
|
43
45
|
_validateRelation(modelName, relName, relDef) {
|
|
44
|
-
if (!modelName || typeof modelName !== 'string')
|
|
46
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
45
47
|
throw new InvalidArgumentError(
|
|
46
48
|
'The first argument of RelationsDefinitionValidator._validateRelation ' +
|
|
47
49
|
'should be a non-empty String, but %v was given.',
|
|
48
50
|
modelName,
|
|
49
51
|
);
|
|
50
|
-
|
|
52
|
+
}
|
|
53
|
+
if (!relName || typeof relName !== 'string') {
|
|
51
54
|
throw new InvalidArgumentError(
|
|
52
55
|
'The relation name of the model %v should be ' +
|
|
53
56
|
'a non-empty String, but %v was given.',
|
|
54
57
|
modelName,
|
|
55
58
|
relName,
|
|
56
59
|
);
|
|
57
|
-
|
|
60
|
+
}
|
|
61
|
+
if (!relDef || typeof relDef !== 'object' || Array.isArray(relDef)) {
|
|
58
62
|
throw new InvalidArgumentError(
|
|
59
63
|
'The relation %v of the model %v should be an Object, but %v was given.',
|
|
60
64
|
relName,
|
|
61
65
|
modelName,
|
|
62
66
|
relDef,
|
|
63
67
|
);
|
|
64
|
-
|
|
68
|
+
}
|
|
69
|
+
if (!relDef.type || !Object.values(RelationType).includes(relDef.type)) {
|
|
65
70
|
throw new InvalidArgumentError(
|
|
66
71
|
'The relation %v of the model %v requires the option "type" ' +
|
|
67
72
|
'to have one of relation types: %l, but %v was given.',
|
|
@@ -70,6 +75,7 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
70
75
|
Object.values(RelationType),
|
|
71
76
|
relDef.type,
|
|
72
77
|
);
|
|
78
|
+
}
|
|
73
79
|
this._validateBelongsTo(modelName, relName, relDef);
|
|
74
80
|
this._validateHasOne(modelName, relName, relDef);
|
|
75
81
|
this._validateHasMany(modelName, relName, relDef);
|
|
@@ -104,10 +110,12 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
104
110
|
* @private
|
|
105
111
|
*/
|
|
106
112
|
_validateBelongsTo(modelName, relName, relDef) {
|
|
107
|
-
if (relDef.type !== RelationType.BELONGS_TO)
|
|
113
|
+
if (relDef.type !== RelationType.BELONGS_TO) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
108
116
|
if (relDef.polymorphic) {
|
|
109
117
|
// A polymorphic "belongsTo" relation.
|
|
110
|
-
if (typeof relDef.polymorphic !== 'boolean')
|
|
118
|
+
if (typeof relDef.polymorphic !== 'boolean') {
|
|
111
119
|
throw new InvalidArgumentError(
|
|
112
120
|
'The relation %v of the model %v has the type "belongsTo", ' +
|
|
113
121
|
'so it expects the option "polymorphic" to be a Boolean, ' +
|
|
@@ -116,7 +124,8 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
116
124
|
modelName,
|
|
117
125
|
relDef.polymorphic,
|
|
118
126
|
);
|
|
119
|
-
|
|
127
|
+
}
|
|
128
|
+
if (relDef.foreignKey && typeof relDef.foreignKey !== 'string') {
|
|
120
129
|
throw new InvalidArgumentError(
|
|
121
130
|
'The relation %v of the model %v is a polymorphic "belongsTo" relation, ' +
|
|
122
131
|
'so it expects the provided option "foreignKey" to be a String, ' +
|
|
@@ -125,7 +134,8 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
125
134
|
modelName,
|
|
126
135
|
relDef.foreignKey,
|
|
127
136
|
);
|
|
128
|
-
|
|
137
|
+
}
|
|
138
|
+
if (relDef.discriminator && typeof relDef.discriminator !== 'string') {
|
|
129
139
|
throw new InvalidArgumentError(
|
|
130
140
|
'The relation %v of the model %v is a polymorphic "belongsTo" relation, ' +
|
|
131
141
|
'so it expects the provided option "discriminator" to be a String, ' +
|
|
@@ -134,9 +144,10 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
134
144
|
modelName,
|
|
135
145
|
relDef.discriminator,
|
|
136
146
|
);
|
|
147
|
+
}
|
|
137
148
|
} else {
|
|
138
149
|
// A regular "belongsTo" relation.
|
|
139
|
-
if (!relDef.model || typeof relDef.model !== 'string')
|
|
150
|
+
if (!relDef.model || typeof relDef.model !== 'string') {
|
|
140
151
|
throw new InvalidArgumentError(
|
|
141
152
|
'The relation %v of the model %v has the type "belongsTo", ' +
|
|
142
153
|
'so it requires the option "model" to be a non-empty String, ' +
|
|
@@ -145,7 +156,8 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
145
156
|
modelName,
|
|
146
157
|
relDef.model,
|
|
147
158
|
);
|
|
148
|
-
|
|
159
|
+
}
|
|
160
|
+
if (relDef.foreignKey && typeof relDef.foreignKey !== 'string') {
|
|
149
161
|
throw new InvalidArgumentError(
|
|
150
162
|
'The relation %v of the model %v has the type "belongsTo", ' +
|
|
151
163
|
'so it expects the provided option "foreignKey" to be a String, ' +
|
|
@@ -154,13 +166,15 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
154
166
|
modelName,
|
|
155
167
|
relDef.foreignKey,
|
|
156
168
|
);
|
|
157
|
-
|
|
169
|
+
}
|
|
170
|
+
if (relDef.discriminator) {
|
|
158
171
|
throw new InvalidArgumentError(
|
|
159
172
|
'The relation %v of the model %v is a non-polymorphic "belongsTo" relation, ' +
|
|
160
173
|
'so it should not have the option "discriminator" to be provided.',
|
|
161
174
|
relName,
|
|
162
175
|
modelName,
|
|
163
176
|
);
|
|
177
|
+
}
|
|
164
178
|
}
|
|
165
179
|
}
|
|
166
180
|
|
|
@@ -202,8 +216,10 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
202
216
|
* @private
|
|
203
217
|
*/
|
|
204
218
|
_validateHasOne(modelName, relName, relDef) {
|
|
205
|
-
if (relDef.type !== RelationType.HAS_ONE)
|
|
206
|
-
|
|
219
|
+
if (relDef.type !== RelationType.HAS_ONE) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (!relDef.model || typeof relDef.model !== 'string') {
|
|
207
223
|
throw new InvalidArgumentError(
|
|
208
224
|
'The relation %v of the model %v has the type "hasOne", ' +
|
|
209
225
|
'so it requires the option "model" to be a non-empty String, ' +
|
|
@@ -212,10 +228,11 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
212
228
|
modelName,
|
|
213
229
|
relDef.model,
|
|
214
230
|
);
|
|
231
|
+
}
|
|
215
232
|
if (relDef.polymorphic) {
|
|
216
233
|
if (typeof relDef.polymorphic === 'string') {
|
|
217
234
|
// A polymorphic "hasOne" relation with a target relation name.
|
|
218
|
-
if (relDef.foreignKey)
|
|
235
|
+
if (relDef.foreignKey) {
|
|
219
236
|
throw new InvalidArgumentError(
|
|
220
237
|
'The relation %v of the model %v has the option "polymorphic" with ' +
|
|
221
238
|
'a String value, so it should not have the option "foreignKey" ' +
|
|
@@ -223,7 +240,8 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
223
240
|
relName,
|
|
224
241
|
modelName,
|
|
225
242
|
);
|
|
226
|
-
|
|
243
|
+
}
|
|
244
|
+
if (relDef.discriminator) {
|
|
227
245
|
throw new InvalidArgumentError(
|
|
228
246
|
'The relation %v of the model %v has the option "polymorphic" with ' +
|
|
229
247
|
'a String value, so it should not have the option "discriminator" ' +
|
|
@@ -231,9 +249,10 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
231
249
|
relName,
|
|
232
250
|
modelName,
|
|
233
251
|
);
|
|
252
|
+
}
|
|
234
253
|
} else if (typeof relDef.polymorphic === 'boolean') {
|
|
235
254
|
// A polymorphic "hasOne" relation with target relation keys.
|
|
236
|
-
if (!relDef.foreignKey || typeof relDef.foreignKey !== 'string')
|
|
255
|
+
if (!relDef.foreignKey || typeof relDef.foreignKey !== 'string') {
|
|
237
256
|
throw new InvalidArgumentError(
|
|
238
257
|
'The relation %v of the model %v has the option "polymorphic" ' +
|
|
239
258
|
'with "true" value, so it requires the option "foreignKey" ' +
|
|
@@ -242,7 +261,8 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
242
261
|
modelName,
|
|
243
262
|
relDef.foreignKey,
|
|
244
263
|
);
|
|
245
|
-
|
|
264
|
+
}
|
|
265
|
+
if (!relDef.discriminator || typeof relDef.discriminator !== 'string') {
|
|
246
266
|
throw new InvalidArgumentError(
|
|
247
267
|
'The relation %v of the model %v has the option "polymorphic" ' +
|
|
248
268
|
'with "true" value, so it requires the option "discriminator" ' +
|
|
@@ -251,6 +271,7 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
251
271
|
modelName,
|
|
252
272
|
relDef.discriminator,
|
|
253
273
|
);
|
|
274
|
+
}
|
|
254
275
|
} else {
|
|
255
276
|
throw new InvalidArgumentError(
|
|
256
277
|
'The relation %v of the model %v has the type "hasOne", ' +
|
|
@@ -263,7 +284,7 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
263
284
|
}
|
|
264
285
|
} else {
|
|
265
286
|
// A regular "hasOne" relation.
|
|
266
|
-
if (!relDef.foreignKey || typeof relDef.foreignKey !== 'string')
|
|
287
|
+
if (!relDef.foreignKey || typeof relDef.foreignKey !== 'string') {
|
|
267
288
|
throw new InvalidArgumentError(
|
|
268
289
|
'The relation %v of the model %v has the type "hasOne", ' +
|
|
269
290
|
'so it requires the option "foreignKey" to be a non-empty String, ' +
|
|
@@ -272,13 +293,15 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
272
293
|
modelName,
|
|
273
294
|
relDef.foreignKey,
|
|
274
295
|
);
|
|
275
|
-
|
|
296
|
+
}
|
|
297
|
+
if (relDef.discriminator) {
|
|
276
298
|
throw new InvalidArgumentError(
|
|
277
299
|
'The relation %v of the model %v is a non-polymorphic "hasOne" relation, ' +
|
|
278
300
|
'so it should not have the option "discriminator" to be provided.',
|
|
279
301
|
relName,
|
|
280
302
|
modelName,
|
|
281
303
|
);
|
|
304
|
+
}
|
|
282
305
|
}
|
|
283
306
|
}
|
|
284
307
|
|
|
@@ -320,8 +343,10 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
320
343
|
* @private
|
|
321
344
|
*/
|
|
322
345
|
_validateHasMany(modelName, relName, relDef) {
|
|
323
|
-
if (relDef.type !== RelationType.HAS_MANY)
|
|
324
|
-
|
|
346
|
+
if (relDef.type !== RelationType.HAS_MANY) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (!relDef.model || typeof relDef.model !== 'string') {
|
|
325
350
|
throw new InvalidArgumentError(
|
|
326
351
|
'The relation %v of the model %v has the type "hasMany", ' +
|
|
327
352
|
'so it requires the option "model" to be a non-empty String, ' +
|
|
@@ -330,10 +355,11 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
330
355
|
modelName,
|
|
331
356
|
relDef.model,
|
|
332
357
|
);
|
|
358
|
+
}
|
|
333
359
|
if (relDef.polymorphic) {
|
|
334
360
|
if (typeof relDef.polymorphic === 'string') {
|
|
335
361
|
// A polymorphic "hasMany" relation with a target relation name.
|
|
336
|
-
if (relDef.foreignKey)
|
|
362
|
+
if (relDef.foreignKey) {
|
|
337
363
|
throw new InvalidArgumentError(
|
|
338
364
|
'The relation %v of the model %v has the option "polymorphic" with ' +
|
|
339
365
|
'a String value, so it should not have the option "foreignKey" ' +
|
|
@@ -341,7 +367,8 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
341
367
|
relName,
|
|
342
368
|
modelName,
|
|
343
369
|
);
|
|
344
|
-
|
|
370
|
+
}
|
|
371
|
+
if (relDef.discriminator) {
|
|
345
372
|
throw new InvalidArgumentError(
|
|
346
373
|
'The relation %v of the model %v has the option "polymorphic" with ' +
|
|
347
374
|
'a String value, so it should not have the option "discriminator" ' +
|
|
@@ -349,9 +376,10 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
349
376
|
relName,
|
|
350
377
|
modelName,
|
|
351
378
|
);
|
|
379
|
+
}
|
|
352
380
|
} else if (typeof relDef.polymorphic === 'boolean') {
|
|
353
381
|
// A polymorphic "hasMany" relation with target relation keys.
|
|
354
|
-
if (!relDef.foreignKey || typeof relDef.foreignKey !== 'string')
|
|
382
|
+
if (!relDef.foreignKey || typeof relDef.foreignKey !== 'string') {
|
|
355
383
|
throw new InvalidArgumentError(
|
|
356
384
|
'The relation %v of the model %v has the option "polymorphic" ' +
|
|
357
385
|
'with "true" value, so it requires the option "foreignKey" ' +
|
|
@@ -360,7 +388,8 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
360
388
|
modelName,
|
|
361
389
|
relDef.foreignKey,
|
|
362
390
|
);
|
|
363
|
-
|
|
391
|
+
}
|
|
392
|
+
if (!relDef.discriminator || typeof relDef.discriminator !== 'string') {
|
|
364
393
|
throw new InvalidArgumentError(
|
|
365
394
|
'The relation %v of the model %v has the option "polymorphic" ' +
|
|
366
395
|
'with "true" value, so it requires the option "discriminator" ' +
|
|
@@ -369,6 +398,7 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
369
398
|
modelName,
|
|
370
399
|
relDef.discriminator,
|
|
371
400
|
);
|
|
401
|
+
}
|
|
372
402
|
} else {
|
|
373
403
|
throw new InvalidArgumentError(
|
|
374
404
|
'The relation %v of the model %v has the type "hasMany", ' +
|
|
@@ -381,7 +411,7 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
381
411
|
}
|
|
382
412
|
} else {
|
|
383
413
|
// A regular "hasMany" relation.
|
|
384
|
-
if (!relDef.foreignKey || typeof relDef.foreignKey !== 'string')
|
|
414
|
+
if (!relDef.foreignKey || typeof relDef.foreignKey !== 'string') {
|
|
385
415
|
throw new InvalidArgumentError(
|
|
386
416
|
'The relation %v of the model %v has the type "hasMany", ' +
|
|
387
417
|
'so it requires the option "foreignKey" to be a non-empty String, ' +
|
|
@@ -390,13 +420,15 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
390
420
|
modelName,
|
|
391
421
|
relDef.foreignKey,
|
|
392
422
|
);
|
|
393
|
-
|
|
423
|
+
}
|
|
424
|
+
if (relDef.discriminator) {
|
|
394
425
|
throw new InvalidArgumentError(
|
|
395
426
|
'The relation %v of the model %v is a non-polymorphic "hasMany" relation, ' +
|
|
396
427
|
'so it should not have the option "discriminator" to be provided.',
|
|
397
428
|
relName,
|
|
398
429
|
modelName,
|
|
399
430
|
);
|
|
431
|
+
}
|
|
400
432
|
}
|
|
401
433
|
}
|
|
402
434
|
|
|
@@ -418,8 +450,10 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
418
450
|
* @private
|
|
419
451
|
*/
|
|
420
452
|
_validateReferencesMany(modelName, relName, relDef) {
|
|
421
|
-
if (relDef.type !== RelationType.REFERENCES_MANY)
|
|
422
|
-
|
|
453
|
+
if (relDef.type !== RelationType.REFERENCES_MANY) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (!relDef.model || typeof relDef.model !== 'string') {
|
|
423
457
|
throw new InvalidArgumentError(
|
|
424
458
|
'The relation %v of the model %v has the type "referencesMany", ' +
|
|
425
459
|
'so it requires the option "model" to be a non-empty String, ' +
|
|
@@ -428,7 +462,8 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
428
462
|
modelName,
|
|
429
463
|
relDef.model,
|
|
430
464
|
);
|
|
431
|
-
|
|
465
|
+
}
|
|
466
|
+
if (relDef.foreignKey && typeof relDef.foreignKey !== 'string') {
|
|
432
467
|
throw new InvalidArgumentError(
|
|
433
468
|
'The relation %v of the model %v has the type "referencesMany", ' +
|
|
434
469
|
'so it expects the provided option "foreignKey" to be a String, ' +
|
|
@@ -437,12 +472,14 @@ export class RelationsDefinitionValidator extends Service {
|
|
|
437
472
|
modelName,
|
|
438
473
|
relDef.foreignKey,
|
|
439
474
|
);
|
|
440
|
-
|
|
475
|
+
}
|
|
476
|
+
if (relDef.discriminator) {
|
|
441
477
|
throw new InvalidArgumentError(
|
|
442
478
|
'The relation %v of the model %v has the type "referencesMany", ' +
|
|
443
479
|
'so it should not have the option "discriminator" to be provided.',
|
|
444
480
|
relName,
|
|
445
481
|
modelName,
|
|
446
482
|
);
|
|
483
|
+
}
|
|
447
484
|
}
|
|
448
485
|
}
|
|
@@ -19,39 +19,48 @@ export class FieldsClauseTool extends Service {
|
|
|
19
19
|
const isArray = Array.isArray(input);
|
|
20
20
|
let entities = isArray ? input : [input];
|
|
21
21
|
entities.forEach(entity => {
|
|
22
|
-
if (!entity || typeof entity !== 'object' || Array.isArray(entity))
|
|
22
|
+
if (!entity || typeof entity !== 'object' || Array.isArray(entity)) {
|
|
23
23
|
throw new InvalidArgumentError(
|
|
24
24
|
'The first argument of FieldsClauseTool.filter should be an Object or ' +
|
|
25
25
|
'an Array of Object, but %v was given.',
|
|
26
26
|
entity,
|
|
27
27
|
);
|
|
28
|
+
}
|
|
28
29
|
});
|
|
29
30
|
|
|
30
|
-
if (!modelName || typeof modelName !== 'string')
|
|
31
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
31
32
|
throw new InvalidArgumentError(
|
|
32
33
|
'The second argument of FieldsClauseTool.filter should be ' +
|
|
33
34
|
'a non-empty String, but %v was given.',
|
|
34
35
|
modelName,
|
|
35
36
|
);
|
|
37
|
+
}
|
|
36
38
|
|
|
37
|
-
if (clause == null)
|
|
39
|
+
if (clause == null) {
|
|
40
|
+
return input;
|
|
41
|
+
}
|
|
38
42
|
const fields = Array.isArray(clause) ? clause.slice() : [clause];
|
|
39
|
-
if (!fields.length)
|
|
43
|
+
if (!fields.length) {
|
|
44
|
+
return input;
|
|
45
|
+
}
|
|
40
46
|
|
|
41
47
|
fields.forEach(field => {
|
|
42
|
-
if (!field || typeof field !== 'string')
|
|
48
|
+
if (!field || typeof field !== 'string') {
|
|
43
49
|
throw new InvalidArgumentError(
|
|
44
50
|
'The provided option "fields" should be a non-empty String ' +
|
|
45
51
|
'or an Array of non-empty String, but %v was given.',
|
|
46
52
|
field,
|
|
47
53
|
);
|
|
54
|
+
}
|
|
48
55
|
});
|
|
49
56
|
|
|
50
57
|
const pkPropName =
|
|
51
58
|
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
52
59
|
modelName,
|
|
53
60
|
);
|
|
54
|
-
if (fields.indexOf(pkPropName) === -1)
|
|
61
|
+
if (fields.indexOf(pkPropName) === -1) {
|
|
62
|
+
fields.push(pkPropName);
|
|
63
|
+
}
|
|
55
64
|
|
|
56
65
|
entities = entities.map(entity => selectObjectKeys(entity, fields));
|
|
57
66
|
return isArray ? entities : entities[0];
|
|
@@ -63,16 +72,21 @@ export class FieldsClauseTool extends Service {
|
|
|
63
72
|
* @param {string|string[]|undefined} clause
|
|
64
73
|
*/
|
|
65
74
|
static validateFieldsClause(clause) {
|
|
66
|
-
if (clause == null)
|
|
75
|
+
if (clause == null) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
67
78
|
const fields = Array.isArray(clause) ? clause : [clause];
|
|
68
|
-
if (!fields.length)
|
|
79
|
+
if (!fields.length) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
69
82
|
fields.forEach(field => {
|
|
70
|
-
if (!field || typeof field !== 'string')
|
|
83
|
+
if (!field || typeof field !== 'string') {
|
|
71
84
|
throw new InvalidArgumentError(
|
|
72
85
|
'The provided option "fields" should be a non-empty String ' +
|
|
73
86
|
'or an Array of non-empty String, but %v was given.',
|
|
74
87
|
field,
|
|
75
88
|
);
|
|
89
|
+
}
|
|
76
90
|
});
|
|
77
91
|
}
|
|
78
92
|
|
|
@@ -83,16 +97,21 @@ export class FieldsClauseTool extends Service {
|
|
|
83
97
|
* @returns {string[]|undefined}
|
|
84
98
|
*/
|
|
85
99
|
static normalizeFieldsClause(clause) {
|
|
86
|
-
if (clause == null)
|
|
100
|
+
if (clause == null) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
87
103
|
const fields = Array.isArray(clause) ? clause : [clause];
|
|
88
|
-
if (!fields.length)
|
|
104
|
+
if (!fields.length) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
89
107
|
fields.forEach(field => {
|
|
90
|
-
if (!field || typeof field !== 'string')
|
|
108
|
+
if (!field || typeof field !== 'string') {
|
|
91
109
|
throw new InvalidArgumentError(
|
|
92
110
|
'The provided option "fields" should be a non-empty String ' +
|
|
93
111
|
'or an Array of non-empty String, but %v was given.',
|
|
94
112
|
field,
|
|
95
113
|
);
|
|
114
|
+
}
|
|
96
115
|
});
|
|
97
116
|
return fields;
|
|
98
117
|
}
|
|
@@ -178,8 +178,9 @@ export class IncludeClauseTool extends Service {
|
|
|
178
178
|
relNames.push(el);
|
|
179
179
|
} else if (typeof el === 'object') {
|
|
180
180
|
Object.keys(el).forEach(key => {
|
|
181
|
-
if (Object.prototype.hasOwnProperty.call(el, key))
|
|
181
|
+
if (Object.prototype.hasOwnProperty.call(el, key)) {
|
|
182
182
|
relNames.push(key);
|
|
183
|
+
}
|
|
183
184
|
});
|
|
184
185
|
}
|
|
185
186
|
});
|
|
@@ -187,26 +188,32 @@ export class IncludeClauseTool extends Service {
|
|
|
187
188
|
const duplicateNames = relNames.filter(
|
|
188
189
|
(name, i) => relNames.indexOf(name) !== i,
|
|
189
190
|
);
|
|
190
|
-
if (duplicateNames.length)
|
|
191
|
+
if (duplicateNames.length) {
|
|
191
192
|
throw new InvalidArgumentError(
|
|
192
193
|
'The provided option "include" has duplicates of %v.',
|
|
193
194
|
duplicateNames[0],
|
|
194
195
|
);
|
|
196
|
+
}
|
|
195
197
|
} else if (typeof clause === 'object') {
|
|
196
198
|
// validate object
|
|
197
199
|
if ('relation' in clause) {
|
|
198
200
|
// {relation: 'name', scope: {}}
|
|
199
|
-
if (!clause.relation || typeof clause.relation !== 'string')
|
|
201
|
+
if (!clause.relation || typeof clause.relation !== 'string') {
|
|
200
202
|
throw new InvalidArgumentError(
|
|
201
203
|
'The provided option "relation" should be ' +
|
|
202
204
|
'a non-empty String, but %v was given.',
|
|
203
205
|
clause.relation,
|
|
204
206
|
);
|
|
205
|
-
|
|
207
|
+
}
|
|
208
|
+
if ('scope' in clause && clause) {
|
|
209
|
+
this.validateScopeClause(clause.scope);
|
|
210
|
+
}
|
|
206
211
|
} else {
|
|
207
212
|
// {foo: 'bar', 'baz': ['qux'], ...}
|
|
208
213
|
Object.keys(clause).forEach(key => {
|
|
209
|
-
if (!Object.prototype.hasOwnProperty.call(clause, key))
|
|
214
|
+
if (!Object.prototype.hasOwnProperty.call(clause, key)) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
210
217
|
this.validateIncludeClause(key);
|
|
211
218
|
this.validateIncludeClause(clause[key]);
|
|
212
219
|
});
|
|
@@ -227,12 +234,15 @@ export class IncludeClauseTool extends Service {
|
|
|
227
234
|
* @param {object|undefined} clause
|
|
228
235
|
*/
|
|
229
236
|
static validateScopeClause(clause) {
|
|
230
|
-
if (clause == null)
|
|
231
|
-
|
|
237
|
+
if (clause == null) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (typeof clause !== 'object' || Array.isArray(clause)) {
|
|
232
241
|
throw new InvalidArgumentError(
|
|
233
242
|
'The provided option "scope" should be an Object, but %v was given.',
|
|
234
243
|
clause,
|
|
235
244
|
);
|
|
245
|
+
}
|
|
236
246
|
// {where: ...}
|
|
237
247
|
if (clause.where != null) {
|
|
238
248
|
WhereClauseTool.validateWhereClause(clause.where);
|
|
@@ -284,33 +294,41 @@ export class IncludeClauseTool extends Service {
|
|
|
284
294
|
const duplicateNames = relNames.filter(
|
|
285
295
|
(name, i) => relNames.indexOf(name) !== i,
|
|
286
296
|
);
|
|
287
|
-
if (duplicateNames.length)
|
|
297
|
+
if (duplicateNames.length) {
|
|
288
298
|
throw new InvalidArgumentError(
|
|
289
299
|
'The provided option "include" has duplicates of %v.',
|
|
290
300
|
duplicateNames[0],
|
|
291
301
|
);
|
|
302
|
+
}
|
|
292
303
|
} else if (typeof clause === 'object') {
|
|
293
304
|
// normalize object
|
|
294
305
|
if ('relation' in clause) {
|
|
295
306
|
// {relation: 'name', scope: {...}}
|
|
296
|
-
if (!clause.relation || typeof clause.relation !== 'string')
|
|
307
|
+
if (!clause.relation || typeof clause.relation !== 'string') {
|
|
297
308
|
throw new InvalidArgumentError(
|
|
298
309
|
'The provided option "relation" should be ' +
|
|
299
310
|
'a non-empty String, but %v was given.',
|
|
300
311
|
clause.relation,
|
|
301
312
|
);
|
|
313
|
+
}
|
|
302
314
|
const normalized = {relation: clause.relation};
|
|
303
315
|
const scope = this.normalizeScopeClause(clause.scope);
|
|
304
|
-
if (scope)
|
|
316
|
+
if (scope) {
|
|
317
|
+
normalized.scope = scope;
|
|
318
|
+
}
|
|
305
319
|
result.push(normalized);
|
|
306
320
|
} else {
|
|
307
321
|
// {foo: 'bar', baz: ['qux'], ...}
|
|
308
322
|
Object.keys(clause).forEach(key => {
|
|
309
|
-
if (!Object.prototype.hasOwnProperty.call(clause, key))
|
|
323
|
+
if (!Object.prototype.hasOwnProperty.call(clause, key)) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
310
326
|
this.validateIncludeClause(key);
|
|
311
327
|
const normalized = {relation: key};
|
|
312
328
|
const include = this.normalizeIncludeClause(clause[key]);
|
|
313
|
-
if (include.length)
|
|
329
|
+
if (include.length) {
|
|
330
|
+
normalized.scope = {include};
|
|
331
|
+
}
|
|
314
332
|
result.push(normalized);
|
|
315
333
|
});
|
|
316
334
|
}
|
|
@@ -332,12 +350,15 @@ export class IncludeClauseTool extends Service {
|
|
|
332
350
|
* @returns {object|undefined}
|
|
333
351
|
*/
|
|
334
352
|
static normalizeScopeClause(clause) {
|
|
335
|
-
if (clause == null)
|
|
336
|
-
|
|
353
|
+
if (clause == null) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (typeof clause !== 'object' || Array.isArray(clause)) {
|
|
337
357
|
throw new InvalidArgumentError(
|
|
338
358
|
'The provided option "scope" should be an Object, but %v was given.',
|
|
339
359
|
clause,
|
|
340
360
|
);
|
|
361
|
+
}
|
|
341
362
|
const result = {};
|
|
342
363
|
// {where: ...}
|
|
343
364
|
if (clause.where != null) {
|
|
@@ -368,7 +389,9 @@ export class IncludeClauseTool extends Service {
|
|
|
368
389
|
if (clause.include != null) {
|
|
369
390
|
result.include = this.normalizeIncludeClause(clause.include);
|
|
370
391
|
}
|
|
371
|
-
if (Object.keys(result).length)
|
|
392
|
+
if (Object.keys(result).length) {
|
|
393
|
+
return result;
|
|
394
|
+
}
|
|
372
395
|
return undefined;
|
|
373
396
|
}
|
|
374
397
|
}
|