@e22m4u/js-repository 0.1.2 → 0.1.3
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/.husky/commit-msg +1 -4
- package/.husky/pre-commit +0 -3
- package/README.md +2 -2
- package/docs/classes/Adapter.html +14 -14
- package/docs/classes/AdapterLoader.html +2 -2
- package/docs/classes/AdapterRegistry.html +2 -2
- package/docs/classes/BelongsToResolver.html +3 -3
- package/docs/classes/DatasourceDefinitionValidator.html +2 -2
- package/docs/classes/DefinitionRegistry.html +7 -7
- package/docs/classes/FieldsClauseTool.html +4 -4
- package/docs/classes/HasManyResolver.html +4 -4
- package/docs/classes/HasOneResolver.html +4 -4
- package/docs/classes/IncludeClauseTool.html +6 -6
- package/docs/classes/InvalidArgumentError.html +1 -1
- package/docs/classes/InvalidOperatorValueError.html +2 -2
- package/docs/classes/ModelDataSanitizer.html +2 -2
- package/docs/classes/ModelDataValidator.html +3 -3
- package/docs/classes/ModelDefinitionUtils.html +17 -17
- package/docs/classes/ModelDefinitionValidator.html +2 -2
- package/docs/classes/NotImplementedError.html +1 -1
- package/docs/classes/OperatorClauseTool.html +14 -14
- package/docs/classes/OrderClauseTool.html +4 -4
- package/docs/classes/PrimaryKeysDefinitionValidator.html +2 -2
- package/docs/classes/PropertiesDefinitionValidator.html +2 -2
- package/docs/classes/ReferencesManyResolver.html +2 -2
- package/docs/classes/RelationsDefinitionValidator.html +2 -2
- package/docs/classes/Repository.html +17 -17
- package/docs/classes/RepositoryRegistry.html +3 -3
- package/docs/classes/Schema.html +4 -4
- package/docs/classes/SliceClauseTool.html +4 -4
- package/docs/classes/WhereClauseTool.html +3 -3
- package/docs/enums/DataType.html +2 -2
- package/docs/enums/DecoratorTargetType.html +2 -2
- package/docs/enums/RelationType.html +2 -2
- 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 +2 -2
- package/docs/interfaces/AndClause.html +2 -2
- package/docs/interfaces/Constructor.html +2 -2
- package/docs/interfaces/OrClause.html +2 -2
- 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/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 +20 -21
- package/src/adapter/decorator/data-validation-decorator.js +18 -10
- package/src/adapter/decorator/data-validation-decorator.spec.js +40 -0
- package/src/definition/model/model-data-validator.d.ts +4 -16
- package/src/definition/model/model-data-validator.js +92 -11
- package/src/definition/model/model-data-validator.spec.js +1140 -442
- 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 +50 -0
- package/src/definition/model/properties/property-definition.d.ts +2 -0
- package/src/definition/model/properties/property-validator/index.d.ts +2 -0
- package/src/definition/model/properties/property-validator/index.js +2 -0
- package/src/definition/model/properties/property-validator/property-validator-registry.d.ts +29 -0
- package/src/definition/model/properties/property-validator/property-validator-registry.js +69 -0
- package/src/definition/model/properties/property-validator/property-validator-registry.spec.js +120 -0
- package/src/definition/model/properties/property-validator/property-validator.d.ts +30 -0
- package/src/definition/model/properties/property-validator/property-validator.js +1 -0
- package/src/schema.d.ts +9 -0
- package/src/schema.js +13 -0
- package/src/schema.spec.ts +44 -0
|
@@ -2,6 +2,7 @@ import {Service} from '@e22m4u/js-service';
|
|
|
2
2
|
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
|
+
import {PropertyValidatorRegistry} from './property-validator/index.js';
|
|
5
6
|
import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -203,5 +204,51 @@ export class PropertiesDefinitionValidator extends Service {
|
|
|
203
204
|
);
|
|
204
205
|
}
|
|
205
206
|
}
|
|
207
|
+
if (propDef.validate != null) {
|
|
208
|
+
const propertyValidatorRegistry = this.getService(
|
|
209
|
+
PropertyValidatorRegistry,
|
|
210
|
+
);
|
|
211
|
+
if (propDef.validate && typeof propDef.validate === 'string') {
|
|
212
|
+
if (!propertyValidatorRegistry.hasValidator(propDef.validate))
|
|
213
|
+
throw new InvalidArgumentError(
|
|
214
|
+
'The property validator %v is not found.',
|
|
215
|
+
propDef.validate,
|
|
216
|
+
);
|
|
217
|
+
} else if (Array.isArray(propDef.validate)) {
|
|
218
|
+
for (const validatorName of propDef.validate) {
|
|
219
|
+
if (typeof validatorName !== 'string')
|
|
220
|
+
throw new InvalidArgumentError(
|
|
221
|
+
'The provided option "validate" of the property %v in the model %v ' +
|
|
222
|
+
'has an Array value that should have a non-empty String, ' +
|
|
223
|
+
'but %v given.',
|
|
224
|
+
propName,
|
|
225
|
+
modelName,
|
|
226
|
+
validatorName,
|
|
227
|
+
);
|
|
228
|
+
if (!propertyValidatorRegistry.hasValidator(validatorName))
|
|
229
|
+
throw new InvalidArgumentError(
|
|
230
|
+
'The property validator %v is not found.',
|
|
231
|
+
validatorName,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
} else if (typeof propDef.validate === 'object') {
|
|
235
|
+
for (const validatorName in propDef.validate) {
|
|
236
|
+
if (!propertyValidatorRegistry.hasValidator(validatorName))
|
|
237
|
+
throw new InvalidArgumentError(
|
|
238
|
+
'The property validator %v is not found.',
|
|
239
|
+
validatorName,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
throw new InvalidArgumentError(
|
|
244
|
+
'The provided option "validate" of the property %v in the model %v ' +
|
|
245
|
+
'should be a non-empty String, an Array of String or an Object, ' +
|
|
246
|
+
'but %v given.',
|
|
247
|
+
propName,
|
|
248
|
+
modelName,
|
|
249
|
+
propDef.validate,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
206
253
|
}
|
|
207
254
|
}
|
|
@@ -2,12 +2,15 @@ import chai from 'chai';
|
|
|
2
2
|
import {expect} from 'chai';
|
|
3
3
|
import {DataType} from './data-type.js';
|
|
4
4
|
import {format} from '@e22m4u/js-format';
|
|
5
|
+
import {PropertyValidatorRegistry} from './property-validator/index.js';
|
|
5
6
|
import {PropertiesDefinitionValidator} from './properties-definition-validator.js';
|
|
6
7
|
import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
|
|
7
8
|
|
|
8
9
|
const S = new PropertiesDefinitionValidator();
|
|
9
10
|
const sandbox = chai.spy.sandbox();
|
|
10
11
|
|
|
12
|
+
S.getService(PropertyValidatorRegistry).addValidator('myValidator', () => true);
|
|
13
|
+
|
|
11
14
|
describe('PropertiesDefinitionValidator', function () {
|
|
12
15
|
afterEach(function () {
|
|
13
16
|
sandbox.restore();
|
|
@@ -386,5 +389,52 @@ describe('PropertiesDefinitionValidator', function () {
|
|
|
386
389
|
expect(V.validate).to.have.been.called.once;
|
|
387
390
|
expect(V.validate).to.have.been.called.with.exactly('model', propDefs);
|
|
388
391
|
});
|
|
392
|
+
|
|
393
|
+
it('the option "validate" should have a non-empty String, an Array of String or an Object', function () {
|
|
394
|
+
const validate = v => () => {
|
|
395
|
+
const foo = {
|
|
396
|
+
type: DataType.ANY,
|
|
397
|
+
validate: v,
|
|
398
|
+
};
|
|
399
|
+
S.validate('model', {foo});
|
|
400
|
+
};
|
|
401
|
+
const error = v =>
|
|
402
|
+
format(
|
|
403
|
+
'The provided option "validate" of the property "foo" in the model "model" ' +
|
|
404
|
+
'should be a non-empty String, an Array of String or an Object, ' +
|
|
405
|
+
'but %s given.',
|
|
406
|
+
v,
|
|
407
|
+
);
|
|
408
|
+
expect(validate('')).to.throw(error('""'));
|
|
409
|
+
expect(validate(10)).to.throw(error('10'));
|
|
410
|
+
expect(validate(0)).to.throw(error('0'));
|
|
411
|
+
expect(validate(true)).to.throw(error('true'));
|
|
412
|
+
expect(validate(false)).to.throw(error('false'));
|
|
413
|
+
expect(validate(() => undefined)).to.throw(error('Function'));
|
|
414
|
+
validate('myValidator')();
|
|
415
|
+
validate(['myValidator'])();
|
|
416
|
+
validate([])();
|
|
417
|
+
validate({myValidator: true})();
|
|
418
|
+
validate({})();
|
|
419
|
+
validate(null)();
|
|
420
|
+
validate(undefined)();
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
it('the option "validate" requires only existing validator names', function () {
|
|
424
|
+
const validate = v => () => {
|
|
425
|
+
const foo = {
|
|
426
|
+
type: DataType.ANY,
|
|
427
|
+
validate: v,
|
|
428
|
+
};
|
|
429
|
+
S.validate('model', {foo});
|
|
430
|
+
};
|
|
431
|
+
const error = v => format('The property validator %s is not found.', v);
|
|
432
|
+
expect(validate('unknown')).to.throw(error('"unknown"'));
|
|
433
|
+
expect(validate({unknown: true})).to.throw(error('"unknown"'));
|
|
434
|
+
expect(validate(['unknown'])).to.throw(error('"unknown"'));
|
|
435
|
+
validate('myValidator')();
|
|
436
|
+
validate(['myValidator'])();
|
|
437
|
+
validate({myValidator: true})();
|
|
438
|
+
});
|
|
389
439
|
});
|
|
390
440
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {DataType} from './data-type.js';
|
|
2
|
+
import {PropertyValidateOptions} from './property-validator/index.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Full property definition.
|
|
@@ -12,6 +13,7 @@ export declare type FullPropertyDefinition = {
|
|
|
12
13
|
columnType?: string;
|
|
13
14
|
required?: boolean;
|
|
14
15
|
default?: unknown;
|
|
16
|
+
validate?: PropertyValidateOptions;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {PropertyValidator} from './property-validator.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Property validator registry.
|
|
6
|
+
*/
|
|
7
|
+
export declare class PropertyValidatorRegistry extends Service {
|
|
8
|
+
/**
|
|
9
|
+
* Add validator.
|
|
10
|
+
*
|
|
11
|
+
* @param name
|
|
12
|
+
* @param validator
|
|
13
|
+
*/
|
|
14
|
+
addValidator(name: string, validator: PropertyValidator): this;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Has validator.
|
|
18
|
+
*
|
|
19
|
+
* @param name
|
|
20
|
+
*/
|
|
21
|
+
hasValidator(name: string): boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get validator.
|
|
25
|
+
*
|
|
26
|
+
* @param name
|
|
27
|
+
*/
|
|
28
|
+
getValidator(name: string): PropertyValidator;
|
|
29
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {InvalidArgumentError} from '../../../../errors/index.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Property validator registry.
|
|
6
|
+
*/
|
|
7
|
+
export class PropertyValidatorRegistry extends Service {
|
|
8
|
+
/**
|
|
9
|
+
* Validators.
|
|
10
|
+
*
|
|
11
|
+
* @type {object}
|
|
12
|
+
*/
|
|
13
|
+
_validators = {};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Add validator.
|
|
17
|
+
*
|
|
18
|
+
* @param {string} name
|
|
19
|
+
* @param {Function} validator
|
|
20
|
+
* @returns {PropertyValidatorRegistry}
|
|
21
|
+
*/
|
|
22
|
+
addValidator(name, validator) {
|
|
23
|
+
if (!name || typeof name !== 'string')
|
|
24
|
+
throw new InvalidArgumentError(
|
|
25
|
+
'A name of the property validator must ' +
|
|
26
|
+
'be a non-empty String, but %v given.',
|
|
27
|
+
name,
|
|
28
|
+
);
|
|
29
|
+
if (name in this._validators)
|
|
30
|
+
throw new InvalidArgumentError(
|
|
31
|
+
'The property validator %v is already defined.',
|
|
32
|
+
name,
|
|
33
|
+
);
|
|
34
|
+
if (typeof validator !== 'function')
|
|
35
|
+
throw new InvalidArgumentError(
|
|
36
|
+
'The property validator %v must be a Function, but %v given.',
|
|
37
|
+
name,
|
|
38
|
+
validator,
|
|
39
|
+
);
|
|
40
|
+
this._validators[name] = validator;
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Has validator.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} name
|
|
48
|
+
* @returns {boolean}
|
|
49
|
+
*/
|
|
50
|
+
hasValidator(name) {
|
|
51
|
+
return Boolean(this._validators[name]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get validator.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} name
|
|
58
|
+
* @returns {Function}
|
|
59
|
+
*/
|
|
60
|
+
getValidator(name) {
|
|
61
|
+
const validator = this._validators[name];
|
|
62
|
+
if (!validator)
|
|
63
|
+
throw new InvalidArgumentError(
|
|
64
|
+
'The property validator %v is not defined.',
|
|
65
|
+
name,
|
|
66
|
+
);
|
|
67
|
+
return validator;
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/definition/model/properties/property-validator/property-validator-registry.spec.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {format} from '@e22m4u/js-format';
|
|
3
|
+
import {PropertyValidatorRegistry} from './property-validator-registry.js';
|
|
4
|
+
|
|
5
|
+
describe('PropertyValidatorRegistry', function () {
|
|
6
|
+
describe('addValidator', function () {
|
|
7
|
+
it('adds a given validator with the name', function () {
|
|
8
|
+
const s = new PropertyValidatorRegistry();
|
|
9
|
+
const myValidator = () => {};
|
|
10
|
+
const res = s.addValidator('myValidator', myValidator);
|
|
11
|
+
expect(res).to.be.eq(s);
|
|
12
|
+
expect(s['_validators']).to.be.eql({myValidator});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('requires the given name to be a non-empty string', function () {
|
|
16
|
+
const s = new PropertyValidatorRegistry();
|
|
17
|
+
const throwable = v => () => s.addValidator(v, () => undefined);
|
|
18
|
+
const error = v =>
|
|
19
|
+
format(
|
|
20
|
+
'A name of the property validator must ' +
|
|
21
|
+
'be a non-empty String, but %s given.',
|
|
22
|
+
v,
|
|
23
|
+
);
|
|
24
|
+
expect(throwable('')).to.throw(error('""'));
|
|
25
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
26
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
27
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
28
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
29
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
30
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
31
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
32
|
+
expect(throwable(() => undefined)).to.throw(error('Function'));
|
|
33
|
+
throwable('str')();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('throws an error if the given name already exists', function () {
|
|
37
|
+
const s = new PropertyValidatorRegistry();
|
|
38
|
+
s.addValidator('test', () => undefined);
|
|
39
|
+
const throwable = () => s.addValidator('test', () => undefined);
|
|
40
|
+
expect(throwable).to.throw(
|
|
41
|
+
'The property validator "test" is already defined.',
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('requires the given validator to be a function', function () {
|
|
46
|
+
const s = new PropertyValidatorRegistry();
|
|
47
|
+
const throwable = v => () => s.addValidator('test', v);
|
|
48
|
+
const error = v =>
|
|
49
|
+
format(
|
|
50
|
+
'The property validator "test" must be a Function, but %s given.',
|
|
51
|
+
v,
|
|
52
|
+
);
|
|
53
|
+
expect(throwable('str')).to.throw(error('"str"'));
|
|
54
|
+
expect(throwable('')).to.throw(error('""'));
|
|
55
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
56
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
57
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
58
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
59
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
60
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
61
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
62
|
+
throwable(() => undefined)();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('hasValidator', function () {
|
|
67
|
+
it('returns false for a not existing name', function () {
|
|
68
|
+
const s = new PropertyValidatorRegistry();
|
|
69
|
+
expect(s.hasValidator('str')).to.be.false;
|
|
70
|
+
expect(s.hasValidator('')).to.be.false;
|
|
71
|
+
expect(s.hasValidator(10)).to.be.false;
|
|
72
|
+
expect(s.hasValidator(0)).to.be.false;
|
|
73
|
+
expect(s.hasValidator(true)).to.be.false;
|
|
74
|
+
expect(s.hasValidator(false)).to.be.false;
|
|
75
|
+
expect(s.hasValidator(null)).to.be.false;
|
|
76
|
+
expect(s.hasValidator(undefined)).to.be.false;
|
|
77
|
+
expect(s.hasValidator({})).to.be.false;
|
|
78
|
+
expect(s.hasValidator([])).to.be.false;
|
|
79
|
+
expect(s.hasValidator(() => undefined)).to.be.false;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('returns true for an existing name', function () {
|
|
83
|
+
const s = new PropertyValidatorRegistry();
|
|
84
|
+
expect(s.hasValidator('test')).to.be.false;
|
|
85
|
+
s.addValidator('test', () => undefined);
|
|
86
|
+
expect(s.hasValidator('test')).to.be.true;
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('getValidator', function () {
|
|
91
|
+
it('returns validator by its name', function () {
|
|
92
|
+
const s = new PropertyValidatorRegistry();
|
|
93
|
+
const validator1 = () => undefined;
|
|
94
|
+
const validator2 = () => undefined;
|
|
95
|
+
s.addValidator('foo', validator1);
|
|
96
|
+
s.addValidator('bar', validator2);
|
|
97
|
+
const res1 = s.getValidator('foo');
|
|
98
|
+
const res2 = s.getValidator('bar');
|
|
99
|
+
expect(res1).to.be.eq(validator1);
|
|
100
|
+
expect(res2).to.be.eq(validator2);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('throws an error for a not existed name', function () {
|
|
104
|
+
const s = new PropertyValidatorRegistry();
|
|
105
|
+
const throwable = v => () => s.getValidator(v);
|
|
106
|
+
const error = v => format('The property validator %s is not defined.', v);
|
|
107
|
+
expect(throwable('str')).to.throw(error('"str"'));
|
|
108
|
+
expect(throwable('')).to.throw(error('""'));
|
|
109
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
110
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
111
|
+
expect(throwable(true)).to.throw(error('true'));
|
|
112
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
113
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
114
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
115
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
116
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
117
|
+
expect(throwable(() => undefined)).to.throw(error('Function'));
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {ServiceContainer} from '@e22m4u/js-service';
|
|
2
|
+
import {FullPropertyDefinition} from '../property-definition.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Property validator context.
|
|
6
|
+
*/
|
|
7
|
+
export type PropertyValidatorContext = {
|
|
8
|
+
validatorName: string,
|
|
9
|
+
modelName: string,
|
|
10
|
+
propName: string,
|
|
11
|
+
propDef: FullPropertyDefinition,
|
|
12
|
+
container: ServiceContainer,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Property validator.
|
|
17
|
+
*/
|
|
18
|
+
export type PropertyValidator = (
|
|
19
|
+
value: unknown,
|
|
20
|
+
options: unknown,
|
|
21
|
+
context: PropertyValidatorContext,
|
|
22
|
+
) => Promise<boolean> | boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Property validate options.
|
|
26
|
+
*/
|
|
27
|
+
export type PropertyValidateOptions =
|
|
28
|
+
| string
|
|
29
|
+
| string[]
|
|
30
|
+
| {[key: string]: unknown};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/src/schema.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {ModelData} from './types.js';
|
|
|
3
3
|
import {Service} from '@e22m4u/js-service';
|
|
4
4
|
import {Repository} from './repository/index.js';
|
|
5
5
|
import {ModelDefinition} from './definition/index.js';
|
|
6
|
+
import {PropertyValidator} from './definition/index.js';
|
|
6
7
|
import {DatasourceDefinition} from './definition/index.js';
|
|
7
8
|
import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME} from './definition/index.js';
|
|
8
9
|
|
|
@@ -34,4 +35,12 @@ export declare class Schema extends Service {
|
|
|
34
35
|
IdType extends ModelId = ModelId,
|
|
35
36
|
IdName extends string = DEFAULT_PRIMARY_KEY_PROPERTY_NAME,
|
|
36
37
|
>(modelName: string): Repository<Data, IdType, IdName>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Add property validator.
|
|
41
|
+
*
|
|
42
|
+
* @param name
|
|
43
|
+
* @param validator
|
|
44
|
+
*/
|
|
45
|
+
addPropertyValidator(name: string, validator: PropertyValidator): this;
|
|
37
46
|
}
|
package/src/schema.js
CHANGED
|
@@ -2,6 +2,7 @@ import {Service} from '@e22m4u/js-service';
|
|
|
2
2
|
import {Repository} from './repository/index.js';
|
|
3
3
|
import {DefinitionRegistry} from './definition/index.js';
|
|
4
4
|
import {RepositoryRegistry} from './repository/index.js';
|
|
5
|
+
import {PropertyValidatorRegistry} from './definition/index.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Schema.
|
|
@@ -38,4 +39,16 @@ export class Schema extends Service {
|
|
|
38
39
|
getRepository(modelName) {
|
|
39
40
|
return this.getService(RepositoryRegistry).getRepository(modelName);
|
|
40
41
|
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Add property validator.
|
|
45
|
+
*
|
|
46
|
+
* @param {string} name
|
|
47
|
+
* @param {Function} validator
|
|
48
|
+
* @returns {this}
|
|
49
|
+
*/
|
|
50
|
+
addPropertyValidator(name, validator) {
|
|
51
|
+
this.getService(PropertyValidatorRegistry).addValidator(name, validator);
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
41
54
|
}
|
package/src/schema.spec.ts
CHANGED
|
@@ -2,9 +2,19 @@ import {expect} from 'chai';
|
|
|
2
2
|
import {Schema} from './schema.js';
|
|
3
3
|
import {Repository} from './repository/index.js';
|
|
4
4
|
import {DefinitionRegistry} from './definition/index.js';
|
|
5
|
+
import {PropertyValidatorRegistry} from './definition/index.js';
|
|
5
6
|
|
|
6
7
|
describe('Schema', function () {
|
|
7
8
|
describe('defineDatasource', function () {
|
|
9
|
+
it('returns this', function () {
|
|
10
|
+
const schema = new Schema();
|
|
11
|
+
const res = schema.defineDatasource({
|
|
12
|
+
name: 'datasource',
|
|
13
|
+
adapter: 'memory',
|
|
14
|
+
});
|
|
15
|
+
expect(res).to.be.eq(schema);
|
|
16
|
+
});
|
|
17
|
+
|
|
8
18
|
it('sets the datasource definition', function () {
|
|
9
19
|
const schema = new Schema();
|
|
10
20
|
schema.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
@@ -25,6 +35,12 @@ describe('Schema', function () {
|
|
|
25
35
|
});
|
|
26
36
|
|
|
27
37
|
describe('defineModel', function () {
|
|
38
|
+
it('returns this', function () {
|
|
39
|
+
const schema = new Schema();
|
|
40
|
+
const res = schema.defineModel({name: 'model'});
|
|
41
|
+
expect(res).to.be.eq(schema);
|
|
42
|
+
});
|
|
43
|
+
|
|
28
44
|
it('sets the model definition', function () {
|
|
29
45
|
const schema = new Schema();
|
|
30
46
|
schema.defineModel({name: 'model'});
|
|
@@ -68,4 +84,32 @@ describe('Schema', function () {
|
|
|
68
84
|
expect(res1).to.be.eq(res2);
|
|
69
85
|
});
|
|
70
86
|
});
|
|
87
|
+
|
|
88
|
+
describe('addPropertyValidator', function () {
|
|
89
|
+
it('returns this', function () {
|
|
90
|
+
const schema = new Schema();
|
|
91
|
+
const res = schema.addPropertyValidator('validator', () => true);
|
|
92
|
+
expect(res).to.be.eq(schema);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('adds a new property validator', function () {
|
|
96
|
+
const schema = new Schema();
|
|
97
|
+
const validator = () => true;
|
|
98
|
+
schema.addPropertyValidator('validator', validator);
|
|
99
|
+
const res = schema.getService(PropertyValidatorRegistry)
|
|
100
|
+
.getValidator('validator');
|
|
101
|
+
expect(res).to.be.eq(validator);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('throws an error for already existing validator name', function () {
|
|
105
|
+
const schema = new Schema();
|
|
106
|
+
const validator = () => true;
|
|
107
|
+
schema.addPropertyValidator('validator', validator);
|
|
108
|
+
const throwable =
|
|
109
|
+
() => schema.addPropertyValidator('validator', validator);
|
|
110
|
+
expect(throwable).to.throw(
|
|
111
|
+
'The property validator "validator" is already defined.',
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
71
115
|
});
|