@e22m4u/js-repository 0.1.7 → 0.1.9
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 +6 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/PropertyUniquenessValidator.html +16 -0
- package/docs/index.html +5 -1
- package/docs/modules.html +2 -0
- package/docs/types/CountMethod.html +2 -0
- package/docs/types/FullPropertyDefinition.html +2 -2
- package/docs/types/PropertyDefinition.html +1 -1
- package/package.json +4 -4
- package/src/adapter/adapter.js +2 -0
- package/src/adapter/adapter.spec.js +8 -2
- package/src/adapter/decorator/index.d.ts +1 -0
- package/src/adapter/decorator/index.js +1 -0
- package/src/adapter/decorator/property-uniqueness-decorator.d.ts +14 -0
- package/src/adapter/decorator/property-uniqueness-decorator.js +76 -0
- package/src/adapter/decorator/property-uniqueness-decorator.spec.js +135 -0
- package/src/definition/definition-registry.spec.js +1 -0
- package/src/definition/model/properties/index.d.ts +1 -0
- package/src/definition/model/properties/index.js +1 -0
- package/src/definition/model/properties/properties-definition-validator.js +15 -0
- package/src/definition/model/properties/properties-definition-validator.spec.js +46 -5
- package/src/definition/model/properties/property-definition.d.ts +3 -0
- package/src/definition/model/properties/property-transformer/builtin/index.d.ts +3 -0
- package/src/definition/model/properties/property-transformer/builtin/index.js +3 -0
- package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.d.ts +6 -0
- package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.js +19 -0
- package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.spec.js +39 -0
- package/src/definition/model/properties/property-transformer/builtin/to-title-case-transformer.d.ts +6 -0
- package/src/definition/model/properties/property-transformer/builtin/to-title-case-transformer.js +22 -0
- package/src/definition/model/properties/property-transformer/builtin/to-title-case-transformer.spec.js +41 -0
- package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.d.ts +6 -0
- package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.js +19 -0
- package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.spec.js +39 -0
- package/src/definition/model/properties/property-transformer/property-transformer-registry.js +6 -0
- package/src/definition/model/properties/property-transformer/property-transformer-registry.spec.js +6 -0
- package/src/definition/model/properties/property-uniqueness-validator.d.ts +31 -0
- package/src/definition/model/properties/property-uniqueness-validator.js +131 -0
- package/src/definition/model/properties/property-uniqueness-validator.spec.js +943 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import chai from 'chai';
|
|
2
|
+
import {expect} from 'chai';
|
|
3
|
+
import {Adapter} from '../adapter.js';
|
|
4
|
+
import {Schema} from '../../schema.js';
|
|
5
|
+
import {PropertyUniquenessValidator} from '../../definition/index.js';
|
|
6
|
+
|
|
7
|
+
const S = new Schema();
|
|
8
|
+
S.defineModel({name: 'model'});
|
|
9
|
+
|
|
10
|
+
class TestAdapter extends Adapter {
|
|
11
|
+
// eslint-disable-next-line no-unused-vars
|
|
12
|
+
create(modelName, modelData, filter = undefined) {
|
|
13
|
+
return Promise.resolve(modelData);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// eslint-disable-next-line no-unused-vars
|
|
17
|
+
replaceById(modelName, id, modelData, filter = undefined) {
|
|
18
|
+
return Promise.resolve(modelData);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line no-unused-vars
|
|
22
|
+
replaceOrCreate(modelName, modelData, filter = undefined) {
|
|
23
|
+
return Promise.resolve(modelData);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// eslint-disable-next-line no-unused-vars
|
|
27
|
+
patch(modelName, modelData, where = undefined) {
|
|
28
|
+
return Promise.resolve(modelData);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// eslint-disable-next-line no-unused-vars
|
|
32
|
+
patchById(modelName, id, modelData, filter = undefined) {
|
|
33
|
+
return Promise.resolve(modelData);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const A = S.getService(TestAdapter);
|
|
38
|
+
const V = S.getService(PropertyUniquenessValidator);
|
|
39
|
+
const sandbox = chai.spy.sandbox();
|
|
40
|
+
|
|
41
|
+
describe('PropertyUniquenessDecorator', function () {
|
|
42
|
+
afterEach(function () {
|
|
43
|
+
sandbox.restore();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('overrides the "create" method and validates a given data', async function () {
|
|
47
|
+
const data = {kind: 'data'};
|
|
48
|
+
sandbox.on(
|
|
49
|
+
V,
|
|
50
|
+
'validate',
|
|
51
|
+
(countMethod, methodName, modelName, modelData, id = undefined) => {
|
|
52
|
+
expect(typeof countMethod).to.be.eq('function');
|
|
53
|
+
expect(methodName).to.be.eq('create');
|
|
54
|
+
expect(modelName).to.be.eq('model');
|
|
55
|
+
expect(modelData).to.be.eql(data);
|
|
56
|
+
expect(id).to.be.undefined;
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
const res = await A.create('model', data);
|
|
60
|
+
expect(res).to.be.eql(data);
|
|
61
|
+
expect(V.validate).to.be.called.once;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('overrides the "replaceById" method and validates a given data', async function () {
|
|
65
|
+
const data = {kind: 'data'};
|
|
66
|
+
sandbox.on(
|
|
67
|
+
V,
|
|
68
|
+
'validate',
|
|
69
|
+
(countMethod, methodName, modelName, modelData, id = undefined) => {
|
|
70
|
+
expect(typeof countMethod).to.be.eq('function');
|
|
71
|
+
expect(methodName).to.be.eq('replaceById');
|
|
72
|
+
expect(modelName).to.be.eq('model');
|
|
73
|
+
expect(modelData).to.be.eql(data);
|
|
74
|
+
expect(id).to.be.eq(1);
|
|
75
|
+
},
|
|
76
|
+
);
|
|
77
|
+
const res = await A.replaceById('model', 1, data);
|
|
78
|
+
expect(res).to.be.eql(data);
|
|
79
|
+
expect(V.validate).to.be.called.once;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('overrides the "replaceOrCreate" method and validates a given data', async function () {
|
|
83
|
+
const data = {kind: 'data'};
|
|
84
|
+
sandbox.on(
|
|
85
|
+
V,
|
|
86
|
+
'validate',
|
|
87
|
+
(countMethod, methodName, modelName, modelData, id = undefined) => {
|
|
88
|
+
expect(typeof countMethod).to.be.eq('function');
|
|
89
|
+
expect(methodName).to.be.eq('replaceOrCreate');
|
|
90
|
+
expect(modelName).to.be.eq('model');
|
|
91
|
+
expect(modelData).to.be.eql(data);
|
|
92
|
+
expect(id).to.be.undefined;
|
|
93
|
+
},
|
|
94
|
+
);
|
|
95
|
+
const res = await A.replaceOrCreate('model', data);
|
|
96
|
+
expect(res).to.be.eql(data);
|
|
97
|
+
expect(V.validate).to.be.called.once;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('overrides the "patch" method and validates a given data', async function () {
|
|
101
|
+
const data = {kind: 'data'};
|
|
102
|
+
sandbox.on(
|
|
103
|
+
V,
|
|
104
|
+
'validate',
|
|
105
|
+
(countMethod, methodName, modelName, modelData, id = undefined) => {
|
|
106
|
+
expect(typeof countMethod).to.be.eq('function');
|
|
107
|
+
expect(methodName).to.be.eq('patch');
|
|
108
|
+
expect(modelName).to.be.eq('model');
|
|
109
|
+
expect(modelData).to.be.eql(data);
|
|
110
|
+
expect(id).to.be.undefined;
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
const res = await A.patch('model', data);
|
|
114
|
+
expect(res).to.be.eql(data);
|
|
115
|
+
expect(V.validate).to.be.called.once;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('overrides the "patchById" method and validates a given data', async function () {
|
|
119
|
+
const data = {kind: 'data'};
|
|
120
|
+
sandbox.on(
|
|
121
|
+
V,
|
|
122
|
+
'validate',
|
|
123
|
+
(countMethod, methodName, modelName, modelData, id = undefined) => {
|
|
124
|
+
expect(typeof countMethod).to.be.eq('function');
|
|
125
|
+
expect(methodName).to.be.eq('patchById');
|
|
126
|
+
expect(modelName).to.be.eq('model');
|
|
127
|
+
expect(modelData).to.be.eql(data);
|
|
128
|
+
expect(id).to.be.eq(1);
|
|
129
|
+
},
|
|
130
|
+
);
|
|
131
|
+
const res = await A.patchById('model', 1, data);
|
|
132
|
+
expect(res).to.be.eql(data);
|
|
133
|
+
expect(V.validate).to.be.called.once;
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -2,5 +2,6 @@ export * from './data-type.js';
|
|
|
2
2
|
export * from './property-definition.js';
|
|
3
3
|
export * from './property-validator/index.js';
|
|
4
4
|
export * from './property-transformer/index.js';
|
|
5
|
+
export * from './property-uniqueness-validator.js';
|
|
5
6
|
export * from './properties-definition-validator.js';
|
|
6
7
|
export * from './primary-keys-definition-validator.js';
|
|
@@ -2,5 +2,6 @@ export * from './data-type.js';
|
|
|
2
2
|
export * from './property-definition.js';
|
|
3
3
|
export * from './property-validator/index.js';
|
|
4
4
|
export * from './property-transformer/index.js';
|
|
5
|
+
export * from './property-uniqueness-validator.js';
|
|
5
6
|
export * from './properties-definition-validator.js';
|
|
6
7
|
export * from './primary-keys-definition-validator.js';
|
|
@@ -297,5 +297,20 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
297
297
|
);
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
|
+
if (propDef.unique && typeof propDef.unique !== 'boolean')
|
|
301
|
+
throw new InvalidArgumentError(
|
|
302
|
+
'The provided option "unique" of the property %v in the model %v ' +
|
|
303
|
+
'should be a Boolean, but %v given.',
|
|
304
|
+
propName,
|
|
305
|
+
modelName,
|
|
306
|
+
propDef.unique,
|
|
307
|
+
);
|
|
308
|
+
if (propDef.unique && propDef.primaryKey)
|
|
309
|
+
throw new InvalidArgumentError(
|
|
310
|
+
'The property %v of the model %v is a primary key, ' +
|
|
311
|
+
'so it should not have the option "unique" to be provided.',
|
|
312
|
+
propName,
|
|
313
|
+
modelName,
|
|
314
|
+
);
|
|
300
315
|
}
|
|
301
316
|
}
|
|
@@ -250,6 +250,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
250
250
|
'should be a Boolean, but %s given.',
|
|
251
251
|
v,
|
|
252
252
|
);
|
|
253
|
+
expect(validate('str')).to.throw(error('"str"'));
|
|
253
254
|
expect(validate(10)).to.throw(error('10'));
|
|
254
255
|
expect(validate([])).to.throw(error('Array'));
|
|
255
256
|
expect(validate({})).to.throw(error('Object'));
|
|
@@ -277,7 +278,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
277
278
|
expect(validate([])).to.throw(error);
|
|
278
279
|
expect(validate({})).to.throw(error);
|
|
279
280
|
expect(validate(null)).to.throw(error);
|
|
280
|
-
validate(undefined);
|
|
281
|
+
validate(undefined)();
|
|
281
282
|
});
|
|
282
283
|
|
|
283
284
|
it('expects the primary key should not have the option "required" to be true', function () {
|
|
@@ -294,8 +295,8 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
294
295
|
'so it should not have the option "required" to be provided.',
|
|
295
296
|
);
|
|
296
297
|
expect(validate(true)).to.throw(error);
|
|
297
|
-
validate(false);
|
|
298
|
-
validate(undefined);
|
|
298
|
+
validate(false)();
|
|
299
|
+
validate(undefined)();
|
|
299
300
|
});
|
|
300
301
|
|
|
301
302
|
it('expects the primary key should not have the option "default" to be provided', function () {
|
|
@@ -318,7 +319,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
318
319
|
expect(validate([])).to.throw(error);
|
|
319
320
|
expect(validate({})).to.throw(error);
|
|
320
321
|
expect(validate(null)).to.throw(error);
|
|
321
|
-
validate(undefined);
|
|
322
|
+
validate(undefined)();
|
|
322
323
|
});
|
|
323
324
|
|
|
324
325
|
it('expects a non-array property should not have the option "itemType" to be provided', function () {
|
|
@@ -337,7 +338,7 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
337
338
|
expect(validate(DataType.NUMBER)).to.throw(error);
|
|
338
339
|
expect(validate(DataType.BOOLEAN)).to.throw(error);
|
|
339
340
|
expect(validate(DataType.OBJECT)).to.throw(error);
|
|
340
|
-
validate(DataType.ARRAY);
|
|
341
|
+
validate(DataType.ARRAY)();
|
|
341
342
|
});
|
|
342
343
|
|
|
343
344
|
it('the option "model" requires the "object" property type', function () {
|
|
@@ -488,5 +489,45 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
488
489
|
validate(['myTransformer'])();
|
|
489
490
|
validate({myTransformer: true})();
|
|
490
491
|
});
|
|
492
|
+
|
|
493
|
+
it('expects provided the option "unique" to be a boolean', function () {
|
|
494
|
+
const validate = v => {
|
|
495
|
+
const foo = {
|
|
496
|
+
type: DataType.STRING,
|
|
497
|
+
unique: v,
|
|
498
|
+
};
|
|
499
|
+
return () => S.validate('model', {foo});
|
|
500
|
+
};
|
|
501
|
+
const error = v =>
|
|
502
|
+
format(
|
|
503
|
+
'The provided option "unique" of the property "foo" in the model "model" ' +
|
|
504
|
+
'should be a Boolean, but %s given.',
|
|
505
|
+
v,
|
|
506
|
+
);
|
|
507
|
+
expect(validate('str')).to.throw(error('"str"'));
|
|
508
|
+
expect(validate(10)).to.throw(error('10'));
|
|
509
|
+
expect(validate([])).to.throw(error('Array'));
|
|
510
|
+
expect(validate({})).to.throw(error('Object'));
|
|
511
|
+
validate(true)();
|
|
512
|
+
validate(false)();
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
it('expects the primary key should not have the option "unique" to be true', function () {
|
|
516
|
+
const validate = v => () => {
|
|
517
|
+
const foo = {
|
|
518
|
+
type: DataType.ANY,
|
|
519
|
+
primaryKey: true,
|
|
520
|
+
unique: v,
|
|
521
|
+
};
|
|
522
|
+
S.validate('model', {foo});
|
|
523
|
+
};
|
|
524
|
+
const error = format(
|
|
525
|
+
'The property "foo" of the model "model" is a primary key, ' +
|
|
526
|
+
'so it should not have the option "unique" to be provided.',
|
|
527
|
+
);
|
|
528
|
+
expect(validate(true)).to.throw(error);
|
|
529
|
+
validate(false)();
|
|
530
|
+
validate(undefined)();
|
|
531
|
+
});
|
|
491
532
|
});
|
|
492
533
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {DataType} from './data-type.js';
|
|
2
2
|
import {PropertyValidateOptions} from './property-validator/index.js';
|
|
3
|
+
import {PropertyTransformOptions} from './property-transformer/index.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Full property definition.
|
|
@@ -14,6 +15,8 @@ export declare type FullPropertyDefinition = {
|
|
|
14
15
|
required?: boolean;
|
|
15
16
|
default?: unknown;
|
|
16
17
|
validate?: PropertyValidateOptions;
|
|
18
|
+
transform?: PropertyTransformOptions;
|
|
19
|
+
unique?: boolean;
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
/**
|
package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {InvalidArgumentError} from '../../../../../errors/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* To lower case transformer.
|
|
5
|
+
*
|
|
6
|
+
* @param {*} value
|
|
7
|
+
* @param {undefined} options
|
|
8
|
+
* @param {object} context
|
|
9
|
+
* @returns {string|undefined|null}
|
|
10
|
+
*/
|
|
11
|
+
export function toLowerCaseTransformer(value, options, context) {
|
|
12
|
+
if (value == null) return value;
|
|
13
|
+
if (typeof value === 'string') return value.toLowerCase();
|
|
14
|
+
throw new InvalidArgumentError(
|
|
15
|
+
'The property transformer %v requires a String value, but %v given.',
|
|
16
|
+
context.transformerName,
|
|
17
|
+
value,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {format} from '@e22m4u/js-format';
|
|
3
|
+
import {toLowerCaseTransformer} from './to-lower-case-transformer.js';
|
|
4
|
+
|
|
5
|
+
describe('toLowerCaseTransformer', function () {
|
|
6
|
+
it('returns undefined and null values as is', function () {
|
|
7
|
+
const res1 = toLowerCaseTransformer(undefined, undefined, {});
|
|
8
|
+
const res2 = toLowerCaseTransformer(null, undefined, {});
|
|
9
|
+
expect(res1).to.be.undefined;
|
|
10
|
+
expect(res2).to.be.null;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('converts the given string to lower case', function () {
|
|
14
|
+
const res = toLowerCaseTransformer('TEST', undefined, {});
|
|
15
|
+
expect(res).to.be.eq('test');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('throws an error if the given value is not a string', function () {
|
|
19
|
+
const throwable = v => () =>
|
|
20
|
+
toLowerCaseTransformer(v, undefined, {
|
|
21
|
+
transformerName: 'toLowerCase',
|
|
22
|
+
});
|
|
23
|
+
const error = v =>
|
|
24
|
+
format(
|
|
25
|
+
'The property transformer "toLowerCase" requires a String value, but %s given.',
|
|
26
|
+
v,
|
|
27
|
+
);
|
|
28
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
29
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
30
|
+
expect(throwable(true)).to.throw(error('true'));
|
|
31
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
32
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
33
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
34
|
+
throwable('str')();
|
|
35
|
+
throwable('')();
|
|
36
|
+
throwable(undefined)();
|
|
37
|
+
throwable(null)();
|
|
38
|
+
});
|
|
39
|
+
});
|
package/src/definition/model/properties/property-transformer/builtin/to-title-case-transformer.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {InvalidArgumentError} from '../../../../../errors/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* To title case transformer.
|
|
5
|
+
*
|
|
6
|
+
* @param {*} value
|
|
7
|
+
* @param {undefined} options
|
|
8
|
+
* @param {object} context
|
|
9
|
+
* @returns {string|undefined|null}
|
|
10
|
+
*/
|
|
11
|
+
export function toTitleCaseTransformer(value, options, context) {
|
|
12
|
+
if (value == null) return value;
|
|
13
|
+
if (typeof value === 'string')
|
|
14
|
+
return value.replace(/\p{L}\S*/gu, text => {
|
|
15
|
+
return text.charAt(0).toUpperCase() + text.substring(1).toLowerCase();
|
|
16
|
+
});
|
|
17
|
+
throw new InvalidArgumentError(
|
|
18
|
+
'The property transformer %v requires a String value, but %v given.',
|
|
19
|
+
context.transformerName,
|
|
20
|
+
value,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {format} from '@e22m4u/js-format';
|
|
3
|
+
import {toTitleCaseTransformer} from './to-title-case-transformer.js';
|
|
4
|
+
|
|
5
|
+
describe('toTitleCaseTransformer', function () {
|
|
6
|
+
it('returns undefined and null values as is', function () {
|
|
7
|
+
const res1 = toTitleCaseTransformer(undefined, undefined, {});
|
|
8
|
+
const res2 = toTitleCaseTransformer(null, undefined, {});
|
|
9
|
+
expect(res1).to.be.undefined;
|
|
10
|
+
expect(res2).to.be.null;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('converts the given string to title case', function () {
|
|
14
|
+
const res1 = toTitleCaseTransformer('TEST', undefined, {});
|
|
15
|
+
const res2 = toTitleCaseTransformer('test', undefined, {});
|
|
16
|
+
expect(res1).to.be.eq('Test');
|
|
17
|
+
expect(res2).to.be.eq('Test');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('throws an error if the given value is not a string', function () {
|
|
21
|
+
const throwable = v => () =>
|
|
22
|
+
toTitleCaseTransformer(v, undefined, {
|
|
23
|
+
transformerName: 'toTitleCase',
|
|
24
|
+
});
|
|
25
|
+
const error = v =>
|
|
26
|
+
format(
|
|
27
|
+
'The property transformer "toTitleCase" requires a String value, but %s given.',
|
|
28
|
+
v,
|
|
29
|
+
);
|
|
30
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
31
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
32
|
+
expect(throwable(true)).to.throw(error('true'));
|
|
33
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
34
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
35
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
36
|
+
throwable('str')();
|
|
37
|
+
throwable('')();
|
|
38
|
+
throwable(undefined)();
|
|
39
|
+
throwable(null)();
|
|
40
|
+
});
|
|
41
|
+
});
|
package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {InvalidArgumentError} from '../../../../../errors/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* To upper case transformer.
|
|
5
|
+
*
|
|
6
|
+
* @param {*} value
|
|
7
|
+
* @param {undefined} options
|
|
8
|
+
* @param {object} context
|
|
9
|
+
* @returns {string|undefined|null}
|
|
10
|
+
*/
|
|
11
|
+
export function toUpperCaseTransformer(value, options, context) {
|
|
12
|
+
if (value == null) return value;
|
|
13
|
+
if (typeof value === 'string') return value.toUpperCase();
|
|
14
|
+
throw new InvalidArgumentError(
|
|
15
|
+
'The property transformer %v requires a String value, but %v given.',
|
|
16
|
+
context.transformerName,
|
|
17
|
+
value,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {format} from '@e22m4u/js-format';
|
|
3
|
+
import {toUpperCaseTransformer} from './to-upper-case-transformer.js';
|
|
4
|
+
|
|
5
|
+
describe('toUpperCaseTransformer', function () {
|
|
6
|
+
it('returns undefined and null values as is', function () {
|
|
7
|
+
const res1 = toUpperCaseTransformer(undefined, undefined, {});
|
|
8
|
+
const res2 = toUpperCaseTransformer(null, undefined, {});
|
|
9
|
+
expect(res1).to.be.undefined;
|
|
10
|
+
expect(res2).to.be.null;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('converts the given string to upper case', function () {
|
|
14
|
+
const res = toUpperCaseTransformer('test', undefined, {});
|
|
15
|
+
expect(res).to.be.eq('TEST');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('throws an error if the given value is not a string', function () {
|
|
19
|
+
const throwable = v => () =>
|
|
20
|
+
toUpperCaseTransformer(v, undefined, {
|
|
21
|
+
transformerName: 'toUpperCase',
|
|
22
|
+
});
|
|
23
|
+
const error = v =>
|
|
24
|
+
format(
|
|
25
|
+
'The property transformer "toUpperCase" requires a String value, but %s given.',
|
|
26
|
+
v,
|
|
27
|
+
);
|
|
28
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
29
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
30
|
+
expect(throwable(true)).to.throw(error('true'));
|
|
31
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
32
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
33
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
34
|
+
throwable('str')();
|
|
35
|
+
throwable('')();
|
|
36
|
+
throwable(undefined)();
|
|
37
|
+
throwable(null)();
|
|
38
|
+
});
|
|
39
|
+
});
|
package/src/definition/model/properties/property-transformer/property-transformer-registry.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {Service} from '@e22m4u/js-service';
|
|
2
2
|
import {trimTransformer} from './builtin/index.js';
|
|
3
|
+
import {toUpperCaseTransformer} from './builtin/index.js';
|
|
4
|
+
import {toLowerCaseTransformer} from './builtin/index.js';
|
|
5
|
+
import {toTitleCaseTransformer} from './builtin/index.js';
|
|
3
6
|
import {InvalidArgumentError} from '../../../../errors/index.js';
|
|
4
7
|
|
|
5
8
|
/**
|
|
@@ -13,6 +16,9 @@ export class PropertyTransformerRegistry extends Service {
|
|
|
13
16
|
*/
|
|
14
17
|
_transformers = {
|
|
15
18
|
trim: trimTransformer,
|
|
19
|
+
toUpperCase: toUpperCaseTransformer,
|
|
20
|
+
toLowerCase: toLowerCaseTransformer,
|
|
21
|
+
toTitleCase: toTitleCaseTransformer,
|
|
16
22
|
};
|
|
17
23
|
|
|
18
24
|
/**
|
package/src/definition/model/properties/property-transformer/property-transformer-registry.spec.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {expect} from 'chai';
|
|
2
2
|
import {format} from '@e22m4u/js-format';
|
|
3
3
|
import {trimTransformer} from './builtin/index.js';
|
|
4
|
+
import {toUpperCaseTransformer} from './builtin/index.js';
|
|
5
|
+
import {toLowerCaseTransformer} from './builtin/index.js';
|
|
6
|
+
import {toTitleCaseTransformer} from './builtin/index.js';
|
|
4
7
|
import {PropertyTransformerRegistry} from './property-transformer-registry.js';
|
|
5
8
|
|
|
6
9
|
describe('PropertyTransformerRegistry', function () {
|
|
@@ -9,6 +12,9 @@ describe('PropertyTransformerRegistry', function () {
|
|
|
9
12
|
const S = new PropertyTransformerRegistry();
|
|
10
13
|
expect(S['_transformers']).to.be.eql({
|
|
11
14
|
trim: trimTransformer,
|
|
15
|
+
toUpperCase: toUpperCaseTransformer,
|
|
16
|
+
toLowerCase: toLowerCaseTransformer,
|
|
17
|
+
toTitleCase: toTitleCaseTransformer,
|
|
12
18
|
});
|
|
13
19
|
});
|
|
14
20
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {ModelId} from '../../../types.js';
|
|
2
|
+
import {Service} from '@e22m4u/js-service';
|
|
3
|
+
import {ModelData} from '../../../types.js';
|
|
4
|
+
import {WhereClause} from '../../../filter/index.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Count method.
|
|
8
|
+
*/
|
|
9
|
+
type CountMethod = (where: WhereClause) => Promise<number>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Property uniqueness validator.
|
|
13
|
+
*/
|
|
14
|
+
export declare class PropertyUniquenessValidator extends Service {
|
|
15
|
+
/**
|
|
16
|
+
* Validate.
|
|
17
|
+
*
|
|
18
|
+
* @param countMethod
|
|
19
|
+
* @param methodName
|
|
20
|
+
* @param modelName
|
|
21
|
+
* @param modelData
|
|
22
|
+
* @param modelId
|
|
23
|
+
*/
|
|
24
|
+
validate(
|
|
25
|
+
countMethod: CountMethod,
|
|
26
|
+
methodName: string,
|
|
27
|
+
modelName: string,
|
|
28
|
+
modelData: ModelData,
|
|
29
|
+
modelId?: ModelId,
|
|
30
|
+
): Promise<void>;
|
|
31
|
+
}
|