@e22m4u/js-repository 0.1.6 → 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 +31 -0
- 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 +1 -1
- 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 +16 -1
- 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 +1 -1
- package/docs/types/PropertyValidatorContext.html +1 -1
- 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 +6 -5
- package/src/adapter/decorator/data-validation-decorator.spec.js +49 -21
- 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.js +10 -12
- package/src/definition/model/model-data-validator.spec.js +133 -32
- 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
|
@@ -3,6 +3,7 @@ import {Schema} from '../../schema.js';
|
|
|
3
3
|
import {format} from '@e22m4u/js-format';
|
|
4
4
|
import {DataType} from './properties/index.js';
|
|
5
5
|
import {ModelDataValidator} from './model-data-validator.js';
|
|
6
|
+
import {DefinitionRegistry} from '../definition-registry.js';
|
|
6
7
|
import {PropertyValidatorRegistry} from './properties/index.js';
|
|
7
8
|
|
|
8
9
|
describe('ModelDataValidator', function () {
|
|
@@ -1998,7 +1999,7 @@ describe('ModelDataValidator', function () {
|
|
|
1998
1999
|
|
|
1999
2000
|
describe('validate by property validators', function () {
|
|
2000
2001
|
describe('the option "validate" with the string value', function () {
|
|
2001
|
-
it('
|
|
2002
|
+
it('validates a property value even is not provided', function () {
|
|
2002
2003
|
const S = new Schema();
|
|
2003
2004
|
S.getService(PropertyValidatorRegistry).addValidator(
|
|
2004
2005
|
'myValidator',
|
|
@@ -2011,20 +2012,41 @@ describe('ModelDataValidator', function () {
|
|
|
2011
2012
|
type: DataType.ANY,
|
|
2012
2013
|
validate: 'myValidator',
|
|
2013
2014
|
},
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2015
|
+
},
|
|
2016
|
+
});
|
|
2017
|
+
const validator = S.getService(ModelDataValidator);
|
|
2018
|
+
const throwable = () => validator.validate('model', {});
|
|
2019
|
+
expect(throwable).to.throw(
|
|
2020
|
+
'The property "foo" of the model "model" has an invalid value undefined ' +
|
|
2021
|
+
'that caught by the validator "myValidator".',
|
|
2022
|
+
);
|
|
2023
|
+
});
|
|
2024
|
+
|
|
2025
|
+
it('validates undefined and null values', function () {
|
|
2026
|
+
const S = new Schema();
|
|
2027
|
+
S.getService(PropertyValidatorRegistry).addValidator(
|
|
2028
|
+
'myValidator',
|
|
2029
|
+
() => false,
|
|
2030
|
+
);
|
|
2031
|
+
S.defineModel({
|
|
2032
|
+
name: 'model',
|
|
2033
|
+
properties: {
|
|
2034
|
+
foo: {
|
|
2019
2035
|
type: DataType.ANY,
|
|
2020
2036
|
validate: 'myValidator',
|
|
2021
2037
|
},
|
|
2022
2038
|
},
|
|
2023
2039
|
});
|
|
2024
|
-
S.getService(ModelDataValidator)
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2040
|
+
const validator = S.getService(ModelDataValidator);
|
|
2041
|
+
const throwable = v => () => validator.validate('model', {foo: v});
|
|
2042
|
+
const error = v =>
|
|
2043
|
+
format(
|
|
2044
|
+
'The property "foo" of the model "model" has an invalid value %s ' +
|
|
2045
|
+
'that caught by the validator "myValidator".',
|
|
2046
|
+
v,
|
|
2047
|
+
);
|
|
2048
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
2049
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
2028
2050
|
});
|
|
2029
2051
|
|
|
2030
2052
|
it('throws an error from the validator', function () {
|
|
@@ -2211,7 +2233,7 @@ describe('ModelDataValidator', function () {
|
|
|
2211
2233
|
});
|
|
2212
2234
|
});
|
|
2213
2235
|
|
|
2214
|
-
it('
|
|
2236
|
+
it('validates a property value even is not provided', function () {
|
|
2215
2237
|
const S = new Schema();
|
|
2216
2238
|
S.getService(PropertyValidatorRegistry).addValidator(
|
|
2217
2239
|
'myValidator',
|
|
@@ -2224,20 +2246,41 @@ describe('ModelDataValidator', function () {
|
|
|
2224
2246
|
type: DataType.ANY,
|
|
2225
2247
|
validate: ['myValidator'],
|
|
2226
2248
|
},
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2249
|
+
},
|
|
2250
|
+
});
|
|
2251
|
+
const validator = S.getService(ModelDataValidator);
|
|
2252
|
+
const throwable = () => validator.validate('model', {});
|
|
2253
|
+
expect(throwable).to.throw(
|
|
2254
|
+
'The property "foo" of the model "model" has an invalid value undefined ' +
|
|
2255
|
+
'that caught by the validator "myValidator".',
|
|
2256
|
+
);
|
|
2257
|
+
});
|
|
2258
|
+
|
|
2259
|
+
it('validates undefined and null values', function () {
|
|
2260
|
+
const S = new Schema();
|
|
2261
|
+
S.getService(PropertyValidatorRegistry).addValidator(
|
|
2262
|
+
'myValidator',
|
|
2263
|
+
() => false,
|
|
2264
|
+
);
|
|
2265
|
+
S.defineModel({
|
|
2266
|
+
name: 'model',
|
|
2267
|
+
properties: {
|
|
2268
|
+
foo: {
|
|
2232
2269
|
type: DataType.ANY,
|
|
2233
2270
|
validate: ['myValidator'],
|
|
2234
2271
|
},
|
|
2235
2272
|
},
|
|
2236
2273
|
});
|
|
2237
|
-
S.getService(ModelDataValidator)
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2274
|
+
const validator = S.getService(ModelDataValidator);
|
|
2275
|
+
const throwable = v => () => validator.validate('model', {foo: v});
|
|
2276
|
+
const error = v =>
|
|
2277
|
+
format(
|
|
2278
|
+
'The property "foo" of the model "model" has an invalid value %s ' +
|
|
2279
|
+
'that caught by the validator "myValidator".',
|
|
2280
|
+
v,
|
|
2281
|
+
);
|
|
2282
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
2283
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
2241
2284
|
});
|
|
2242
2285
|
|
|
2243
2286
|
it('throws an error from the validator', function () {
|
|
@@ -2425,7 +2468,7 @@ describe('ModelDataValidator', function () {
|
|
|
2425
2468
|
});
|
|
2426
2469
|
});
|
|
2427
2470
|
|
|
2428
|
-
it('
|
|
2471
|
+
it('validates a property value even is not provided', function () {
|
|
2429
2472
|
const S = new Schema();
|
|
2430
2473
|
S.getService(PropertyValidatorRegistry).addValidator(
|
|
2431
2474
|
'myValidator',
|
|
@@ -2440,13 +2483,26 @@ describe('ModelDataValidator', function () {
|
|
|
2440
2483
|
myValidator: true,
|
|
2441
2484
|
},
|
|
2442
2485
|
},
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2486
|
+
},
|
|
2487
|
+
});
|
|
2488
|
+
const validator = S.getService(ModelDataValidator);
|
|
2489
|
+
const throwable = () => validator.validate('model', {});
|
|
2490
|
+
expect(throwable).to.throw(
|
|
2491
|
+
'The property "foo" of the model "model" has an invalid value undefined ' +
|
|
2492
|
+
'that caught by the validator "myValidator".',
|
|
2493
|
+
);
|
|
2494
|
+
});
|
|
2495
|
+
|
|
2496
|
+
it('validates undefined and null values', function () {
|
|
2497
|
+
const S = new Schema();
|
|
2498
|
+
S.getService(PropertyValidatorRegistry).addValidator(
|
|
2499
|
+
'myValidator',
|
|
2500
|
+
() => false,
|
|
2501
|
+
);
|
|
2502
|
+
S.defineModel({
|
|
2503
|
+
name: 'model',
|
|
2504
|
+
properties: {
|
|
2505
|
+
foo: {
|
|
2450
2506
|
type: DataType.ANY,
|
|
2451
2507
|
validate: {
|
|
2452
2508
|
myValidator: true,
|
|
@@ -2454,10 +2510,16 @@ describe('ModelDataValidator', function () {
|
|
|
2454
2510
|
},
|
|
2455
2511
|
},
|
|
2456
2512
|
});
|
|
2457
|
-
S.getService(ModelDataValidator)
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2513
|
+
const validator = S.getService(ModelDataValidator);
|
|
2514
|
+
const throwable = v => () => validator.validate('model', {foo: v});
|
|
2515
|
+
const error = v =>
|
|
2516
|
+
format(
|
|
2517
|
+
'The property "foo" of the model "model" has an invalid value %s ' +
|
|
2518
|
+
'that caught by the validator "myValidator".',
|
|
2519
|
+
v,
|
|
2520
|
+
);
|
|
2521
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
2522
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
2461
2523
|
});
|
|
2462
2524
|
|
|
2463
2525
|
it('throws an error from the validator', function () {
|
|
@@ -2676,6 +2738,45 @@ describe('ModelDataValidator', function () {
|
|
|
2676
2738
|
expect(validated).to.be.true;
|
|
2677
2739
|
});
|
|
2678
2740
|
});
|
|
2741
|
+
|
|
2742
|
+
it('the option "validate" requires a non-empty String, an Array or an Object', function () {
|
|
2743
|
+
const schema = new Schema();
|
|
2744
|
+
schema
|
|
2745
|
+
.getService(PropertyValidatorRegistry)
|
|
2746
|
+
.addValidator('myValidator', () => true);
|
|
2747
|
+
schema.defineModel({
|
|
2748
|
+
name: 'model',
|
|
2749
|
+
properties: {
|
|
2750
|
+
foo: {
|
|
2751
|
+
type: DataType.STRING,
|
|
2752
|
+
validate: undefined,
|
|
2753
|
+
},
|
|
2754
|
+
},
|
|
2755
|
+
});
|
|
2756
|
+
const V = schema.getService(ModelDataValidator);
|
|
2757
|
+
const throwable = v => () => {
|
|
2758
|
+
const models = schema.getService(DefinitionRegistry)['_models'];
|
|
2759
|
+
models.model.properties.foo.validate = v;
|
|
2760
|
+
V.validate('model', {});
|
|
2761
|
+
};
|
|
2762
|
+
const error = v =>
|
|
2763
|
+
format(
|
|
2764
|
+
'The provided option "validate" of the property "foo" in the model "model" ' +
|
|
2765
|
+
'should be a non-empty String, an Array of String or an Object, ' +
|
|
2766
|
+
'but %s given.',
|
|
2767
|
+
v,
|
|
2768
|
+
);
|
|
2769
|
+
expect(throwable('')).to.throw(error('""'));
|
|
2770
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
2771
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
2772
|
+
expect(throwable(true)).to.throw(error('true'));
|
|
2773
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
2774
|
+
throwable('myValidator')();
|
|
2775
|
+
throwable(['myValidator'])();
|
|
2776
|
+
throwable([])();
|
|
2777
|
+
throwable({myValidator: true})();
|
|
2778
|
+
throwable({})();
|
|
2779
|
+
});
|
|
2679
2780
|
});
|
|
2680
2781
|
});
|
|
2681
2782
|
});
|
|
@@ -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
|
+
}
|