UNPKG

node-blead-sl

Version:

The node-blead-sl is a controller of BLE beacon "BLEAD-SL" equipped with a buzzer. Note that "BLEAD-SL" is available only in Japan.

496 lines (458 loc) 15.6 kB
/* ------------------------------------------------------------------ * node-blead-sl - parameter-checker.js * * Copyright (c) 2019, Futomi Hatano, All rights reserved. * Released under the MIT license * Date: 2020-03-30 * ---------------------------------------------------------------- */ 'use strict'; class ParameterChecker { constructor() { this._error = null; } get error() { // ---------------------------------- // Error // { // code: 'TYPE_INVALID', // message: 'The `age` must be an integer.' // name: 'age', // } // --------------------------------- return this._error; } isSpecified(value) { return (value === void 0) ? false : true; } /* ------------------------------------------------------------------ * check(obj, rule, required) * - Check if the specified object contains valid values * * [Arguments] * - obj | Object | Required | Object including parameters you want to check * - rules | Object | Required | Object including rules for the parameters * - required | Boolean | Optional | Flag whther the `obj` is required or not. * | | | The default is `false` * * [Return value] * - If the value is valid, this method will return `true`. * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * * [Usage] * let valid = parameterChecker.check(params, { * level: { * required: false, * type: 'integer', * max: 100 * }, * greeting: { * required: true, // But an empty string is allowed. * type: 'string', * max: 20 // the number of characters must be up to 20. * } * }); * if(!valid) { * let e = parameterChecker.error.message; * throw new Error(message); * } * ---------------------------------------------------------------- */ check(obj, rules, required = false) { this._error = null; if (required) { if (!this.isSpecified(obj)) { this._error = { code: 'MISSING_REQUIRED', message: 'The first argument is missing.' }; return false; } } else { if (!obj) { return true; } } if (!this.isObject(obj)) { this._error = { code: 'MISSING_REQUIRED', message: 'The first argument is missing.' }; return false; } let result = true; let name_list = Object.keys(rules); for (let i = 0; i < name_list.length; i++) { let name = name_list[i]; let v = obj[name]; let rule = rules[name]; if (!rule) { rule = {}; } if (!this.isSpecified(v)) { if (rule.required) { result = false; this._error = { code: 'MISSING_REQUIRED', message: 'The `' + name + '` is required.' }; break; } else { continue; } } if (rule.type === 'float') { result = this.isFloat(v, rule, name); } else if (rule.type === 'integer') { result = this.isInteger(v, rule, name); } else if (rule.type === 'boolean') { result = this.isBoolean(v, rule, name); } else if (rule.type === 'array') { result = this.isArray(v, rule, name); } else if (rule.type === 'object') { result = this.isObject(v, rule, name); } else if (rule.type === 'string') { result = this.isString(v, rule, name); } else { result = false; this._error = { code: 'TYPE_UNKNOWN', message: 'The rule specified for the `' + name + '` includes an unknown type: ' + rule.type, }; } if (result === false) { this._error.name = name; break; } } return result; } /* ------------------------------------------------------------------ * isFloat(value, rule, name) * - Check if the value is a float * * [Arguments] * - value | Any | Required | The value you want to check * - rule | Object | Optional | * - required | Boolean | Optional | Required or not. Default is `false`. * - min | Float | Optional | Minimum number * - max | Float | Optional | Maximum number * - enum | Array | Optional | list of possible values * - name | String | Optional | Parameter name * * If non-number value is specified to the `min` or `max`, * they will be ignored. * * [Return value] * - If the value is valid, this method will return `true`. * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ isFloat(value, rule = {}, name = 'value') { this._error = null; if (!rule.required && !this.isSpecified(value)) { return true; } if (typeof (value) !== 'number') { this._error = { code: 'TYPE_INVALID', message: 'The `' + name + '` must be a number (integer or float).' }; return false; } if (typeof (rule.min) === 'number') { if (value < rule.min) { this._error = { code: 'VALUE_UNDERFLOW', message: 'The `' + name + '` must be grater than or equal to ' + rule.min + '.' }; return false; } } if (typeof (rule.max) === 'number') { if (value > rule.max) { this._error = { code: 'VALUE_OVERFLOW', message: 'The `' + name + '` must be less than or equal to ' + rule.max + '.' }; return false; } } if (Array.isArray(rule.enum) && rule.enum.length > 0) { if (rule.enum.indexOf(value) === -1) { this._error = { code: 'ENUM_UNMATCH', message: 'The `' + name + '` must be any one of ' + JSON.stringify(rule.enum) + '.' }; return false; } } return true; } /* ------------------------------------------------------------------ * isInteger(value, rule) * - Check if the value is an integer * * [Arguments] * - value | Any | Required | The value you want to check * - rule | Object | Optional | * - required | Boolean | Optional | Required or not. Default is `false`.| * - min | Float | Optional | Minimum number * - max | Float | Optional | Maximum number * - enum | Array | Optional | list of possible values * - name | String | Optional | Parameter name * * If non-number value is specified to the `min` or `max`, * they will be ignored. * * [Return value] * - If the value is valid, this method will return `true`. * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ isInteger(value, rule = {}, name = 'value') { this._error = null; if (!rule.required && !this.isSpecified(value)) { return true; } if (typeof (value) !== 'number') { this._error = { code: 'TYPE_INVALID', message: 'The `' + name + '` must be an integer.' }; return false; } if (typeof (rule.min) === 'number') { if (value < rule.min) { this._error = { code: 'VALUE_UNDERFLOW', message: 'The `' + name + '` must be grater than or equal to ' + rule.min + '.' }; return false; } } if (typeof (rule.max) === 'number') { if (value > rule.max) { this._error = { code: 'VALUE_OVERFLOW', message: 'The `' + name + '` must be less than or equal to ' + rule.max + '.' }; return false; } } if (Array.isArray(rule.enum) && rule.enum.length > 0) { if (rule.enum.indexOf(value) === -1) { this._error = { code: 'ENUM_UNMATCH', message: 'The `' + name + '` must be any one of ' + JSON.stringify(rule.enum) + '.' }; return false; } } return true; } /* ------------------------------------------------------------------ * isBoolean(value, rule, name) * - Check if the value is a boolean. * * [Arguments] * - value | Any | Required | The value you want to check * - rule | Object | Optional | * - required | Boolean | Optional | Required or not. Default is `false`. * - name | String | Optional | Parameter name * * [Return value] * - If the value is valid, this method will return `true`. * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ isBoolean(value, rule = {}, name = 'value') { this._error = null; if (!rule.required && !this.isSpecified(value)) { return true; } if (typeof (value) !== 'boolean') { this._error = { code: 'TYPE_INVALID', message: 'The `' + name + '` must be boolean.' }; return false; } return true; } /* ------------------------------------------------------------------ * isObject(value) * - Check if the value is an object * * [Arguments] * - value | Any | Required | The value you want to check * - rule | Object | Optional | * - required | Boolean | Optional | Required or not. Default is `false`. * - name | String | Optional | Parameter name * * [Return value] * - If the value is valid, this method will return `true`. * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ isObject(value, rule = {}, name = 'value') { this._error = null; if (!rule.required && !this.isSpecified(value)) { return true; } if (typeof (value) !== 'object' || value === null || Array.isArray(value)) { this._error = { code: 'TYPE_INVALID', message: 'The `' + name + '` must be an object.' }; return false; } return true; } /* ------------------------------------------------------------------ * isArray(value, rule, name) * - Check if the value is an `Array` object * * [Arguments] * - value | Any | Required | The value you want to check * - rule | Object | Optional | * - required | Boolean | Optional | Required or not. Default is `false`. * - min | Integer | Optional | Minimum number of elements in the array * - max | Integer | Optional | Maximum number of elements in the array * - name | String | Optional | Parameter name * * If non-number value is specified to the `min` or `max`, * they will be ignored. * * [Return value] * - If the value is valid, this method will return `true`. * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ isArray(value, rule = {}, name = 'value') { this._error = null; if (!rule.required && !this.isSpecified(value)) { return true; } if (!Array.isArray(value)) { this._error = { code: 'TYPE_INVALID', message: 'The value must be an array.' }; return false; } if (typeof (rule.min) === 'number') { if (value.length < rule.min) { this._error = { code: 'LENGTH_UNDERFLOW', message: 'The number of characters in the `' + name + '` must be grater than or equal to ' + rule.min + '.' }; return false; } } if (typeof (rule.max) === 'number') { if (value.length > rule.max) { this._error = { code: 'LENGTH_OVERFLOW', message: 'The number of characters in the `' + name + '` must be less than or equal to ' + rule.max + '.' }; return false; } } return true; } /* ------------------------------------------------------------------ * isString(value, rule, name) * - Check if the value is an `Array` object * * [Arguments] * - value | Any | Required | The value you want to check * - rule | Object | Optional | * - required | Boolean | Optional | Required or not. Default is `false`. * - min | Integer | Optional | Minimum number of characters in the string * - max | Integer | Optional | Maximum number of characters in the string * - minBytes | Integer | Optional | Minimum bytes of the string (UTF-8) * - maxBytes | Integer | Optional | Maximum bytes of the string (UTF-8) * - pattern | RegExp | Optional | Pattern of the string * - enum | Array | Optional | list of possible values * - name | String | Optional | Parameter name * * If non-number value is specified to the `min` or `max`, * they will be ignored. * * [Return value] * - If the value is valid, this method will return `true`. * - If the value is invalid, this method will return `false` and * an `Error` object will be set to `this._error`. * ---------------------------------------------------------------- */ isString(value, rule = {}, name = 'value') { this._error = null; if (!rule.required && !this.isSpecified(value)) { return true; } if (typeof (value) !== 'string') { this._error = { code: 'TYPE_INVALID', message: 'The value must be a string.' }; return false; } if (typeof (rule.min) === 'number') { if (value.length < rule.min) { this._error = { code: 'LENGTH_UNDERFLOW', message: 'The number of characters in the `' + name + '` must be grater than or equal to ' + rule.min + '.' }; return false; } } if (typeof (rule.max) === 'number') { if (value.length > rule.max) { this._error = { code: 'LENGTH_OVERFLOW', message: 'The number of characters in the `' + name + '` must be less than or equal to ' + rule.max + '.' }; return false; } } if (typeof (rule.minBytes) === 'number') { let blen = Buffer.from(value, 'utf8').length; if (blen < rule.minBytes) { this._error = { code: 'LENGTH_UNDERFLOW', message: 'The byte length of the `' + name + '` (' + blen + ' bytes) must be grater than or equal to ' + rule.minBytes + ' bytes.' }; return false; } } if (typeof (rule.maxBytes) === 'number') { let blen = Buffer.from(value, 'utf8').length; if (blen > rule.maxBytes) { this._error = { code: 'LENGTH_OVERFLOW', message: 'The byte length of the `' + name + '` (' + blen + ' bytes) must be less than or equal to ' + rule.maxBytes + ' bytes.' }; return false; } } if (rule.pattern instanceof RegExp) { if (!rule.pattern.test(v)) { this._error = { code: 'PATTERN_UNMATCH', message: 'The `' + name + '` does not conform with the pattern.' }; return false; } } if (Array.isArray(rule.enum) && rule.enum.length > 0) { if (rule.enum.indexOf(value) === -1) { this._error = { code: 'ENUM_UNMATCH', message: 'The `' + name + '` must be any one of ' + JSON.stringify(rule.enum) + '.' }; return false; } } return true; } } module.exports = new ParameterChecker();