n4s 3.0.0 → 4.0.0-dev-1aae50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +129 -0
- package/LICENSE +1 -2
- package/README.md +2 -5
- package/compose/package.json +7 -0
- package/compounds/package.json +7 -0
- package/dist/cjs/compose.development.js +139 -0
- package/dist/cjs/compose.js +7 -0
- package/dist/cjs/compose.production.js +1 -0
- package/dist/cjs/compounds.development.js +132 -0
- package/dist/cjs/compounds.js +7 -0
- package/dist/cjs/compounds.production.js +1 -0
- package/dist/cjs/n4s.development.js +602 -0
- package/dist/cjs/n4s.js +7 -0
- package/dist/cjs/n4s.production.js +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/schema.development.js +144 -0
- package/dist/cjs/schema.js +7 -0
- package/dist/cjs/schema.production.js +1 -0
- package/dist/es/compose.development.js +137 -0
- package/dist/es/compose.production.js +1 -0
- package/dist/es/compounds.development.js +130 -0
- package/dist/es/compounds.production.js +1 -0
- package/dist/es/n4s.development.js +597 -0
- package/dist/es/n4s.production.js +1 -0
- package/dist/es/package.json +1 -0
- package/dist/es/schema.development.js +140 -0
- package/dist/es/schema.production.js +1 -0
- package/dist/umd/compose.development.js +143 -0
- package/dist/umd/compose.production.js +1 -0
- package/dist/umd/compounds.development.js +136 -0
- package/dist/umd/compounds.production.js +1 -0
- package/dist/umd/n4s.development.js +606 -0
- package/dist/umd/n4s.production.js +1 -0
- package/dist/umd/schema.development.js +148 -0
- package/dist/umd/schema.production.js +1 -0
- package/docs/README.md +2 -5
- package/docs/_sidebar.md +1 -2
- package/docs/external.md +1 -28
- package/docs/rules.md +28 -0
- package/package.json +129 -42
- package/schema/package.json +7 -0
- package/tsconfig.json +8 -0
- package/types/compose.d.ts +134 -0
- package/types/compounds.d.ts +146 -0
- package/types/n4s.d.ts +167 -0
- package/types/schema.d.ts +151 -0
- package/config/jest/jest.setup.js +0 -14
- package/config/rollup/enforce.js +0 -8
- package/config/rollup/rollup.config.js +0 -3
- package/docs/compound.md +0 -187
- package/docs/custom.md +0 -52
- package/docs/template.md +0 -53
- package/esm/n4s.mjs.development.js +0 -1101
- package/esm/n4s.mjs.production.js +0 -1101
- package/esm/n4s.mjs.production.min.js +0 -1
- package/esm/package.json +0 -1
- package/jest.config.js +0 -3
- package/n4s.cjs.development.js +0 -1103
- package/n4s.cjs.production.js +0 -1103
- package/n4s.cjs.production.min.js +0 -1
- package/n4s.js +0 -7
- package/n4s.umd.development.js +0 -1109
- package/n4s.umd.production.js +0 -1192
- package/n4s.umd.production.min.js +0 -1
package/n4s.umd.production.js
DELETED
|
@@ -1,1192 +0,0 @@
|
|
|
1
|
-
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.n4s = factory());
|
|
5
|
-
}(this, (function () { 'use strict';
|
|
6
|
-
|
|
7
|
-
function _unsupportedIterableToArray(o, minLen) {
|
|
8
|
-
if (!o) return;
|
|
9
|
-
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
10
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
11
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
12
|
-
if (n === "Map" || n === "Set") return Array.from(o);
|
|
13
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function _arrayLikeToArray(arr, len) {
|
|
17
|
-
if (len == null || len > arr.length) len = arr.length;
|
|
18
|
-
|
|
19
|
-
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
20
|
-
|
|
21
|
-
return arr2;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function _createForOfIteratorHelperLoose(o, allowArrayLike) {
|
|
25
|
-
var it;
|
|
26
|
-
|
|
27
|
-
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
|
|
28
|
-
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
|
29
|
-
if (it) o = it;
|
|
30
|
-
var i = 0;
|
|
31
|
-
return function () {
|
|
32
|
-
if (i >= o.length) return {
|
|
33
|
-
done: true
|
|
34
|
-
};
|
|
35
|
-
return {
|
|
36
|
-
done: false,
|
|
37
|
-
value: o[i++]
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
it = o[Symbol.iterator]();
|
|
46
|
-
return it.next.bind(it);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Stores values and configuration passed down to compound rules.
|
|
51
|
-
*
|
|
52
|
-
* @param {Object} content
|
|
53
|
-
*/
|
|
54
|
-
function EnforceContext(content) {
|
|
55
|
-
Object.assign(this, content);
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Sets an EnforceContext config `failFast`
|
|
59
|
-
*
|
|
60
|
-
* @param {Boolean} failFast
|
|
61
|
-
* @return {EnforceContext}
|
|
62
|
-
*/
|
|
63
|
-
|
|
64
|
-
EnforceContext.prototype.setFailFast = function (failFast) {
|
|
65
|
-
this.failFast = !!failFast;
|
|
66
|
-
return this;
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* Extracts the literal value from an EnforceContext object
|
|
70
|
-
* @param {*} value
|
|
71
|
-
* @return {*}
|
|
72
|
-
*/
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
EnforceContext.unwrap = function unwrap(value) {
|
|
76
|
-
return EnforceContext.is(value) ? value.value : value;
|
|
77
|
-
};
|
|
78
|
-
/**
|
|
79
|
-
* Wraps a literal value within a context.
|
|
80
|
-
* @param {*} value
|
|
81
|
-
* @return {EnforceContext}
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
EnforceContext.wrap = function wrap(value) {
|
|
86
|
-
return EnforceContext.is(value) ? value : new EnforceContext({
|
|
87
|
-
value: value
|
|
88
|
-
});
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* Checks whether a given value is an EnforceContext instance
|
|
92
|
-
*
|
|
93
|
-
* @param {*} value
|
|
94
|
-
* @returns {boolean}
|
|
95
|
-
*/
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
EnforceContext.is = function is(value) {
|
|
99
|
-
return value instanceof EnforceContext;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* A safe hasOwnProperty access
|
|
104
|
-
*/
|
|
105
|
-
function hasOwnProperty(obj, key) {
|
|
106
|
-
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function bindNot(fn) {
|
|
110
|
-
return function () {
|
|
111
|
-
return !fn.apply(this, arguments);
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function isBoolean(value) {
|
|
116
|
-
return !!value === value;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
var isNotBoolean = bindNot(isBoolean);
|
|
120
|
-
|
|
121
|
-
function isNumeric(value) {
|
|
122
|
-
var result = !isNaN(parseFloat(value)) && !isNaN(Number(value)) && isFinite(value);
|
|
123
|
-
return Boolean(result);
|
|
124
|
-
}
|
|
125
|
-
var isNotNumeric = bindNot(isNumeric);
|
|
126
|
-
|
|
127
|
-
function lengthEquals(value, arg1) {
|
|
128
|
-
return value.length === Number(arg1);
|
|
129
|
-
}
|
|
130
|
-
var lengthNotEquals = bindNot(lengthEquals);
|
|
131
|
-
|
|
132
|
-
function isEmpty(value) {
|
|
133
|
-
if (!value) {
|
|
134
|
-
return true;
|
|
135
|
-
} else if (isNumeric(value)) {
|
|
136
|
-
return value === 0;
|
|
137
|
-
} else if (hasOwnProperty(value, 'length')) {
|
|
138
|
-
return lengthEquals(value, 0);
|
|
139
|
-
} else if (typeof value === 'object') {
|
|
140
|
-
return lengthEquals(Object.keys(value), 0);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
var isNotEmpty = bindNot(isEmpty);
|
|
146
|
-
|
|
147
|
-
function isUndefined(value) {
|
|
148
|
-
return value === undefined;
|
|
149
|
-
}
|
|
150
|
-
var isNotUndefined = bindNot(isUndefined);
|
|
151
|
-
|
|
152
|
-
var HAS_WARNINGS = 'hasWarnings';
|
|
153
|
-
var HAS_ERRORS = 'hasErrors';
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Stores a rule result in an easy to inspect and manipulate structure.
|
|
157
|
-
*
|
|
158
|
-
* @param {boolean|RuleResult} ruleRunResult
|
|
159
|
-
*/
|
|
160
|
-
|
|
161
|
-
function RuleResult(ruleRunResult) {
|
|
162
|
-
if (isUndefined(ruleRunResult)) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (isBoolean(ruleRunResult)) {
|
|
167
|
-
this.setFailed(!ruleRunResult);
|
|
168
|
-
} else {
|
|
169
|
-
this.extend(ruleRunResult);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Determines whether a given value is a RuleResult instance
|
|
174
|
-
* @param {*} res
|
|
175
|
-
* @return {boolean}
|
|
176
|
-
*/
|
|
177
|
-
|
|
178
|
-
RuleResult.is = function (res) {
|
|
179
|
-
return res instanceof RuleResult;
|
|
180
|
-
};
|
|
181
|
-
/**
|
|
182
|
-
* Marks the current result object as an array
|
|
183
|
-
*/
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
RuleResult.prototype.asArray = function () {
|
|
187
|
-
this.isArray = true;
|
|
188
|
-
return this;
|
|
189
|
-
};
|
|
190
|
-
/**
|
|
191
|
-
* @param {string} key
|
|
192
|
-
* @param {value} value
|
|
193
|
-
* @return {RuleResult} current instance
|
|
194
|
-
*/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
RuleResult.prototype.setAttribute = function (key, value) {
|
|
198
|
-
this[key] = value;
|
|
199
|
-
return this;
|
|
200
|
-
};
|
|
201
|
-
/**
|
|
202
|
-
* @param {boolean} failed
|
|
203
|
-
* @return {RuleResult} current instance
|
|
204
|
-
*/
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
RuleResult.prototype.setFailed = function (failed) {
|
|
208
|
-
this.setAttribute(this.warn ? HAS_WARNINGS : HAS_ERRORS, failed);
|
|
209
|
-
return this.setAttribute('failed', failed);
|
|
210
|
-
};
|
|
211
|
-
/**
|
|
212
|
-
* Adds a nested result object
|
|
213
|
-
*
|
|
214
|
-
* @param {string} key
|
|
215
|
-
* @param {RuleResult} child
|
|
216
|
-
*/
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
RuleResult.prototype.setChild = function (key, child) {
|
|
220
|
-
var isWarning = this[HAS_WARNINGS] || child[HAS_WARNINGS] || child.warn || this.warn;
|
|
221
|
-
this.setAttribute(HAS_WARNINGS, isWarning && child.failed || false);
|
|
222
|
-
this.setAttribute(HAS_ERRORS, this[HAS_ERRORS] || child[HAS_ERRORS] || !isWarning && child.failed || false);
|
|
223
|
-
this.setFailed(this.failed || child.failed);
|
|
224
|
-
this.children = this.children || {};
|
|
225
|
-
this.children[key] = child;
|
|
226
|
-
return child;
|
|
227
|
-
};
|
|
228
|
-
/**
|
|
229
|
-
* Retrieves a child by its key
|
|
230
|
-
*
|
|
231
|
-
* @param {string} key
|
|
232
|
-
* @return {RuleResult|undefined}
|
|
233
|
-
*/
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
RuleResult.prototype.getChild = function (key) {
|
|
237
|
-
return (this.children || {})[key];
|
|
238
|
-
};
|
|
239
|
-
/**
|
|
240
|
-
* Extends current instance with a new provided result
|
|
241
|
-
* @param {Boolean|RuleResult} newRes
|
|
242
|
-
*/
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
RuleResult.prototype.extend = function (newRes) {
|
|
246
|
-
var res = RuleResult.is(newRes) ? newRes : new RuleResult().setAttribute('warn', !!this.warn).setFailed(!newRes);
|
|
247
|
-
var failed = this.failed || res.failed;
|
|
248
|
-
var children = mergeChildren(res, this).children;
|
|
249
|
-
Object.assign(this, res);
|
|
250
|
-
|
|
251
|
-
if (!isEmpty(children)) {
|
|
252
|
-
this.children = children;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
this.setFailed(failed);
|
|
256
|
-
this.setAttribute(HAS_WARNINGS, !!(this[HAS_WARNINGS] || res[HAS_WARNINGS]));
|
|
257
|
-
this.setAttribute(HAS_ERRORS, !!(this[HAS_ERRORS] || res[HAS_ERRORS]));
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
Object.defineProperty(RuleResult.prototype, 'pass', {
|
|
261
|
-
get: function get() {
|
|
262
|
-
return !this.failed;
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
/**
|
|
266
|
-
* Deeply merge the nested children of compound rules
|
|
267
|
-
*
|
|
268
|
-
* @param {?RuleResult} base
|
|
269
|
-
* @param {?RuleResult} add
|
|
270
|
-
* @return {RuleResult}
|
|
271
|
-
*/
|
|
272
|
-
|
|
273
|
-
function mergeChildren(base, add) {
|
|
274
|
-
var isRuleResultBase = RuleResult.is(base);
|
|
275
|
-
var isRuleResultAdd = RuleResult.is(add); // If both base and add are result objects
|
|
276
|
-
|
|
277
|
-
if (isRuleResultBase && isRuleResultAdd) {
|
|
278
|
-
// Use failed if either is failing
|
|
279
|
-
base.setFailed(base.failed || add.failed); // If neither has a children object, or the children object is
|
|
280
|
-
|
|
281
|
-
if (isEmpty(base.children) && isEmpty(add.children)) {
|
|
282
|
-
return base;
|
|
283
|
-
} // If both have a children object
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
if (base.children && add.children) {
|
|
287
|
-
// Merge all the "right side" children back to base
|
|
288
|
-
for (var key in base.children) {
|
|
289
|
-
mergeChildren(base.children[key], add.children[key]);
|
|
290
|
-
} // If a child exists in "add" but not in "base", just copy the child as is
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
for (var _key in add.children) {
|
|
294
|
-
if (!hasOwnProperty(base.children, _key)) {
|
|
295
|
-
base.setChild(_key, add.children[_key]);
|
|
296
|
-
}
|
|
297
|
-
} // Return the modified base object
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
return base; // If base has no children (but add does)
|
|
301
|
-
} else if (!base.children) {
|
|
302
|
-
// Use add's children
|
|
303
|
-
base.children = add.children; // If add has no children
|
|
304
|
-
} else if (!add.children) {
|
|
305
|
-
// return base as is
|
|
306
|
-
return base;
|
|
307
|
-
} // If only base is `RuleResult`
|
|
308
|
-
|
|
309
|
-
} else if (isRuleResultBase) {
|
|
310
|
-
// Return base as is
|
|
311
|
-
return base; // If only add is RuleResult
|
|
312
|
-
} else if (isRuleResultAdd) {
|
|
313
|
-
// Return add as is
|
|
314
|
-
return add;
|
|
315
|
-
} // That's a weird case. Let's fail. Very unlikely.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
return new RuleResult(false);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
var RUN_RULE = 'run';
|
|
322
|
-
var TEST_RULE = 'test';
|
|
323
|
-
var MODE_ALL = 'all';
|
|
324
|
-
var MODE_ONE = 'one';
|
|
325
|
-
var MODE_ANY = 'any';
|
|
326
|
-
|
|
327
|
-
function isFunction (v) {
|
|
328
|
-
return typeof v === 'function';
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
function asArray(possibleArg) {
|
|
332
|
-
return [].concat(possibleArg);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Determines whether we should bail out of an enforcement.
|
|
337
|
-
*
|
|
338
|
-
* @param {EnforceContext} ctx
|
|
339
|
-
* @param {RuleResult} result
|
|
340
|
-
*/
|
|
341
|
-
|
|
342
|
-
function shouldFailFast(ctx, result) {
|
|
343
|
-
if (result.pass || result.warn) {
|
|
344
|
-
return false;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
return !!EnforceContext.is(ctx) && ctx.failFast;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Runs multiple enforce rules that are passed to compounds.
|
|
352
|
-
* Example: enforce.allOf(enforce.ruleOne(), enforce.ruleTwo().ruleThree())
|
|
353
|
-
*
|
|
354
|
-
* @param {{run: Function}[]} ruleGroups
|
|
355
|
-
* @param {*} value
|
|
356
|
-
* @return {RuleResult}
|
|
357
|
-
*/
|
|
358
|
-
|
|
359
|
-
function runLazyRules(ruleGroups, value) {
|
|
360
|
-
var result = new RuleResult(true);
|
|
361
|
-
|
|
362
|
-
for (var _iterator = _createForOfIteratorHelperLoose(asArray(ruleGroups)), _step; !(_step = _iterator()).done;) {
|
|
363
|
-
var chain = _step.value;
|
|
364
|
-
|
|
365
|
-
if (shouldFailFast(value, result)) {
|
|
366
|
-
break;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
result.extend(runLazyRule(chain, value));
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return result;
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Runs a single lazy rule
|
|
376
|
-
*
|
|
377
|
-
* @param {{run: Function}} ruleGroup
|
|
378
|
-
* @param {*} value
|
|
379
|
-
* @return {boolean|RuleResult}
|
|
380
|
-
*/
|
|
381
|
-
|
|
382
|
-
function runLazyRule(ruleGroup, value) {
|
|
383
|
-
return ruleGroup[RUN_RULE](value);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Runs chains of rules
|
|
388
|
-
*
|
|
389
|
-
* @param {EnforceContext} value
|
|
390
|
-
* @param {[{test: Function, run: Function}]} rules
|
|
391
|
-
* @param {RuleResult} options
|
|
392
|
-
*/
|
|
393
|
-
|
|
394
|
-
function runCompoundChain(value, rules, options) {
|
|
395
|
-
var result = new RuleResult(true);
|
|
396
|
-
|
|
397
|
-
if (isEmpty(rules)) {
|
|
398
|
-
result.setFailed(true);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
var failedResults = [];
|
|
402
|
-
var count = 0;
|
|
403
|
-
|
|
404
|
-
for (var _iterator = _createForOfIteratorHelperLoose(rules), _step; !(_step = _iterator()).done;) {
|
|
405
|
-
var chain = _step.value;
|
|
406
|
-
// Inner result for each iteration
|
|
407
|
-
var currentResult = runLazyRule(chain, value);
|
|
408
|
-
var pass = currentResult.pass;
|
|
409
|
-
|
|
410
|
-
if (pass) {
|
|
411
|
-
count++;
|
|
412
|
-
} else {
|
|
413
|
-
failedResults.push(currentResult);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (options) {
|
|
417
|
-
// "anyOf" is a special case.
|
|
418
|
-
// It shouldn't extend with failed results,
|
|
419
|
-
// that's why we continue
|
|
420
|
-
if (options.mode === MODE_ANY) {
|
|
421
|
-
if (pass) {
|
|
422
|
-
result.extend(currentResult);
|
|
423
|
-
break;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
continue;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
result.extend(currentResult); // MODE_ALL: All must pass.
|
|
430
|
-
// If one failed, exit.
|
|
431
|
-
|
|
432
|
-
if (options.mode === MODE_ALL) {
|
|
433
|
-
if (!pass) {
|
|
434
|
-
break;
|
|
435
|
-
}
|
|
436
|
-
} // MODE_ONE: only one must pass.
|
|
437
|
-
// If more than one passed, exit.
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
if (options.mode === MODE_ONE) {
|
|
441
|
-
result.setFailed(count !== 1);
|
|
442
|
-
|
|
443
|
-
if (count > 1) {
|
|
444
|
-
break;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
} else {
|
|
448
|
-
result.extend(currentResult);
|
|
449
|
-
|
|
450
|
-
if (pass) {
|
|
451
|
-
break;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
if (result.pass && count === 0) {
|
|
457
|
-
result.setFailed(true); // In some cases we do not want to extend failures, for example - in ANY
|
|
458
|
-
// when there is a valid response, so we do it before returning
|
|
459
|
-
|
|
460
|
-
failedResults.forEach(function (failedResult) {
|
|
461
|
-
return result.extend(failedResult);
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
return result;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
function setFnName(fn, value) {
|
|
469
|
-
return Object.defineProperty(fn, 'name', {
|
|
470
|
-
value: value
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* ES5 Transpilation increases the size of spread arguments by a lot.
|
|
476
|
-
* Wraps a function and passes its spread params as an array.
|
|
477
|
-
*
|
|
478
|
-
* @param {Function} cb
|
|
479
|
-
* @param {String} [fnName]
|
|
480
|
-
* @return {Function}
|
|
481
|
-
*/
|
|
482
|
-
|
|
483
|
-
function withArgs(cb, fnName) {
|
|
484
|
-
return setFnName(function () {
|
|
485
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
486
|
-
args[_key] = arguments[_key];
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
var right = args.splice(cb.length - 1);
|
|
490
|
-
return cb.apply(null, args.concat([right]));
|
|
491
|
-
}, fnName || cb.name);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Runs a chaen of rules, making sure that all assertions pass
|
|
496
|
-
*
|
|
497
|
-
* @param {EnforceContext} value
|
|
498
|
-
* @param {[{test: Function, run: Function}]} ruleChains
|
|
499
|
-
* @return {RuleResult}
|
|
500
|
-
*/
|
|
501
|
-
|
|
502
|
-
function allOf(value, rules) {
|
|
503
|
-
return runCompoundChain(value, rules, {
|
|
504
|
-
mode: MODE_ALL
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
var allOf$1 = withArgs(allOf);
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* Runs chains of rules, making sure
|
|
512
|
-
* that at least one assertion passes
|
|
513
|
-
*
|
|
514
|
-
* @param {EnforceContext} value
|
|
515
|
-
* @param {[{test: Function, run: Function}]} ruleChains
|
|
516
|
-
* @return {RuleResult}
|
|
517
|
-
*/
|
|
518
|
-
|
|
519
|
-
function anyOf(value, ruleChains) {
|
|
520
|
-
return runCompoundChain(value, ruleChains, {
|
|
521
|
-
mode: MODE_ANY
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
var anyOf$1 = withArgs(anyOf);
|
|
526
|
-
|
|
527
|
-
function isArray(value) {
|
|
528
|
-
return Boolean(Array.isArray(value));
|
|
529
|
-
}
|
|
530
|
-
var isNotArray = bindNot(isArray);
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Asserts that each element in an array passes
|
|
534
|
-
* at least one of the provided rule chain
|
|
535
|
-
*
|
|
536
|
-
* @param {EnforceContext} value
|
|
537
|
-
* @param {[{test: Function, run: Function}]} ruleChains
|
|
538
|
-
* @return {RuleResult}
|
|
539
|
-
*/
|
|
540
|
-
|
|
541
|
-
function isArrayOf(value, ruleChains) {
|
|
542
|
-
var plainValue = EnforceContext.unwrap(value);
|
|
543
|
-
var result = new RuleResult(true).asArray(); // Fails if current value is not an array
|
|
544
|
-
|
|
545
|
-
if (isNotArray(plainValue)) {
|
|
546
|
-
return result.setFailed(true);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
for (var i = 0; i < plainValue.length; i++) {
|
|
550
|
-
// Set result per each item in the array|
|
|
551
|
-
result.setChild(i, runCompoundChain(EnforceContext.wrap(plainValue[i]).setFailFast(value.failFast), ruleChains, {
|
|
552
|
-
mode: MODE_ANY
|
|
553
|
-
}));
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
return result;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
var isArrayOf$1 = withArgs(isArrayOf);
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* @param {EnforceContext} value
|
|
563
|
-
* @param {[{test: Function, run: Function}]} ruleChains
|
|
564
|
-
* @return {RuleResult}
|
|
565
|
-
*/
|
|
566
|
-
|
|
567
|
-
function oneOf(value, rules) {
|
|
568
|
-
return runCompoundChain(value, rules, {
|
|
569
|
-
mode: MODE_ONE
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
var oneOf$1 = withArgs(oneOf);
|
|
574
|
-
|
|
575
|
-
function isNull(value) {
|
|
576
|
-
return value === null;
|
|
577
|
-
}
|
|
578
|
-
var isNotNull = bindNot(isNull);
|
|
579
|
-
|
|
580
|
-
/**
|
|
581
|
-
* @param {Array} ObjectEntry Object and key leading to current value
|
|
582
|
-
* @param {Function[]} rules Rules to validate the value with
|
|
583
|
-
*/
|
|
584
|
-
|
|
585
|
-
function optional(inputObject, ruleGroups) {
|
|
586
|
-
var obj = inputObject.obj,
|
|
587
|
-
key = inputObject.key; // If current value is not defined, undefined or null
|
|
588
|
-
// Pass without further assertions
|
|
589
|
-
|
|
590
|
-
if (!hasOwnProperty(obj, key) || isUndefined(obj[key] || isNull(obj[key]))) {
|
|
591
|
-
return true;
|
|
592
|
-
} // Pass if exists but no assertions
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
if (isEmpty(ruleGroups)) {
|
|
596
|
-
return true;
|
|
597
|
-
} // Run chain with `all` mode
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
return runCompoundChain(obj[key], ruleGroups, {
|
|
601
|
-
mode: MODE_ALL
|
|
602
|
-
});
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
var optional$1 = withArgs(optional);
|
|
606
|
-
|
|
607
|
-
/**
|
|
608
|
-
* @param {EnforceContext} inputObject Data object that gets validated
|
|
609
|
-
* @param {Object} shapeObj Shape definition
|
|
610
|
-
* @param {Object} options
|
|
611
|
-
* @param {boolean} options.loose Ignore extra keys not defined in shapeObj
|
|
612
|
-
*/
|
|
613
|
-
|
|
614
|
-
function shape(inputObject, shapeObj, options) {
|
|
615
|
-
// Extract the object from context
|
|
616
|
-
var obj = EnforceContext.unwrap(inputObject); // Create a new result object
|
|
617
|
-
|
|
618
|
-
var result = new RuleResult(true); // Iterate over the shape keys
|
|
619
|
-
|
|
620
|
-
for (var key in shapeObj) {
|
|
621
|
-
var current = shapeObj[key];
|
|
622
|
-
var value = obj[key];
|
|
623
|
-
|
|
624
|
-
if (shouldFailFast(value, result)) {
|
|
625
|
-
break;
|
|
626
|
-
} // Set each key in the result object
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
result.setChild(key, runLazyRule(current, new EnforceContext({
|
|
630
|
-
value: value,
|
|
631
|
-
obj: obj,
|
|
632
|
-
key: key
|
|
633
|
-
}).setFailFast(inputObject.failFast)));
|
|
634
|
-
} // If mode is not loose
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
if (!(options || {}).loose) {
|
|
638
|
-
// Check that each key in the input object exists in the shape
|
|
639
|
-
for (var _key in obj) {
|
|
640
|
-
if (!hasOwnProperty(shapeObj, _key)) {
|
|
641
|
-
return result.setFailed(true);
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
return result;
|
|
647
|
-
}
|
|
648
|
-
var loose = function loose(obj, shapeObj) {
|
|
649
|
-
return shape(obj, shapeObj, {
|
|
650
|
-
loose: true
|
|
651
|
-
});
|
|
652
|
-
};
|
|
653
|
-
|
|
654
|
-
var compounds = {
|
|
655
|
-
allOf: allOf$1,
|
|
656
|
-
anyOf: anyOf$1,
|
|
657
|
-
isArrayOf: isArrayOf$1,
|
|
658
|
-
loose: loose,
|
|
659
|
-
oneOf: oneOf$1,
|
|
660
|
-
optional: optional$1,
|
|
661
|
-
shape: shape
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
* Takes a value. If it is a function, runs it and returns the result.
|
|
666
|
-
* Otherwise, returns the value as is.
|
|
667
|
-
*
|
|
668
|
-
* @param {Function|*} value Value to return. Run it if a function.
|
|
669
|
-
* @param {Any[]} [args] Arguments to pass if a function
|
|
670
|
-
* @return {Any}
|
|
671
|
-
*/
|
|
672
|
-
|
|
673
|
-
function optionalFunctionValue(value, args) {
|
|
674
|
-
return isFunction(value) ? value.apply(null, args) : value;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
function message(value, msg) {
|
|
678
|
-
return optionalFunctionValue(msg, [EnforceContext.unwrap(value)]);
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
function warn(_, isWarn) {
|
|
682
|
-
if (isWarn === void 0) {
|
|
683
|
-
isWarn = true;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
return isWarn;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
var ruleMeta = {
|
|
690
|
-
warn: warn,
|
|
691
|
-
message: message
|
|
692
|
-
};
|
|
693
|
-
|
|
694
|
-
function isString (v) {
|
|
695
|
-
return String(v) === v;
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
function endsWith(value, arg1) {
|
|
699
|
-
return isString(value) && isString(arg1) && value.endsWith(arg1);
|
|
700
|
-
}
|
|
701
|
-
var doesNotEndWith = bindNot(endsWith);
|
|
702
|
-
|
|
703
|
-
function equals(value, arg1) {
|
|
704
|
-
return value === arg1;
|
|
705
|
-
}
|
|
706
|
-
var notEquals = bindNot(equals);
|
|
707
|
-
|
|
708
|
-
function greaterThan(value, arg1) {
|
|
709
|
-
return isNumeric(value) && isNumeric(arg1) && Number(value) > Number(arg1);
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
function greaterThanOrEquals(value, arg1) {
|
|
713
|
-
return isNumeric(value) && isNumeric(arg1) && Number(value) >= Number(arg1);
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
function inside(value, arg1) {
|
|
717
|
-
if (Array.isArray(arg1) && /^[s|n|b]/.test(typeof value)) {
|
|
718
|
-
return arg1.indexOf(value) !== -1;
|
|
719
|
-
} // both value and arg1 are strings
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if (isString(arg1) && isString(value)) {
|
|
723
|
-
return arg1.indexOf(value) !== -1;
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
return false;
|
|
727
|
-
}
|
|
728
|
-
var notInside = bindNot(inside);
|
|
729
|
-
|
|
730
|
-
function lessThanOrEquals(value, arg1) {
|
|
731
|
-
return isNumeric(value) && isNumeric(arg1) && Number(value) <= Number(arg1);
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
function isBetween(value, min, max) {
|
|
735
|
-
return greaterThanOrEquals(value, min) && lessThanOrEquals(value, max);
|
|
736
|
-
}
|
|
737
|
-
var isNotBetween = bindNot(isBetween);
|
|
738
|
-
|
|
739
|
-
/**
|
|
740
|
-
* Validates that a given value is an even number
|
|
741
|
-
* @param {Number|String} value Value to be validated
|
|
742
|
-
* @return {Boolean}
|
|
743
|
-
*/
|
|
744
|
-
|
|
745
|
-
var isEven = function isEven(value) {
|
|
746
|
-
if (isNumeric(value)) {
|
|
747
|
-
return value % 2 === 0;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
return false;
|
|
751
|
-
};
|
|
752
|
-
|
|
753
|
-
function isNaN$1(value) {
|
|
754
|
-
return Number.isNaN(value);
|
|
755
|
-
}
|
|
756
|
-
var isNotNaN = bindNot(isNaN$1);
|
|
757
|
-
|
|
758
|
-
function isNegative(value) {
|
|
759
|
-
if (isNumeric(value)) {
|
|
760
|
-
return Number(value) < 0;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
return false;
|
|
764
|
-
}
|
|
765
|
-
var isPositive = bindNot(isNegative);
|
|
766
|
-
|
|
767
|
-
function isNumber(value) {
|
|
768
|
-
return Boolean(typeof value === 'number');
|
|
769
|
-
}
|
|
770
|
-
var isNotNumber = bindNot(isNumber);
|
|
771
|
-
|
|
772
|
-
/**
|
|
773
|
-
* Validates that a given value is an odd number
|
|
774
|
-
* @param {Number|String} value Value to be validated
|
|
775
|
-
* @return {Boolean}
|
|
776
|
-
*/
|
|
777
|
-
|
|
778
|
-
var isOdd = function isOdd(value) {
|
|
779
|
-
if (isNumeric(value)) {
|
|
780
|
-
return value % 2 !== 0;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
return false;
|
|
784
|
-
};
|
|
785
|
-
|
|
786
|
-
var isNotString = bindNot(isString);
|
|
787
|
-
|
|
788
|
-
function isTruthy(value) {
|
|
789
|
-
return !!value;
|
|
790
|
-
}
|
|
791
|
-
var isFalsy = bindNot(isTruthy);
|
|
792
|
-
|
|
793
|
-
function lessThan(value, arg1) {
|
|
794
|
-
return isNumeric(value) && isNumeric(arg1) && Number(value) < Number(arg1);
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
function longerThan(value, arg1) {
|
|
798
|
-
return value.length > Number(arg1);
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
function longerThanOrEquals(value, arg1) {
|
|
802
|
-
return value.length >= Number(arg1);
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
function matches(value, regex) {
|
|
806
|
-
if (regex instanceof RegExp) {
|
|
807
|
-
return regex.test(value);
|
|
808
|
-
} else if (isString(regex)) {
|
|
809
|
-
return new RegExp(regex).test(value);
|
|
810
|
-
} else {
|
|
811
|
-
return false;
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
var notMatches = bindNot(matches);
|
|
815
|
-
|
|
816
|
-
function numberEquals(value, arg1) {
|
|
817
|
-
return isNumeric(value) && isNumeric(arg1) && Number(value) === Number(arg1);
|
|
818
|
-
}
|
|
819
|
-
var numberNotEquals = bindNot(numberEquals);
|
|
820
|
-
|
|
821
|
-
function shorterThan(value, arg1) {
|
|
822
|
-
return value.length < Number(arg1);
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
function shorterThanOrEquals(value, arg1) {
|
|
826
|
-
return value.length <= Number(arg1);
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
function startsWith(value, arg1) {
|
|
830
|
-
return isString(value) && isString(arg1) && value.startsWith(arg1);
|
|
831
|
-
}
|
|
832
|
-
var doesNotStartWith = bindNot(startsWith);
|
|
833
|
-
|
|
834
|
-
function rules() {
|
|
835
|
-
return {
|
|
836
|
-
doesNotEndWith: doesNotEndWith,
|
|
837
|
-
doesNotStartWith: doesNotStartWith,
|
|
838
|
-
endsWith: endsWith,
|
|
839
|
-
equals: equals,
|
|
840
|
-
greaterThan: greaterThan,
|
|
841
|
-
greaterThanOrEquals: greaterThanOrEquals,
|
|
842
|
-
gt: greaterThan,
|
|
843
|
-
gte: greaterThanOrEquals,
|
|
844
|
-
inside: inside,
|
|
845
|
-
isArray: isArray,
|
|
846
|
-
isBetween: isBetween,
|
|
847
|
-
isBoolean: isBoolean,
|
|
848
|
-
isEmpty: isEmpty,
|
|
849
|
-
isEven: isEven,
|
|
850
|
-
isFalsy: isFalsy,
|
|
851
|
-
isNaN: isNaN$1,
|
|
852
|
-
isNegative: isNegative,
|
|
853
|
-
isNotArray: isNotArray,
|
|
854
|
-
isNotBetween: isNotBetween,
|
|
855
|
-
isNotBoolean: isNotBoolean,
|
|
856
|
-
isNotEmpty: isNotEmpty,
|
|
857
|
-
isNotNaN: isNotNaN,
|
|
858
|
-
isNotNull: isNotNull,
|
|
859
|
-
isNotNumber: isNotNumber,
|
|
860
|
-
isNotNumeric: isNotNumeric,
|
|
861
|
-
isNotString: isNotString,
|
|
862
|
-
isNotUndefined: isNotUndefined,
|
|
863
|
-
isNull: isNull,
|
|
864
|
-
isNumber: isNumber,
|
|
865
|
-
isNumeric: isNumeric,
|
|
866
|
-
isOdd: isOdd,
|
|
867
|
-
isPositive: isPositive,
|
|
868
|
-
isString: isString,
|
|
869
|
-
isTruthy: isTruthy,
|
|
870
|
-
isUndefined: isUndefined,
|
|
871
|
-
lengthEquals: lengthEquals,
|
|
872
|
-
lengthNotEquals: lengthNotEquals,
|
|
873
|
-
lessThan: lessThan,
|
|
874
|
-
lessThanOrEquals: lessThanOrEquals,
|
|
875
|
-
longerThan: longerThan,
|
|
876
|
-
longerThanOrEquals: longerThanOrEquals,
|
|
877
|
-
lt: lessThan,
|
|
878
|
-
lte: lessThanOrEquals,
|
|
879
|
-
matches: matches,
|
|
880
|
-
notEquals: notEquals,
|
|
881
|
-
notInside: notInside,
|
|
882
|
-
notMatches: notMatches,
|
|
883
|
-
numberEquals: numberEquals,
|
|
884
|
-
numberNotEquals: numberNotEquals,
|
|
885
|
-
shorterThan: shorterThan,
|
|
886
|
-
shorterThanOrEquals: shorterThanOrEquals,
|
|
887
|
-
startsWith: startsWith
|
|
888
|
-
};
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
var runtimeRules = Object.assign(rules(), compounds, ruleMeta);
|
|
892
|
-
|
|
893
|
-
/**
|
|
894
|
-
* Determines whether a given string is a name of a rule
|
|
895
|
-
*
|
|
896
|
-
* @param {string} name
|
|
897
|
-
* @return {boolean}
|
|
898
|
-
*/
|
|
899
|
-
|
|
900
|
-
var isRule = function isRule(name) {
|
|
901
|
-
return hasOwnProperty(runtimeRules, name) && isFunction(runtimeRules[name]);
|
|
902
|
-
};
|
|
903
|
-
|
|
904
|
-
var GLOBAL_OBJECT = Function('return this')();
|
|
905
|
-
|
|
906
|
-
var proxySupported = function proxySupported() {
|
|
907
|
-
return isFunction(GLOBAL_OBJECT.Proxy);
|
|
908
|
-
};
|
|
909
|
-
|
|
910
|
-
function genRuleProxy(target, output) {
|
|
911
|
-
if (proxySupported()) {
|
|
912
|
-
return new Proxy(target, {
|
|
913
|
-
get: function get(target, fnName) {
|
|
914
|
-
// A faster bailout when we access `run` and `test`
|
|
915
|
-
if (hasOwnProperty(target, fnName)) {
|
|
916
|
-
return target[fnName];
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
if (isRule(fnName)) {
|
|
920
|
-
return output(fnName);
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
return target[fnName];
|
|
924
|
-
}
|
|
925
|
-
});
|
|
926
|
-
} else {
|
|
927
|
-
var _loop = function _loop(fnName) {
|
|
928
|
-
if (!isFunction(target[fnName])) {
|
|
929
|
-
var _Object$definePropert;
|
|
930
|
-
|
|
931
|
-
Object.defineProperties(target, (_Object$definePropert = {}, _Object$definePropert[fnName] = {
|
|
932
|
-
get: function get() {
|
|
933
|
-
return output(fnName);
|
|
934
|
-
}
|
|
935
|
-
}, _Object$definePropert));
|
|
936
|
-
}
|
|
937
|
-
};
|
|
938
|
-
|
|
939
|
-
/**
|
|
940
|
-
* This method is REALLY not recommended as it is slow and iterates over
|
|
941
|
-
* all the rules for each direct enforce reference. We only use it as a
|
|
942
|
-
* lightweight alternative for the much faster proxy interface
|
|
943
|
-
*/
|
|
944
|
-
for (var fnName in runtimeRules) {
|
|
945
|
-
_loop(fnName);
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
return target;
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
/**
|
|
953
|
-
* Determines whether a given rule is a compound.
|
|
954
|
-
*
|
|
955
|
-
* @param {Function} rule
|
|
956
|
-
* @return {boolean}
|
|
957
|
-
*/
|
|
958
|
-
|
|
959
|
-
function isCompound(rule) {
|
|
960
|
-
return hasOwnProperty(compounds, rule.name);
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
/**
|
|
964
|
-
* Creates a rule of lazily called rules.
|
|
965
|
-
* Each rule gets added a `.run()` property
|
|
966
|
-
* which runs all the accumulated rules in
|
|
967
|
-
* the chain against the supplied value
|
|
968
|
-
*
|
|
969
|
-
* @param {string} ruleName
|
|
970
|
-
* @return {{run: Function}}
|
|
971
|
-
*/
|
|
972
|
-
|
|
973
|
-
function bindLazyRule(ruleName) {
|
|
974
|
-
var registeredRules = []; // Chained rules
|
|
975
|
-
|
|
976
|
-
var meta = []; // Meta properties to add onto the rule context
|
|
977
|
-
// Appends a function to the registeredRules array.
|
|
978
|
-
// It gets called every time the consumer usess chaining
|
|
979
|
-
// so, for example - enforce.isArray() <- this calles addFn
|
|
980
|
-
|
|
981
|
-
var addFn = function addFn(ruleName) {
|
|
982
|
-
return withArgs(function (args) {
|
|
983
|
-
var rule = runtimeRules[ruleName]; // Add a meta function
|
|
984
|
-
|
|
985
|
-
if (ruleMeta[rule.name] === rule) {
|
|
986
|
-
meta.push(function (value, ruleResult) {
|
|
987
|
-
ruleResult.setAttribute(rule.name, rule(value, args[0]));
|
|
988
|
-
});
|
|
989
|
-
} else {
|
|
990
|
-
// Register a rule
|
|
991
|
-
registeredRules.push(setFnName(function (value) {
|
|
992
|
-
return rule.apply(null, [// If the rule is compound - wraps the value with context
|
|
993
|
-
// Otherwise - unwraps it
|
|
994
|
-
isCompound(rule) ? EnforceContext.wrap(value) : EnforceContext.unwrap(value)].concat(args));
|
|
995
|
-
}, ruleName));
|
|
996
|
-
} // set addFn as the proxy handler
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
var returnvalue = genRuleProxy({}, addFn);
|
|
1000
|
-
|
|
1001
|
-
returnvalue[RUN_RULE] = function (value) {
|
|
1002
|
-
var result = new RuleResult(true); // Run meta chains
|
|
1003
|
-
|
|
1004
|
-
meta.forEach(function (fn) {
|
|
1005
|
-
fn(value, result);
|
|
1006
|
-
}); // Iterate over all the registered rules
|
|
1007
|
-
// This runs the function that's inside `addFn`
|
|
1008
|
-
|
|
1009
|
-
for (var _iterator = _createForOfIteratorHelperLoose(registeredRules), _step; !(_step = _iterator()).done;) {
|
|
1010
|
-
var fn = _step.value;
|
|
1011
|
-
|
|
1012
|
-
try {
|
|
1013
|
-
result.extend(fn(value)); // If a chained rule fails, exit. We failed.
|
|
1014
|
-
|
|
1015
|
-
if (!result.pass) {
|
|
1016
|
-
break;
|
|
1017
|
-
}
|
|
1018
|
-
} catch (e) {
|
|
1019
|
-
result.setFailed(true);
|
|
1020
|
-
break;
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
return result;
|
|
1025
|
-
};
|
|
1026
|
-
|
|
1027
|
-
returnvalue[TEST_RULE] = function (value) {
|
|
1028
|
-
return returnvalue[RUN_RULE](EnforceContext.wrap(value).setFailFast(true)).pass;
|
|
1029
|
-
};
|
|
1030
|
-
|
|
1031
|
-
return returnvalue;
|
|
1032
|
-
}, ruleName);
|
|
1033
|
-
}; // Returns the initial rule in the chain
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
return addFn(ruleName);
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
function bindExtend(enforce, Enforce) {
|
|
1040
|
-
enforce.extend = function (customRules) {
|
|
1041
|
-
Object.assign(runtimeRules, customRules);
|
|
1042
|
-
|
|
1043
|
-
if (!proxySupported()) {
|
|
1044
|
-
genRuleProxy(Enforce, bindLazyRule);
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
return enforce;
|
|
1048
|
-
};
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
/**
|
|
1052
|
-
* Throws a timed out error.
|
|
1053
|
-
* @param {String} message Error message to display.
|
|
1054
|
-
* @param {Error} [type] Alternative Error type.
|
|
1055
|
-
*/
|
|
1056
|
-
var throwError = function throwError(message, type) {
|
|
1057
|
-
if (type === void 0) {
|
|
1058
|
-
type = Error;
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
throw new type("[" + "n4s" + "]: " + message);
|
|
1062
|
-
};
|
|
1063
|
-
|
|
1064
|
-
function validateResult(result, rule) {
|
|
1065
|
-
// if result is boolean, or if result.pass is boolean
|
|
1066
|
-
if (isBoolean(result) || result && isBoolean(result.pass)) {
|
|
1067
|
-
return;
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
throwError( rule.name + 'wrong return value');
|
|
1071
|
-
} // for easier testing and mocking
|
|
1072
|
-
|
|
1073
|
-
function getDefaultResult(value, rule) {
|
|
1074
|
-
return {
|
|
1075
|
-
message: formatResultMessage(rule, "invalid " + typeof value + " value")
|
|
1076
|
-
};
|
|
1077
|
-
}
|
|
1078
|
-
function formatResultMessage(rule, msg) {
|
|
1079
|
-
return "[" + "n4s" + "]:" + rule.name + " " + msg;
|
|
1080
|
-
}
|
|
1081
|
-
/**
|
|
1082
|
-
* Transform the result of a rule into a standard format
|
|
1083
|
-
* @param {string} interfaceName to be used in the messages
|
|
1084
|
-
* @param {*} result of the rule
|
|
1085
|
-
* @param {Object} options
|
|
1086
|
-
* @param {function} options.rule
|
|
1087
|
-
* @param {*} options.value
|
|
1088
|
-
* @returns {Object} result
|
|
1089
|
-
* @returns {string} result.message
|
|
1090
|
-
* @returns {boolean} result.pass indicates if the test passes or not
|
|
1091
|
-
*/
|
|
1092
|
-
|
|
1093
|
-
function transformResult(result, _ref) {
|
|
1094
|
-
var rule = _ref.rule,
|
|
1095
|
-
value = _ref.value;
|
|
1096
|
-
var defaultResult = getDefaultResult(value, rule);
|
|
1097
|
-
validateResult(result, rule); // if result is boolean
|
|
1098
|
-
|
|
1099
|
-
if (isBoolean(result)) {
|
|
1100
|
-
return defaultResult.pass = result, defaultResult;
|
|
1101
|
-
} else {
|
|
1102
|
-
defaultResult.pass = result.pass;
|
|
1103
|
-
|
|
1104
|
-
if (result.message) {
|
|
1105
|
-
defaultResult.message = formatResultMessage(rule, optionalFunctionValue(result.message));
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
return defaultResult;
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
/**
|
|
1113
|
-
* Run a single rule against enforced value (e.g. `isNumber()`)
|
|
1114
|
-
*
|
|
1115
|
-
* @param {Function} rule - rule to run
|
|
1116
|
-
* @param {Any} value
|
|
1117
|
-
* @param {Array} args list of arguments sent from consumer
|
|
1118
|
-
* @throws
|
|
1119
|
-
*/
|
|
1120
|
-
|
|
1121
|
-
function runner(rule, value, args) {
|
|
1122
|
-
if (args === void 0) {
|
|
1123
|
-
args = [];
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
var result;
|
|
1127
|
-
var isCompoundRule = isCompound(rule);
|
|
1128
|
-
var ruleValue = isCompoundRule ? EnforceContext.wrap(value).setFailFast(true) : EnforceContext.unwrap(value);
|
|
1129
|
-
result = rule.apply(null, [ruleValue].concat(args));
|
|
1130
|
-
|
|
1131
|
-
if (!isCompoundRule) {
|
|
1132
|
-
result = transformResult(result, {
|
|
1133
|
-
rule: rule,
|
|
1134
|
-
value: value
|
|
1135
|
-
});
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
if (!result.pass) {
|
|
1139
|
-
throw new Error(result.message);
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
/**
|
|
1144
|
-
* Adds `template` property to enforce.
|
|
1145
|
-
*
|
|
1146
|
-
* @param {Function} enforce
|
|
1147
|
-
*/
|
|
1148
|
-
|
|
1149
|
-
function bindTemplate(enforce) {
|
|
1150
|
-
enforce.template = withArgs(function (rules) {
|
|
1151
|
-
var template = function template(value) {
|
|
1152
|
-
runner(runLazyRules.bind(null, rules), value);
|
|
1153
|
-
var proxy = genRuleProxy({}, function (ruleName) {
|
|
1154
|
-
return withArgs(function (args) {
|
|
1155
|
-
runner(runtimeRules[ruleName], value, args);
|
|
1156
|
-
return proxy;
|
|
1157
|
-
});
|
|
1158
|
-
});
|
|
1159
|
-
return proxy;
|
|
1160
|
-
}; // `run` returns a deep ResultObject
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
template[RUN_RULE] = function (value) {
|
|
1164
|
-
return runLazyRules(rules, value);
|
|
1165
|
-
}; // `test` returns a boolean
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
template[TEST_RULE] = function (value) {
|
|
1169
|
-
return runLazyRules(rules, EnforceContext.wrap(value).setFailFast(true)).pass;
|
|
1170
|
-
};
|
|
1171
|
-
|
|
1172
|
-
return template;
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
var Enforce = function Enforce(value) {
|
|
1177
|
-
var proxy = genRuleProxy({}, function (ruleName) {
|
|
1178
|
-
return withArgs(function (args) {
|
|
1179
|
-
runner(runtimeRules[ruleName], value, args);
|
|
1180
|
-
return proxy;
|
|
1181
|
-
});
|
|
1182
|
-
});
|
|
1183
|
-
return proxy;
|
|
1184
|
-
};
|
|
1185
|
-
|
|
1186
|
-
var enforce = genRuleProxy(Enforce, bindLazyRule);
|
|
1187
|
-
bindExtend(enforce, Enforce);
|
|
1188
|
-
bindTemplate(enforce);
|
|
1189
|
-
|
|
1190
|
-
return enforce;
|
|
1191
|
-
|
|
1192
|
-
})));
|