@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
|
@@ -32,7 +32,7 @@ export class ModelDefinitionUtils extends Service {
|
|
|
32
32
|
const isDefaultPrimaryKeyAlreadyInUse = Object.keys(propDefs).includes(
|
|
33
33
|
DEFAULT_PRIMARY_KEY_PROPERTY_NAME,
|
|
34
34
|
);
|
|
35
|
-
if (isDefaultPrimaryKeyAlreadyInUse)
|
|
35
|
+
if (isDefaultPrimaryKeyAlreadyInUse) {
|
|
36
36
|
throw new InvalidArgumentError(
|
|
37
37
|
'The property name %v of the model %v is defined as a regular property. ' +
|
|
38
38
|
'In this case, a primary key should be defined explicitly. ' +
|
|
@@ -40,6 +40,7 @@ export class ModelDefinitionUtils extends Service {
|
|
|
40
40
|
DEFAULT_PRIMARY_KEY_PROPERTY_NAME,
|
|
41
41
|
modelName,
|
|
42
42
|
);
|
|
43
|
+
}
|
|
43
44
|
return DEFAULT_PRIMARY_KEY_PROPERTY_NAME;
|
|
44
45
|
}
|
|
45
46
|
return propNames[0];
|
|
@@ -57,9 +58,13 @@ export class ModelDefinitionUtils extends Service {
|
|
|
57
58
|
try {
|
|
58
59
|
pkColName = this.getColumnNameByPropertyName(modelName, pkPropName);
|
|
59
60
|
} catch (error) {
|
|
60
|
-
if (!(error instanceof InvalidArgumentError))
|
|
61
|
+
if (!(error instanceof InvalidArgumentError)) {
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (pkColName === undefined) {
|
|
66
|
+
return pkPropName;
|
|
61
67
|
}
|
|
62
|
-
if (pkColName === undefined) return pkPropName;
|
|
63
68
|
return pkColName;
|
|
64
69
|
}
|
|
65
70
|
|
|
@@ -85,14 +90,16 @@ export class ModelDefinitionUtils extends Service {
|
|
|
85
90
|
const propDefs =
|
|
86
91
|
this.getPropertiesDefinitionInBaseModelHierarchy(modelName);
|
|
87
92
|
const propDef = propDefs[propertyName];
|
|
88
|
-
if (!propDef)
|
|
93
|
+
if (!propDef) {
|
|
89
94
|
throw new InvalidArgumentError(
|
|
90
95
|
'The model %v does not have the property %v.',
|
|
91
96
|
modelName,
|
|
92
97
|
propertyName,
|
|
93
98
|
);
|
|
94
|
-
|
|
99
|
+
}
|
|
100
|
+
if (propDef && typeof propDef === 'object') {
|
|
95
101
|
return propDef.columnName ?? propertyName;
|
|
102
|
+
}
|
|
96
103
|
return propertyName;
|
|
97
104
|
}
|
|
98
105
|
|
|
@@ -107,16 +114,18 @@ export class ModelDefinitionUtils extends Service {
|
|
|
107
114
|
const propDefs =
|
|
108
115
|
this.getPropertiesDefinitionInBaseModelHierarchy(modelName);
|
|
109
116
|
const propDef = propDefs[propertyName];
|
|
110
|
-
if (!propDef)
|
|
117
|
+
if (!propDef) {
|
|
111
118
|
throw new InvalidArgumentError(
|
|
112
119
|
'The model %v does not have the property %v.',
|
|
113
120
|
modelName,
|
|
114
121
|
propertyName,
|
|
115
122
|
);
|
|
116
|
-
|
|
123
|
+
}
|
|
124
|
+
if (propDef && typeof propDef === 'object') {
|
|
117
125
|
return propDef.default instanceof Function
|
|
118
126
|
? propDef.default()
|
|
119
127
|
: propDef.default;
|
|
128
|
+
}
|
|
120
129
|
}
|
|
121
130
|
|
|
122
131
|
/**
|
|
@@ -173,7 +182,9 @@ export class ModelDefinitionUtils extends Service {
|
|
|
173
182
|
const propNames = Object.keys(propDefs);
|
|
174
183
|
const convertedData = cloneDeep(modelData);
|
|
175
184
|
propNames.forEach(propName => {
|
|
176
|
-
if (!(propName in convertedData))
|
|
185
|
+
if (!(propName in convertedData)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
177
188
|
const colName = this.getColumnNameByPropertyName(modelName, propName);
|
|
178
189
|
let propValue = convertedData[propName];
|
|
179
190
|
// если значением является объект, то проверяем
|
|
@@ -232,7 +243,9 @@ export class ModelDefinitionUtils extends Service {
|
|
|
232
243
|
const convertedData = cloneDeep(tableData);
|
|
233
244
|
propNames.forEach(propName => {
|
|
234
245
|
const colName = this.getColumnNameByPropertyName(modelName, propName);
|
|
235
|
-
if (!(colName in convertedData))
|
|
246
|
+
if (!(colName in convertedData)) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
236
249
|
let colValue = convertedData[colName];
|
|
237
250
|
// если значением является объект, то проверяем
|
|
238
251
|
// тип свойства и наличие модели для замены
|
|
@@ -289,14 +302,18 @@ export class ModelDefinitionUtils extends Service {
|
|
|
289
302
|
const propDef = propDefs[propertyName];
|
|
290
303
|
if (!propDef) {
|
|
291
304
|
const pkPropName = this.getPrimaryKeyAsPropertyName(modelName);
|
|
292
|
-
if (pkPropName === propertyName)
|
|
305
|
+
if (pkPropName === propertyName) {
|
|
306
|
+
return DataType.ANY;
|
|
307
|
+
}
|
|
293
308
|
throw new InvalidArgumentError(
|
|
294
309
|
'The model %v does not have the property %v.',
|
|
295
310
|
modelName,
|
|
296
311
|
propertyName,
|
|
297
312
|
);
|
|
298
313
|
}
|
|
299
|
-
if (typeof propDef === 'string')
|
|
314
|
+
if (typeof propDef === 'string') {
|
|
315
|
+
return propDef;
|
|
316
|
+
}
|
|
300
317
|
return propDef.type;
|
|
301
318
|
}
|
|
302
319
|
|
|
@@ -317,15 +334,18 @@ export class ModelDefinitionUtils extends Service {
|
|
|
317
334
|
propDef,
|
|
318
335
|
);
|
|
319
336
|
}
|
|
320
|
-
if (typeof propDef === 'string')
|
|
337
|
+
if (typeof propDef === 'string') {
|
|
338
|
+
return propDef;
|
|
339
|
+
}
|
|
321
340
|
const dataType = propDef.type;
|
|
322
|
-
if (!Object.values(DataType).includes(dataType))
|
|
341
|
+
if (!Object.values(DataType).includes(dataType)) {
|
|
323
342
|
throw new InvalidArgumentError(
|
|
324
343
|
'The given Object to the ModelDefinitionUtils.getDataTypeFromPropertyDefinition ' +
|
|
325
344
|
'should have the "type" property with one of values: %l, but %v was given.',
|
|
326
345
|
Object.values(DataType),
|
|
327
346
|
propDef.type,
|
|
328
347
|
);
|
|
348
|
+
}
|
|
329
349
|
return dataType;
|
|
330
350
|
}
|
|
331
351
|
|
|
@@ -356,7 +376,9 @@ export class ModelDefinitionUtils extends Service {
|
|
|
356
376
|
const propDefs = modelDef.properties ?? {};
|
|
357
377
|
return Object.keys(propDefs).reduce((result, propName) => {
|
|
358
378
|
const propDef = propDefs[propName];
|
|
359
|
-
if (typeof propDef === 'object' && propDef.primaryKey)
|
|
379
|
+
if (typeof propDef === 'object' && propDef.primaryKey) {
|
|
380
|
+
return result;
|
|
381
|
+
}
|
|
360
382
|
return {...result, [propName]: propDef};
|
|
361
383
|
}, {});
|
|
362
384
|
}
|
|
@@ -371,21 +393,25 @@ export class ModelDefinitionUtils extends Service {
|
|
|
371
393
|
let pkPropDefs = {};
|
|
372
394
|
let regularPropDefs = {};
|
|
373
395
|
const recursion = (currModelName, prevModelName = undefined) => {
|
|
374
|
-
if (currModelName === prevModelName)
|
|
396
|
+
if (currModelName === prevModelName) {
|
|
375
397
|
throw new InvalidArgumentError(
|
|
376
398
|
'The model %v has a circular inheritance.',
|
|
377
399
|
currModelName,
|
|
378
400
|
);
|
|
379
|
-
|
|
401
|
+
}
|
|
402
|
+
if (Object.keys(pkPropDefs).length === 0) {
|
|
380
403
|
pkPropDefs =
|
|
381
404
|
this.getOwnPropertiesDefinitionOfPrimaryKeys(currModelName);
|
|
405
|
+
}
|
|
382
406
|
regularPropDefs = {
|
|
383
407
|
...this.getOwnPropertiesDefinitionWithoutPrimaryKeys(currModelName),
|
|
384
408
|
...regularPropDefs,
|
|
385
409
|
};
|
|
386
410
|
const modelDef =
|
|
387
411
|
this.getService(DefinitionRegistry).getModel(currModelName);
|
|
388
|
-
if (modelDef.base)
|
|
412
|
+
if (modelDef.base) {
|
|
413
|
+
recursion(modelDef.base, currModelName);
|
|
414
|
+
}
|
|
389
415
|
};
|
|
390
416
|
recursion(modelName);
|
|
391
417
|
return {...pkPropDefs, ...regularPropDefs};
|
|
@@ -411,16 +437,19 @@ export class ModelDefinitionUtils extends Service {
|
|
|
411
437
|
getRelationsDefinitionInBaseModelHierarchy(modelName) {
|
|
412
438
|
let result = {};
|
|
413
439
|
const recursion = (currModelName, prevModelName = undefined) => {
|
|
414
|
-
if (currModelName === prevModelName)
|
|
440
|
+
if (currModelName === prevModelName) {
|
|
415
441
|
throw new InvalidArgumentError(
|
|
416
442
|
'The model %v has a circular inheritance.',
|
|
417
443
|
currModelName,
|
|
418
444
|
);
|
|
445
|
+
}
|
|
419
446
|
const modelDef =
|
|
420
447
|
this.getService(DefinitionRegistry).getModel(currModelName);
|
|
421
448
|
const ownRelDefs = modelDef.relations ?? {};
|
|
422
449
|
result = {...ownRelDefs, ...result};
|
|
423
|
-
if (modelDef.base)
|
|
450
|
+
if (modelDef.base) {
|
|
451
|
+
recursion(modelDef.base, currModelName);
|
|
452
|
+
}
|
|
424
453
|
};
|
|
425
454
|
recursion(modelName);
|
|
426
455
|
return result;
|
|
@@ -443,12 +472,13 @@ export class ModelDefinitionUtils extends Service {
|
|
|
443
472
|
break;
|
|
444
473
|
}
|
|
445
474
|
}
|
|
446
|
-
if (!foundDef)
|
|
475
|
+
if (!foundDef) {
|
|
447
476
|
throw new InvalidArgumentError(
|
|
448
477
|
'The model %v does not have relation name %v.',
|
|
449
478
|
modelName,
|
|
450
479
|
relationName,
|
|
451
480
|
);
|
|
481
|
+
}
|
|
452
482
|
return foundDef;
|
|
453
483
|
}
|
|
454
484
|
|
|
@@ -460,12 +490,17 @@ export class ModelDefinitionUtils extends Service {
|
|
|
460
490
|
* @returns {object}
|
|
461
491
|
*/
|
|
462
492
|
excludeObjectKeysByRelationNames(modelName, modelData) {
|
|
463
|
-
if (
|
|
493
|
+
if (
|
|
494
|
+
!modelData ||
|
|
495
|
+
typeof modelData !== 'object' ||
|
|
496
|
+
Array.isArray(modelData)
|
|
497
|
+
) {
|
|
464
498
|
throw new InvalidArgumentError(
|
|
465
499
|
'The second argument of ModelDefinitionUtils.excludeObjectKeysByRelationNames ' +
|
|
466
500
|
'should be an Object, but %v was given.',
|
|
467
501
|
modelData,
|
|
468
502
|
);
|
|
503
|
+
}
|
|
469
504
|
const relDefs = this.getRelationsDefinitionInBaseModelHierarchy(modelName);
|
|
470
505
|
const relNames = Object.keys(relDefs);
|
|
471
506
|
return excludeObjectKeys(modelData, relNames);
|
|
@@ -479,26 +514,30 @@ export class ModelDefinitionUtils extends Service {
|
|
|
479
514
|
* @returns {string|undefined}
|
|
480
515
|
*/
|
|
481
516
|
getModelNameOfPropertyValueIfDefined(modelName, propertyName) {
|
|
482
|
-
if (!modelName || typeof modelName !== 'string')
|
|
517
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
483
518
|
throw new InvalidArgumentError(
|
|
484
519
|
'Parameter "modelName" of ' +
|
|
485
520
|
'ModelDefinitionUtils.getModelNameOfPropertyValueIfDefined ' +
|
|
486
521
|
'requires a non-empty String, but %v was given.',
|
|
487
522
|
modelName,
|
|
488
523
|
);
|
|
489
|
-
|
|
524
|
+
}
|
|
525
|
+
if (!propertyName || typeof propertyName !== 'string') {
|
|
490
526
|
throw new InvalidArgumentError(
|
|
491
527
|
'Parameter "propertyName" of ' +
|
|
492
528
|
'ModelDefinitionUtils.getModelNameOfPropertyValueIfDefined ' +
|
|
493
529
|
'requires a non-empty String, but %v was given.',
|
|
494
530
|
propertyName,
|
|
495
531
|
);
|
|
532
|
+
}
|
|
496
533
|
// если определение свойства не найдено,
|
|
497
534
|
// то возвращаем undefined
|
|
498
535
|
const propDefs =
|
|
499
536
|
this.getPropertiesDefinitionInBaseModelHierarchy(modelName);
|
|
500
537
|
const propDef = propDefs[propertyName];
|
|
501
|
-
if (!propDef)
|
|
538
|
+
if (!propDef) {
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
502
541
|
// если определение свойства является
|
|
503
542
|
// объектом, то проверяем тип и возвращаем
|
|
504
543
|
// название модели
|
|
@@ -506,12 +545,15 @@ export class ModelDefinitionUtils extends Service {
|
|
|
506
545
|
// если тип свойства является объектом,
|
|
507
546
|
// то возвращаем значение опции "model",
|
|
508
547
|
// или undefined
|
|
509
|
-
if (propDef.type === DataType.OBJECT)
|
|
548
|
+
if (propDef.type === DataType.OBJECT) {
|
|
549
|
+
return propDef.model || undefined;
|
|
550
|
+
}
|
|
510
551
|
// если тип свойства является массивом,
|
|
511
552
|
// то возвращаем значение опции "itemModel",
|
|
512
553
|
// или undefined
|
|
513
|
-
if (propDef.type === DataType.ARRAY)
|
|
554
|
+
if (propDef.type === DataType.ARRAY) {
|
|
514
555
|
return propDef.itemModel || undefined;
|
|
556
|
+
}
|
|
515
557
|
}
|
|
516
558
|
// если определение свойства не является
|
|
517
559
|
// объектом, то возвращаем undefined
|
|
@@ -13,38 +13,43 @@ export class ModelDefinitionValidator extends Service {
|
|
|
13
13
|
* @param {object} modelDef
|
|
14
14
|
*/
|
|
15
15
|
validate(modelDef) {
|
|
16
|
-
if (!modelDef || typeof modelDef !== 'object' || Array.isArray(modelDef))
|
|
16
|
+
if (!modelDef || typeof modelDef !== 'object' || Array.isArray(modelDef)) {
|
|
17
17
|
throw new InvalidArgumentError(
|
|
18
18
|
'The model definition should be an Object, but %v was given.',
|
|
19
19
|
modelDef,
|
|
20
20
|
);
|
|
21
|
-
|
|
21
|
+
}
|
|
22
|
+
if (!modelDef.name || typeof modelDef.name !== 'string') {
|
|
22
23
|
throw new InvalidArgumentError(
|
|
23
24
|
'The model definition requires the option "name" ' +
|
|
24
25
|
'as a non-empty String, but %v was given.',
|
|
25
26
|
modelDef.name,
|
|
26
27
|
);
|
|
27
|
-
|
|
28
|
+
}
|
|
29
|
+
if (modelDef.datasource && typeof modelDef.datasource !== 'string') {
|
|
28
30
|
throw new InvalidArgumentError(
|
|
29
31
|
'The provided option "datasource" of the model %v ' +
|
|
30
32
|
'should be a String, but %v was given.',
|
|
31
33
|
modelDef.name,
|
|
32
34
|
modelDef.datasource,
|
|
33
35
|
);
|
|
34
|
-
|
|
36
|
+
}
|
|
37
|
+
if (modelDef.base && typeof modelDef.base !== 'string') {
|
|
35
38
|
throw new InvalidArgumentError(
|
|
36
39
|
'The provided option "base" of the model %v ' +
|
|
37
40
|
'should be a String, but %v was given.',
|
|
38
41
|
modelDef.name,
|
|
39
42
|
modelDef.base,
|
|
40
43
|
);
|
|
41
|
-
|
|
44
|
+
}
|
|
45
|
+
if (modelDef.tableName && typeof modelDef.tableName !== 'string') {
|
|
42
46
|
throw new InvalidArgumentError(
|
|
43
47
|
'The provided option "tableName" of the model %v ' +
|
|
44
48
|
'should be a String, but %v was given.',
|
|
45
49
|
modelDef.name,
|
|
46
50
|
modelDef.tableName,
|
|
47
51
|
);
|
|
52
|
+
}
|
|
48
53
|
if (modelDef.properties) {
|
|
49
54
|
if (
|
|
50
55
|
typeof modelDef.properties !== 'object' ||
|
|
@@ -20,7 +20,7 @@ export class PrimaryKeysDefinitionValidator extends Service {
|
|
|
20
20
|
if (propNames.length < 1) {
|
|
21
21
|
const isDefaultPrimaryKeyAlreadyInUse =
|
|
22
22
|
Object.keys(propDefs).includes(DEF_PK);
|
|
23
|
-
if (isDefaultPrimaryKeyAlreadyInUse)
|
|
23
|
+
if (isDefaultPrimaryKeyAlreadyInUse) {
|
|
24
24
|
throw new InvalidArgumentError(
|
|
25
25
|
'The property name %v of the model %v is defined as a regular property. ' +
|
|
26
26
|
'In this case, a primary key should be defined explicitly. ' +
|
|
@@ -28,15 +28,17 @@ export class PrimaryKeysDefinitionValidator extends Service {
|
|
|
28
28
|
DEF_PK,
|
|
29
29
|
modelName,
|
|
30
30
|
);
|
|
31
|
+
}
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
|
-
if (propNames.length > 1)
|
|
34
|
+
if (propNames.length > 1) {
|
|
34
35
|
throw new InvalidArgumentError(
|
|
35
36
|
'The model definition %v should not have ' +
|
|
36
37
|
'multiple primary keys, but %v keys given.',
|
|
37
38
|
modelName,
|
|
38
39
|
propNames.length,
|
|
39
40
|
);
|
|
41
|
+
}
|
|
40
42
|
const pkPropName = propNames[0];
|
|
41
43
|
const pkPropDef = propDefs[pkPropName];
|
|
42
44
|
if (
|
|
@@ -16,12 +16,13 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
16
16
|
* @param {object} propDefs
|
|
17
17
|
*/
|
|
18
18
|
validate(modelName, propDefs) {
|
|
19
|
-
if (!modelName || typeof modelName !== 'string')
|
|
19
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
20
20
|
throw new InvalidArgumentError(
|
|
21
21
|
'The first argument of PropertiesDefinitionValidator.validate ' +
|
|
22
22
|
'should be a non-empty String, but %v was given.',
|
|
23
23
|
modelName,
|
|
24
24
|
);
|
|
25
|
+
}
|
|
25
26
|
if (!propDefs || typeof propDefs !== 'object' || Array.isArray(propDefs)) {
|
|
26
27
|
throw new InvalidArgumentError(
|
|
27
28
|
'The provided option "properties" of the model %v ' +
|
|
@@ -49,20 +50,22 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
49
50
|
* @param {object} propDef
|
|
50
51
|
*/
|
|
51
52
|
_validateProperty(modelName, propName, propDef) {
|
|
52
|
-
if (!modelName || typeof modelName !== 'string')
|
|
53
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
53
54
|
throw new InvalidArgumentError(
|
|
54
55
|
'The first argument of PropertiesDefinitionValidator._validateProperty ' +
|
|
55
56
|
'should be a non-empty String, but %v was given.',
|
|
56
57
|
modelName,
|
|
57
58
|
);
|
|
58
|
-
|
|
59
|
+
}
|
|
60
|
+
if (!propName || typeof propName !== 'string') {
|
|
59
61
|
throw new InvalidArgumentError(
|
|
60
62
|
'The property name of the model %v should be ' +
|
|
61
63
|
'a non-empty String, but %v was given.',
|
|
62
64
|
modelName,
|
|
63
65
|
propName,
|
|
64
66
|
);
|
|
65
|
-
|
|
67
|
+
}
|
|
68
|
+
if (!propDef) {
|
|
66
69
|
throw new InvalidArgumentError(
|
|
67
70
|
'The property %v of the model %v should have ' +
|
|
68
71
|
'a property definition, but %v was given.',
|
|
@@ -70,8 +73,9 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
70
73
|
modelName,
|
|
71
74
|
propDef,
|
|
72
75
|
);
|
|
76
|
+
}
|
|
73
77
|
if (typeof propDef === 'string') {
|
|
74
|
-
if (!Object.values(Type).includes(propDef))
|
|
78
|
+
if (!Object.values(Type).includes(propDef)) {
|
|
75
79
|
throw new InvalidArgumentError(
|
|
76
80
|
'In case of a short property definition, the property %v ' +
|
|
77
81
|
'of the model %v should have one of data types: %l, but %v was given.',
|
|
@@ -80,6 +84,7 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
80
84
|
Object.values(Type),
|
|
81
85
|
propDef,
|
|
82
86
|
);
|
|
87
|
+
}
|
|
83
88
|
return;
|
|
84
89
|
}
|
|
85
90
|
if (!propDef || typeof propDef !== 'object' || Array.isArray(propDef)) {
|
|
@@ -91,7 +96,7 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
91
96
|
propDef,
|
|
92
97
|
);
|
|
93
98
|
}
|
|
94
|
-
if (!propDef.type || !Object.values(Type).includes(propDef.type))
|
|
99
|
+
if (!propDef.type || !Object.values(Type).includes(propDef.type)) {
|
|
95
100
|
throw new InvalidArgumentError(
|
|
96
101
|
'The property %v of the model %v requires the option "type" ' +
|
|
97
102
|
'to have one of data types: %l, but %v was given.',
|
|
@@ -100,6 +105,7 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
100
105
|
Object.values(Type),
|
|
101
106
|
propDef.type,
|
|
102
107
|
);
|
|
108
|
+
}
|
|
103
109
|
if (propDef.itemType && !Object.values(Type).includes(propDef.itemType)) {
|
|
104
110
|
throw new InvalidArgumentError(
|
|
105
111
|
'The provided option "itemType" of the property %v in the model %v ' +
|
|
@@ -119,7 +125,7 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
119
125
|
propDef.itemModel,
|
|
120
126
|
);
|
|
121
127
|
}
|
|
122
|
-
if (propDef.model && typeof propDef.model !== 'string')
|
|
128
|
+
if (propDef.model && typeof propDef.model !== 'string') {
|
|
123
129
|
throw new InvalidArgumentError(
|
|
124
130
|
'The provided option "model" of the property %v in the model %v ' +
|
|
125
131
|
'should be a String, but %v was given.',
|
|
@@ -127,7 +133,8 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
127
133
|
modelName,
|
|
128
134
|
propDef.model,
|
|
129
135
|
);
|
|
130
|
-
|
|
136
|
+
}
|
|
137
|
+
if (propDef.primaryKey && typeof propDef.primaryKey !== 'boolean') {
|
|
131
138
|
throw new InvalidArgumentError(
|
|
132
139
|
'The provided option "primaryKey" of the property %v in the model %v ' +
|
|
133
140
|
'should be a Boolean, but %v was given.',
|
|
@@ -135,7 +142,8 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
135
142
|
modelName,
|
|
136
143
|
propDef.primaryKey,
|
|
137
144
|
);
|
|
138
|
-
|
|
145
|
+
}
|
|
146
|
+
if (propDef.columnName && typeof propDef.columnName !== 'string') {
|
|
139
147
|
throw new InvalidArgumentError(
|
|
140
148
|
'The provided option "columnName" of the property %v in the model %v ' +
|
|
141
149
|
'should be a String, but %v was given.',
|
|
@@ -143,7 +151,8 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
143
151
|
modelName,
|
|
144
152
|
propDef.columnName,
|
|
145
153
|
);
|
|
146
|
-
|
|
154
|
+
}
|
|
155
|
+
if (propDef.columnType && typeof propDef.columnType !== 'string') {
|
|
147
156
|
throw new InvalidArgumentError(
|
|
148
157
|
'The provided option "columnType" of the property %v in the model %v ' +
|
|
149
158
|
'should be a String, but %v was given.',
|
|
@@ -151,7 +160,8 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
151
160
|
modelName,
|
|
152
161
|
propDef.columnType,
|
|
153
162
|
);
|
|
154
|
-
|
|
163
|
+
}
|
|
164
|
+
if (propDef.required && typeof propDef.required !== 'boolean') {
|
|
155
165
|
throw new InvalidArgumentError(
|
|
156
166
|
'The provided option "required" of the property %v in the model %v ' +
|
|
157
167
|
'should be a Boolean, but %v was given.',
|
|
@@ -159,28 +169,32 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
159
169
|
modelName,
|
|
160
170
|
propDef.required,
|
|
161
171
|
);
|
|
162
|
-
|
|
172
|
+
}
|
|
173
|
+
if (propDef.required && propDef.default !== undefined) {
|
|
163
174
|
throw new InvalidArgumentError(
|
|
164
175
|
'The property %v of the model %v is a required property, ' +
|
|
165
176
|
'so it should not have the option "default" to be provided.',
|
|
166
177
|
propName,
|
|
167
178
|
modelName,
|
|
168
179
|
);
|
|
169
|
-
|
|
180
|
+
}
|
|
181
|
+
if (propDef.primaryKey && propDef.required) {
|
|
170
182
|
throw new InvalidArgumentError(
|
|
171
183
|
'The property %v of the model %v is a primary key, ' +
|
|
172
184
|
'so it should not have the option "required" to be provided.',
|
|
173
185
|
propName,
|
|
174
186
|
modelName,
|
|
175
187
|
);
|
|
176
|
-
|
|
188
|
+
}
|
|
189
|
+
if (propDef.primaryKey && propDef.default !== undefined) {
|
|
177
190
|
throw new InvalidArgumentError(
|
|
178
191
|
'The property %v of the model %v is a primary key, ' +
|
|
179
192
|
'so it should not have the option "default" to be provided.',
|
|
180
193
|
propName,
|
|
181
194
|
modelName,
|
|
182
195
|
);
|
|
183
|
-
|
|
196
|
+
}
|
|
197
|
+
if (propDef.itemType && propDef.type !== Type.ARRAY) {
|
|
184
198
|
throw new InvalidArgumentError(
|
|
185
199
|
'The property %v of the model %v has a non-array type, ' +
|
|
186
200
|
'so it should not have the option "itemType" to be provided.',
|
|
@@ -188,7 +202,8 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
188
202
|
modelName,
|
|
189
203
|
propDef.type,
|
|
190
204
|
);
|
|
191
|
-
|
|
205
|
+
}
|
|
206
|
+
if (propDef.itemModel && propDef.type !== Type.ARRAY) {
|
|
192
207
|
throw new InvalidArgumentError(
|
|
193
208
|
'The option "itemModel" is not supported for %s property type, ' +
|
|
194
209
|
'so the property %v of the model %v should not have ' +
|
|
@@ -197,6 +212,7 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
197
212
|
propName,
|
|
198
213
|
modelName,
|
|
199
214
|
);
|
|
215
|
+
}
|
|
200
216
|
if (propDef.itemModel && propDef.itemType !== Type.OBJECT) {
|
|
201
217
|
if (propDef.itemType) {
|
|
202
218
|
throw new InvalidArgumentError(
|
|
@@ -217,7 +233,7 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
217
233
|
);
|
|
218
234
|
}
|
|
219
235
|
}
|
|
220
|
-
if (propDef.model && propDef.type !== Type.OBJECT)
|
|
236
|
+
if (propDef.model && propDef.type !== Type.OBJECT) {
|
|
221
237
|
throw new InvalidArgumentError(
|
|
222
238
|
'The option "model" is not supported for %s property type, ' +
|
|
223
239
|
'so the property %v of the model %v should not have ' +
|
|
@@ -226,6 +242,7 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
226
242
|
propName,
|
|
227
243
|
modelName,
|
|
228
244
|
);
|
|
245
|
+
}
|
|
229
246
|
if (propDef.unique) {
|
|
230
247
|
if (
|
|
231
248
|
typeof propDef.unique !== 'boolean' &&
|
|
@@ -241,12 +258,13 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
241
258
|
);
|
|
242
259
|
}
|
|
243
260
|
}
|
|
244
|
-
if (propDef.unique && propDef.primaryKey)
|
|
261
|
+
if (propDef.unique && propDef.primaryKey) {
|
|
245
262
|
throw new InvalidArgumentError(
|
|
246
263
|
'The property %v of the model %v is a primary key, ' +
|
|
247
264
|
'so it should not have the option "unique" to be provided.',
|
|
248
265
|
propName,
|
|
249
266
|
modelName,
|
|
250
267
|
);
|
|
268
|
+
}
|
|
251
269
|
}
|
|
252
270
|
}
|
|
@@ -25,30 +25,34 @@ export class PropertyUniquenessValidator extends Service {
|
|
|
25
25
|
modelData,
|
|
26
26
|
modelId = undefined,
|
|
27
27
|
) {
|
|
28
|
-
if (typeof countMethod !== 'function')
|
|
28
|
+
if (typeof countMethod !== 'function') {
|
|
29
29
|
throw new InvalidArgumentError(
|
|
30
30
|
'The parameter "countMethod" of the PropertyUniquenessValidator ' +
|
|
31
31
|
'must be a Function, but %v was given.',
|
|
32
32
|
countMethod,
|
|
33
33
|
);
|
|
34
|
-
|
|
34
|
+
}
|
|
35
|
+
if (!methodName || typeof methodName !== 'string') {
|
|
35
36
|
throw new InvalidArgumentError(
|
|
36
37
|
'The parameter "methodName" of the PropertyUniquenessValidator ' +
|
|
37
38
|
'must be a non-empty String, but %v was given.',
|
|
38
39
|
methodName,
|
|
39
40
|
);
|
|
40
|
-
|
|
41
|
+
}
|
|
42
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
41
43
|
throw new InvalidArgumentError(
|
|
42
44
|
'The parameter "modelName" of the PropertyUniquenessValidator ' +
|
|
43
45
|
'must be a non-empty String, but %v was given.',
|
|
44
46
|
modelName,
|
|
45
47
|
);
|
|
46
|
-
|
|
48
|
+
}
|
|
49
|
+
if (!isPlainObject(modelData)) {
|
|
47
50
|
throw new InvalidArgumentError(
|
|
48
51
|
'The data of the model %v should be an Object, but %v was given.',
|
|
49
52
|
modelName,
|
|
50
53
|
modelData,
|
|
51
54
|
);
|
|
55
|
+
}
|
|
52
56
|
const propDefs =
|
|
53
57
|
this.getService(
|
|
54
58
|
ModelDefinitionUtils,
|
|
@@ -87,7 +91,9 @@ export class PropertyUniquenessValidator extends Service {
|
|
|
87
91
|
// create
|
|
88
92
|
if (methodName === 'create') {
|
|
89
93
|
const count = await countMethod({[propName]: propValue});
|
|
90
|
-
if (count > 0)
|
|
94
|
+
if (count > 0) {
|
|
95
|
+
throw createError(propName, propValue);
|
|
96
|
+
}
|
|
91
97
|
}
|
|
92
98
|
// replaceById
|
|
93
99
|
else if (methodName === 'replaceById') {
|
|
@@ -95,7 +101,9 @@ export class PropertyUniquenessValidator extends Service {
|
|
|
95
101
|
[idProp]: {neq: modelId},
|
|
96
102
|
[propName]: propValue,
|
|
97
103
|
});
|
|
98
|
-
if (count > 0)
|
|
104
|
+
if (count > 0) {
|
|
105
|
+
throw createError(propName, propValue);
|
|
106
|
+
}
|
|
99
107
|
}
|
|
100
108
|
// replaceOrCreate
|
|
101
109
|
else if (methodName === 'replaceOrCreate') {
|
|
@@ -110,18 +118,24 @@ export class PropertyUniquenessValidator extends Service {
|
|
|
110
118
|
[idProp]: {neq: idFromData},
|
|
111
119
|
[propName]: propValue,
|
|
112
120
|
});
|
|
113
|
-
if (count > 0)
|
|
121
|
+
if (count > 0) {
|
|
122
|
+
throw createError(propName, propValue);
|
|
123
|
+
}
|
|
114
124
|
}
|
|
115
125
|
// create by replaceOrCreate
|
|
116
126
|
else {
|
|
117
127
|
const count = await countMethod({[propName]: propValue});
|
|
118
|
-
if (count > 0)
|
|
128
|
+
if (count > 0) {
|
|
129
|
+
throw createError(propName, propValue);
|
|
130
|
+
}
|
|
119
131
|
}
|
|
120
132
|
}
|
|
121
133
|
// patch
|
|
122
134
|
else if (methodName === 'patch') {
|
|
123
135
|
const count = await countMethod({[propName]: propValue});
|
|
124
|
-
if (count > 0)
|
|
136
|
+
if (count > 0) {
|
|
137
|
+
throw createError(propName, propValue);
|
|
138
|
+
}
|
|
125
139
|
}
|
|
126
140
|
// patchById
|
|
127
141
|
else if (methodName === 'patchById') {
|
|
@@ -129,7 +143,9 @@ export class PropertyUniquenessValidator extends Service {
|
|
|
129
143
|
[idProp]: {neq: modelId},
|
|
130
144
|
[propName]: propValue,
|
|
131
145
|
});
|
|
132
|
-
if (count > 0)
|
|
146
|
+
if (count > 0) {
|
|
147
|
+
throw createError(propName, propValue);
|
|
148
|
+
}
|
|
133
149
|
}
|
|
134
150
|
// unsupported method
|
|
135
151
|
else {
|