@e22m4u/js-repository 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -4
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Adapter.html +1 -1
- package/docs/classes/AdapterLoader.html +1 -1
- package/docs/classes/AdapterRegistry.html +1 -1
- package/docs/classes/BelongsToResolver.html +1 -1
- package/docs/classes/DatasourceDefinitionValidator.html +1 -1
- package/docs/classes/DefinitionRegistry.html +1 -1
- package/docs/classes/FieldsClauseTool.html +1 -1
- package/docs/classes/HasManyResolver.html +1 -1
- package/docs/classes/HasOneResolver.html +1 -1
- package/docs/classes/IncludeClauseTool.html +1 -1
- package/docs/classes/InvalidArgumentError.html +1 -1
- package/docs/classes/InvalidOperatorValueError.html +1 -1
- package/docs/classes/ModelDataSanitizer.html +1 -1
- package/docs/classes/ModelDataTransformer.html +16 -0
- package/docs/classes/ModelDataValidator.html +2 -2
- package/docs/classes/ModelDefinitionUtils.html +1 -1
- package/docs/classes/ModelDefinitionValidator.html +1 -1
- package/docs/classes/NotImplementedError.html +1 -1
- package/docs/classes/OperatorClauseTool.html +1 -1
- package/docs/classes/OrderClauseTool.html +1 -1
- package/docs/classes/PrimaryKeysDefinitionValidator.html +1 -1
- package/docs/classes/PropertiesDefinitionValidator.html +1 -1
- package/docs/classes/PropertyTransformerRegistry.html +20 -0
- package/docs/classes/PropertyValidatorRegistry.html +1 -1
- package/docs/classes/ReferencesManyResolver.html +1 -1
- package/docs/classes/RelationsDefinitionValidator.html +1 -1
- package/docs/classes/Repository.html +1 -1
- package/docs/classes/RepositoryRegistry.html +1 -1
- package/docs/classes/Schema.html +1 -1
- package/docs/classes/SliceClauseTool.html +1 -1
- package/docs/classes/WhereClauseTool.html +1 -1
- package/docs/enums/DataType.html +1 -1
- package/docs/enums/DecoratorTargetType.html +1 -1
- package/docs/enums/RelationType.html +1 -1
- package/docs/functions/capitalize.html +1 -1
- package/docs/functions/cloneDeep.html +1 -1
- package/docs/functions/excludeObjectKeys.html +1 -1
- package/docs/functions/getCtorName.html +1 -1
- package/docs/functions/getDecoratorTargetType.html +1 -1
- package/docs/functions/getValueByPath.html +1 -1
- package/docs/functions/isCtor.html +1 -1
- package/docs/functions/isPureObject.html +1 -1
- package/docs/functions/selectObjectKeys.html +1 -1
- package/docs/functions/singularize.html +1 -1
- package/docs/functions/stringToRegexp.html +1 -1
- package/docs/index.html +20 -5
- package/docs/interfaces/AndClause.html +1 -1
- package/docs/interfaces/Constructor.html +1 -1
- package/docs/interfaces/OrClause.html +1 -1
- package/docs/modules.html +6 -1
- package/docs/types/AnyObject.html +1 -1
- package/docs/types/BelongsToDefinition.html +1 -1
- package/docs/types/DEFAULT_PRIMARY_KEY_PROPERTY_NAME.html +1 -1
- package/docs/types/DatasourceDefinition.html +1 -1
- package/docs/types/FieldsClause.html +1 -1
- package/docs/types/FilterClause.html +1 -1
- package/docs/types/Flatten.html +1 -1
- package/docs/types/FullPropertyDefinition.html +1 -1
- package/docs/types/HasManyDefinition.html +1 -1
- package/docs/types/HasOneDefinition.html +1 -1
- package/docs/types/Identity.html +1 -1
- package/docs/types/IncludeClause.html +1 -1
- package/docs/types/ItemFilterClause.html +1 -1
- package/docs/types/ModelData.html +1 -1
- package/docs/types/ModelDefinition.html +1 -1
- package/docs/types/ModelId.html +1 -1
- package/docs/types/NestedIncludeClause.html +1 -1
- package/docs/types/NormalizedFieldsClause.html +1 -1
- package/docs/types/NormalizedIncludeClause.html +1 -1
- package/docs/types/OperatorClause.html +1 -1
- package/docs/types/OptionalUnlessRequiredId.html +1 -1
- package/docs/types/OrderClause.html +1 -1
- package/docs/types/PartialBy.html +1 -1
- package/docs/types/PartialWithoutId.html +1 -1
- package/docs/types/PolyBelongsToDefinition.html +1 -1
- package/docs/types/PolyHasManyDefinitionWithTargetKeys.html +1 -1
- package/docs/types/PolyHasManyDefinitionWithTargetRelationName.html +1 -1
- package/docs/types/PolyHasOneDefinitionWithTargetKeys.html +1 -1
- package/docs/types/PolyHasOneDefinitionWithTargetRelationName.html +1 -1
- package/docs/types/PropertiesClause.html +1 -1
- package/docs/types/PropertyDefinition.html +1 -1
- package/docs/types/PropertyDefinitionMap.html +1 -1
- package/docs/types/PropertyTransformOptions.html +2 -0
- package/docs/types/PropertyTransformer.html +2 -0
- package/docs/types/PropertyTransformerContext.html +2 -0
- package/docs/types/PropertyValidateOptions.html +1 -1
- package/docs/types/PropertyValidator.html +2 -2
- package/docs/types/PropertyValidatorContext.html +2 -2
- package/docs/types/ReferencesManyDefinition.html +1 -1
- package/docs/types/RelationDefinition.html +1 -1
- package/docs/types/RelationDefinitionMap.html +1 -1
- package/docs/types/WhereClause.html +1 -1
- package/docs/types/WithoutId.html +1 -1
- package/package.json +3 -3
- package/src/adapter/adapter.js +2 -0
- package/src/adapter/adapter.spec.js +9 -3
- package/src/adapter/decorator/data-transformation-decorator.d.ts +14 -0
- package/src/adapter/decorator/data-transformation-decorator.js +54 -0
- package/src/adapter/decorator/data-transformation-decorator.spec.js +95 -0
- package/src/adapter/decorator/data-validation-decorator.js +11 -18
- package/src/adapter/decorator/data-validation-decorator.spec.js +48 -60
- package/src/adapter/decorator/default-values-decorator.spec.js +89 -113
- package/src/adapter/decorator/index.d.ts +1 -0
- package/src/adapter/decorator/index.js +1 -0
- package/src/definition/model/index.d.ts +1 -0
- package/src/definition/model/index.js +1 -0
- package/src/definition/model/model-data-transformer.d.ts +15 -0
- package/src/definition/model/model-data-transformer.js +96 -0
- package/src/definition/model/model-data-transformer.spec.js +534 -0
- package/src/definition/model/model-data-validator.d.ts +1 -5
- package/src/definition/model/model-data-validator.js +51 -53
- package/src/definition/model/model-data-validator.spec.js +772 -719
- 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 +47 -0
- package/src/definition/model/properties/properties-definition-validator.spec.js +52 -0
- package/src/definition/model/properties/property-transformer/builtin/index.d.ts +1 -0
- package/src/definition/model/properties/property-transformer/builtin/index.js +1 -0
- package/src/definition/model/properties/property-transformer/builtin/trim-transformer.d.ts +6 -0
- package/src/definition/model/properties/property-transformer/builtin/trim-transformer.js +19 -0
- package/src/definition/model/properties/property-transformer/builtin/trim-transformer.spec.js +39 -0
- package/src/definition/model/properties/property-transformer/index.d.ts +2 -0
- package/src/definition/model/properties/property-transformer/index.js +2 -0
- package/src/definition/model/properties/property-transformer/property-transformer-registry.d.ts +29 -0
- package/src/definition/model/properties/property-transformer/property-transformer-registry.js +72 -0
- package/src/definition/model/properties/property-transformer/property-transformer-registry.spec.js +129 -0
- package/src/definition/model/properties/property-transformer/property-transformer.d.ts +25 -0
- package/src/definition/model/properties/property-transformer/property-transformer.js +1 -0
- package/src/definition/model/properties/property-validator/builtin/max-length-validator.js +1 -1
- package/src/definition/model/properties/property-validator/builtin/max-length-validator.spec.js +10 -3
- package/src/definition/model/properties/property-validator/builtin/min-length-validator.js +1 -1
- package/src/definition/model/properties/property-validator/builtin/min-length-validator.spec.js +10 -3
- package/src/definition/model/properties/property-validator/builtin/regexp-validator.js +1 -1
- package/src/definition/model/properties/property-validator/builtin/regexp-validator.spec.js +10 -3
- package/src/definition/model/properties/property-validator/property-validator-registry.spec.js +51 -39
- package/src/definition/model/properties/property-validator/property-validator.d.ts +1 -6
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './data-type.js';
|
|
2
2
|
export * from './property-definition.js';
|
|
3
3
|
export * from './property-validator/index.js';
|
|
4
|
+
export * from './property-transformer/index.js';
|
|
4
5
|
export * from './properties-definition-validator.js';
|
|
5
6
|
export * from './primary-keys-definition-validator.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './data-type.js';
|
|
2
2
|
export * from './property-definition.js';
|
|
3
3
|
export * from './property-validator/index.js';
|
|
4
|
+
export * from './property-transformer/index.js';
|
|
4
5
|
export * from './properties-definition-validator.js';
|
|
5
6
|
export * from './primary-keys-definition-validator.js';
|
|
@@ -3,6 +3,7 @@ import {DataType as Type} from './data-type.js';
|
|
|
3
3
|
import {capitalize} from '../../../utils/index.js';
|
|
4
4
|
import {InvalidArgumentError} from '../../../errors/index.js';
|
|
5
5
|
import {PropertyValidatorRegistry} from './property-validator/index.js';
|
|
6
|
+
import {PropertyTransformerRegistry} from './property-transformer/index.js';
|
|
6
7
|
import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -250,5 +251,51 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
250
251
|
);
|
|
251
252
|
}
|
|
252
253
|
}
|
|
254
|
+
if (propDef.transform != null) {
|
|
255
|
+
const propertyTransformerRegistry = this.getService(
|
|
256
|
+
PropertyTransformerRegistry,
|
|
257
|
+
);
|
|
258
|
+
if (propDef.transform && typeof propDef.transform === 'string') {
|
|
259
|
+
if (!propertyTransformerRegistry.hasTransformer(propDef.transform))
|
|
260
|
+
throw new InvalidArgumentError(
|
|
261
|
+
'The property transformer %v is not found.',
|
|
262
|
+
propDef.transform,
|
|
263
|
+
);
|
|
264
|
+
} else if (Array.isArray(propDef.transform)) {
|
|
265
|
+
for (const transformerName of propDef.transform) {
|
|
266
|
+
if (typeof transformerName !== 'string')
|
|
267
|
+
throw new InvalidArgumentError(
|
|
268
|
+
'The provided option "transform" of the property %v in the model %v ' +
|
|
269
|
+
'has an Array value that should have a non-empty String, ' +
|
|
270
|
+
'but %v given.',
|
|
271
|
+
propName,
|
|
272
|
+
modelName,
|
|
273
|
+
transformerName,
|
|
274
|
+
);
|
|
275
|
+
if (!propertyTransformerRegistry.hasTransformer(transformerName))
|
|
276
|
+
throw new InvalidArgumentError(
|
|
277
|
+
'The property transformer %v is not found.',
|
|
278
|
+
transformerName,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
} else if (typeof propDef.transform === 'object') {
|
|
282
|
+
for (const transformerName in propDef.transform) {
|
|
283
|
+
if (!propertyTransformerRegistry.hasTransformer(transformerName))
|
|
284
|
+
throw new InvalidArgumentError(
|
|
285
|
+
'The property transformer %v is not found.',
|
|
286
|
+
transformerName,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
throw new InvalidArgumentError(
|
|
291
|
+
'The provided option "transform" of the property %v in the model %v ' +
|
|
292
|
+
'should be a non-empty String, an Array of String or an Object, ' +
|
|
293
|
+
'but %v given.',
|
|
294
|
+
propName,
|
|
295
|
+
modelName,
|
|
296
|
+
propDef.transform,
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
253
300
|
}
|
|
254
301
|
}
|
|
@@ -3,6 +3,7 @@ import {expect} from 'chai';
|
|
|
3
3
|
import {DataType} from './data-type.js';
|
|
4
4
|
import {format} from '@e22m4u/js-format';
|
|
5
5
|
import {PropertyValidatorRegistry} from './property-validator/index.js';
|
|
6
|
+
import {PropertyTransformerRegistry} from './property-transformer/index.js';
|
|
6
7
|
import {PropertiesDefinitionValidator} from './properties-definition-validator.js';
|
|
7
8
|
import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
|
|
8
9
|
|
|
@@ -10,6 +11,10 @@ const S = new PropertiesDefinitionValidator();
|
|
|
10
11
|
const sandbox = chai.spy.sandbox();
|
|
11
12
|
|
|
12
13
|
S.getService(PropertyValidatorRegistry).addValidator('myValidator', () => true);
|
|
14
|
+
S.getService(PropertyTransformerRegistry).addTransformer(
|
|
15
|
+
'myTransformer',
|
|
16
|
+
() => true,
|
|
17
|
+
);
|
|
13
18
|
|
|
14
19
|
describe('PropertiesDefinitionValidator', function () {
|
|
15
20
|
afterEach(function () {
|
|
@@ -436,5 +441,52 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
436
441
|
validate(['myValidator'])();
|
|
437
442
|
validate({myValidator: true})();
|
|
438
443
|
});
|
|
444
|
+
|
|
445
|
+
it('the option "transform" should have a non-empty String, an Array of String or an Object', function () {
|
|
446
|
+
const validate = v => () => {
|
|
447
|
+
const foo = {
|
|
448
|
+
type: DataType.ANY,
|
|
449
|
+
transform: v,
|
|
450
|
+
};
|
|
451
|
+
S.validate('model', {foo});
|
|
452
|
+
};
|
|
453
|
+
const error = v =>
|
|
454
|
+
format(
|
|
455
|
+
'The provided option "transform" of the property "foo" in the model "model" ' +
|
|
456
|
+
'should be a non-empty String, an Array of String or an Object, ' +
|
|
457
|
+
'but %s given.',
|
|
458
|
+
v,
|
|
459
|
+
);
|
|
460
|
+
expect(validate('')).to.throw(error('""'));
|
|
461
|
+
expect(validate(10)).to.throw(error('10'));
|
|
462
|
+
expect(validate(0)).to.throw(error('0'));
|
|
463
|
+
expect(validate(true)).to.throw(error('true'));
|
|
464
|
+
expect(validate(false)).to.throw(error('false'));
|
|
465
|
+
expect(validate(() => undefined)).to.throw(error('Function'));
|
|
466
|
+
validate('myTransformer')();
|
|
467
|
+
validate(['myTransformer'])();
|
|
468
|
+
validate([])();
|
|
469
|
+
validate({myTransformer: true})();
|
|
470
|
+
validate({})();
|
|
471
|
+
validate(null)();
|
|
472
|
+
validate(undefined)();
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
it('the option "transform" requires only existing transformer names', function () {
|
|
476
|
+
const validate = v => () => {
|
|
477
|
+
const foo = {
|
|
478
|
+
type: DataType.ANY,
|
|
479
|
+
transform: v,
|
|
480
|
+
};
|
|
481
|
+
S.validate('model', {foo});
|
|
482
|
+
};
|
|
483
|
+
const error = v => format('The property transformer %s is not found.', v);
|
|
484
|
+
expect(validate('unknown')).to.throw(error('"unknown"'));
|
|
485
|
+
expect(validate({unknown: true})).to.throw(error('"unknown"'));
|
|
486
|
+
expect(validate(['unknown'])).to.throw(error('"unknown"'));
|
|
487
|
+
validate('myTransformer')();
|
|
488
|
+
validate(['myTransformer'])();
|
|
489
|
+
validate({myTransformer: true})();
|
|
490
|
+
});
|
|
439
491
|
});
|
|
440
492
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './trim-transformer.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './trim-transformer.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {InvalidArgumentError} from '../../../../../errors/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Trim transformer.
|
|
5
|
+
*
|
|
6
|
+
* @param {*} value
|
|
7
|
+
* @param {undefined} options
|
|
8
|
+
* @param {object} context
|
|
9
|
+
* @returns {string|undefined|null}
|
|
10
|
+
*/
|
|
11
|
+
export function trimTransformer(value, options, context) {
|
|
12
|
+
if (value == null) return value;
|
|
13
|
+
if (typeof value === 'string') return value.trim();
|
|
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 {trimTransformer} from './trim-transformer.js';
|
|
4
|
+
|
|
5
|
+
describe('trimTransformer', function () {
|
|
6
|
+
it('returns undefined and null values as is', function () {
|
|
7
|
+
const res1 = trimTransformer(undefined, undefined, {});
|
|
8
|
+
const res2 = trimTransformer(null, undefined, {});
|
|
9
|
+
expect(res1).to.be.undefined;
|
|
10
|
+
expect(res2).to.be.null;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('trims the given string', function () {
|
|
14
|
+
const res = trimTransformer(' 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
|
+
trimTransformer(v, undefined, {
|
|
21
|
+
transformerName: 'trim',
|
|
22
|
+
});
|
|
23
|
+
const error = v =>
|
|
24
|
+
format(
|
|
25
|
+
'The property transformer "trim" 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.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {PropertyTransformer} from './property-transformer.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Property transformer registry.
|
|
6
|
+
*/
|
|
7
|
+
export declare class PropertyTransformerRegistry extends Service {
|
|
8
|
+
/**
|
|
9
|
+
* Add transformer.
|
|
10
|
+
*
|
|
11
|
+
* @param name
|
|
12
|
+
* @param transformer
|
|
13
|
+
*/
|
|
14
|
+
addTransformer(name: string, transformer: PropertyTransformer): this;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Has transformer.
|
|
18
|
+
*
|
|
19
|
+
* @param name
|
|
20
|
+
*/
|
|
21
|
+
hasTransformer(name: string): boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get transformer.
|
|
25
|
+
*
|
|
26
|
+
* @param name
|
|
27
|
+
*/
|
|
28
|
+
getTransformer(name: string): PropertyTransformer;
|
|
29
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {trimTransformer} from './builtin/index.js';
|
|
3
|
+
import {InvalidArgumentError} from '../../../../errors/index.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Property transformer registry.
|
|
7
|
+
*/
|
|
8
|
+
export class PropertyTransformerRegistry extends Service {
|
|
9
|
+
/**
|
|
10
|
+
* Transformers.
|
|
11
|
+
*
|
|
12
|
+
* @type {object}
|
|
13
|
+
*/
|
|
14
|
+
_transformers = {
|
|
15
|
+
trim: trimTransformer,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Add transformer.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} name
|
|
22
|
+
* @param {Function} transformer
|
|
23
|
+
* @returns {PropertyTransformerRegistry}
|
|
24
|
+
*/
|
|
25
|
+
addTransformer(name, transformer) {
|
|
26
|
+
if (!name || typeof name !== 'string')
|
|
27
|
+
throw new InvalidArgumentError(
|
|
28
|
+
'A name of the property transformer must ' +
|
|
29
|
+
'be a non-empty String, but %v given.',
|
|
30
|
+
name,
|
|
31
|
+
);
|
|
32
|
+
if (name in this._transformers)
|
|
33
|
+
throw new InvalidArgumentError(
|
|
34
|
+
'The property transformer %v is already defined.',
|
|
35
|
+
name,
|
|
36
|
+
);
|
|
37
|
+
if (typeof transformer !== 'function')
|
|
38
|
+
throw new InvalidArgumentError(
|
|
39
|
+
'The property transformer %v must be a Function, but %v given.',
|
|
40
|
+
name,
|
|
41
|
+
transformer,
|
|
42
|
+
);
|
|
43
|
+
this._transformers[name] = transformer;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Has transformer.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} name
|
|
51
|
+
* @returns {boolean}
|
|
52
|
+
*/
|
|
53
|
+
hasTransformer(name) {
|
|
54
|
+
return Boolean(this._transformers[name]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get transformer.
|
|
59
|
+
*
|
|
60
|
+
* @param {string} name
|
|
61
|
+
* @returns {Function}
|
|
62
|
+
*/
|
|
63
|
+
getTransformer(name) {
|
|
64
|
+
const transformer = this._transformers[name];
|
|
65
|
+
if (!transformer)
|
|
66
|
+
throw new InvalidArgumentError(
|
|
67
|
+
'The property transformer %v is not defined.',
|
|
68
|
+
name,
|
|
69
|
+
);
|
|
70
|
+
return transformer;
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/definition/model/properties/property-transformer/property-transformer-registry.spec.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {format} from '@e22m4u/js-format';
|
|
3
|
+
import {trimTransformer} from './builtin/index.js';
|
|
4
|
+
import {PropertyTransformerRegistry} from './property-transformer-registry.js';
|
|
5
|
+
|
|
6
|
+
describe('PropertyTransformerRegistry', function () {
|
|
7
|
+
describe('addTransformer', function () {
|
|
8
|
+
it('has builtin transformers', function () {
|
|
9
|
+
const S = new PropertyTransformerRegistry();
|
|
10
|
+
expect(S['_transformers']).to.be.eql({
|
|
11
|
+
trim: trimTransformer,
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('adds a given transformer with the name', function () {
|
|
16
|
+
const S = new PropertyTransformerRegistry();
|
|
17
|
+
const myTransformer = () => undefined;
|
|
18
|
+
const res = S.addTransformer('myTransformer', myTransformer);
|
|
19
|
+
expect(res).to.be.eq(S);
|
|
20
|
+
expect(S['_transformers']['myTransformer']).to.be.eq(myTransformer);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('requires the given name to be a non-empty string', function () {
|
|
24
|
+
const S = new PropertyTransformerRegistry();
|
|
25
|
+
const throwable = v => () => S.addTransformer(v, () => undefined);
|
|
26
|
+
const error = v =>
|
|
27
|
+
format(
|
|
28
|
+
'A name of the property transformer must ' +
|
|
29
|
+
'be a non-empty String, but %s given.',
|
|
30
|
+
v,
|
|
31
|
+
);
|
|
32
|
+
expect(throwable('')).to.throw(error('""'));
|
|
33
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
34
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
35
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
36
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
37
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
38
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
39
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
40
|
+
expect(throwable(() => undefined)).to.throw(error('Function'));
|
|
41
|
+
throwable('str')();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('throws an error if the given name already exists', function () {
|
|
45
|
+
const S = new PropertyTransformerRegistry();
|
|
46
|
+
S.addTransformer('test', () => undefined);
|
|
47
|
+
const throwable = () => S.addTransformer('test', () => undefined);
|
|
48
|
+
expect(throwable).to.throw(
|
|
49
|
+
'The property transformer "test" is already defined.',
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('requires the given transformer to be a function', function () {
|
|
54
|
+
const S = new PropertyTransformerRegistry();
|
|
55
|
+
const throwable = v => () => S.addTransformer('test', v);
|
|
56
|
+
const error = v =>
|
|
57
|
+
format(
|
|
58
|
+
'The property transformer "test" must be a Function, but %s given.',
|
|
59
|
+
v,
|
|
60
|
+
);
|
|
61
|
+
expect(throwable('str')).to.throw(error('"str"'));
|
|
62
|
+
expect(throwable('')).to.throw(error('""'));
|
|
63
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
64
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
65
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
66
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
67
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
68
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
69
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
70
|
+
throwable(() => undefined)();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('hasTransformer', function () {
|
|
75
|
+
it('returns false for a not existing name', function () {
|
|
76
|
+
const S = new PropertyTransformerRegistry();
|
|
77
|
+
expect(S.hasTransformer('str')).to.be.false;
|
|
78
|
+
expect(S.hasTransformer('')).to.be.false;
|
|
79
|
+
expect(S.hasTransformer(10)).to.be.false;
|
|
80
|
+
expect(S.hasTransformer(0)).to.be.false;
|
|
81
|
+
expect(S.hasTransformer(true)).to.be.false;
|
|
82
|
+
expect(S.hasTransformer(false)).to.be.false;
|
|
83
|
+
expect(S.hasTransformer(null)).to.be.false;
|
|
84
|
+
expect(S.hasTransformer(undefined)).to.be.false;
|
|
85
|
+
expect(S.hasTransformer({})).to.be.false;
|
|
86
|
+
expect(S.hasTransformer([])).to.be.false;
|
|
87
|
+
expect(S.hasTransformer(() => undefined)).to.be.false;
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('returns true for an existing name', function () {
|
|
91
|
+
const S = new PropertyTransformerRegistry();
|
|
92
|
+
expect(S.hasTransformer('test')).to.be.false;
|
|
93
|
+
S.addTransformer('test', () => undefined);
|
|
94
|
+
expect(S.hasTransformer('test')).to.be.true;
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('getTransformer', function () {
|
|
99
|
+
it('returns transformer by its name', function () {
|
|
100
|
+
const S = new PropertyTransformerRegistry();
|
|
101
|
+
const myTransformer1 = () => undefined;
|
|
102
|
+
const myTransformer2 = () => undefined;
|
|
103
|
+
S.addTransformer('foo', myTransformer1);
|
|
104
|
+
S.addTransformer('bar', myTransformer2);
|
|
105
|
+
const res1 = S.getTransformer('foo');
|
|
106
|
+
const res2 = S.getTransformer('bar');
|
|
107
|
+
expect(res1).to.be.eq(myTransformer1);
|
|
108
|
+
expect(res2).to.be.eq(myTransformer2);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('throws an error for a not existed name', function () {
|
|
112
|
+
const S = new PropertyTransformerRegistry();
|
|
113
|
+
const throwable = v => () => S.getTransformer(v);
|
|
114
|
+
const error = v =>
|
|
115
|
+
format('The property transformer %s is not defined.', v);
|
|
116
|
+
expect(throwable('str')).to.throw(error('"str"'));
|
|
117
|
+
expect(throwable('')).to.throw(error('""'));
|
|
118
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
119
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
120
|
+
expect(throwable(true)).to.throw(error('true'));
|
|
121
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
122
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
123
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
124
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
125
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
126
|
+
expect(throwable(() => undefined)).to.throw(error('Function'));
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property transformer context.
|
|
3
|
+
*/
|
|
4
|
+
export declare type PropertyTransformerContext = {
|
|
5
|
+
transformerName: string,
|
|
6
|
+
modelName: string,
|
|
7
|
+
propName: string,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Property transformer.
|
|
12
|
+
*/
|
|
13
|
+
export declare type PropertyTransformer = (
|
|
14
|
+
value: unknown,
|
|
15
|
+
options: unknown,
|
|
16
|
+
context: PropertyTransformerContext,
|
|
17
|
+
) => boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Property transform options.
|
|
21
|
+
*/
|
|
22
|
+
export type PropertyTransformOptions =
|
|
23
|
+
| string
|
|
24
|
+
| string[]
|
|
25
|
+
| {[key: string]: unknown};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -9,7 +9,7 @@ import {InvalidArgumentError} from '../../../../../errors/index.js';
|
|
|
9
9
|
* @returns {boolean}
|
|
10
10
|
*/
|
|
11
11
|
export function maxLengthValidator(value, options, context) {
|
|
12
|
-
if (options === false) return true;
|
|
12
|
+
if (value == null || options === false) return true;
|
|
13
13
|
if (typeof options !== 'number')
|
|
14
14
|
throw new InvalidArgumentError(
|
|
15
15
|
'The validator %v requires the "options" argument ' +
|
package/src/definition/model/properties/property-validator/builtin/max-length-validator.spec.js
CHANGED
|
@@ -4,10 +4,17 @@ import {maxLengthValidator} from './max-length-validator.js';
|
|
|
4
4
|
|
|
5
5
|
describe('maxLengthValidator', function () {
|
|
6
6
|
it('returns true if the "options" argument is false', function () {
|
|
7
|
-
const res = maxLengthValidator(
|
|
7
|
+
const res = maxLengthValidator('test', false, {});
|
|
8
8
|
expect(res).to.be.true;
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
it('returns true for undefined and null values', function () {
|
|
12
|
+
const res1 = maxLengthValidator(undefined, 10, {});
|
|
13
|
+
const res2 = maxLengthValidator(null, 10, {});
|
|
14
|
+
expect(res1).to.be.true;
|
|
15
|
+
expect(res2).to.be.true;
|
|
16
|
+
});
|
|
17
|
+
|
|
11
18
|
it('requires the "value" argument as a String or an Array', function () {
|
|
12
19
|
const throwable = v => () =>
|
|
13
20
|
maxLengthValidator(v, 10, {
|
|
@@ -23,14 +30,14 @@ describe('maxLengthValidator', function () {
|
|
|
23
30
|
expect(throwable(0)).to.throw(error('0'));
|
|
24
31
|
expect(throwable(true)).to.throw(error('true'));
|
|
25
32
|
expect(throwable(false)).to.throw(error('false'));
|
|
26
|
-
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
27
|
-
expect(throwable(null)).to.throw(error('null'));
|
|
28
33
|
expect(throwable({})).to.throw(error('Object'));
|
|
29
34
|
expect(throwable(() => undefined)).to.throw(error('Function'));
|
|
30
35
|
throwable('str')();
|
|
31
36
|
throwable('')();
|
|
32
37
|
throwable([1, 2, 3])();
|
|
33
38
|
throwable([])();
|
|
39
|
+
throwable(undefined)();
|
|
40
|
+
throwable(null)();
|
|
34
41
|
});
|
|
35
42
|
|
|
36
43
|
it('requires the "options" argument to be a number', function () {
|
|
@@ -9,7 +9,7 @@ import {InvalidArgumentError} from '../../../../../errors/index.js';
|
|
|
9
9
|
* @returns {boolean}
|
|
10
10
|
*/
|
|
11
11
|
export function minLengthValidator(value, options, context) {
|
|
12
|
-
if (options === false) return true;
|
|
12
|
+
if (value == null || options === false) return true;
|
|
13
13
|
if (typeof options !== 'number')
|
|
14
14
|
throw new InvalidArgumentError(
|
|
15
15
|
'The validator %v requires the "options" argument ' +
|
package/src/definition/model/properties/property-validator/builtin/min-length-validator.spec.js
CHANGED
|
@@ -4,10 +4,17 @@ import {minLengthValidator} from './min-length-validator.js';
|
|
|
4
4
|
|
|
5
5
|
describe('minLengthValidator', function () {
|
|
6
6
|
it('returns true if the "options" argument is false', function () {
|
|
7
|
-
const res = minLengthValidator(
|
|
7
|
+
const res = minLengthValidator('test', false, {});
|
|
8
8
|
expect(res).to.be.true;
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
it('returns true for undefined and null values', function () {
|
|
12
|
+
const res1 = minLengthValidator(undefined, 10, {});
|
|
13
|
+
const res2 = minLengthValidator(null, 10, {});
|
|
14
|
+
expect(res1).to.be.true;
|
|
15
|
+
expect(res2).to.be.true;
|
|
16
|
+
});
|
|
17
|
+
|
|
11
18
|
it('requires the "value" argument as a String or an Array', function () {
|
|
12
19
|
const throwable = v => () =>
|
|
13
20
|
minLengthValidator(v, 0, {
|
|
@@ -23,14 +30,14 @@ describe('minLengthValidator', function () {
|
|
|
23
30
|
expect(throwable(0)).to.throw(error('0'));
|
|
24
31
|
expect(throwable(true)).to.throw(error('true'));
|
|
25
32
|
expect(throwable(false)).to.throw(error('false'));
|
|
26
|
-
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
27
|
-
expect(throwable(null)).to.throw(error('null'));
|
|
28
33
|
expect(throwable({})).to.throw(error('Object'));
|
|
29
34
|
expect(throwable(() => undefined)).to.throw(error('Function'));
|
|
30
35
|
throwable('str')();
|
|
31
36
|
throwable('')();
|
|
32
37
|
throwable([1, 2, 3])();
|
|
33
38
|
throwable([])();
|
|
39
|
+
throwable(undefined)();
|
|
40
|
+
throwable(null)();
|
|
34
41
|
});
|
|
35
42
|
|
|
36
43
|
it('requires the "options" argument to be a number', function () {
|
|
@@ -10,7 +10,7 @@ import {InvalidArgumentError} from '../../../../../errors/index.js';
|
|
|
10
10
|
* @returns {boolean}
|
|
11
11
|
*/
|
|
12
12
|
export function regexpValidator(value, options, context) {
|
|
13
|
-
if (options === false) return true;
|
|
13
|
+
if (value == null || options === false) return true;
|
|
14
14
|
if (typeof options !== 'string' && !(options instanceof RegExp))
|
|
15
15
|
throw new InvalidArgumentError(
|
|
16
16
|
'The validator %v requires the "options" argument ' +
|
|
@@ -4,10 +4,17 @@ import {regexpValidator} from './regexp-validator.js';
|
|
|
4
4
|
|
|
5
5
|
describe('regexpValidator', function () {
|
|
6
6
|
it('returns true if the "options" argument is false', function () {
|
|
7
|
-
const res = regexpValidator(
|
|
7
|
+
const res = regexpValidator('test', false, {});
|
|
8
8
|
expect(res).to.be.true;
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
it('returns true for undefined and null values', function () {
|
|
12
|
+
const res1 = regexpValidator(undefined, '.*', {});
|
|
13
|
+
const res2 = regexpValidator(null, '.*', {});
|
|
14
|
+
expect(res1).to.be.true;
|
|
15
|
+
expect(res2).to.be.true;
|
|
16
|
+
});
|
|
17
|
+
|
|
11
18
|
it('requires the "value" argument to be a string', function () {
|
|
12
19
|
const throwable = v => () =>
|
|
13
20
|
regexpValidator(v, '.*', {
|
|
@@ -21,13 +28,13 @@ describe('regexpValidator', function () {
|
|
|
21
28
|
);
|
|
22
29
|
expect(throwable(true)).to.throw(error('true'));
|
|
23
30
|
expect(throwable(false)).to.throw(error('false'));
|
|
24
|
-
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
25
|
-
expect(throwable(null)).to.throw(error('null'));
|
|
26
31
|
expect(throwable({})).to.throw(error('Object'));
|
|
27
32
|
expect(throwable([])).to.throw(error('Array'));
|
|
28
33
|
expect(throwable(() => undefined)).to.throw(error('Function'));
|
|
29
34
|
throwable('str')();
|
|
30
35
|
throwable('')();
|
|
36
|
+
throwable(undefined)();
|
|
37
|
+
throwable(null)();
|
|
31
38
|
});
|
|
32
39
|
|
|
33
40
|
it('requires the "options" argument to be a string or RegExp', function () {
|