UNPKG

4.2 kBJavaScriptView Raw
1/**
2 * @fileoverview Validates configs.
3 * @author Brandon Mills
4 * @copyright 2015 Brandon Mills
5 */
6
7"use strict";
8
9//------------------------------------------------------------------------------
10// Requirements
11//------------------------------------------------------------------------------
12
13var rules = require("./rules"),
14 environments = require("../conf/environments"),
15 schemaValidator = require("is-my-json-valid");
16
17var validators = {
18 rules: Object.create(null)
19};
20
21/**
22 * Gets a complete options schema for a rule.
23 * @param {string} id The rule's unique name.
24 * @returns {object} JSON Schema for the rule's options.
25 */
26function getRuleOptionsSchema(id) {
27 var rule = rules.get(id),
28 schema = rule && rule.schema;
29
30 if (!schema) {
31 return {
32 "type": "array",
33 "items": [
34 {
35 "enum": [0, 1, 2]
36 }
37 ],
38 "minItems": 1
39 };
40 }
41
42 // Given a tuple of schemas, insert warning level at the beginning
43 if (Array.isArray(schema)) {
44 return {
45 "type": "array",
46 "items": [
47 {
48 "enum": [0, 1, 2]
49 }
50 ].concat(schema),
51 "minItems": 1,
52 "maxItems": schema.length + 1
53 };
54 }
55
56 // Given a full schema, leave it alone
57 return schema;
58}
59
60/**
61 * Validates a rule's options against its schema.
62 * @param {string} id The rule's unique name.
63 * @param {array|number} options The given options for the rule.
64 * @param {string} source The name of the configuration source.
65 * @returns {void}
66 */
67function validateRuleOptions(id, options, source) {
68 var validateRule = validators.rules[id],
69 message;
70
71 if (!validateRule) {
72 validateRule = schemaValidator(getRuleOptionsSchema(id), { verbose: true });
73 validators.rules[id] = validateRule;
74 }
75
76 if (typeof options === "number") {
77 options = [options];
78 }
79
80 validateRule(options);
81
82 if (validateRule.errors) {
83 message = [
84 source, ":\n",
85 "\tConfiguration for rule \"", id, "\" is invalid:\n"
86 ];
87 validateRule.errors.forEach(function(error) {
88 if (error.field === "data[\"0\"]") { // better error for severity
89 message.push(
90 "\tSeverity should be one of the following: 0 = off, 1 = warning, 2 = error (you passed \"", error.value, "\").\n");
91 } else {
92 message.push(
93 "\tValue \"", error.value, "\" ", error.message, ".\n"
94 );
95 }
96 });
97
98 throw new Error(message.join(""));
99 }
100}
101
102/**
103 * Validates an environment object
104 * @param {object} environment The environment config object to validate.
105 * @param {string} source The location to report with any errors.
106 * @returns {void}
107 */
108function validateEnvironment(environment, source) {
109
110 // not having an environment is ok
111 if (!environment) {
112 return;
113 }
114
115 if (Array.isArray(environment)) {
116 throw new Error("Environment must not be an array");
117 }
118
119 if (typeof environment === "object") {
120 Object.keys(environment).forEach(function(env) {
121 if (!environments[env]) {
122 var message = [
123 source, ":\n",
124 "\tEnvironment key \"", env, "\" is unknown\n"
125 ];
126 throw new Error(message.join(""));
127 }
128 });
129 } else {
130 throw new Error("Environment must be an object");
131 }
132}
133
134/**
135 * Validates an entire config object.
136 * @param {object} config The config object to validate.
137 * @param {string} source The location to report with any errors.
138 * @returns {void}
139 */
140function validate(config, source) {
141
142 if (typeof config.rules === "object") {
143 Object.keys(config.rules).forEach(function(id) {
144 validateRuleOptions(id, config.rules[id], source);
145 });
146 }
147
148 validateEnvironment(config.env, source);
149}
150
151module.exports = {
152 getRuleOptionsSchema: getRuleOptionsSchema,
153 validate: validate,
154 validateRuleOptions: validateRuleOptions
155};