Просмотр исходного кода

chore: do not validate default values at model definition, it may cause an error of undefined model

e22m4u 2 лет назад
Родитель
Сommit
0e60273b1e

+ 1 - 1
src/adapter/adapter.js

@@ -39,9 +39,9 @@ export class Adapter extends Service {
     this._settings = settings;
     // decorate only extended classes
     if (this.constructor !== Adapter) {
-      this.getService(DataValidationDecorator).decorate(this);
       this.getService(DataSanitizingDecorator).decorate(this);
       this.getService(DefaultValuesDecorator).decorate(this);
+      this.getService(DataValidationDecorator).decorate(this);
       this.getService(FieldsFilteringDecorator).decorate(this);
       this.getService(InclusionDecorator).decorate(this);
     }

+ 3 - 3
src/adapter/adapter.spec.js

@@ -33,9 +33,9 @@ describe('Adapter', function () {
 
     it('decorates only extended adapter', function () {
       const schema = new Schema();
-      const dec1 = schema.getService(DataValidationDecorator);
-      const dec2 = schema.getService(DataSanitizingDecorator);
-      const dec3 = schema.getService(DefaultValuesDecorator);
+      const dec1 = schema.getService(DataSanitizingDecorator);
+      const dec2 = schema.getService(DefaultValuesDecorator);
+      const dec3 = schema.getService(DataValidationDecorator);
       const dec4 = schema.getService(FieldsFilteringDecorator);
       const dec5 = schema.getService(InclusionDecorator);
       const order = [];

+ 2 - 2
src/definition/model/model-data-validator.js

@@ -31,7 +31,7 @@ export class ModelDataValidator extends Service {
     propNames.forEach(propName => {
       const propDef = propDefs[propName];
       if (!propDef) return;
-      this.validatePropertyValue(
+      this._validatePropertyValue(
         modelName,
         propName,
         propDef,
@@ -48,7 +48,7 @@ export class ModelDataValidator extends Service {
    * @param {string|object} propDef
    * @param {*} propValue
    */
-  validatePropertyValue(modelName, propName, propDef, propValue) {
+  _validatePropertyValue(modelName, propName, propDef, propValue) {
     // undefined and null
     if (propValue == null) {
       const isRequired =

+ 0 - 15
src/definition/model/properties/default-values-definition-validator.d.ts

@@ -1,15 +0,0 @@
-import {Service} from '@e22m4u/js-service';
-import {PropertyDefinitionMap} from '../model-definition.js';
-
-/**
- * Default values definition validator.
- */
-export declare class DefaultValuesDefinitionValidator extends Service {
-  /**
-   * Validate.
-   *
-   * @param modelName
-   * @param propDefs
-   */
-  validate(modelName: string, propDefs: PropertyDefinitionMap): void;
-}

+ 0 - 53
src/definition/model/properties/default-values-definition-validator.js

@@ -1,53 +0,0 @@
-import {Service} from '@e22m4u/js-service';
-import {ModelDataValidator} from '../model-data-validator.js';
-import {InvalidArgumentError} from '../../../errors/index.js';
-
-/**
- * Default values definition validator.
- */
-export class DefaultValuesDefinitionValidator extends Service {
-  /**
-   * Validate.
-   *
-   * @param {string} modelName
-   * @param {object} propDefs
-   */
-  validate(modelName, propDefs) {
-    if (!modelName || typeof modelName !== 'string')
-      throw new InvalidArgumentError(
-        'The first argument of DefaultValuesDefinitionValidator.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,
-      );
-    Object.keys(propDefs).forEach(propName => {
-      const propDef = propDefs[propName];
-      if (typeof propDef === 'string') return;
-      if (!('default' in propDef)) return;
-      const propValue =
-        propDef.default instanceof Function
-          ? propDef.default()
-          : propDef.default;
-      try {
-        this.getService(ModelDataValidator).validatePropertyValue(
-          modelName,
-          propName,
-          propDef,
-          propValue,
-        );
-      } catch (error) {
-        if (error instanceof InvalidArgumentError)
-          throw new InvalidArgumentError(
-            `A default value is invalid. ${error.message}`,
-          );
-        throw error;
-      }
-    });
-  }
-}

+ 0 - 136
src/definition/model/properties/default-values-definition-validator.spec.js

@@ -1,136 +0,0 @@
-import {expect} from 'chai';
-import {DataType} from './data-type.js';
-import {format} from '@e22m4u/js-format';
-import {DefaultValuesDefinitionValidator} from './default-values-definition-validator.js';
-
-const S = new DefaultValuesDefinitionValidator();
-
-describe('DefaultValuesDefinitionValidator', function () {
-  describe('validate', function () {
-    it('requires a first argument to be a non-empty string', function () {
-      const validate = v => () => S.validate(v, {});
-      const error = v =>
-        format(
-          'The first argument of DefaultValuesDefinitionValidator.validate ' +
-            'should be a non-empty String, but %s given.',
-          v,
-        );
-      expect(validate('')).to.throw(error('""'));
-      expect(validate(10)).to.throw(error('10'));
-      expect(validate(true)).to.throw(error('true'));
-      expect(validate(false)).to.throw(error('false'));
-      expect(validate([])).to.throw(error('Array'));
-      expect(validate({})).to.throw(error('Object'));
-      expect(validate(undefined)).to.throw(error('undefined'));
-      expect(validate(null)).to.throw(error('null'));
-      validate('model')();
-    });
-
-    it('requires a second argument to be an object', function () {
-      const validate = v => () => S.validate('model', v);
-      const error = v =>
-        format(
-          'The provided option "properties" of the model "model" ' +
-            'should be an Object, but %s given.',
-          v,
-        );
-      expect(validate('str')).to.throw(error('"str"'));
-      expect(validate(10)).to.throw(error('10'));
-      expect(validate(true)).to.throw(error('true'));
-      expect(validate(false)).to.throw(error('false'));
-      expect(validate([])).to.throw(error('Array'));
-      expect(validate(undefined)).to.throw(error('undefined'));
-      expect(validate(null)).to.throw(error('null'));
-      validate({})();
-    });
-
-    it('does not throw an error if no properties defined', function () {
-      S.validate('model', {});
-    });
-
-    it('does not throw an error if no default value specified for a required property', function () {
-      S.validate('model', {
-        foo: {
-          type: DataType.STRING,
-          required: true,
-        },
-      });
-    });
-
-    it('does not throw an error if a default value matches a property type', function () {
-      S.validate('model', {
-        foo: {
-          type: DataType.BOOLEAN,
-          default: false,
-        },
-      });
-    });
-
-    it('does not throw an error if a default value from a factory function matches a property type', function () {
-      S.validate('model', {
-        foo: {
-          type: DataType.BOOLEAN,
-          default: () => false,
-        },
-      });
-    });
-
-    it('throws an error if a default value does not match a property type', function () {
-      const throwable = () =>
-        S.validate('model', {
-          foo: {
-            type: DataType.STRING,
-            default: 10,
-          },
-        });
-      expect(throwable).to.throw(
-        'A default value is invalid. The property "foo" of the model ' +
-          '"model" must have a String, but Number given.',
-      );
-    });
-
-    it('throws an error if a default value from a factory function does not match a property type', function () {
-      const throwable = () =>
-        S.validate('model', {
-          foo: {
-            type: DataType.STRING,
-            default: () => 10,
-          },
-        });
-      expect(throwable).to.throw(
-        'A default value is invalid. The property "foo" of the model ' +
-          '"model" must have a String, but Number given.',
-      );
-    });
-
-    it('throws an error if an array element of a default value does not match an item type', function () {
-      const throwable = () =>
-        S.validate('model', {
-          foo: {
-            type: DataType.ARRAY,
-            itemType: DataType.STRING,
-            default: [10],
-          },
-        });
-      expect(throwable).to.throw(
-        'A default value is invalid. The array property "foo" of the model "model" ' +
-          'must have a String element, but Number given.',
-      );
-    });
-
-    it('throws an error if an array element from a default value factory does not match an item type', function () {
-      const throwable = () =>
-        S.validate('model', {
-          foo: {
-            type: DataType.ARRAY,
-            itemType: DataType.STRING,
-            default: () => [10],
-          },
-        });
-      expect(throwable).to.throw(
-        'A default value is invalid. The array property "foo" of the model "model" ' +
-          'must have a String element, but Number given.',
-      );
-    });
-  });
-});

+ 0 - 1
src/definition/model/properties/index.d.ts

@@ -2,4 +2,3 @@ export * from './data-type.js';
 export * from './property-definition.js';
 export * from './properties-definition-validator.js';
 export * from './primary-keys-definition-validator.js';
-export * from './default-values-definition-validator.js';

+ 0 - 1
src/definition/model/properties/index.js

@@ -1,4 +1,3 @@
 export * from './data-type.js';
 export * from './properties-definition-validator.js';
 export * from './primary-keys-definition-validator.js';
-export * from './default-values-definition-validator.js';

+ 0 - 5
src/definition/model/properties/properties-definition-validator.js

@@ -2,7 +2,6 @@ import {Service} from '@e22m4u/js-service';
 import {DataType as Type} from './data-type.js';
 import {InvalidArgumentError} from '../../../errors/index.js';
 import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
-import {DefaultValuesDefinitionValidator} from './default-values-definition-validator.js';
 
 /**
  * Properties definition validator.
@@ -38,10 +37,6 @@ export class PropertiesDefinitionValidator extends Service {
       modelName,
       propDefs,
     );
-    this.getService(DefaultValuesDefinitionValidator).validate(
-      modelName,
-      propDefs,
-    );
   }
 
   /**

+ 0 - 10
src/definition/model/properties/properties-definition-validator.spec.js

@@ -4,7 +4,6 @@ import {DataType} from './data-type.js';
 import {format} from '@e22m4u/js-format';
 import {PropertiesDefinitionValidator} from './properties-definition-validator.js';
 import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
-import {DefaultValuesDefinitionValidator} from './default-values-definition-validator.js';
 
 const S = new PropertiesDefinitionValidator();
 const sandbox = chai.spy.sandbox();
@@ -360,14 +359,5 @@ describe('PropertiesDefinitionValidator', function () {
       expect(V.validate).to.have.been.called.once;
       expect(V.validate).to.have.been.called.with.exactly('model', propDefs);
     });
-
-    it('uses DefaultValuesDefinitionValidator to validate default values', function () {
-      const V = S.getService(DefaultValuesDefinitionValidator);
-      sandbox.on(V, 'validate');
-      const propDefs = {};
-      S.validate('model', propDefs);
-      expect(V.validate).to.have.been.called.once;
-      expect(V.validate).to.have.been.called.with.exactly('model', propDefs);
-    });
   });
 });