@e22m4u/js-repository 0.1.26 → 0.2.2
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/dist/cjs/index.cjs +70 -18
- package/package.json +11 -11
- package/src/adapter/adapter-loader.js +6 -1
- package/src/adapter/adapter.js +8 -1
- package/src/adapter/adapter.spec.js +6 -6
- package/src/definition/model/model-data-validator.js +7 -3
- package/src/definition/model/model-data-validator.spec.js +18 -3
- package/src/definition/model/model-definition-utils.js +75 -4
- package/src/definition/model/model-definition-utils.spec.js +368 -0
- package/src/definition/model/properties/properties-definition-validator.js +37 -15
- package/src/definition/model/properties/properties-definition-validator.spec.js +48 -19
- package/src/definition/model/properties/property-definition.d.ts +1 -0
package/dist/cjs/index.cjs
CHANGED
|
@@ -2348,8 +2348,19 @@ var init_model_definition_utils = __esm({
|
|
|
2348
2348
|
propNames.forEach((propName) => {
|
|
2349
2349
|
if (!(propName in convertedData)) return;
|
|
2350
2350
|
const colName = this.getColumnNameByPropertyName(modelName, propName);
|
|
2351
|
-
|
|
2352
|
-
const
|
|
2351
|
+
let propValue = convertedData[propName];
|
|
2352
|
+
const propDef = propDefs[propName];
|
|
2353
|
+
if (propValue !== null && typeof propValue === "object" && !Array.isArray(propValue) && propDef !== null && typeof propDef === "object" && propDef.type === DataType.OBJECT && propDef.model) {
|
|
2354
|
+
propValue = this.convertPropertyNamesToColumnNames(
|
|
2355
|
+
propDef.model,
|
|
2356
|
+
propValue
|
|
2357
|
+
);
|
|
2358
|
+
}
|
|
2359
|
+
if (Array.isArray(propValue) && propDef !== null && typeof propDef === "object" && propDef.type === DataType.ARRAY && propDef.itemModel) {
|
|
2360
|
+
propValue = propValue.map((el) => {
|
|
2361
|
+
return el !== null && typeof el === "object" && !Array.isArray(el) ? this.convertPropertyNamesToColumnNames(propDef.itemModel, el) : el;
|
|
2362
|
+
});
|
|
2363
|
+
}
|
|
2353
2364
|
delete convertedData[propName];
|
|
2354
2365
|
convertedData[colName] = propValue;
|
|
2355
2366
|
});
|
|
@@ -2368,8 +2379,20 @@ var init_model_definition_utils = __esm({
|
|
|
2368
2379
|
const convertedData = cloneDeep(tableData);
|
|
2369
2380
|
propNames.forEach((propName) => {
|
|
2370
2381
|
const colName = this.getColumnNameByPropertyName(modelName, propName);
|
|
2371
|
-
if (!(colName in convertedData)
|
|
2372
|
-
|
|
2382
|
+
if (!(colName in convertedData)) return;
|
|
2383
|
+
let colValue = convertedData[colName];
|
|
2384
|
+
const propDef = propDefs[propName];
|
|
2385
|
+
if (colValue !== null && typeof colValue === "object" && !Array.isArray(colValue) && propDef !== null && typeof propDef === "object" && propDef.type === DataType.OBJECT && propDef.model) {
|
|
2386
|
+
colValue = this.convertColumnNamesToPropertyNames(
|
|
2387
|
+
propDef.model,
|
|
2388
|
+
colValue
|
|
2389
|
+
);
|
|
2390
|
+
}
|
|
2391
|
+
if (Array.isArray(colValue) && propDef !== null && typeof propDef === "object" && propDef.type === DataType.ARRAY && propDef.itemModel) {
|
|
2392
|
+
colValue = colValue.map((el) => {
|
|
2393
|
+
return el !== null && typeof el === "object" && !Array.isArray(el) ? this.convertColumnNamesToPropertyNames(propDef.itemModel, el) : el;
|
|
2394
|
+
});
|
|
2395
|
+
}
|
|
2373
2396
|
delete convertedData[colName];
|
|
2374
2397
|
convertedData[propName] = colValue;
|
|
2375
2398
|
});
|
|
@@ -2838,6 +2861,14 @@ var init_properties_definition_validator = __esm({
|
|
|
2838
2861
|
propDef.itemType
|
|
2839
2862
|
);
|
|
2840
2863
|
}
|
|
2864
|
+
if (propDef.itemModel && typeof propDef.itemModel !== "string") {
|
|
2865
|
+
throw new InvalidArgumentError(
|
|
2866
|
+
'The provided option "itemModel" of the property %v in the model %v should be a String, but %v given.',
|
|
2867
|
+
propName,
|
|
2868
|
+
modelName,
|
|
2869
|
+
propDef.itemModel
|
|
2870
|
+
);
|
|
2871
|
+
}
|
|
2841
2872
|
if (propDef.model && typeof propDef.model !== "string")
|
|
2842
2873
|
throw new InvalidArgumentError(
|
|
2843
2874
|
'The provided option "model" of the property %v in the model %v should be a String, but %v given.',
|
|
@@ -2893,28 +2924,41 @@ var init_properties_definition_validator = __esm({
|
|
|
2893
2924
|
);
|
|
2894
2925
|
if (propDef.itemType && propDef.type !== DataType.ARRAY)
|
|
2895
2926
|
throw new InvalidArgumentError(
|
|
2896
|
-
'The property %v of the model %v has
|
|
2927
|
+
'The property %v of the model %v has a non-array type, so it should not have the option "itemType" to be provided.',
|
|
2897
2928
|
propName,
|
|
2898
2929
|
modelName,
|
|
2899
2930
|
propDef.type
|
|
2900
2931
|
);
|
|
2901
|
-
if (propDef.
|
|
2902
|
-
|
|
2932
|
+
if (propDef.itemModel && propDef.type !== DataType.ARRAY)
|
|
2933
|
+
throw new InvalidArgumentError(
|
|
2934
|
+
'The option "itemModel" is not supported for %s property type, so the property %v of the model %v should not have the option "itemModel" to be provided.',
|
|
2935
|
+
capitalize(propDef.type),
|
|
2936
|
+
propName,
|
|
2937
|
+
modelName
|
|
2938
|
+
);
|
|
2939
|
+
if (propDef.itemModel && propDef.itemType !== DataType.OBJECT) {
|
|
2940
|
+
if (propDef.itemType) {
|
|
2903
2941
|
throw new InvalidArgumentError(
|
|
2904
|
-
'The option "
|
|
2905
|
-
capitalize(propDef.type),
|
|
2942
|
+
'The provided option "itemModel" requires the option "itemType" to be explicitly set to Object, but the property %v of the model %v has specified item type as %s.',
|
|
2906
2943
|
propName,
|
|
2907
|
-
modelName
|
|
2944
|
+
modelName,
|
|
2945
|
+
capitalize(propDef.itemType)
|
|
2908
2946
|
);
|
|
2909
2947
|
} else {
|
|
2910
2948
|
throw new InvalidArgumentError(
|
|
2911
|
-
'The option "
|
|
2912
|
-
capitalize(propDef.itemType),
|
|
2949
|
+
'The provided option "itemModel" requires the option "itemType" to be explicitly set to Object, but the property %v of the model %v does not have specified item type.',
|
|
2913
2950
|
propName,
|
|
2914
2951
|
modelName
|
|
2915
2952
|
);
|
|
2916
2953
|
}
|
|
2917
2954
|
}
|
|
2955
|
+
if (propDef.model && propDef.type !== DataType.OBJECT)
|
|
2956
|
+
throw new InvalidArgumentError(
|
|
2957
|
+
'The option "model" is not supported for %s property type, so the property %v of the model %v should not have the option "model" to be provided.',
|
|
2958
|
+
capitalize(propDef.type),
|
|
2959
|
+
propName,
|
|
2960
|
+
modelName
|
|
2961
|
+
);
|
|
2918
2962
|
if (propDef.validate != null) {
|
|
2919
2963
|
const propertyValidatorRegistry = this.getService(
|
|
2920
2964
|
PropertyValidatorRegistry
|
|
@@ -3186,11 +3230,15 @@ var init_model_data_validator = __esm({
|
|
|
3186
3230
|
);
|
|
3187
3231
|
break;
|
|
3188
3232
|
// OBJECT
|
|
3189
|
-
case DataType.OBJECT:
|
|
3233
|
+
case DataType.OBJECT: {
|
|
3190
3234
|
if (!isPureObject(propValue)) throw createError("an Object");
|
|
3191
|
-
if (typeof propDef === "object"
|
|
3192
|
-
|
|
3235
|
+
if (typeof propDef === "object") {
|
|
3236
|
+
const modelOptionField = isArrayValue ? "itemModel" : "model";
|
|
3237
|
+
const modelOptionValue = propDef[modelOptionField];
|
|
3238
|
+
if (modelOptionValue) this.validate(modelOptionValue, propValue);
|
|
3239
|
+
}
|
|
3193
3240
|
break;
|
|
3241
|
+
}
|
|
3194
3242
|
}
|
|
3195
3243
|
}
|
|
3196
3244
|
/**
|
|
@@ -5321,7 +5369,7 @@ var init_decorator = __esm({
|
|
|
5321
5369
|
});
|
|
5322
5370
|
|
|
5323
5371
|
// src/adapter/adapter.js
|
|
5324
|
-
var import_js_service32, _Adapter, Adapter;
|
|
5372
|
+
var import_js_service32, ADAPTER_CLASS_NAME, _Adapter, Adapter;
|
|
5325
5373
|
var init_adapter = __esm({
|
|
5326
5374
|
"src/adapter/adapter.js"() {
|
|
5327
5375
|
"use strict";
|
|
@@ -5334,6 +5382,7 @@ var init_adapter = __esm({
|
|
|
5334
5382
|
init_decorator();
|
|
5335
5383
|
init_decorator();
|
|
5336
5384
|
init_decorator();
|
|
5385
|
+
ADAPTER_CLASS_NAME = "Adapter";
|
|
5337
5386
|
_Adapter = class _Adapter extends import_js_service32.Service {
|
|
5338
5387
|
/**
|
|
5339
5388
|
* Settings.
|
|
@@ -5526,7 +5575,7 @@ var init_adapter = __esm({
|
|
|
5526
5575
|
*
|
|
5527
5576
|
* @type {string}
|
|
5528
5577
|
*/
|
|
5529
|
-
__publicField(_Adapter, "
|
|
5578
|
+
__publicField(_Adapter, "kinds", [...import_js_service32.Service.kinds, ADAPTER_CLASS_NAME]);
|
|
5530
5579
|
Adapter = _Adapter;
|
|
5531
5580
|
}
|
|
5532
5581
|
});
|
|
@@ -5928,7 +5977,7 @@ function findAdapterCtorInModule(module2) {
|
|
|
5928
5977
|
let adapterCtor;
|
|
5929
5978
|
if (!module2 || typeof module2 !== "object" || Array.isArray(module2)) return;
|
|
5930
5979
|
for (const ctor of Object.values(module2)) {
|
|
5931
|
-
if (typeof ctor === "function" && ctor.
|
|
5980
|
+
if (typeof ctor === "function" && Array.isArray(ctor.kinds) && Adapter.kinds.includes(ADAPTER_CLASS_NAME)) {
|
|
5932
5981
|
adapterCtor = ctor;
|
|
5933
5982
|
break;
|
|
5934
5983
|
}
|
|
@@ -5941,6 +5990,7 @@ var init_adapter_loader = __esm({
|
|
|
5941
5990
|
"use strict";
|
|
5942
5991
|
init_adapter();
|
|
5943
5992
|
import_js_service33 = require("@e22m4u/js-service");
|
|
5993
|
+
init_adapter();
|
|
5944
5994
|
init_errors();
|
|
5945
5995
|
init_();
|
|
5946
5996
|
_AdapterLoader = class _AdapterLoader extends import_js_service33.Service {
|
|
@@ -6303,6 +6353,7 @@ var init_repository2 = __esm({
|
|
|
6303
6353
|
// src/index.js
|
|
6304
6354
|
var src_exports = {};
|
|
6305
6355
|
__export(src_exports, {
|
|
6356
|
+
ADAPTER_CLASS_NAME: () => ADAPTER_CLASS_NAME,
|
|
6306
6357
|
Adapter: () => Adapter,
|
|
6307
6358
|
AdapterLoader: () => AdapterLoader,
|
|
6308
6359
|
AdapterRegistry: () => AdapterRegistry,
|
|
@@ -6407,6 +6458,7 @@ init_definition();
|
|
|
6407
6458
|
init_repository2();
|
|
6408
6459
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6409
6460
|
0 && (module.exports = {
|
|
6461
|
+
ADAPTER_CLASS_NAME,
|
|
6410
6462
|
Adapter,
|
|
6411
6463
|
AdapterLoader,
|
|
6412
6464
|
AdapterRegistry,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e22m4u/js-repository",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Модуль для работы с базами данных для Node.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
@@ -40,32 +40,32 @@
|
|
|
40
40
|
"homepage": "https://github.com/e22m4u/js-repository",
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@e22m4u/js-format": "0.1.x",
|
|
43
|
-
"@e22m4u/js-service": "0.
|
|
43
|
+
"@e22m4u/js-service": "0.2.x"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@commitlint/cli": "~19.
|
|
47
|
-
"@commitlint/config-conventional": "~19.
|
|
46
|
+
"@commitlint/cli": "~19.6.0",
|
|
47
|
+
"@commitlint/config-conventional": "~19.6.0",
|
|
48
48
|
"@types/chai": "~5.0.1",
|
|
49
49
|
"@types/chai-as-promised": "~8.0.1",
|
|
50
50
|
"@types/chai-spies": "~1.0.6",
|
|
51
|
-
"@types/mocha": "~10.0.
|
|
51
|
+
"@types/mocha": "~10.0.10",
|
|
52
52
|
"c8": "~10.1.2",
|
|
53
53
|
"chai": "~5.1.2",
|
|
54
|
-
"chai-as-promised": "~8.0.
|
|
54
|
+
"chai-as-promised": "~8.0.1",
|
|
55
55
|
"chai-spies": "~1.1.0",
|
|
56
56
|
"chai-subset": "~1.6.0",
|
|
57
57
|
"esbuild": "~0.24.0",
|
|
58
|
-
"eslint": "~9.
|
|
58
|
+
"eslint": "~9.15.0",
|
|
59
59
|
"eslint-config-prettier": "~9.1.0",
|
|
60
60
|
"eslint-plugin-chai-expect": "~3.1.0",
|
|
61
|
-
"eslint-plugin-jsdoc": "~50.
|
|
61
|
+
"eslint-plugin-jsdoc": "~50.5.0",
|
|
62
62
|
"eslint-plugin-mocha": "~10.5.0",
|
|
63
|
-
"husky": "~9.1.
|
|
63
|
+
"husky": "~9.1.7",
|
|
64
64
|
"mocha": "~10.8.2",
|
|
65
65
|
"prettier": "~3.3.3",
|
|
66
|
-
"rimraf": "
|
|
66
|
+
"rimraf": "~6.0.1",
|
|
67
67
|
"tsx": "~4.19.2",
|
|
68
68
|
"typescript": "~5.6.3",
|
|
69
|
-
"typescript-eslint": "~8.
|
|
69
|
+
"typescript-eslint": "~8.15.0"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Adapter} from './adapter.js';
|
|
2
2
|
import {Service} from '@e22m4u/js-service';
|
|
3
|
+
import {ADAPTER_CLASS_NAME} from './adapter.js';
|
|
3
4
|
import {InvalidArgumentError} from '../errors/index.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -54,7 +55,11 @@ function findAdapterCtorInModule(module) {
|
|
|
54
55
|
let adapterCtor;
|
|
55
56
|
if (!module || typeof module !== 'object' || Array.isArray(module)) return;
|
|
56
57
|
for (const ctor of Object.values(module)) {
|
|
57
|
-
if (
|
|
58
|
+
if (
|
|
59
|
+
typeof ctor === 'function' &&
|
|
60
|
+
Array.isArray(ctor.kinds) &&
|
|
61
|
+
Adapter.kinds.includes(ADAPTER_CLASS_NAME)
|
|
62
|
+
) {
|
|
58
63
|
adapterCtor = ctor;
|
|
59
64
|
break;
|
|
60
65
|
}
|
package/src/adapter/adapter.js
CHANGED
|
@@ -10,6 +10,13 @@ import {FieldsFilteringDecorator} from './decorator/index.js';
|
|
|
10
10
|
import {DataTransformationDecorator} from './decorator/index.js';
|
|
11
11
|
import {PropertyUniquenessDecorator} from './decorator/index.js';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Adapter class name.
|
|
15
|
+
*
|
|
16
|
+
* @type {string}
|
|
17
|
+
*/
|
|
18
|
+
export const ADAPTER_CLASS_NAME = 'Adapter';
|
|
19
|
+
|
|
13
20
|
/**
|
|
14
21
|
* Adapter.
|
|
15
22
|
*/
|
|
@@ -19,7 +26,7 @@ export class Adapter extends Service {
|
|
|
19
26
|
*
|
|
20
27
|
* @type {string}
|
|
21
28
|
*/
|
|
22
|
-
static
|
|
29
|
+
static kinds = [...Service.kinds, ADAPTER_CLASS_NAME];
|
|
23
30
|
|
|
24
31
|
/**
|
|
25
32
|
* Settings.
|
|
@@ -3,6 +3,7 @@ import {chai} from '../chai.js';
|
|
|
3
3
|
import {Schema} from '../schema.js';
|
|
4
4
|
import {Adapter} from './adapter.js';
|
|
5
5
|
import {Service} from '@e22m4u/js-service';
|
|
6
|
+
import {ADAPTER_CLASS_NAME} from './adapter.js';
|
|
6
7
|
import {ServiceContainer} from '@e22m4u/js-service';
|
|
7
8
|
import {InclusionDecorator} from './decorator/index.js';
|
|
8
9
|
import {DefaultValuesDecorator} from './decorator/index.js';
|
|
@@ -15,12 +16,11 @@ import {PropertyUniquenessDecorator} from './decorator/index.js';
|
|
|
15
16
|
const sandbox = chai.spy.sandbox();
|
|
16
17
|
|
|
17
18
|
describe('Adapter', function () {
|
|
18
|
-
it('exposes static property "
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
expect(MyAdapter2.kind).to.be.eq(Adapter.name);
|
|
19
|
+
it('exposes static property "kinds"', function () {
|
|
20
|
+
const kinds = [...Service.kinds, ADAPTER_CLASS_NAME];
|
|
21
|
+
expect(Adapter.kinds).to.be.eql(kinds);
|
|
22
|
+
const MyAdapter = class extends Adapter {};
|
|
23
|
+
expect(MyAdapter.kinds).to.be.eql(kinds);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
describe('constructor', function () {
|
|
@@ -157,11 +157,15 @@ export class ModelDataValidator extends Service {
|
|
|
157
157
|
);
|
|
158
158
|
break;
|
|
159
159
|
// OBJECT
|
|
160
|
-
case DataType.OBJECT:
|
|
160
|
+
case DataType.OBJECT: {
|
|
161
161
|
if (!isPureObject(propValue)) throw createError('an Object');
|
|
162
|
-
if (typeof propDef === 'object'
|
|
163
|
-
|
|
162
|
+
if (typeof propDef === 'object') {
|
|
163
|
+
const modelOptionField = isArrayValue ? 'itemModel' : 'model';
|
|
164
|
+
const modelOptionValue = propDef[modelOptionField];
|
|
165
|
+
if (modelOptionValue) this.validate(modelOptionValue, propValue);
|
|
166
|
+
}
|
|
164
167
|
break;
|
|
168
|
+
}
|
|
165
169
|
}
|
|
166
170
|
}
|
|
167
171
|
|
|
@@ -1651,7 +1651,22 @@ describe('ModelDataValidator', function () {
|
|
|
1651
1651
|
);
|
|
1652
1652
|
});
|
|
1653
1653
|
|
|
1654
|
-
describe('the "
|
|
1654
|
+
describe('the "itemModel" option', function () {
|
|
1655
|
+
it('does not throw an error if the option "itemModel" is not specified in case of Object item type', function () {
|
|
1656
|
+
const S = new Schema();
|
|
1657
|
+
S.defineModel({
|
|
1658
|
+
name: 'model',
|
|
1659
|
+
properties: {
|
|
1660
|
+
foo: {
|
|
1661
|
+
type: DataType.ARRAY,
|
|
1662
|
+
itemType: DataType.OBJECT,
|
|
1663
|
+
},
|
|
1664
|
+
},
|
|
1665
|
+
});
|
|
1666
|
+
const value = {foo: [{a: 1}, {b: 2}]};
|
|
1667
|
+
S.getService(ModelDataValidator).validate('model', value);
|
|
1668
|
+
});
|
|
1669
|
+
|
|
1655
1670
|
it('throws an error when the given object element has an invalid model', function () {
|
|
1656
1671
|
const S = new Schema();
|
|
1657
1672
|
S.defineModel({
|
|
@@ -1667,7 +1682,7 @@ describe('ModelDataValidator', function () {
|
|
|
1667
1682
|
bar: {
|
|
1668
1683
|
type: DataType.ARRAY,
|
|
1669
1684
|
itemType: DataType.OBJECT,
|
|
1670
|
-
|
|
1685
|
+
itemModel: 'modelA',
|
|
1671
1686
|
},
|
|
1672
1687
|
},
|
|
1673
1688
|
});
|
|
@@ -1696,7 +1711,7 @@ describe('ModelDataValidator', function () {
|
|
|
1696
1711
|
bar: {
|
|
1697
1712
|
type: DataType.ARRAY,
|
|
1698
1713
|
itemType: DataType.OBJECT,
|
|
1699
|
-
|
|
1714
|
+
itemModel: 'modelA',
|
|
1700
1715
|
},
|
|
1701
1716
|
},
|
|
1702
1717
|
});
|
|
@@ -179,8 +179,43 @@ export class ModelDefinitionUtils extends Service {
|
|
|
179
179
|
propNames.forEach(propName => {
|
|
180
180
|
if (!(propName in convertedData)) return;
|
|
181
181
|
const colName = this.getColumnNameByPropertyName(modelName, propName);
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
let propValue = convertedData[propName];
|
|
183
|
+
// если значением является объект, то проверяем
|
|
184
|
+
// тип свойства и наличие модели для замены
|
|
185
|
+
// полей данного объекта
|
|
186
|
+
const propDef = propDefs[propName];
|
|
187
|
+
if (
|
|
188
|
+
propValue !== null &&
|
|
189
|
+
typeof propValue === 'object' &&
|
|
190
|
+
!Array.isArray(propValue) &&
|
|
191
|
+
propDef !== null &&
|
|
192
|
+
typeof propDef === 'object' &&
|
|
193
|
+
propDef.type === DataType.OBJECT &&
|
|
194
|
+
propDef.model
|
|
195
|
+
) {
|
|
196
|
+
propValue = this.convertPropertyNamesToColumnNames(
|
|
197
|
+
propDef.model,
|
|
198
|
+
propValue,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
// если значением является массив, то проверяем
|
|
202
|
+
// тип свойства и наличие модели элементов массива
|
|
203
|
+
// для замены полей каждого объекта
|
|
204
|
+
if (
|
|
205
|
+
Array.isArray(propValue) &&
|
|
206
|
+
propDef !== null &&
|
|
207
|
+
typeof propDef === 'object' &&
|
|
208
|
+
propDef.type === DataType.ARRAY &&
|
|
209
|
+
propDef.itemModel
|
|
210
|
+
) {
|
|
211
|
+
propValue = propValue.map(el => {
|
|
212
|
+
// если элементом массива является объект,
|
|
213
|
+
// то конвертируем поля согласно модели
|
|
214
|
+
return el !== null && typeof el === 'object' && !Array.isArray(el)
|
|
215
|
+
? this.convertPropertyNamesToColumnNames(propDef.itemModel, el)
|
|
216
|
+
: el;
|
|
217
|
+
});
|
|
218
|
+
}
|
|
184
219
|
delete convertedData[propName];
|
|
185
220
|
convertedData[colName] = propValue;
|
|
186
221
|
});
|
|
@@ -201,8 +236,44 @@ export class ModelDefinitionUtils extends Service {
|
|
|
201
236
|
const convertedData = cloneDeep(tableData);
|
|
202
237
|
propNames.forEach(propName => {
|
|
203
238
|
const colName = this.getColumnNameByPropertyName(modelName, propName);
|
|
204
|
-
if (!(colName in convertedData)
|
|
205
|
-
|
|
239
|
+
if (!(colName in convertedData)) return;
|
|
240
|
+
let colValue = convertedData[colName];
|
|
241
|
+
// если значением является объект, то проверяем
|
|
242
|
+
// тип свойства и наличие модели для замены
|
|
243
|
+
// полей данного объекта
|
|
244
|
+
const propDef = propDefs[propName];
|
|
245
|
+
if (
|
|
246
|
+
colValue !== null &&
|
|
247
|
+
typeof colValue === 'object' &&
|
|
248
|
+
!Array.isArray(colValue) &&
|
|
249
|
+
propDef !== null &&
|
|
250
|
+
typeof propDef === 'object' &&
|
|
251
|
+
propDef.type === DataType.OBJECT &&
|
|
252
|
+
propDef.model
|
|
253
|
+
) {
|
|
254
|
+
colValue = this.convertColumnNamesToPropertyNames(
|
|
255
|
+
propDef.model,
|
|
256
|
+
colValue,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
// если значением является массив, то проверяем
|
|
260
|
+
// тип свойства и наличие модели элементов массива
|
|
261
|
+
// для замены полей каждого объекта
|
|
262
|
+
if (
|
|
263
|
+
Array.isArray(colValue) &&
|
|
264
|
+
propDef !== null &&
|
|
265
|
+
typeof propDef === 'object' &&
|
|
266
|
+
propDef.type === DataType.ARRAY &&
|
|
267
|
+
propDef.itemModel
|
|
268
|
+
) {
|
|
269
|
+
colValue = colValue.map(el => {
|
|
270
|
+
// если элементом массива является объект,
|
|
271
|
+
// то конвертируем поля согласно модели
|
|
272
|
+
return el !== null && typeof el === 'object' && !Array.isArray(el)
|
|
273
|
+
? this.convertColumnNamesToPropertyNames(propDef.itemModel, el)
|
|
274
|
+
: el;
|
|
275
|
+
});
|
|
276
|
+
}
|
|
206
277
|
delete convertedData[colName];
|
|
207
278
|
convertedData[propName] = colValue;
|
|
208
279
|
});
|
|
@@ -690,6 +690,191 @@ describe('ModelDefinitionUtils', function () {
|
|
|
690
690
|
.convertPropertyNamesToColumnNames('modelB', {foo: 'string'});
|
|
691
691
|
expect(result).to.be.eql({fooColumn: 'string'});
|
|
692
692
|
});
|
|
693
|
+
|
|
694
|
+
describe('embedded object with model', function () {
|
|
695
|
+
it('does nothing if no property definitions', function () {
|
|
696
|
+
const schema = new Schema();
|
|
697
|
+
schema.defineModel({
|
|
698
|
+
name: 'modelA',
|
|
699
|
+
properties: {
|
|
700
|
+
embedded: {
|
|
701
|
+
type: DataType.OBJECT,
|
|
702
|
+
model: 'modelB',
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
});
|
|
706
|
+
schema.defineModel({
|
|
707
|
+
name: 'modelB',
|
|
708
|
+
});
|
|
709
|
+
const result = schema
|
|
710
|
+
.getService(ModelDefinitionUtils)
|
|
711
|
+
.convertPropertyNamesToColumnNames('modelA', {
|
|
712
|
+
embedded: {foo: 'string'},
|
|
713
|
+
});
|
|
714
|
+
expect(result).to.be.eql({embedded: {foo: 'string'}});
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
it('does nothing if no column name specified', function () {
|
|
718
|
+
const schema = new Schema();
|
|
719
|
+
schema.defineModel({
|
|
720
|
+
name: 'modelA',
|
|
721
|
+
properties: {
|
|
722
|
+
embedded: {
|
|
723
|
+
type: DataType.OBJECT,
|
|
724
|
+
model: 'modelB',
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
});
|
|
728
|
+
schema.defineModel({
|
|
729
|
+
name: 'modelB',
|
|
730
|
+
properties: {
|
|
731
|
+
foo: DataType.STRING,
|
|
732
|
+
bar: DataType.NUMBER,
|
|
733
|
+
},
|
|
734
|
+
});
|
|
735
|
+
const result = schema
|
|
736
|
+
.getService(ModelDefinitionUtils)
|
|
737
|
+
.convertPropertyNamesToColumnNames('modelA', {
|
|
738
|
+
embedded: {foo: 'string', bar: 10},
|
|
739
|
+
});
|
|
740
|
+
expect(result).to.be.eql({embedded: {foo: 'string', bar: 10}});
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
it('replaces property names by column names', function () {
|
|
744
|
+
const schema = new Schema();
|
|
745
|
+
schema.defineModel({
|
|
746
|
+
name: 'modelA',
|
|
747
|
+
properties: {
|
|
748
|
+
embedded: {
|
|
749
|
+
type: DataType.OBJECT,
|
|
750
|
+
model: 'modelB',
|
|
751
|
+
},
|
|
752
|
+
},
|
|
753
|
+
});
|
|
754
|
+
schema.defineModel({
|
|
755
|
+
name: 'modelB',
|
|
756
|
+
properties: {
|
|
757
|
+
foo: {
|
|
758
|
+
type: DataType.STRING,
|
|
759
|
+
columnName: 'fooColumn',
|
|
760
|
+
},
|
|
761
|
+
bar: {
|
|
762
|
+
type: DataType.NUMBER,
|
|
763
|
+
columnName: 'barColumn',
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
});
|
|
767
|
+
const result = schema
|
|
768
|
+
.getService(ModelDefinitionUtils)
|
|
769
|
+
.convertPropertyNamesToColumnNames('modelA', {
|
|
770
|
+
embedded: {foo: 'string', bar: 10},
|
|
771
|
+
});
|
|
772
|
+
expect(result).to.be.eql({
|
|
773
|
+
embedded: {fooColumn: 'string', barColumn: 10},
|
|
774
|
+
});
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
describe('embedded array with items model', function () {
|
|
779
|
+
it('does nothing if no property definitions', function () {
|
|
780
|
+
const schema = new Schema();
|
|
781
|
+
schema.defineModel({
|
|
782
|
+
name: 'modelA',
|
|
783
|
+
properties: {
|
|
784
|
+
embedded: {
|
|
785
|
+
type: DataType.ARRAY,
|
|
786
|
+
itemType: DataType.OBJECT,
|
|
787
|
+
itemModel: 'modelB',
|
|
788
|
+
},
|
|
789
|
+
},
|
|
790
|
+
});
|
|
791
|
+
schema.defineModel({
|
|
792
|
+
name: 'modelB',
|
|
793
|
+
});
|
|
794
|
+
const result = schema
|
|
795
|
+
.getService(ModelDefinitionUtils)
|
|
796
|
+
.convertPropertyNamesToColumnNames('modelA', {
|
|
797
|
+
embedded: [{foo: 'val'}, {bar: 10}],
|
|
798
|
+
});
|
|
799
|
+
expect(result).to.be.eql({embedded: [{foo: 'val'}, {bar: 10}]});
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
it('does nothing if no column name specified', function () {
|
|
803
|
+
const schema = new Schema();
|
|
804
|
+
schema.defineModel({
|
|
805
|
+
name: 'modelA',
|
|
806
|
+
properties: {
|
|
807
|
+
embedded: {
|
|
808
|
+
type: DataType.ARRAY,
|
|
809
|
+
itemType: DataType.OBJECT,
|
|
810
|
+
itemModel: 'modelB',
|
|
811
|
+
},
|
|
812
|
+
},
|
|
813
|
+
});
|
|
814
|
+
schema.defineModel({
|
|
815
|
+
name: 'modelB',
|
|
816
|
+
properties: {
|
|
817
|
+
foo: DataType.STRING,
|
|
818
|
+
bar: DataType.NUMBER,
|
|
819
|
+
},
|
|
820
|
+
});
|
|
821
|
+
const result = schema
|
|
822
|
+
.getService(ModelDefinitionUtils)
|
|
823
|
+
.convertPropertyNamesToColumnNames('modelA', {
|
|
824
|
+
embedded: [
|
|
825
|
+
{foo: 'val1', bar: 10},
|
|
826
|
+
{foo: 'val2', bar: 20},
|
|
827
|
+
],
|
|
828
|
+
});
|
|
829
|
+
expect(result).to.be.eql({
|
|
830
|
+
embedded: [
|
|
831
|
+
{foo: 'val1', bar: 10},
|
|
832
|
+
{foo: 'val2', bar: 20},
|
|
833
|
+
],
|
|
834
|
+
});
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
it('replaces property names by column names', function () {
|
|
838
|
+
const schema = new Schema();
|
|
839
|
+
schema.defineModel({
|
|
840
|
+
name: 'modelA',
|
|
841
|
+
properties: {
|
|
842
|
+
embedded: {
|
|
843
|
+
type: DataType.ARRAY,
|
|
844
|
+
itemType: DataType.OBJECT,
|
|
845
|
+
itemModel: 'modelB',
|
|
846
|
+
},
|
|
847
|
+
},
|
|
848
|
+
});
|
|
849
|
+
schema.defineModel({
|
|
850
|
+
name: 'modelB',
|
|
851
|
+
properties: {
|
|
852
|
+
foo: {
|
|
853
|
+
type: DataType.STRING,
|
|
854
|
+
columnName: 'fooColumn',
|
|
855
|
+
},
|
|
856
|
+
bar: {
|
|
857
|
+
type: DataType.NUMBER,
|
|
858
|
+
columnName: 'barColumn',
|
|
859
|
+
},
|
|
860
|
+
},
|
|
861
|
+
});
|
|
862
|
+
const result = schema
|
|
863
|
+
.getService(ModelDefinitionUtils)
|
|
864
|
+
.convertPropertyNamesToColumnNames('modelA', {
|
|
865
|
+
embedded: [
|
|
866
|
+
{foo: 'val1', bar: 10},
|
|
867
|
+
{foo: 'val2', bar: 20},
|
|
868
|
+
],
|
|
869
|
+
});
|
|
870
|
+
expect(result).to.be.eql({
|
|
871
|
+
embedded: [
|
|
872
|
+
{fooColumn: 'val1', barColumn: 10},
|
|
873
|
+
{fooColumn: 'val2', barColumn: 20},
|
|
874
|
+
],
|
|
875
|
+
});
|
|
876
|
+
});
|
|
877
|
+
});
|
|
693
878
|
});
|
|
694
879
|
|
|
695
880
|
describe('convertColumnNamesToPropertyNames', function () {
|
|
@@ -764,6 +949,189 @@ describe('ModelDefinitionUtils', function () {
|
|
|
764
949
|
.convertColumnNamesToPropertyNames('modelA', {fooColumn: 'string'});
|
|
765
950
|
expect(result).to.be.eql({foo: 'string'});
|
|
766
951
|
});
|
|
952
|
+
|
|
953
|
+
describe('embedded object with model', function () {
|
|
954
|
+
it('does nothing if no property definitions', function () {
|
|
955
|
+
const schema = new Schema();
|
|
956
|
+
schema.defineModel({
|
|
957
|
+
name: 'modelA',
|
|
958
|
+
properties: {
|
|
959
|
+
embedded: {
|
|
960
|
+
type: DataType.OBJECT,
|
|
961
|
+
model: 'modelB',
|
|
962
|
+
},
|
|
963
|
+
},
|
|
964
|
+
});
|
|
965
|
+
schema.defineModel({
|
|
966
|
+
name: 'modelB',
|
|
967
|
+
});
|
|
968
|
+
const result = schema
|
|
969
|
+
.getService(ModelDefinitionUtils)
|
|
970
|
+
.convertColumnNamesToPropertyNames('modelA', {
|
|
971
|
+
embedded: {foo: 'string'},
|
|
972
|
+
});
|
|
973
|
+
expect(result).to.be.eql({embedded: {foo: 'string'}});
|
|
974
|
+
});
|
|
975
|
+
|
|
976
|
+
it('does nothing if no column name specified', function () {
|
|
977
|
+
const schema = new Schema();
|
|
978
|
+
schema.defineModel({
|
|
979
|
+
name: 'modelA',
|
|
980
|
+
properties: {
|
|
981
|
+
embedded: {
|
|
982
|
+
type: DataType.OBJECT,
|
|
983
|
+
model: 'modelB',
|
|
984
|
+
},
|
|
985
|
+
},
|
|
986
|
+
});
|
|
987
|
+
schema.defineModel({
|
|
988
|
+
name: 'modelB',
|
|
989
|
+
properties: {
|
|
990
|
+
foo: DataType.STRING,
|
|
991
|
+
bar: DataType.NUMBER,
|
|
992
|
+
},
|
|
993
|
+
});
|
|
994
|
+
const result = schema
|
|
995
|
+
.getService(ModelDefinitionUtils)
|
|
996
|
+
.convertColumnNamesToPropertyNames('modelA', {
|
|
997
|
+
embedded: {foo: 'string', bar: 10},
|
|
998
|
+
});
|
|
999
|
+
expect(result).to.be.eql({embedded: {foo: 'string', bar: 10}});
|
|
1000
|
+
});
|
|
1001
|
+
|
|
1002
|
+
it('replaces property names by column names', function () {
|
|
1003
|
+
const schema = new Schema();
|
|
1004
|
+
schema.defineModel({
|
|
1005
|
+
name: 'modelA',
|
|
1006
|
+
properties: {
|
|
1007
|
+
embedded: {
|
|
1008
|
+
type: DataType.OBJECT,
|
|
1009
|
+
model: 'modelB',
|
|
1010
|
+
},
|
|
1011
|
+
},
|
|
1012
|
+
});
|
|
1013
|
+
schema.defineModel({
|
|
1014
|
+
name: 'modelB',
|
|
1015
|
+
properties: {
|
|
1016
|
+
foo: {
|
|
1017
|
+
type: DataType.STRING,
|
|
1018
|
+
columnName: 'fooColumn',
|
|
1019
|
+
},
|
|
1020
|
+
bar: {
|
|
1021
|
+
type: DataType.NUMBER,
|
|
1022
|
+
columnName: 'barColumn',
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
});
|
|
1026
|
+
const result = schema
|
|
1027
|
+
.getService(ModelDefinitionUtils)
|
|
1028
|
+
.convertColumnNamesToPropertyNames('modelA', {
|
|
1029
|
+
embedded: {fooColumn: 'string', barColumn: 10},
|
|
1030
|
+
});
|
|
1031
|
+
expect(result).to.be.eql({embedded: {foo: 'string', bar: 10}});
|
|
1032
|
+
});
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
describe('embedded array with items model', function () {
|
|
1036
|
+
it('does nothing if no property definitions', function () {
|
|
1037
|
+
const schema = new Schema();
|
|
1038
|
+
schema.defineModel({
|
|
1039
|
+
name: 'modelA',
|
|
1040
|
+
properties: {
|
|
1041
|
+
embedded: {
|
|
1042
|
+
type: DataType.ARRAY,
|
|
1043
|
+
itemType: DataType.OBJECT,
|
|
1044
|
+
itemModel: 'modelB',
|
|
1045
|
+
},
|
|
1046
|
+
},
|
|
1047
|
+
});
|
|
1048
|
+
schema.defineModel({
|
|
1049
|
+
name: 'modelB',
|
|
1050
|
+
});
|
|
1051
|
+
const result = schema
|
|
1052
|
+
.getService(ModelDefinitionUtils)
|
|
1053
|
+
.convertColumnNamesToPropertyNames('modelA', {
|
|
1054
|
+
embedded: [{foo: 'val'}, {bar: 10}],
|
|
1055
|
+
});
|
|
1056
|
+
expect(result).to.be.eql({embedded: [{foo: 'val'}, {bar: 10}]});
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1059
|
+
it('does nothing if no column name specified', function () {
|
|
1060
|
+
const schema = new Schema();
|
|
1061
|
+
schema.defineModel({
|
|
1062
|
+
name: 'modelA',
|
|
1063
|
+
properties: {
|
|
1064
|
+
embedded: {
|
|
1065
|
+
type: DataType.ARRAY,
|
|
1066
|
+
itemType: DataType.OBJECT,
|
|
1067
|
+
itemModel: 'modelB',
|
|
1068
|
+
},
|
|
1069
|
+
},
|
|
1070
|
+
});
|
|
1071
|
+
schema.defineModel({
|
|
1072
|
+
name: 'modelB',
|
|
1073
|
+
properties: {
|
|
1074
|
+
foo: DataType.STRING,
|
|
1075
|
+
bar: DataType.NUMBER,
|
|
1076
|
+
},
|
|
1077
|
+
});
|
|
1078
|
+
const result = schema
|
|
1079
|
+
.getService(ModelDefinitionUtils)
|
|
1080
|
+
.convertColumnNamesToPropertyNames('modelA', {
|
|
1081
|
+
embedded: [
|
|
1082
|
+
{foo: 'val1', bar: 10},
|
|
1083
|
+
{foo: 'val2', bar: 20},
|
|
1084
|
+
],
|
|
1085
|
+
});
|
|
1086
|
+
expect(result).to.be.eql({
|
|
1087
|
+
embedded: [
|
|
1088
|
+
{foo: 'val1', bar: 10},
|
|
1089
|
+
{foo: 'val2', bar: 20},
|
|
1090
|
+
],
|
|
1091
|
+
});
|
|
1092
|
+
});
|
|
1093
|
+
|
|
1094
|
+
it('replaces property names by column names', function () {
|
|
1095
|
+
const schema = new Schema();
|
|
1096
|
+
schema.defineModel({
|
|
1097
|
+
name: 'modelA',
|
|
1098
|
+
properties: {
|
|
1099
|
+
embedded: {
|
|
1100
|
+
type: DataType.ARRAY,
|
|
1101
|
+
itemType: DataType.OBJECT,
|
|
1102
|
+
itemModel: 'modelB',
|
|
1103
|
+
},
|
|
1104
|
+
},
|
|
1105
|
+
});
|
|
1106
|
+
schema.defineModel({
|
|
1107
|
+
name: 'modelB',
|
|
1108
|
+
properties: {
|
|
1109
|
+
foo: {
|
|
1110
|
+
type: DataType.STRING,
|
|
1111
|
+
columnName: 'fooColumn',
|
|
1112
|
+
},
|
|
1113
|
+
bar: {
|
|
1114
|
+
type: DataType.NUMBER,
|
|
1115
|
+
columnName: 'barColumn',
|
|
1116
|
+
},
|
|
1117
|
+
},
|
|
1118
|
+
});
|
|
1119
|
+
const result = schema
|
|
1120
|
+
.getService(ModelDefinitionUtils)
|
|
1121
|
+
.convertColumnNamesToPropertyNames('modelA', {
|
|
1122
|
+
embedded: [
|
|
1123
|
+
{fooColumn: 'val1', barColumn: 10},
|
|
1124
|
+
{fooColumn: 'val2', barColumn: 20},
|
|
1125
|
+
],
|
|
1126
|
+
});
|
|
1127
|
+
expect(result).to.be.eql({
|
|
1128
|
+
embedded: [
|
|
1129
|
+
{foo: 'val1', bar: 10},
|
|
1130
|
+
{foo: 'val2', bar: 20},
|
|
1131
|
+
],
|
|
1132
|
+
});
|
|
1133
|
+
});
|
|
1134
|
+
});
|
|
767
1135
|
});
|
|
768
1136
|
|
|
769
1137
|
describe('getDataTypeByPropertyName', function () {
|
|
@@ -112,6 +112,15 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
112
112
|
propDef.itemType,
|
|
113
113
|
);
|
|
114
114
|
}
|
|
115
|
+
if (propDef.itemModel && typeof propDef.itemModel !== 'string') {
|
|
116
|
+
throw new InvalidArgumentError(
|
|
117
|
+
'The provided option "itemModel" of the property %v in the model %v ' +
|
|
118
|
+
'should be a String, but %v given.',
|
|
119
|
+
propName,
|
|
120
|
+
modelName,
|
|
121
|
+
propDef.itemModel,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
115
124
|
if (propDef.model && typeof propDef.model !== 'string')
|
|
116
125
|
throw new InvalidArgumentError(
|
|
117
126
|
'The provided option "model" of the property %v in the model %v ' +
|
|
@@ -175,37 +184,50 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
175
184
|
);
|
|
176
185
|
if (propDef.itemType && propDef.type !== Type.ARRAY)
|
|
177
186
|
throw new InvalidArgumentError(
|
|
178
|
-
'The property %v of the model %v has
|
|
187
|
+
'The property %v of the model %v has a non-array type, ' +
|
|
179
188
|
'so it should not have the option "itemType" to be provided.',
|
|
180
189
|
propName,
|
|
181
190
|
modelName,
|
|
182
191
|
propDef.type,
|
|
183
192
|
);
|
|
184
|
-
if (
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
193
|
+
if (propDef.itemModel && propDef.type !== Type.ARRAY)
|
|
194
|
+
throw new InvalidArgumentError(
|
|
195
|
+
'The option "itemModel" is not supported for %s property type, ' +
|
|
196
|
+
'so the property %v of the model %v should not have ' +
|
|
197
|
+
'the option "itemModel" to be provided.',
|
|
198
|
+
capitalize(propDef.type),
|
|
199
|
+
propName,
|
|
200
|
+
modelName,
|
|
201
|
+
);
|
|
202
|
+
if (propDef.itemModel && propDef.itemType !== Type.OBJECT) {
|
|
203
|
+
if (propDef.itemType) {
|
|
190
204
|
throw new InvalidArgumentError(
|
|
191
|
-
'The option "
|
|
192
|
-
'
|
|
193
|
-
'the
|
|
194
|
-
capitalize(propDef.type),
|
|
205
|
+
'The provided option "itemModel" requires the option "itemType" ' +
|
|
206
|
+
'to be explicitly set to Object, but the property %v of ' +
|
|
207
|
+
'the model %v has specified item type as %s.',
|
|
195
208
|
propName,
|
|
196
209
|
modelName,
|
|
210
|
+
capitalize(propDef.itemType),
|
|
197
211
|
);
|
|
198
212
|
} else {
|
|
199
213
|
throw new InvalidArgumentError(
|
|
200
|
-
'The option "
|
|
201
|
-
'
|
|
202
|
-
'the
|
|
203
|
-
capitalize(propDef.itemType),
|
|
214
|
+
'The provided option "itemModel" requires the option "itemType" ' +
|
|
215
|
+
'to be explicitly set to Object, but the property %v of ' +
|
|
216
|
+
'the model %v does not have specified item type.',
|
|
204
217
|
propName,
|
|
205
218
|
modelName,
|
|
206
219
|
);
|
|
207
220
|
}
|
|
208
221
|
}
|
|
222
|
+
if (propDef.model && propDef.type !== Type.OBJECT)
|
|
223
|
+
throw new InvalidArgumentError(
|
|
224
|
+
'The option "model" is not supported for %s property type, ' +
|
|
225
|
+
'so the property %v of the model %v should not have ' +
|
|
226
|
+
'the option "model" to be provided.',
|
|
227
|
+
capitalize(propDef.type),
|
|
228
|
+
propName,
|
|
229
|
+
modelName,
|
|
230
|
+
);
|
|
209
231
|
if (propDef.validate != null) {
|
|
210
232
|
const propertyValidatorRegistry = this.getService(
|
|
211
233
|
PropertyValidatorRegistry,
|
|
@@ -133,7 +133,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
133
133
|
validate(DataType.STRING)();
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
-
it('expects provided
|
|
136
|
+
it('expects the provided option "itemType" to be a DataType', function () {
|
|
137
137
|
const validate = v => {
|
|
138
138
|
const foo = {type: DataType.ARRAY, itemType: v};
|
|
139
139
|
return () => S.validate('model', {foo});
|
|
@@ -153,7 +153,29 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
153
153
|
validate(DataType.STRING)();
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
-
it('expects provided
|
|
156
|
+
it('expects the provided option "itemModel" to be a string', function () {
|
|
157
|
+
const validate = v => {
|
|
158
|
+
const foo = {
|
|
159
|
+
type: DataType.ARRAY,
|
|
160
|
+
itemType: DataType.OBJECT,
|
|
161
|
+
itemModel: v,
|
|
162
|
+
};
|
|
163
|
+
return () => S.validate('model', {foo});
|
|
164
|
+
};
|
|
165
|
+
const error = v =>
|
|
166
|
+
format(
|
|
167
|
+
'The provided option "itemModel" of the property "foo" ' +
|
|
168
|
+
'in the model "model" should be a String, but %s given.',
|
|
169
|
+
v,
|
|
170
|
+
);
|
|
171
|
+
expect(validate(10)).to.throw(error('10'));
|
|
172
|
+
expect(validate(true)).to.throw(error('true'));
|
|
173
|
+
expect(validate([])).to.throw(error('Array'));
|
|
174
|
+
expect(validate({})).to.throw(error('Object'));
|
|
175
|
+
validate('model')();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('expects the provided option "model" to be a string', function () {
|
|
157
179
|
const validate = v => {
|
|
158
180
|
const foo = {
|
|
159
181
|
type: DataType.OBJECT,
|
|
@@ -174,7 +196,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
174
196
|
validate('model')();
|
|
175
197
|
});
|
|
176
198
|
|
|
177
|
-
it('expects provided
|
|
199
|
+
it('expects the provided option "primaryKey" to be a boolean', function () {
|
|
178
200
|
const validate = v => {
|
|
179
201
|
const foo = {
|
|
180
202
|
type: DataType.STRING,
|
|
@@ -195,7 +217,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
195
217
|
validate(false)();
|
|
196
218
|
});
|
|
197
219
|
|
|
198
|
-
it('expects provided
|
|
220
|
+
it('expects the provided option "columnName" to be a string', function () {
|
|
199
221
|
const validate = v => {
|
|
200
222
|
const foo = {
|
|
201
223
|
type: DataType.STRING,
|
|
@@ -216,7 +238,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
216
238
|
validate('columnName')();
|
|
217
239
|
});
|
|
218
240
|
|
|
219
|
-
it('expects provided
|
|
241
|
+
it('expects the provided option "columnType" to be a string', function () {
|
|
220
242
|
const validate = v => {
|
|
221
243
|
const foo = {
|
|
222
244
|
type: DataType.STRING,
|
|
@@ -237,7 +259,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
237
259
|
validate('columnType')();
|
|
238
260
|
});
|
|
239
261
|
|
|
240
|
-
it('expects provided
|
|
262
|
+
it('expects the provided option "required" to be a boolean', function () {
|
|
241
263
|
const validate = v => {
|
|
242
264
|
const foo = {
|
|
243
265
|
type: DataType.STRING,
|
|
@@ -332,7 +354,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
332
354
|
S.validate('model', {foo});
|
|
333
355
|
};
|
|
334
356
|
const error =
|
|
335
|
-
'The property "foo" of the model "model" has
|
|
357
|
+
'The property "foo" of the model "model" has a non-array type, ' +
|
|
336
358
|
'so it should not have the option "itemType" to be provided.';
|
|
337
359
|
expect(validate(DataType.ANY)).to.throw(error);
|
|
338
360
|
expect(validate(DataType.STRING)).to.throw(error);
|
|
@@ -364,27 +386,34 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
364
386
|
validate(DataType.OBJECT)();
|
|
365
387
|
});
|
|
366
388
|
|
|
367
|
-
it('the option "
|
|
389
|
+
it('the option "itemModel" requires the "object" item type', function () {
|
|
368
390
|
const validate = v => () => {
|
|
369
391
|
const foo = {
|
|
370
392
|
type: DataType.ARRAY,
|
|
371
393
|
itemType: v,
|
|
372
|
-
|
|
394
|
+
itemModel: 'model',
|
|
373
395
|
};
|
|
374
396
|
S.validate('model', {foo});
|
|
375
397
|
};
|
|
376
|
-
const
|
|
398
|
+
const errorForNonEmpty = v =>
|
|
377
399
|
format(
|
|
378
|
-
'The option "
|
|
379
|
-
'
|
|
380
|
-
'the
|
|
400
|
+
'The provided option "itemModel" requires the option "itemType" ' +
|
|
401
|
+
'to be explicitly set to Object, but the property "foo" of ' +
|
|
402
|
+
'the model "model" has specified item type as %s.',
|
|
381
403
|
v,
|
|
382
404
|
);
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
405
|
+
const errorForEmpty = format(
|
|
406
|
+
'The provided option "itemModel" requires the option "itemType" ' +
|
|
407
|
+
'to be explicitly set to Object, but the property "foo" of ' +
|
|
408
|
+
'the model "model" does not have specified item type.',
|
|
409
|
+
);
|
|
410
|
+
expect(validate(DataType.ANY)).to.throw(errorForNonEmpty('Any'));
|
|
411
|
+
expect(validate(DataType.STRING)).to.throw(errorForNonEmpty('String'));
|
|
412
|
+
expect(validate(DataType.NUMBER)).to.throw(errorForNonEmpty('Number'));
|
|
413
|
+
expect(validate(DataType.BOOLEAN)).to.throw(errorForNonEmpty('Boolean'));
|
|
414
|
+
expect(validate(DataType.ARRAY)).to.throw(errorForNonEmpty('Array'));
|
|
415
|
+
expect(validate(undefined)).to.throw(errorForEmpty);
|
|
416
|
+
expect(validate(null)).to.throw(errorForEmpty);
|
|
388
417
|
validate(DataType.OBJECT)();
|
|
389
418
|
});
|
|
390
419
|
|
|
@@ -491,7 +520,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
491
520
|
validate({myTransformer: true})();
|
|
492
521
|
});
|
|
493
522
|
|
|
494
|
-
it('expects provided
|
|
523
|
+
it('expects the provided option "unique" to be a Boolean or the PropertyUniqueness', function () {
|
|
495
524
|
const validate = v => {
|
|
496
525
|
const foo = {
|
|
497
526
|
type: DataType.STRING,
|