@e22m4u/js-repository 0.8.5 → 0.8.7
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/build-cjs.js +1 -1
- package/dist/cjs/index.cjs +947 -516
- package/eslint.config.js +1 -0
- package/package.json +16 -15
- 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
|
@@ -47,8 +47,12 @@ export class OperatorClauseTool extends Service {
|
|
|
47
47
|
}
|
|
48
48
|
// лексикографическое сравнение
|
|
49
49
|
if (type1 === 'string' && type2 === 'string') {
|
|
50
|
-
if (val1 > val2)
|
|
51
|
-
|
|
50
|
+
if (val1 > val2) {
|
|
51
|
+
return 1;
|
|
52
|
+
}
|
|
53
|
+
if (val1 < val2) {
|
|
54
|
+
return -1;
|
|
55
|
+
}
|
|
52
56
|
return 0;
|
|
53
57
|
}
|
|
54
58
|
return NaN;
|
|
@@ -62,12 +66,13 @@ export class OperatorClauseTool extends Service {
|
|
|
62
66
|
* @returns {boolean|undefined}
|
|
63
67
|
*/
|
|
64
68
|
testAll(clause, value) {
|
|
65
|
-
if (!clause || typeof clause !== 'object' || Array.isArray(clause))
|
|
69
|
+
if (!clause || typeof clause !== 'object' || Array.isArray(clause)) {
|
|
66
70
|
throw new InvalidArgumentError(
|
|
67
71
|
'The first argument of OperatorUtils.testAll ' +
|
|
68
72
|
'should be an Object, but %v was given.',
|
|
69
73
|
clause,
|
|
70
74
|
);
|
|
75
|
+
}
|
|
71
76
|
const operatorMap = {
|
|
72
77
|
eq: this.testEqNeq,
|
|
73
78
|
neq: this.testEqNeq,
|
|
@@ -130,14 +135,19 @@ export class OperatorClauseTool extends Service {
|
|
|
130
135
|
* @returns {boolean|undefined}
|
|
131
136
|
*/
|
|
132
137
|
testEqNeq(clause, value) {
|
|
133
|
-
if (!clause || typeof clause !== 'object')
|
|
138
|
+
if (!clause || typeof clause !== 'object') {
|
|
134
139
|
throw new InvalidArgumentError(
|
|
135
140
|
'The first argument of OperatorUtils.testEqNeq ' +
|
|
136
141
|
'should be an Object, but %v was given.',
|
|
137
142
|
clause,
|
|
138
143
|
);
|
|
139
|
-
|
|
140
|
-
if ('
|
|
144
|
+
}
|
|
145
|
+
if ('eq' in clause) {
|
|
146
|
+
return this.compare(clause.eq, value, true) === 0;
|
|
147
|
+
}
|
|
148
|
+
if ('neq' in clause) {
|
|
149
|
+
return this.compare(clause.neq, value, true) !== 0;
|
|
150
|
+
}
|
|
141
151
|
}
|
|
142
152
|
|
|
143
153
|
/**
|
|
@@ -176,16 +186,25 @@ export class OperatorClauseTool extends Service {
|
|
|
176
186
|
* @returns {boolean|undefined}
|
|
177
187
|
*/
|
|
178
188
|
testGtLt(clause, value) {
|
|
179
|
-
if (!clause || typeof clause !== 'object')
|
|
189
|
+
if (!clause || typeof clause !== 'object') {
|
|
180
190
|
throw new InvalidArgumentError(
|
|
181
191
|
'The first argument of OperatorUtils.testGtLt ' +
|
|
182
192
|
'should be an Object, but %v was given.',
|
|
183
193
|
clause,
|
|
184
194
|
);
|
|
185
|
-
|
|
186
|
-
if ('
|
|
187
|
-
|
|
188
|
-
|
|
195
|
+
}
|
|
196
|
+
if ('gt' in clause) {
|
|
197
|
+
return this.compare(value, clause.gt) > 0;
|
|
198
|
+
}
|
|
199
|
+
if ('gte' in clause) {
|
|
200
|
+
return this.compare(value, clause.gte) >= 0;
|
|
201
|
+
}
|
|
202
|
+
if ('lt' in clause) {
|
|
203
|
+
return this.compare(value, clause.lt) < 0;
|
|
204
|
+
}
|
|
205
|
+
if ('lte' in clause) {
|
|
206
|
+
return this.compare(value, clause.lte) <= 0;
|
|
207
|
+
}
|
|
189
208
|
}
|
|
190
209
|
|
|
191
210
|
/**
|
|
@@ -203,12 +222,13 @@ export class OperatorClauseTool extends Service {
|
|
|
203
222
|
* @returns {boolean|undefined}
|
|
204
223
|
*/
|
|
205
224
|
testInq(clause, value) {
|
|
206
|
-
if (!clause || typeof clause !== 'object')
|
|
225
|
+
if (!clause || typeof clause !== 'object') {
|
|
207
226
|
throw new InvalidArgumentError(
|
|
208
227
|
'The first argument of OperatorUtils.testInq ' +
|
|
209
228
|
'should be an Object, but %v was given.',
|
|
210
229
|
clause,
|
|
211
230
|
);
|
|
231
|
+
}
|
|
212
232
|
if ('inq' in clause && clause.inq !== undefined) {
|
|
213
233
|
if (!clause.inq || !Array.isArray(clause.inq)) {
|
|
214
234
|
throw new InvalidOperatorValueError(
|
|
@@ -241,12 +261,13 @@ export class OperatorClauseTool extends Service {
|
|
|
241
261
|
* @returns {boolean|undefined}
|
|
242
262
|
*/
|
|
243
263
|
testNin(clause, value) {
|
|
244
|
-
if (!clause || typeof clause !== 'object')
|
|
264
|
+
if (!clause || typeof clause !== 'object') {
|
|
245
265
|
throw new InvalidArgumentError(
|
|
246
266
|
'The first argument of OperatorUtils.testNin ' +
|
|
247
267
|
'should be an Object, but %v was given.',
|
|
248
268
|
clause,
|
|
249
269
|
);
|
|
270
|
+
}
|
|
250
271
|
if ('nin' in clause && clause.nin !== undefined) {
|
|
251
272
|
if (!clause.nin || !Array.isArray(clause.nin)) {
|
|
252
273
|
throw new InvalidOperatorValueError(
|
|
@@ -276,12 +297,13 @@ export class OperatorClauseTool extends Service {
|
|
|
276
297
|
* @returns {boolean|undefined}
|
|
277
298
|
*/
|
|
278
299
|
testBetween(clause, value) {
|
|
279
|
-
if (!clause || typeof clause !== 'object')
|
|
300
|
+
if (!clause || typeof clause !== 'object') {
|
|
280
301
|
throw new InvalidArgumentError(
|
|
281
302
|
'The first argument of OperatorUtils.testBetween ' +
|
|
282
303
|
'should be an Object, but %v was given.',
|
|
283
304
|
clause,
|
|
284
305
|
);
|
|
306
|
+
}
|
|
285
307
|
if ('between' in clause && clause.between !== undefined) {
|
|
286
308
|
if (!Array.isArray(clause.between) || clause.between.length !== 2) {
|
|
287
309
|
throw new InvalidOperatorValueError(
|
|
@@ -312,12 +334,13 @@ export class OperatorClauseTool extends Service {
|
|
|
312
334
|
* @returns {boolean|undefined}
|
|
313
335
|
*/
|
|
314
336
|
testExists(clause, value) {
|
|
315
|
-
if (!clause || typeof clause !== 'object')
|
|
337
|
+
if (!clause || typeof clause !== 'object') {
|
|
316
338
|
throw new InvalidArgumentError(
|
|
317
339
|
'The first argument of OperatorUtils.testExists ' +
|
|
318
340
|
'should be an Object, but %v was given.',
|
|
319
341
|
clause,
|
|
320
342
|
);
|
|
343
|
+
}
|
|
321
344
|
if ('exists' in clause && clause.exists !== undefined) {
|
|
322
345
|
if (typeof clause.exists !== 'boolean') {
|
|
323
346
|
throw new InvalidOperatorValueError(
|
|
@@ -345,15 +368,17 @@ export class OperatorClauseTool extends Service {
|
|
|
345
368
|
* @returns {boolean|undefined}
|
|
346
369
|
*/
|
|
347
370
|
testLike(clause, value) {
|
|
348
|
-
if (!clause || typeof clause !== 'object' || Array.isArray(clause))
|
|
371
|
+
if (!clause || typeof clause !== 'object' || Array.isArray(clause)) {
|
|
349
372
|
throw new InvalidArgumentError(
|
|
350
373
|
'The first argument of OperatorUtils.testLike ' +
|
|
351
374
|
'should be an Object, but %v was given.',
|
|
352
375
|
clause,
|
|
353
376
|
);
|
|
377
|
+
}
|
|
354
378
|
if ('like' in clause && clause.like !== undefined) {
|
|
355
|
-
if (typeof clause.like !== 'string')
|
|
379
|
+
if (typeof clause.like !== 'string') {
|
|
356
380
|
throw new InvalidOperatorValueError('like', 'a String', clause.like);
|
|
381
|
+
}
|
|
357
382
|
return likeToRegexp(clause.like).test(value);
|
|
358
383
|
}
|
|
359
384
|
}
|
|
@@ -373,12 +398,13 @@ export class OperatorClauseTool extends Service {
|
|
|
373
398
|
* @returns {boolean|undefined}
|
|
374
399
|
*/
|
|
375
400
|
testNlike(clause, value) {
|
|
376
|
-
if (!clause || typeof clause !== 'object' || Array.isArray(clause))
|
|
401
|
+
if (!clause || typeof clause !== 'object' || Array.isArray(clause)) {
|
|
377
402
|
throw new InvalidArgumentError(
|
|
378
403
|
'The first argument of OperatorUtils.testNlike ' +
|
|
379
404
|
'should be an Object, but %v was given.',
|
|
380
405
|
clause,
|
|
381
406
|
);
|
|
407
|
+
}
|
|
382
408
|
if ('nlike' in clause && clause.nlike !== undefined) {
|
|
383
409
|
if (typeof clause.nlike !== 'string') {
|
|
384
410
|
throw new InvalidOperatorValueError('nlike', 'a String', clause.nlike);
|
|
@@ -402,12 +428,13 @@ export class OperatorClauseTool extends Service {
|
|
|
402
428
|
* @returns {boolean|undefined}
|
|
403
429
|
*/
|
|
404
430
|
testIlike(clause, value) {
|
|
405
|
-
if (!clause || typeof clause !== 'object' || Array.isArray(clause))
|
|
431
|
+
if (!clause || typeof clause !== 'object' || Array.isArray(clause)) {
|
|
406
432
|
throw new InvalidArgumentError(
|
|
407
433
|
'The first argument of OperatorUtils.testIlike ' +
|
|
408
434
|
'should be an Object, but %v was given.',
|
|
409
435
|
clause,
|
|
410
436
|
);
|
|
437
|
+
}
|
|
411
438
|
if ('ilike' in clause && clause.ilike !== undefined) {
|
|
412
439
|
if (typeof clause.ilike !== 'string') {
|
|
413
440
|
throw new InvalidOperatorValueError('ilike', 'a String', clause.ilike);
|
|
@@ -431,12 +458,13 @@ export class OperatorClauseTool extends Service {
|
|
|
431
458
|
* @returns {boolean|undefined}
|
|
432
459
|
*/
|
|
433
460
|
testNilike(clause, value) {
|
|
434
|
-
if (!clause || typeof clause !== 'object' || Array.isArray(clause))
|
|
461
|
+
if (!clause || typeof clause !== 'object' || Array.isArray(clause)) {
|
|
435
462
|
throw new InvalidArgumentError(
|
|
436
463
|
'The first argument of OperatorUtils.testNilike ' +
|
|
437
464
|
'should be an Object, but %v was given.',
|
|
438
465
|
clause,
|
|
439
466
|
);
|
|
467
|
+
}
|
|
440
468
|
if ('nilike' in clause && clause.nilike !== undefined) {
|
|
441
469
|
if (typeof clause.nilike !== 'string') {
|
|
442
470
|
throw new InvalidOperatorValueError(
|
|
@@ -472,12 +500,13 @@ export class OperatorClauseTool extends Service {
|
|
|
472
500
|
* @returns {boolean|undefined}
|
|
473
501
|
*/
|
|
474
502
|
testRegexp(clause, value) {
|
|
475
|
-
if (!clause || typeof clause !== 'object')
|
|
503
|
+
if (!clause || typeof clause !== 'object') {
|
|
476
504
|
throw new InvalidArgumentError(
|
|
477
505
|
'The first argument of OperatorUtils.testRegexp ' +
|
|
478
506
|
'should be an Object, but %v was given.',
|
|
479
507
|
clause,
|
|
480
508
|
);
|
|
509
|
+
}
|
|
481
510
|
if ('regexp' in clause && clause.regexp !== undefined) {
|
|
482
511
|
if (
|
|
483
512
|
typeof clause.regexp !== 'string' &&
|
|
@@ -490,12 +519,15 @@ export class OperatorClauseTool extends Service {
|
|
|
490
519
|
);
|
|
491
520
|
}
|
|
492
521
|
const flags = clause.flags || undefined;
|
|
493
|
-
if (flags && typeof flags !== 'string')
|
|
522
|
+
if (flags && typeof flags !== 'string') {
|
|
494
523
|
throw new InvalidArgumentError(
|
|
495
524
|
'RegExp flags should be a String, but %v was given.',
|
|
496
525
|
clause.flags,
|
|
497
526
|
);
|
|
498
|
-
|
|
527
|
+
}
|
|
528
|
+
if (!value || typeof value !== 'string') {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
499
531
|
const regExp = stringToRegexp(clause.regexp, flags);
|
|
500
532
|
return !!value.match(regExp);
|
|
501
533
|
}
|
|
@@ -13,22 +13,31 @@ export class OrderClauseTool extends Service {
|
|
|
13
13
|
* @param {string|string[]|undefined} clause
|
|
14
14
|
*/
|
|
15
15
|
sort(entities, clause) {
|
|
16
|
-
if (clause == null)
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
if (clause == null) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (Array.isArray(clause) === false) {
|
|
20
|
+
clause = [clause];
|
|
21
|
+
}
|
|
22
|
+
if (!clause.length) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
19
25
|
const mapping = [];
|
|
20
26
|
clause.forEach((key, index) => {
|
|
21
|
-
if (!key || typeof key !== 'string')
|
|
27
|
+
if (!key || typeof key !== 'string') {
|
|
22
28
|
throw new InvalidArgumentError(
|
|
23
29
|
'The provided option "order" should be a non-empty String ' +
|
|
24
30
|
'or an Array of non-empty String, but %v was given.',
|
|
25
31
|
key,
|
|
26
32
|
);
|
|
33
|
+
}
|
|
27
34
|
let reverse = 1;
|
|
28
35
|
const matches = key.match(/\s+(A|DE)SC$/i);
|
|
29
36
|
if (matches) {
|
|
30
37
|
key = key.replace(/\s+(A|DE)SC/i, '');
|
|
31
|
-
if (matches[1].toLowerCase() === 'de')
|
|
38
|
+
if (matches[1].toLowerCase() === 'de') {
|
|
39
|
+
reverse = -1;
|
|
40
|
+
}
|
|
32
41
|
}
|
|
33
42
|
mapping[index] = {key: key, reverse};
|
|
34
43
|
});
|
|
@@ -41,16 +50,23 @@ export class OrderClauseTool extends Service {
|
|
|
41
50
|
* @param {string|string[]|undefined} clause
|
|
42
51
|
*/
|
|
43
52
|
static validateOrderClause(clause) {
|
|
44
|
-
if (clause == null)
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
if (clause == null) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(clause) === false) {
|
|
57
|
+
clause = [clause];
|
|
58
|
+
}
|
|
59
|
+
if (!clause.length) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
47
62
|
clause.forEach(field => {
|
|
48
|
-
if (!field || typeof field !== 'string')
|
|
63
|
+
if (!field || typeof field !== 'string') {
|
|
49
64
|
throw new InvalidArgumentError(
|
|
50
65
|
'The provided option "order" should be a non-empty String ' +
|
|
51
66
|
'or an Array of non-empty String, but %v was given.',
|
|
52
67
|
field,
|
|
53
68
|
);
|
|
69
|
+
}
|
|
54
70
|
});
|
|
55
71
|
}
|
|
56
72
|
|
|
@@ -61,16 +77,23 @@ export class OrderClauseTool extends Service {
|
|
|
61
77
|
* @returns {string[]|undefined}
|
|
62
78
|
*/
|
|
63
79
|
static normalizeOrderClause(clause) {
|
|
64
|
-
if (clause == null)
|
|
65
|
-
|
|
66
|
-
|
|
80
|
+
if (clause == null) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (Array.isArray(clause) === false) {
|
|
84
|
+
clause = [clause];
|
|
85
|
+
}
|
|
86
|
+
if (!clause.length) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
67
89
|
clause.forEach(field => {
|
|
68
|
-
if (!field || typeof field !== 'string')
|
|
90
|
+
if (!field || typeof field !== 'string') {
|
|
69
91
|
throw new InvalidArgumentError(
|
|
70
92
|
'The provided option "order" should be a non-empty String ' +
|
|
71
93
|
'or an Array of non-empty String, but %v was given.',
|
|
72
94
|
field,
|
|
73
95
|
);
|
|
96
|
+
}
|
|
74
97
|
});
|
|
75
98
|
return clause;
|
|
76
99
|
}
|
|
@@ -14,22 +14,25 @@ export class SliceClauseTool extends Service {
|
|
|
14
14
|
* @returns {object[]}
|
|
15
15
|
*/
|
|
16
16
|
slice(entities, skip = undefined, limit = undefined) {
|
|
17
|
-
if (!Array.isArray(entities))
|
|
17
|
+
if (!Array.isArray(entities)) {
|
|
18
18
|
throw new InvalidArgumentError(
|
|
19
19
|
'The first argument of SliceClauseTool.slice ' +
|
|
20
20
|
'should be an Array, but %v was given.',
|
|
21
21
|
entities,
|
|
22
22
|
);
|
|
23
|
-
|
|
23
|
+
}
|
|
24
|
+
if (skip != null && typeof skip !== 'number') {
|
|
24
25
|
throw new InvalidArgumentError(
|
|
25
26
|
'The provided option "skip" should be a Number, but %v was given.',
|
|
26
27
|
skip,
|
|
27
28
|
);
|
|
28
|
-
|
|
29
|
+
}
|
|
30
|
+
if (limit != null && typeof limit !== 'number') {
|
|
29
31
|
throw new InvalidArgumentError(
|
|
30
32
|
'The provided option "limit" should be a Number, but %v was given.',
|
|
31
33
|
limit,
|
|
32
34
|
);
|
|
35
|
+
}
|
|
33
36
|
skip = skip || 0;
|
|
34
37
|
limit = limit || entities.length;
|
|
35
38
|
return entities.slice(skip, skip + limit);
|
|
@@ -41,12 +44,15 @@ export class SliceClauseTool extends Service {
|
|
|
41
44
|
* @param {number|undefined} skip
|
|
42
45
|
*/
|
|
43
46
|
static validateSkipClause(skip) {
|
|
44
|
-
if (skip == null)
|
|
45
|
-
|
|
47
|
+
if (skip == null) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (typeof skip !== 'number') {
|
|
46
51
|
throw new InvalidArgumentError(
|
|
47
52
|
'The provided option "skip" should be a Number, but %v was given.',
|
|
48
53
|
skip,
|
|
49
54
|
);
|
|
55
|
+
}
|
|
50
56
|
}
|
|
51
57
|
|
|
52
58
|
/**
|
|
@@ -55,11 +61,14 @@ export class SliceClauseTool extends Service {
|
|
|
55
61
|
* @param {number|undefined} limit
|
|
56
62
|
*/
|
|
57
63
|
static validateLimitClause(limit) {
|
|
58
|
-
if (limit == null)
|
|
59
|
-
|
|
64
|
+
if (limit == null) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (typeof limit !== 'number') {
|
|
60
68
|
throw new InvalidArgumentError(
|
|
61
69
|
'The provided option "limit" should be a Number, but %v was given.',
|
|
62
70
|
limit,
|
|
63
71
|
);
|
|
72
|
+
}
|
|
64
73
|
}
|
|
65
74
|
}
|
|
@@ -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
|
}
|