| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- import {Service} from '@e22m4u/js-service';
- import {DataType as Type} from './data-type.js';
- import {capitalize} from '../../../utils/index.js';
- import {PropertyUniqueness} from './property-uniqueness.js';
- import {InvalidArgumentError} from '../../../errors/index.js';
- import {PropertyValidatorRegistry} from './property-validator/index.js';
- import {PropertyTransformerRegistry} from './property-transformer/index.js';
- import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
- /**
- * Properties definition validator.
- */
- export class PropertiesDefinitionValidator extends Service {
- /**
- * Validate.
- *
- * @param {string} modelName
- * @param {object} propDefs
- */
- validate(modelName, propDefs) {
- if (!modelName || typeof modelName !== 'string')
- throw new InvalidArgumentError(
- 'The first argument of PropertiesDefinitionValidator.validate ' +
- 'should be a non-empty String, but %v given.',
- modelName,
- );
- if (!propDefs || typeof propDefs !== 'object' || Array.isArray(propDefs)) {
- throw new InvalidArgumentError(
- 'The provided option "properties" of the model %v ' +
- 'should be an Object, but %v given.',
- modelName,
- propDefs,
- );
- }
- const propNames = Object.keys(propDefs);
- propNames.forEach(propName => {
- const propDef = propDefs[propName];
- this._validateProperty(modelName, propName, propDef);
- });
- this.getService(PrimaryKeysDefinitionValidator).validate(
- modelName,
- propDefs,
- );
- }
- /**
- * Validate property.
- *
- * @param {string} modelName
- * @param {string} propName
- * @param {object} propDef
- */
- _validateProperty(modelName, propName, propDef) {
- if (!modelName || typeof modelName !== 'string')
- throw new InvalidArgumentError(
- 'The first argument of PropertiesDefinitionValidator._validateProperty ' +
- 'should be a non-empty String, but %v given.',
- modelName,
- );
- if (!propName || typeof propName !== 'string')
- throw new InvalidArgumentError(
- 'The property name of the model %v should be ' +
- 'a non-empty String, but %v given.',
- modelName,
- propName,
- );
- if (!propDef)
- throw new InvalidArgumentError(
- 'The property %v of the model %v should have ' +
- 'a property definition, but %v given.',
- propName,
- modelName,
- propDef,
- );
- if (typeof propDef === 'string') {
- if (!Object.values(Type).includes(propDef))
- throw new InvalidArgumentError(
- 'In case of a short property definition, the property %v ' +
- 'of the model %v should have one of data types: %l, but %v given.',
- propName,
- modelName,
- Object.values(Type),
- propDef,
- );
- return;
- }
- if (!propDef || typeof propDef !== 'object' || Array.isArray(propDef)) {
- throw new InvalidArgumentError(
- 'In case of a full property definition, the property %v ' +
- 'of the model %v should be an Object, but %v given.',
- propName,
- modelName,
- propDef,
- );
- }
- if (!propDef.type || !Object.values(Type).includes(propDef.type))
- throw new InvalidArgumentError(
- 'The property %v of the model %v requires the option "type" ' +
- 'to have one of data types: %l, but %v given.',
- propName,
- modelName,
- Object.values(Type),
- propDef.type,
- );
- if (propDef.itemType && !Object.values(Type).includes(propDef.itemType)) {
- throw new InvalidArgumentError(
- 'The provided option "itemType" of the property %v in the model %v ' +
- 'should have one of data types: %l, but %v given.',
- propName,
- modelName,
- Object.values(Type),
- propDef.itemType,
- );
- }
- if (propDef.model && typeof propDef.model !== 'string')
- throw new InvalidArgumentError(
- 'The provided option "model" of the property %v in the model %v ' +
- 'should be a String, but %v given.',
- propName,
- modelName,
- propDef.model,
- );
- if (propDef.primaryKey && typeof propDef.primaryKey !== 'boolean')
- throw new InvalidArgumentError(
- 'The provided option "primaryKey" of the property %v in the model %v ' +
- 'should be a Boolean, but %v given.',
- propName,
- modelName,
- propDef.primaryKey,
- );
- if (propDef.columnName && typeof propDef.columnName !== 'string')
- throw new InvalidArgumentError(
- 'The provided option "columnName" of the property %v in the model %v ' +
- 'should be a String, but %v given.',
- propName,
- modelName,
- propDef.columnName,
- );
- if (propDef.columnType && typeof propDef.columnType !== 'string')
- throw new InvalidArgumentError(
- 'The provided option "columnType" of the property %v in the model %v ' +
- 'should be a String, but %v given.',
- propName,
- modelName,
- propDef.columnType,
- );
- if (propDef.required && typeof propDef.required !== 'boolean')
- throw new InvalidArgumentError(
- 'The provided option "required" of the property %v in the model %v ' +
- 'should be a Boolean, but %v given.',
- propName,
- modelName,
- propDef.required,
- );
- if (propDef.required && propDef.default !== undefined)
- throw new InvalidArgumentError(
- 'The property %v of the model %v is a required property, ' +
- 'so it should not have the option "default" to be provided.',
- propName,
- modelName,
- );
- if (propDef.primaryKey && propDef.required)
- throw new InvalidArgumentError(
- 'The property %v of the model %v is a primary key, ' +
- 'so it should not have the option "required" to be provided.',
- propName,
- modelName,
- );
- if (propDef.primaryKey && propDef.default !== undefined)
- throw new InvalidArgumentError(
- 'The property %v of the model %v is a primary key, ' +
- 'so it should not have the option "default" to be provided.',
- propName,
- modelName,
- );
- if (propDef.itemType && propDef.type !== Type.ARRAY)
- throw new InvalidArgumentError(
- 'The property %v of the model %v has the non-array type, ' +
- 'so it should not have the option "itemType" to be provided.',
- propName,
- modelName,
- propDef.type,
- );
- if (
- propDef.model &&
- propDef.type !== Type.OBJECT &&
- propDef.itemType !== Type.OBJECT
- ) {
- if (propDef.type !== Type.ARRAY) {
- throw new InvalidArgumentError(
- 'The option "model" is not supported for %s property type, ' +
- 'so the property %v of the model %v should not have ' +
- 'the option "model" to be provided.',
- capitalize(propDef.type),
- propName,
- modelName,
- );
- } else {
- throw new InvalidArgumentError(
- 'The option "model" is not supported for Array property type of %s, ' +
- 'so the property %v of the model %v should not have ' +
- 'the option "model" to be provided.',
- capitalize(propDef.itemType),
- propName,
- modelName,
- );
- }
- }
- if (propDef.validate != null) {
- const propertyValidatorRegistry = this.getService(
- PropertyValidatorRegistry,
- );
- if (propDef.validate && typeof propDef.validate === 'string') {
- if (!propertyValidatorRegistry.hasValidator(propDef.validate))
- throw new InvalidArgumentError(
- 'The property validator %v is not found.',
- propDef.validate,
- );
- } else if (Array.isArray(propDef.validate)) {
- for (const validatorName of propDef.validate) {
- if (typeof validatorName !== 'string')
- throw new InvalidArgumentError(
- 'The provided option "validate" of the property %v in the model %v ' +
- 'has an Array value that should have a non-empty String, ' +
- 'but %v given.',
- propName,
- modelName,
- validatorName,
- );
- if (!propertyValidatorRegistry.hasValidator(validatorName))
- throw new InvalidArgumentError(
- 'The property validator %v is not found.',
- validatorName,
- );
- }
- } else if (typeof propDef.validate === 'object') {
- for (const validatorName in propDef.validate) {
- if (!propertyValidatorRegistry.hasValidator(validatorName))
- throw new InvalidArgumentError(
- 'The property validator %v is not found.',
- validatorName,
- );
- }
- } else {
- throw new InvalidArgumentError(
- 'The provided option "validate" of the property %v in the model %v ' +
- 'should be a non-empty String, an Array of String or an Object, ' +
- 'but %v given.',
- propName,
- modelName,
- propDef.validate,
- );
- }
- }
- if (propDef.transform != null) {
- const propertyTransformerRegistry = this.getService(
- PropertyTransformerRegistry,
- );
- if (propDef.transform && typeof propDef.transform === 'string') {
- if (!propertyTransformerRegistry.hasTransformer(propDef.transform))
- throw new InvalidArgumentError(
- 'The property transformer %v is not found.',
- propDef.transform,
- );
- } else if (Array.isArray(propDef.transform)) {
- for (const transformerName of propDef.transform) {
- if (typeof transformerName !== 'string')
- throw new InvalidArgumentError(
- 'The provided option "transform" of the property %v in the model %v ' +
- 'has an Array value that should have a non-empty String, ' +
- 'but %v given.',
- propName,
- modelName,
- transformerName,
- );
- if (!propertyTransformerRegistry.hasTransformer(transformerName))
- throw new InvalidArgumentError(
- 'The property transformer %v is not found.',
- transformerName,
- );
- }
- } else if (typeof propDef.transform === 'object') {
- for (const transformerName in propDef.transform) {
- if (!propertyTransformerRegistry.hasTransformer(transformerName))
- throw new InvalidArgumentError(
- 'The property transformer %v is not found.',
- transformerName,
- );
- }
- } else {
- throw new InvalidArgumentError(
- 'The provided option "transform" of the property %v in the model %v ' +
- 'should be a non-empty String, an Array of String or an Object, ' +
- 'but %v given.',
- propName,
- modelName,
- propDef.transform,
- );
- }
- }
- if (
- propDef.unique &&
- !Object.values(PropertyUniqueness).includes(propDef.unique)
- ) {
- throw new InvalidArgumentError(
- 'The provided option "unique" of the property %v in the model %v ' +
- 'should be one of values: %l, but %v given.',
- propName,
- modelName,
- Object.values(PropertyUniqueness),
- propDef.unique,
- );
- }
- if (propDef.unique && propDef.primaryKey)
- throw new InvalidArgumentError(
- 'The property %v of the model %v is a primary key, ' +
- 'so it should not have the option "unique" to be provided.',
- propName,
- modelName,
- );
- }
- }
|