Projekt

Obecné

Profil

Stáhnout (3.82 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2

    
3
var IDENTIFIER = /^[a-z_$][a-z0-9_$-]*$/i;
4
var customRuleCode = require('./dotjs/custom');
5
var definitionSchema = require('./definition_schema');
6

    
7
module.exports = {
8
  add: addKeyword,
9
  get: getKeyword,
10
  remove: removeKeyword,
11
  validate: validateKeyword
12
};
13

    
14

    
15
/**
16
 * Define custom keyword
17
 * @this  Ajv
18
 * @param {String} keyword custom keyword, should be unique (including different from all standard, custom and macro keywords).
19
 * @param {Object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`.
20
 * @return {Ajv} this for method chaining
21
 */
22
function addKeyword(keyword, definition) {
23
  /* jshint validthis: true */
24
  /* eslint no-shadow: 0 */
25
  var RULES = this.RULES;
26
  if (RULES.keywords[keyword])
27
    throw new Error('Keyword ' + keyword + ' is already defined');
28

    
29
  if (!IDENTIFIER.test(keyword))
30
    throw new Error('Keyword ' + keyword + ' is not a valid identifier');
31

    
32
  if (definition) {
33
    this.validateKeyword(definition, true);
34

    
35
    var dataType = definition.type;
36
    if (Array.isArray(dataType)) {
37
      for (var i=0; i<dataType.length; i++)
38
        _addRule(keyword, dataType[i], definition);
39
    } else {
40
      _addRule(keyword, dataType, definition);
41
    }
42

    
43
    var metaSchema = definition.metaSchema;
44
    if (metaSchema) {
45
      if (definition.$data && this._opts.$data) {
46
        metaSchema = {
47
          anyOf: [
48
            metaSchema,
49
            { '$ref': 'https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/data.json#' }
50
          ]
51
        };
52
      }
53
      definition.validateSchema = this.compile(metaSchema, true);
54
    }
55
  }
56

    
57
  RULES.keywords[keyword] = RULES.all[keyword] = true;
58

    
59

    
60
  function _addRule(keyword, dataType, definition) {
61
    var ruleGroup;
62
    for (var i=0; i<RULES.length; i++) {
63
      var rg = RULES[i];
64
      if (rg.type == dataType) {
65
        ruleGroup = rg;
66
        break;
67
      }
68
    }
69

    
70
    if (!ruleGroup) {
71
      ruleGroup = { type: dataType, rules: [] };
72
      RULES.push(ruleGroup);
73
    }
74

    
75
    var rule = {
76
      keyword: keyword,
77
      definition: definition,
78
      custom: true,
79
      code: customRuleCode,
80
      implements: definition.implements
81
    };
82
    ruleGroup.rules.push(rule);
83
    RULES.custom[keyword] = rule;
84
  }
85

    
86
  return this;
87
}
88

    
89

    
90
/**
91
 * Get keyword
92
 * @this  Ajv
93
 * @param {String} keyword pre-defined or custom keyword.
94
 * @return {Object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise.
95
 */
96
function getKeyword(keyword) {
97
  /* jshint validthis: true */
98
  var rule = this.RULES.custom[keyword];
99
  return rule ? rule.definition : this.RULES.keywords[keyword] || false;
100
}
101

    
102

    
103
/**
104
 * Remove keyword
105
 * @this  Ajv
106
 * @param {String} keyword pre-defined or custom keyword.
107
 * @return {Ajv} this for method chaining
108
 */
109
function removeKeyword(keyword) {
110
  /* jshint validthis: true */
111
  var RULES = this.RULES;
112
  delete RULES.keywords[keyword];
113
  delete RULES.all[keyword];
114
  delete RULES.custom[keyword];
115
  for (var i=0; i<RULES.length; i++) {
116
    var rules = RULES[i].rules;
117
    for (var j=0; j<rules.length; j++) {
118
      if (rules[j].keyword == keyword) {
119
        rules.splice(j, 1);
120
        break;
121
      }
122
    }
123
  }
124
  return this;
125
}
126

    
127

    
128
/**
129
 * Validate keyword definition
130
 * @this  Ajv
131
 * @param {Object} definition keyword definition object.
132
 * @param {Boolean} throwError true to throw exception if definition is invalid
133
 * @return {boolean} validation result
134
 */
135
function validateKeyword(definition, throwError) {
136
  validateKeyword.errors = null;
137
  var v = this._validateKeyword = this._validateKeyword
138
                                  || this.compile(definitionSchema, true);
139

    
140
  if (v(definition)) return true;
141
  validateKeyword.errors = v.errors;
142
  if (throwError)
143
    throw new Error('custom keyword definition is invalid: '  + this.errorsText(v.errors));
144
  else
145
    return false;
146
}
(6-6/6)