@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
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {Service} from '@e22m4u/js-service';
|
|
2
2
|
import {DataType} from './properties/index.js';
|
|
3
|
-
import {BlankValuesService} from '@e22m4u/js-empty-values';
|
|
4
3
|
import {InvalidArgumentError} from '../../errors/index.js';
|
|
5
4
|
import {DefinitionRegistry} from '../definition-registry.js';
|
|
6
5
|
import {cloneDeep, excludeObjectKeys} from '../../utils/index.js';
|
|
@@ -33,7 +32,7 @@ export class ModelDefinitionUtils extends Service {
|
|
|
33
32
|
const isDefaultPrimaryKeyAlreadyInUse = Object.keys(propDefs).includes(
|
|
34
33
|
DEFAULT_PRIMARY_KEY_PROPERTY_NAME,
|
|
35
34
|
);
|
|
36
|
-
if (isDefaultPrimaryKeyAlreadyInUse)
|
|
35
|
+
if (isDefaultPrimaryKeyAlreadyInUse) {
|
|
37
36
|
throw new InvalidArgumentError(
|
|
38
37
|
'The property name %v of the model %v is defined as a regular property. ' +
|
|
39
38
|
'In this case, a primary key should be defined explicitly. ' +
|
|
@@ -41,6 +40,7 @@ export class ModelDefinitionUtils extends Service {
|
|
|
41
40
|
DEFAULT_PRIMARY_KEY_PROPERTY_NAME,
|
|
42
41
|
modelName,
|
|
43
42
|
);
|
|
43
|
+
}
|
|
44
44
|
return DEFAULT_PRIMARY_KEY_PROPERTY_NAME;
|
|
45
45
|
}
|
|
46
46
|
return propNames[0];
|
|
@@ -58,9 +58,13 @@ export class ModelDefinitionUtils extends Service {
|
|
|
58
58
|
try {
|
|
59
59
|
pkColName = this.getColumnNameByPropertyName(modelName, pkPropName);
|
|
60
60
|
} catch (error) {
|
|
61
|
-
if (!(error instanceof InvalidArgumentError))
|
|
61
|
+
if (!(error instanceof InvalidArgumentError)) {
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (pkColName === undefined) {
|
|
66
|
+
return pkPropName;
|
|
62
67
|
}
|
|
63
|
-
if (pkColName === undefined) return pkPropName;
|
|
64
68
|
return pkColName;
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -86,14 +90,16 @@ export class ModelDefinitionUtils extends Service {
|
|
|
86
90
|
const propDefs =
|
|
87
91
|
this.getPropertiesDefinitionInBaseModelHierarchy(modelName);
|
|
88
92
|
const propDef = propDefs[propertyName];
|
|
89
|
-
if (!propDef)
|
|
93
|
+
if (!propDef) {
|
|
90
94
|
throw new InvalidArgumentError(
|
|
91
95
|
'The model %v does not have the property %v.',
|
|
92
96
|
modelName,
|
|
93
97
|
propertyName,
|
|
94
98
|
);
|
|
95
|
-
|
|
99
|
+
}
|
|
100
|
+
if (propDef && typeof propDef === 'object') {
|
|
96
101
|
return propDef.columnName ?? propertyName;
|
|
102
|
+
}
|
|
97
103
|
return propertyName;
|
|
98
104
|
}
|
|
99
105
|
|
|
@@ -108,20 +114,22 @@ export class ModelDefinitionUtils extends Service {
|
|
|
108
114
|
const propDefs =
|
|
109
115
|
this.getPropertiesDefinitionInBaseModelHierarchy(modelName);
|
|
110
116
|
const propDef = propDefs[propertyName];
|
|
111
|
-
if (!propDef)
|
|
117
|
+
if (!propDef) {
|
|
112
118
|
throw new InvalidArgumentError(
|
|
113
119
|
'The model %v does not have the property %v.',
|
|
114
120
|
modelName,
|
|
115
121
|
propertyName,
|
|
116
122
|
);
|
|
117
|
-
|
|
123
|
+
}
|
|
124
|
+
if (propDef && typeof propDef === 'object') {
|
|
118
125
|
return propDef.default instanceof Function
|
|
119
126
|
? propDef.default()
|
|
120
127
|
: propDef.default;
|
|
128
|
+
}
|
|
121
129
|
}
|
|
122
130
|
|
|
123
131
|
/**
|
|
124
|
-
* Set default values
|
|
132
|
+
* Set default values to empty properties.
|
|
125
133
|
*
|
|
126
134
|
* @param {string} modelName
|
|
127
135
|
* @param {object} modelData
|
|
@@ -139,16 +147,14 @@ export class ModelDefinitionUtils extends Service {
|
|
|
139
147
|
? Object.keys(modelData)
|
|
140
148
|
: Object.keys(propDefs);
|
|
141
149
|
const extendedData = cloneDeep(modelData);
|
|
142
|
-
const blankValuesService = this.getService(BlankValuesService);
|
|
143
150
|
propNames.forEach(propName => {
|
|
144
151
|
const propDef = propDefs[propName];
|
|
145
152
|
const propValue = extendedData[propName];
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (!isBlank) return;
|
|
153
|
+
// если значение свойства не является undefined и null,
|
|
154
|
+
// то свойство пропускается (остается исходное значение)
|
|
155
|
+
if (propValue != null) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
152
158
|
if (
|
|
153
159
|
propDef &&
|
|
154
160
|
typeof propDef === 'object' &&
|
|
@@ -176,7 +182,9 @@ export class ModelDefinitionUtils extends Service {
|
|
|
176
182
|
const propNames = Object.keys(propDefs);
|
|
177
183
|
const convertedData = cloneDeep(modelData);
|
|
178
184
|
propNames.forEach(propName => {
|
|
179
|
-
if (!(propName in convertedData))
|
|
185
|
+
if (!(propName in convertedData)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
180
188
|
const colName = this.getColumnNameByPropertyName(modelName, propName);
|
|
181
189
|
let propValue = convertedData[propName];
|
|
182
190
|
// если значением является объект, то проверяем
|
|
@@ -235,7 +243,9 @@ export class ModelDefinitionUtils extends Service {
|
|
|
235
243
|
const convertedData = cloneDeep(tableData);
|
|
236
244
|
propNames.forEach(propName => {
|
|
237
245
|
const colName = this.getColumnNameByPropertyName(modelName, propName);
|
|
238
|
-
if (!(colName in convertedData))
|
|
246
|
+
if (!(colName in convertedData)) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
239
249
|
let colValue = convertedData[colName];
|
|
240
250
|
// если значением является объект, то проверяем
|
|
241
251
|
// тип свойства и наличие модели для замены
|
|
@@ -292,14 +302,18 @@ export class ModelDefinitionUtils extends Service {
|
|
|
292
302
|
const propDef = propDefs[propertyName];
|
|
293
303
|
if (!propDef) {
|
|
294
304
|
const pkPropName = this.getPrimaryKeyAsPropertyName(modelName);
|
|
295
|
-
if (pkPropName === propertyName)
|
|
305
|
+
if (pkPropName === propertyName) {
|
|
306
|
+
return DataType.ANY;
|
|
307
|
+
}
|
|
296
308
|
throw new InvalidArgumentError(
|
|
297
309
|
'The model %v does not have the property %v.',
|
|
298
310
|
modelName,
|
|
299
311
|
propertyName,
|
|
300
312
|
);
|
|
301
313
|
}
|
|
302
|
-
if (typeof propDef === 'string')
|
|
314
|
+
if (typeof propDef === 'string') {
|
|
315
|
+
return propDef;
|
|
316
|
+
}
|
|
303
317
|
return propDef.type;
|
|
304
318
|
}
|
|
305
319
|
|
|
@@ -320,15 +334,18 @@ export class ModelDefinitionUtils extends Service {
|
|
|
320
334
|
propDef,
|
|
321
335
|
);
|
|
322
336
|
}
|
|
323
|
-
if (typeof propDef === 'string')
|
|
337
|
+
if (typeof propDef === 'string') {
|
|
338
|
+
return propDef;
|
|
339
|
+
}
|
|
324
340
|
const dataType = propDef.type;
|
|
325
|
-
if (!Object.values(DataType).includes(dataType))
|
|
341
|
+
if (!Object.values(DataType).includes(dataType)) {
|
|
326
342
|
throw new InvalidArgumentError(
|
|
327
343
|
'The given Object to the ModelDefinitionUtils.getDataTypeFromPropertyDefinition ' +
|
|
328
344
|
'should have the "type" property with one of values: %l, but %v was given.',
|
|
329
345
|
Object.values(DataType),
|
|
330
346
|
propDef.type,
|
|
331
347
|
);
|
|
348
|
+
}
|
|
332
349
|
return dataType;
|
|
333
350
|
}
|
|
334
351
|
|
|
@@ -359,7 +376,9 @@ export class ModelDefinitionUtils extends Service {
|
|
|
359
376
|
const propDefs = modelDef.properties ?? {};
|
|
360
377
|
return Object.keys(propDefs).reduce((result, propName) => {
|
|
361
378
|
const propDef = propDefs[propName];
|
|
362
|
-
if (typeof propDef === 'object' && propDef.primaryKey)
|
|
379
|
+
if (typeof propDef === 'object' && propDef.primaryKey) {
|
|
380
|
+
return result;
|
|
381
|
+
}
|
|
363
382
|
return {...result, [propName]: propDef};
|
|
364
383
|
}, {});
|
|
365
384
|
}
|
|
@@ -374,21 +393,25 @@ export class ModelDefinitionUtils extends Service {
|
|
|
374
393
|
let pkPropDefs = {};
|
|
375
394
|
let regularPropDefs = {};
|
|
376
395
|
const recursion = (currModelName, prevModelName = undefined) => {
|
|
377
|
-
if (currModelName === prevModelName)
|
|
396
|
+
if (currModelName === prevModelName) {
|
|
378
397
|
throw new InvalidArgumentError(
|
|
379
398
|
'The model %v has a circular inheritance.',
|
|
380
399
|
currModelName,
|
|
381
400
|
);
|
|
382
|
-
|
|
401
|
+
}
|
|
402
|
+
if (Object.keys(pkPropDefs).length === 0) {
|
|
383
403
|
pkPropDefs =
|
|
384
404
|
this.getOwnPropertiesDefinitionOfPrimaryKeys(currModelName);
|
|
405
|
+
}
|
|
385
406
|
regularPropDefs = {
|
|
386
407
|
...this.getOwnPropertiesDefinitionWithoutPrimaryKeys(currModelName),
|
|
387
408
|
...regularPropDefs,
|
|
388
409
|
};
|
|
389
410
|
const modelDef =
|
|
390
411
|
this.getService(DefinitionRegistry).getModel(currModelName);
|
|
391
|
-
if (modelDef.base)
|
|
412
|
+
if (modelDef.base) {
|
|
413
|
+
recursion(modelDef.base, currModelName);
|
|
414
|
+
}
|
|
392
415
|
};
|
|
393
416
|
recursion(modelName);
|
|
394
417
|
return {...pkPropDefs, ...regularPropDefs};
|
|
@@ -414,16 +437,19 @@ export class ModelDefinitionUtils extends Service {
|
|
|
414
437
|
getRelationsDefinitionInBaseModelHierarchy(modelName) {
|
|
415
438
|
let result = {};
|
|
416
439
|
const recursion = (currModelName, prevModelName = undefined) => {
|
|
417
|
-
if (currModelName === prevModelName)
|
|
440
|
+
if (currModelName === prevModelName) {
|
|
418
441
|
throw new InvalidArgumentError(
|
|
419
442
|
'The model %v has a circular inheritance.',
|
|
420
443
|
currModelName,
|
|
421
444
|
);
|
|
445
|
+
}
|
|
422
446
|
const modelDef =
|
|
423
447
|
this.getService(DefinitionRegistry).getModel(currModelName);
|
|
424
448
|
const ownRelDefs = modelDef.relations ?? {};
|
|
425
449
|
result = {...ownRelDefs, ...result};
|
|
426
|
-
if (modelDef.base)
|
|
450
|
+
if (modelDef.base) {
|
|
451
|
+
recursion(modelDef.base, currModelName);
|
|
452
|
+
}
|
|
427
453
|
};
|
|
428
454
|
recursion(modelName);
|
|
429
455
|
return result;
|
|
@@ -446,12 +472,13 @@ export class ModelDefinitionUtils extends Service {
|
|
|
446
472
|
break;
|
|
447
473
|
}
|
|
448
474
|
}
|
|
449
|
-
if (!foundDef)
|
|
475
|
+
if (!foundDef) {
|
|
450
476
|
throw new InvalidArgumentError(
|
|
451
477
|
'The model %v does not have relation name %v.',
|
|
452
478
|
modelName,
|
|
453
479
|
relationName,
|
|
454
480
|
);
|
|
481
|
+
}
|
|
455
482
|
return foundDef;
|
|
456
483
|
}
|
|
457
484
|
|
|
@@ -463,12 +490,17 @@ export class ModelDefinitionUtils extends Service {
|
|
|
463
490
|
* @returns {object}
|
|
464
491
|
*/
|
|
465
492
|
excludeObjectKeysByRelationNames(modelName, modelData) {
|
|
466
|
-
if (
|
|
493
|
+
if (
|
|
494
|
+
!modelData ||
|
|
495
|
+
typeof modelData !== 'object' ||
|
|
496
|
+
Array.isArray(modelData)
|
|
497
|
+
) {
|
|
467
498
|
throw new InvalidArgumentError(
|
|
468
499
|
'The second argument of ModelDefinitionUtils.excludeObjectKeysByRelationNames ' +
|
|
469
500
|
'should be an Object, but %v was given.',
|
|
470
501
|
modelData,
|
|
471
502
|
);
|
|
503
|
+
}
|
|
472
504
|
const relDefs = this.getRelationsDefinitionInBaseModelHierarchy(modelName);
|
|
473
505
|
const relNames = Object.keys(relDefs);
|
|
474
506
|
return excludeObjectKeys(modelData, relNames);
|
|
@@ -482,26 +514,30 @@ export class ModelDefinitionUtils extends Service {
|
|
|
482
514
|
* @returns {string|undefined}
|
|
483
515
|
*/
|
|
484
516
|
getModelNameOfPropertyValueIfDefined(modelName, propertyName) {
|
|
485
|
-
if (!modelName || typeof modelName !== 'string')
|
|
517
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
486
518
|
throw new InvalidArgumentError(
|
|
487
519
|
'Parameter "modelName" of ' +
|
|
488
520
|
'ModelDefinitionUtils.getModelNameOfPropertyValueIfDefined ' +
|
|
489
521
|
'requires a non-empty String, but %v was given.',
|
|
490
522
|
modelName,
|
|
491
523
|
);
|
|
492
|
-
|
|
524
|
+
}
|
|
525
|
+
if (!propertyName || typeof propertyName !== 'string') {
|
|
493
526
|
throw new InvalidArgumentError(
|
|
494
527
|
'Parameter "propertyName" of ' +
|
|
495
528
|
'ModelDefinitionUtils.getModelNameOfPropertyValueIfDefined ' +
|
|
496
529
|
'requires a non-empty String, but %v was given.',
|
|
497
530
|
propertyName,
|
|
498
531
|
);
|
|
532
|
+
}
|
|
499
533
|
// если определение свойства не найдено,
|
|
500
534
|
// то возвращаем undefined
|
|
501
535
|
const propDefs =
|
|
502
536
|
this.getPropertiesDefinitionInBaseModelHierarchy(modelName);
|
|
503
537
|
const propDef = propDefs[propertyName];
|
|
504
|
-
if (!propDef)
|
|
538
|
+
if (!propDef) {
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
505
541
|
// если определение свойства является
|
|
506
542
|
// объектом, то проверяем тип и возвращаем
|
|
507
543
|
// название модели
|
|
@@ -509,12 +545,15 @@ export class ModelDefinitionUtils extends Service {
|
|
|
509
545
|
// если тип свойства является объектом,
|
|
510
546
|
// то возвращаем значение опции "model",
|
|
511
547
|
// или undefined
|
|
512
|
-
if (propDef.type === DataType.OBJECT)
|
|
548
|
+
if (propDef.type === DataType.OBJECT) {
|
|
549
|
+
return propDef.model || undefined;
|
|
550
|
+
}
|
|
513
551
|
// если тип свойства является массивом,
|
|
514
552
|
// то возвращаем значение опции "itemModel",
|
|
515
553
|
// или undefined
|
|
516
|
-
if (propDef.type === DataType.ARRAY)
|
|
554
|
+
if (propDef.type === DataType.ARRAY) {
|
|
517
555
|
return propDef.itemModel || undefined;
|
|
556
|
+
}
|
|
518
557
|
}
|
|
519
558
|
// если определение свойства не является
|
|
520
559
|
// объектом, то возвращаем undefined
|
|
@@ -4,7 +4,6 @@ import {createSandbox} from '@e22m4u/js-spy';
|
|
|
4
4
|
import {DataType} from './properties/index.js';
|
|
5
5
|
import {RelationType} from './relations/index.js';
|
|
6
6
|
import {DatabaseSchema} from '../../database-schema.js';
|
|
7
|
-
import {BlankValuesService} from '@e22m4u/js-empty-values';
|
|
8
7
|
import {InvalidArgumentError} from '../../errors/index.js';
|
|
9
8
|
|
|
10
9
|
import {
|
|
@@ -480,7 +479,7 @@ describe('ModelDefinitionUtils', function () {
|
|
|
480
479
|
expect(result).to.be.eql({foo: 'string'});
|
|
481
480
|
});
|
|
482
481
|
|
|
483
|
-
it('sets a default value if a property
|
|
482
|
+
it('sets a default value if a property value is undefined', function () {
|
|
484
483
|
const dbs = new DatabaseSchema();
|
|
485
484
|
dbs.defineModel({
|
|
486
485
|
name: 'model',
|
|
@@ -491,12 +490,9 @@ describe('ModelDefinitionUtils', function () {
|
|
|
491
490
|
},
|
|
492
491
|
},
|
|
493
492
|
});
|
|
494
|
-
dbs
|
|
495
|
-
.getService(BlankValuesService)
|
|
496
|
-
.setBlankValuesOf(DataType.STRING, ['blank']);
|
|
497
493
|
const result = dbs
|
|
498
494
|
.getService(ModelDefinitionUtils)
|
|
499
|
-
.setDefaultValuesToEmptyProperties('model', {foo:
|
|
495
|
+
.setDefaultValuesToEmptyProperties('model', {foo: undefined});
|
|
500
496
|
expect(result).to.be.eql({foo: 'placeholder'});
|
|
501
497
|
});
|
|
502
498
|
|
|
@@ -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
|
}
|