Path: blob/master/node_modules/ajv/lib/keyword.js
3988 views
'use strict';12var IDENTIFIER = /^[a-z_$][a-z0-9_$-]*$/i;3var customRuleCode = require('./dotjs/custom');4var definitionSchema = require('./definition_schema');56module.exports = {7add: addKeyword,8get: getKeyword,9remove: removeKeyword,10validate: validateKeyword11};121314/**15* Define custom keyword16* @this Ajv17* @param {String} keyword custom keyword, should be unique (including different from all standard, custom and macro keywords).18* @param {Object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`.19* @return {Ajv} this for method chaining20*/21function addKeyword(keyword, definition) {22/* jshint validthis: true */23/* eslint no-shadow: 0 */24var RULES = this.RULES;25if (RULES.keywords[keyword])26throw new Error('Keyword ' + keyword + ' is already defined');2728if (!IDENTIFIER.test(keyword))29throw new Error('Keyword ' + keyword + ' is not a valid identifier');3031if (definition) {32this.validateKeyword(definition, true);3334var dataType = definition.type;35if (Array.isArray(dataType)) {36for (var i=0; i<dataType.length; i++)37_addRule(keyword, dataType[i], definition);38} else {39_addRule(keyword, dataType, definition);40}4142var metaSchema = definition.metaSchema;43if (metaSchema) {44if (definition.$data && this._opts.$data) {45metaSchema = {46anyOf: [47metaSchema,48{ '$ref': 'https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#' }49]50};51}52definition.validateSchema = this.compile(metaSchema, true);53}54}5556RULES.keywords[keyword] = RULES.all[keyword] = true;575859function _addRule(keyword, dataType, definition) {60var ruleGroup;61for (var i=0; i<RULES.length; i++) {62var rg = RULES[i];63if (rg.type == dataType) {64ruleGroup = rg;65break;66}67}6869if (!ruleGroup) {70ruleGroup = { type: dataType, rules: [] };71RULES.push(ruleGroup);72}7374var rule = {75keyword: keyword,76definition: definition,77custom: true,78code: customRuleCode,79implements: definition.implements80};81ruleGroup.rules.push(rule);82RULES.custom[keyword] = rule;83}8485return this;86}878889/**90* Get keyword91* @this Ajv92* @param {String} keyword pre-defined or custom keyword.93* @return {Object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise.94*/95function getKeyword(keyword) {96/* jshint validthis: true */97var rule = this.RULES.custom[keyword];98return rule ? rule.definition : this.RULES.keywords[keyword] || false;99}100101102/**103* Remove keyword104* @this Ajv105* @param {String} keyword pre-defined or custom keyword.106* @return {Ajv} this for method chaining107*/108function removeKeyword(keyword) {109/* jshint validthis: true */110var RULES = this.RULES;111delete RULES.keywords[keyword];112delete RULES.all[keyword];113delete RULES.custom[keyword];114for (var i=0; i<RULES.length; i++) {115var rules = RULES[i].rules;116for (var j=0; j<rules.length; j++) {117if (rules[j].keyword == keyword) {118rules.splice(j, 1);119break;120}121}122}123return this;124}125126127/**128* Validate keyword definition129* @this Ajv130* @param {Object} definition keyword definition object.131* @param {Boolean} throwError true to throw exception if definition is invalid132* @return {boolean} validation result133*/134function validateKeyword(definition, throwError) {135validateKeyword.errors = null;136var v = this._validateKeyword = this._validateKeyword137|| this.compile(definitionSchema, true);138139if (v(definition)) return true;140validateKeyword.errors = v.errors;141if (throwError)142throw new Error('custom keyword definition is invalid: ' + this.errorsText(v.errors));143else144return false;145}146147148