/egg-y-validator

☯️ Egg Magic Validator (Egg 魔法验证工具)

Primary LanguageJavaScriptMIT LicenseMIT

egg-y-validator

NPM version build status Test coverage David deps Known Vulnerabilities npm download FOSSA Status

中文文档

Install

$ npm i egg-y-validator --save

Usage

// {app_root}/config/plugin.js
exports.validator = {
  enable: true,
  package: 'egg-y-validator'
};

Configuration

// {app_root}/config/config.default.js
exports.validator = {
  open: async ctx => 'zh-CN',
  // or
  // open: 'zh-CN',
  languages: {
    'zh-CN': {
      required: '%s 必填'
    }
  },
  async formatter(ctx, error) {
    ctx.type = 'json';
    ctx.status = 400;
    ctx.body = error;
  }
};

see config/config.default.js for more detail.

Create rules

app/schemas/login/login.yml

Suport json、js、yaml、toml file.

all rules you can find in async-validator

name:
  type: 'string'
  required: true

if you want custom rules,and get context ,but only support js、yal file

/* eslint-disable */
'use strict';

module.exports = {
  name: [
    {
      required: true
    },
    {
      validator: ctx => async (rule, value, callback, source, options) => {
        // console.log(ctx);
        // console.log(rule);
        // { validator: [Function],
        // field: 'name',
        // fullField: 'name',
        // type: 'string' }
        // console.log(value);
        // some
        // console.log(source);
        // { name: 'some' }
        // console.log(options);
        // { messages:
        // { default: 'Validation error on field %s',
        //   required: '%s 必填',
        //   enum: '%s must be one of %s',
        //   whitespace: '%s cannot be empty',
        //   date:
        //    { format: '%s date %s is invalid for format %s',
        //      parse: '%s date could not be parsed, %s is invalid ',
        //      invalid: '%s date %s is invalid' },
        //   types:
        //    { string: '%s is not a %s',
        //      method: '%s is not a %s (function)',
        //      array: '%s is not an %s',
        //      object: '%s is not an %s',
        //      number: '%s is not a %s',
        //      date: '%s is not a %s',
        //      boolean: '%s is not a %s',
        //      integer: '%s is not an %s',
        //      float: '%s is not a %s',
        //      regexp: '%s is not a valid %s',
        //      email: '%s is not a valid %s',
        //      url: '%s is not a valid %s',
        //      hex: '%s is not a valid %s' },
        //   string:
        //    { len: '%s must be exactly %s characters',
        //      min: '%s must be at least %s characters',
        //      max: '%s cannot be longer than %s characters',
        //      range: '%s must be between %s and %s characters' },
        //   number:
        //    { len: '%s must equal %s',
        //      min: '%s cannot be less than %s',
        //      max: '%s cannot be greater than %s',
        //      range: '%s must be between %s and %s' },
        //   array:
        //    { len: '%s must be exactly %s in length',
        //      min: '%s cannot be less than %s in length',
        //      max: '%s cannot be greater than %s in length',
        //      range: '%s must be between %s and %s in length' },
        //   pattern: { mismatch: '%s value %s does not match pattern %s' },
        //   clone: [Function: clone] } }
        throw [{ field: 'name', message: '错误' }];
      }
    }
  ]
};
name:
  -
    required: true
  -
    validator: !!js/function >
      function validator(ctx) {
        return async function (rule, value, callback, source, options) {
          throw [{field:'name', message:'错误'}]
        }
      }

throw error you can use throw or callback

Verify on your controller

'use strict';

const Controller = require('egg').Controller;

class HomeController extends Controller {
  async index() {
    const query = await this.ctx.verify('login.login', 'query');
    this.ctx.body = 'hi, ' + this.app.plugins.validator.name;
  }
}

module.exports = HomeController;

api

ctx.verify(path, type)

  • path
    • login.login -> 'app/schemas/login/login.{json/js/toml/yaml}'
    • login -> if login has index propety -> login.index -> 'app/schemas/login/index.{json/js/toml/yaml}'
    • if path type is object use the object
  • type
    • query -> ctx.request.query
    • body -> ctx.request.body
    • params -> ctx.params
    • undefined -> R.merge(this.params, this.request.query, this.request.body)
    • object -> object
    • async function -> will be invoke

ctx.docs

all validator rules

ctx.loadDocs(reload)

  • reload -> boolean true will reload rules file

Questions & Suggestions

Please open an issue here.

support superstruct

but superstruct custom type function not support async function

superstruct api

more info you can see the test file example.

config.default.js

exports.validator = {
  superstruct: true,
  types(ctx) {
    // custom you types not support async
    return {
      email: v => true
    };
  },
  async formatter(ctx, error) {
    const { data, path, value } = error;
    console.log(error);
    ctx.type = 'json';
    ctx.status = 400;
    ctx.body = { field: path[0], message: '无效的值' };
    console.log(ctx.body);
  }
};

controller

  async b() {
    const ret = await this.ctx.verify(
      { // rules
        name: 'string'
      },
      async () => { // data
        return this.ctx.query;
      }
    );
    this.ctx.body = 'hi, ' + this.app.plugins.validator.name;
  }
  async d() {
    await this.ctx.verify('haha', async () => {
      return { name: '123', email: 'ck123.com' };
    });
    this.ctx.body = 'hi, ' + this.app.plugins.validator.name;
  }

rules

module.exports = {
  name: 'string',
  email: 'email',
  types: {
    email: v => {
      console.log('email verify');
      return Boolean(v.indexOf('@') != -1);
    }
  }
};

License

FOSSA Status