n4s 3.1.0 → 4.0.0-dev-e266d9

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