objectmodel 4.3.0 → 4.4.0

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 (59) hide show
  1. package/.eslintignore +8 -8
  2. package/.eslintrc.json +25 -25
  3. package/.travis.yml +2 -2
  4. package/LICENSE +22 -22
  5. package/README.md +67 -67
  6. package/build/{add-banner.cjs → add-banner.js} +13 -13
  7. package/build/bundle-entry.dev.js +2 -2
  8. package/build/bundle-entry.js +11 -11
  9. package/build/{update-docs.cjs → update-docs.js} +7 -5
  10. package/dist/object-model.cjs +466 -472
  11. package/dist/object-model.js +466 -472
  12. package/dist/object-model.js.map +1 -1
  13. package/dist/object-model.min.js +2 -2
  14. package/dist/object-model.min.js.map +1 -1
  15. package/index.html +1603 -1603
  16. package/package.json +20 -10
  17. package/rollup.config.js +13 -13
  18. package/src/array-model.d.ts +16 -0
  19. package/src/array-model.js +68 -68
  20. package/src/devtool-formatter.js +198 -198
  21. package/src/function-model.d.ts +24 -0
  22. package/src/function-model.js +58 -65
  23. package/src/helpers.js +43 -43
  24. package/src/index.js +4 -4
  25. package/src/list-model.js +43 -43
  26. package/src/map-model.d.ts +18 -0
  27. package/src/map-model.js +48 -48
  28. package/src/object-model.d.ts +74 -0
  29. package/src/object-model.js +4 -3
  30. package/src/set-model.d.ts +16 -0
  31. package/src/set-model.js +41 -41
  32. package/test/array-model.spec.cjs +291 -291
  33. package/test/array-model.test-d.ts +24 -0
  34. package/test/basic-model.spec.cjs +263 -263
  35. package/test/basic-model.test-d.ts +30 -0
  36. package/test/bench/array.html +51 -51
  37. package/test/bench/bench-lib.js +49 -49
  38. package/test/bench/map-no-cast.html +53 -53
  39. package/test/bench/map-set.html +52 -52
  40. package/test/bench/map.html +51 -51
  41. package/test/bench/object-models.html +87 -87
  42. package/test/function-model.spec.cjs +161 -162
  43. package/test/function-model.test-d.ts +18 -0
  44. package/test/index.cjs +13 -13
  45. package/test/index.html +27 -27
  46. package/test/map-model.spec.cjs +224 -224
  47. package/test/map-model.test-d.ts +21 -0
  48. package/test/model.spec.cjs +30 -30
  49. package/test/object-model.spec.cjs +1345 -1327
  50. package/test/object-model.test-d.ts +53 -0
  51. package/test/set-model.spec.cjs +213 -213
  52. package/test/set-model.test-d.ts +17 -0
  53. package/test/umd.html +25 -25
  54. package/types/definitions.d.ts +43 -0
  55. package/types/helpers.d.ts +4 -0
  56. package/types/index.d.ts +6 -128
  57. package/test/lib/qunit.css +0 -436
  58. package/test/lib/qunit.js +0 -6582
  59. package/tsconfig.json +0 -10
@@ -1,48 +1,48 @@
1
- // ObjectModel v4.3.0 - http://objectmodel.js.org
1
+ // ObjectModel v4.4.0 - http://objectmodel.js.org
2
2
  // MIT License - Sylvain Pollet-Villard
3
- const
4
- ObjectProto = Object.prototype,
5
- bettertypeof = x => ObjectProto.toString.call(x).match(/\s([a-zA-Z]+)/)[1],
6
- getProto = Object.getPrototypeOf,
7
- setProto = Object.setPrototypeOf,
8
-
9
- has = (o, prop) => ObjectProto.hasOwnProperty.call(o, prop),
10
- is = (Constructor, obj) => obj instanceof Constructor,
11
- isFunction = f => typeof f === "function",
12
- isObject = o => o && typeof o === "object",
13
- isString = s => typeof s === "string",
14
- isPlainObject = o => isObject(o) && getProto(o) === ObjectProto,
15
- isIterable = x => x && isFunction(x[Symbol.iterator]),
16
-
17
- proxify = (val, traps) => new Proxy(val, traps),
18
-
19
- merge = (target, src = {}) => {
20
- for (let key in src) {
21
- if (isPlainObject(src[key])) {
22
- const o = {};
23
- merge(o, target[key]);
24
- merge(o, src[key]);
25
- target[key] = o;
26
- } else {
27
- target[key] = src[key];
28
- }
29
- }
30
- return target
31
- },
32
-
33
- define = (obj, key, value, enumerable = false) => {
34
- Object.defineProperty(obj, key, { value, enumerable, writable: true, configurable: true });
35
- },
36
-
37
- extend = (child, parent, props) => {
38
- child.prototype = Object.assign(Object.create(parent.prototype, {
39
- constructor: {
40
- value: child,
41
- writable: true,
42
- configurable: true
43
- }
44
- }), props);
45
- setProto(child, parent);
3
+ const
4
+ ObjectProto = Object.prototype,
5
+ bettertypeof = x => ObjectProto.toString.call(x).match(/\s([a-zA-Z]+)/)[1],
6
+ getProto = Object.getPrototypeOf,
7
+ setProto = Object.setPrototypeOf,
8
+
9
+ has = (o, prop) => ObjectProto.hasOwnProperty.call(o, prop),
10
+ is = (Constructor, obj) => obj instanceof Constructor,
11
+ isFunction = f => typeof f === "function",
12
+ isObject = o => o && typeof o === "object",
13
+ isString = s => typeof s === "string",
14
+ isPlainObject = o => isObject(o) && getProto(o) === ObjectProto,
15
+ isIterable = x => x && isFunction(x[Symbol.iterator]),
16
+
17
+ proxify = (val, traps) => new Proxy(val, traps),
18
+
19
+ merge = (target, src = {}) => {
20
+ for (let key in src) {
21
+ if (isPlainObject(src[key])) {
22
+ const o = {};
23
+ merge(o, target[key]);
24
+ merge(o, src[key]);
25
+ target[key] = o;
26
+ } else {
27
+ target[key] = src[key];
28
+ }
29
+ }
30
+ return target
31
+ },
32
+
33
+ define = (obj, key, value, enumerable = false) => {
34
+ Object.defineProperty(obj, key, { value, enumerable, writable: true, configurable: true });
35
+ },
36
+
37
+ extend = (child, parent, props) => {
38
+ child.prototype = Object.assign(Object.create(parent.prototype, {
39
+ constructor: {
40
+ value: child,
41
+ writable: true,
42
+ configurable: true
43
+ }
44
+ }), props);
45
+ setProto(child, parent);
46
46
  };
47
47
 
48
48
  const
@@ -74,7 +74,8 @@ const
74
74
  if (is(model, obj)) return obj
75
75
 
76
76
  if (!isObject(obj) && !isFunction(obj) && obj !== undefined) {
77
- stackError(model.errors, Object, obj);
77
+ // short circuit validation if not receiving an object as expected
78
+ return obj
78
79
  }
79
80
 
80
81
  merge(_this, model.default);
@@ -366,8 +367,8 @@ const
366
367
  };
367
368
 
368
369
 
369
- function Model(def, params) {
370
- return isPlainObject(def) ? new ObjectModel(def, params) : new BasicModel(def)
370
+ function Model(def) {
371
+ return isPlainObject(def) ? new ObjectModel(def) : new BasicModel(def)
371
372
  }
372
373
 
373
374
  Object.assign(Model.prototype, {
@@ -519,441 +520,434 @@ extend(Any.remaining, Any, {
519
520
  });
520
521
  Any[Symbol.iterator] = function* () { yield new Any.remaining(this.definition); };
521
522
 
522
- const initListModel = (base, constructor, def, init, clone, mutators, otherTraps) => {
523
-
524
- return initModel(def, constructor, base, init, model => Object.assign({
525
- getPrototypeOf: () => model.prototype,
526
- get(l, key) {
527
- if (key === _original) return l
528
-
529
- const val = l[key];
530
- return isFunction(val) ? proxify(val, {
531
- apply(fn, ctx, args) {
532
- if (has(mutators, key)) {
533
- // indexes of arguments to check def + cast
534
- const [begin, end = args.length - 1, getArgDef] = mutators[key];
535
- for (let i = begin; i <= end; i++) {
536
- const argDef = getArgDef ? getArgDef(i) : model.definition;
537
- args[i] = checkDefinition(
538
- args[i],
539
- argDef,
540
- `${base.name}.${key} arguments[${i}]`,
541
- model.errors,
542
- [],
543
- true
544
- );
545
- }
546
-
547
- if (model.assertions.length > 0) {
548
- const testingClone = clone(l);
549
- fn.apply(testingClone, args);
550
- checkAssertions(testingClone, model, `after ${key} mutation`);
551
- }
552
-
553
- unstackErrors(model);
554
- }
555
-
556
- return fn.apply(l, args)
557
- }
558
- }) : val
559
- }
560
- }, otherTraps))
523
+ const initListModel = (base, constructor, def, init, clone, mutators, otherTraps) => {
524
+
525
+ return initModel(def, constructor, base, init, model => Object.assign({
526
+ getPrototypeOf: () => model.prototype,
527
+ get(l, key) {
528
+ if (key === _original) return l
529
+
530
+ const val = l[key];
531
+ return isFunction(val) ? proxify(val, {
532
+ apply(fn, ctx, args) {
533
+ if (has(mutators, key)) {
534
+ // indexes of arguments to check def + cast
535
+ const [begin, end = args.length - 1, getArgDef] = mutators[key];
536
+ for (let i = begin; i <= end; i++) {
537
+ const argDef = getArgDef ? getArgDef(i) : model.definition;
538
+ args[i] = checkDefinition(
539
+ args[i],
540
+ argDef,
541
+ `${base.name}.${key} arguments[${i}]`,
542
+ model.errors,
543
+ [],
544
+ true
545
+ );
546
+ }
547
+
548
+ if (model.assertions.length > 0) {
549
+ const testingClone = clone(l);
550
+ fn.apply(testingClone, args);
551
+ checkAssertions(testingClone, model, `after ${key} mutation`);
552
+ }
553
+
554
+ unstackErrors(model);
555
+ }
556
+
557
+ return fn.apply(l, args)
558
+ }
559
+ }) : val
560
+ }
561
+ }, otherTraps))
561
562
  };
562
563
 
563
- function ArrayModel(initialDefinition) {
564
- const model = initListModel(
565
- Array,
566
- ArrayModel,
567
- initialDefinition,
568
- a => Array.isArray(a) ? a.map(arg => cast(arg, model.definition)) : a,
569
- a => [...a],
570
- {
571
- "copyWithin": [],
572
- "fill": [0, 0],
573
- "pop": [],
574
- "push": [0],
575
- "reverse": [],
576
- "shift": [],
577
- "sort": [],
578
- "splice": [2],
579
- "unshift": [0]
580
- },
581
- {
582
- set(arr, key, val) {
583
- return controlMutation(model, arr, key, val, (a, v) => a[key] = v, true)
584
- },
585
-
586
- deleteProperty(arr, key) {
587
- return controlMutation(model, arr, key, undefined, a => delete a[key])
588
- }
589
- }
590
- );
591
-
592
- return model
593
- }
594
-
595
- extend(ArrayModel, Model, {
596
- toString(stack) {
597
- return "Array of " + formatDefinition(this.definition, stack)
598
- },
599
-
600
- [_check](arr, path, errors, stack) {
601
- if (Array.isArray(arr))
602
- (arr[_original] || arr).forEach((a, i) => checkDefinition(a, this.definition, `${path || "Array"}[${i}]`, errors, stack));
603
- else stackError(errors, this, arr, path);
604
-
605
- checkAssertions(arr, this, path, errors);
606
- },
607
-
608
- extend(...newParts) {
609
- return extendModel(new ArrayModel(extendDefinition(this.definition, newParts)), this)
610
- }
611
- });
612
-
613
- const controlMutation = (model, array, key, value, applyMutation, canBeExtended) => {
614
- const path = `Array[${key}]`;
615
- const isInDef = (+key >= 0 && (canBeExtended || key in array));
616
- if (isInDef) value = checkDefinition(value, model.definition, path, model.errors, [], true);
617
-
618
- const testArray = [...array];
619
- applyMutation(testArray);
620
- checkAssertions(testArray, model, path);
621
- const isSuccess = !unstackErrors(model);
622
- if (isSuccess) applyMutation(array, value);
623
- return isSuccess
564
+ function ArrayModel(initialDefinition) {
565
+ const model = initListModel(
566
+ Array,
567
+ ArrayModel,
568
+ initialDefinition,
569
+ a => Array.isArray(a) ? a.map(arg => cast(arg, model.definition)) : a,
570
+ a => [...a],
571
+ {
572
+ "copyWithin": [],
573
+ "fill": [0, 0],
574
+ "pop": [],
575
+ "push": [0],
576
+ "reverse": [],
577
+ "shift": [],
578
+ "sort": [],
579
+ "splice": [2],
580
+ "unshift": [0]
581
+ },
582
+ {
583
+ set(arr, key, val) {
584
+ return controlMutation(model, arr, key, val, (a, v) => a[key] = v, true)
585
+ },
586
+
587
+ deleteProperty(arr, key) {
588
+ return controlMutation(model, arr, key, undefined, a => delete a[key])
589
+ }
590
+ }
591
+ );
592
+
593
+ return model
594
+ }
595
+
596
+ extend(ArrayModel, Model, {
597
+ toString(stack) {
598
+ return "Array of " + formatDefinition(this.definition, stack)
599
+ },
600
+
601
+ [_check](arr, path, errors, stack) {
602
+ if (Array.isArray(arr))
603
+ (arr[_original] || arr).forEach((a, i) => checkDefinition(a, this.definition, `${path || "Array"}[${i}]`, errors, stack));
604
+ else stackError(errors, this, arr, path);
605
+
606
+ checkAssertions(arr, this, path, errors);
607
+ },
608
+
609
+ extend(...newParts) {
610
+ return extendModel(new ArrayModel(extendDefinition(this.definition, newParts)), this)
611
+ }
612
+ });
613
+
614
+ const controlMutation = (model, array, key, value, applyMutation, canBeExtended) => {
615
+ const path = `Array[${key}]`;
616
+ const isInDef = (+key >= 0 && (canBeExtended || key in array));
617
+ if (isInDef) value = checkDefinition(value, model.definition, path, model.errors, [], true);
618
+
619
+ const testArray = [...array];
620
+ applyMutation(testArray);
621
+ checkAssertions(testArray, model, path);
622
+ const isSuccess = !unstackErrors(model);
623
+ if (isSuccess) applyMutation(array, value);
624
+ return isSuccess
624
625
  };
625
626
 
626
- function SetModel(initialDefinition) {
627
- const model = initListModel(
628
- Set,
629
- SetModel,
630
- initialDefinition,
631
- it => isIterable(it) ? new Set([...it].map(val => cast(val, model.definition))) : it,
632
- set => new Set(set),
633
- {
634
- "add": [0, 0],
635
- "delete": [],
636
- "clear": []
637
- }
638
- );
639
-
640
- return model
641
- }
642
-
643
- extend(SetModel, Model, {
644
- toString(stack) {
645
- return "Set of " + formatDefinition(this.definition, stack)
646
- },
647
-
648
- [_check](set, path, errors, stack) {
649
- if (is(Set, set)) {
650
- for (let item of set.values()) {
651
- checkDefinition(item, this.definition, `${path || "Set"} value`, errors, stack);
652
- }
653
- } else stackError(errors, this, set, path);
654
- checkAssertions(set, this, path, errors);
655
- },
656
-
657
- extend(...newParts) {
658
- return extendModel(new SetModel(extendDefinition(this.definition, newParts)), this)
659
- }
627
+ function SetModel(initialDefinition) {
628
+ const model = initListModel(
629
+ Set,
630
+ SetModel,
631
+ initialDefinition,
632
+ it => isIterable(it) ? new Set([...it].map(val => cast(val, model.definition))) : it,
633
+ set => new Set(set),
634
+ {
635
+ "add": [0, 0],
636
+ "delete": [],
637
+ "clear": []
638
+ }
639
+ );
640
+
641
+ return model
642
+ }
643
+
644
+ extend(SetModel, Model, {
645
+ toString(stack) {
646
+ return "Set of " + formatDefinition(this.definition, stack)
647
+ },
648
+
649
+ [_check](set, path, errors, stack) {
650
+ if (is(Set, set)) {
651
+ for (let item of set.values()) {
652
+ checkDefinition(item, this.definition, `${path || "Set"} value`, errors, stack);
653
+ }
654
+ } else stackError(errors, this, set, path);
655
+ checkAssertions(set, this, path, errors);
656
+ },
657
+
658
+ extend(...newParts) {
659
+ return extendModel(new SetModel(extendDefinition(this.definition, newParts)), this)
660
+ }
660
661
  });
661
662
 
662
- function MapModel(initialKeyDefinition, initialValueDefinition) {
663
- const getDef = i => i === 0 ? model.definition.key : model.definition.value;
664
- const model = initListModel(
665
- Map,
666
- MapModel,
667
- { key: initialKeyDefinition, value: initialValueDefinition },
668
- it => isIterable(it) ? new Map([...it].map(pair => pair.map((x, i) => cast(x, getDef(i))))) : it,
669
- map => new Map(map),
670
- {
671
- "set": [0, 1, getDef],
672
- "delete": [],
673
- "clear": []
674
- }
675
- );
676
-
677
- return model
678
- }
679
-
680
- extend(MapModel, Model, {
681
- toString(stack) {
682
- return `Map of ${formatDefinition(this.definition.key, stack)} : ${formatDefinition(this.definition.value, stack)}`
683
- },
684
-
685
- [_check](map, path, errors, stack) {
686
- if (is(Map, map)) {
687
- path = path || "Map";
688
- for (let [key, value] of map) {
689
- checkDefinition(key, this.definition.key, `${path} key`, errors, stack);
690
- checkDefinition(value, this.definition.value, `${path}[${format$1(key)}]`, errors, stack);
691
- }
692
- } else stackError(errors, this, map, path);
693
-
694
- checkAssertions(map, this, path, errors);
695
- },
696
-
697
- extend(keyParts, valueParts) {
698
- return extendModel(new MapModel(
699
- extendDefinition(this.definition.key, keyParts),
700
- extendDefinition(this.definition.value, valueParts)
701
- ), this)
702
- }
663
+ function MapModel(initialKeyDefinition, initialValueDefinition) {
664
+ const getDef = i => i === 0 ? model.definition.key : model.definition.value;
665
+ const model = initListModel(
666
+ Map,
667
+ MapModel,
668
+ { key: initialKeyDefinition, value: initialValueDefinition },
669
+ it => isIterable(it) ? new Map([...it].map(pair => pair.map((x, i) => cast(x, getDef(i))))) : it,
670
+ map => new Map(map),
671
+ {
672
+ "set": [0, 1, getDef],
673
+ "delete": [],
674
+ "clear": []
675
+ }
676
+ );
677
+
678
+ return model
679
+ }
680
+
681
+ extend(MapModel, Model, {
682
+ toString(stack) {
683
+ return `Map of ${formatDefinition(this.definition.key, stack)} : ${formatDefinition(this.definition.value, stack)}`
684
+ },
685
+
686
+ [_check](map, path, errors, stack) {
687
+ if (is(Map, map)) {
688
+ path = path || "Map";
689
+ for (let [key, value] of map) {
690
+ checkDefinition(key, this.definition.key, `${path} key`, errors, stack);
691
+ checkDefinition(value, this.definition.value, `${path}[${format$1(key)}]`, errors, stack);
692
+ }
693
+ } else stackError(errors, this, map, path);
694
+
695
+ checkAssertions(map, this, path, errors);
696
+ },
697
+
698
+ extend(keyParts, valueParts) {
699
+ return extendModel(new MapModel(
700
+ extendDefinition(this.definition.key, keyParts),
701
+ extendDefinition(this.definition.value, valueParts)
702
+ ), this)
703
+ }
703
704
  });
704
705
 
705
- function FunctionModel(...argsDef) {
706
- return initModel({ arguments: argsDef }, FunctionModel, Function, null, model => ({
707
- getPrototypeOf: () => model.prototype,
708
-
709
- get(fn, key) {
710
- return key === _original ? fn : fn[key]
711
- },
712
-
713
- apply(fn, ctx, args) {
714
- const def = model.definition;
715
- const remainingArgDef = def.arguments.find(argDef => is(Any.remaining, argDef));
716
- const nbArgsToCheck = remainingArgDef ? Math.max(args.length, def.arguments.length - 1) : def.arguments.length;
717
-
718
- for (let i = 0; i < nbArgsToCheck; i++) {
719
- const argDef = remainingArgDef && i >= def.arguments.length - 1 ? remainingArgDef.definition : def.arguments[i];
720
- args[i] = checkDefinition(args[i], argDef, `arguments[${i}]`, model.errors, [], true);
721
- }
722
-
723
- checkAssertions(args, model, "arguments");
724
-
725
- let result;
726
- if (!model.errors.length) {
727
- result = Reflect.apply(fn, ctx, args);
728
- if ("return" in def)
729
- result = checkDefinition(result, def.return, "return value", model.errors, [], true);
730
- }
731
- unstackErrors(model);
732
- return result
733
- }
734
- }))
735
- }
736
-
737
- extend(FunctionModel, Model, {
738
- toString(stack = []) {
739
- let out = `Function(${this.definition.arguments.map(
740
- argDef => formatDefinition(argDef, [...stack])
741
- ).join(", ")})`;
742
-
743
- if ("return" in this.definition) {
744
- out += " => " + formatDefinition(this.definition.return, stack);
745
- }
746
- return out
747
- },
748
-
749
- return(def) {
750
- this.definition.return = def;
751
- return this
752
- },
753
-
754
- extend(newArgs, newReturns) {
755
- const args = this.definition.arguments,
756
- mixedArgs = newArgs.map((a, i) => extendDefinition(i in args ? args[i] : [], newArgs[i])),
757
- mixedReturns = extendDefinition(this.definition.return, newReturns);
758
- return extendModel(new FunctionModel(...mixedArgs).return(mixedReturns), this)
759
- },
760
-
761
- [_check](f, path, errors) {
762
- if (!isFunction(f)) stackError(errors, "Function", f, path);
763
- }
706
+ function FunctionModel(...argsDef) {
707
+ return initModel({ arguments: argsDef }, FunctionModel, Function, null, model => ({
708
+ getPrototypeOf: () => model.prototype,
709
+
710
+ get(fn, key) {
711
+ return key === _original ? fn : fn[key]
712
+ },
713
+
714
+ apply(fn, ctx, args) {
715
+ const def = model.definition;
716
+ const remainingArgDef = def.arguments.find(argDef => is(Any.remaining, argDef));
717
+ const nbArgsToCheck = remainingArgDef ? Math.max(args.length, def.arguments.length - 1) : def.arguments.length;
718
+
719
+ for (let i = 0; i < nbArgsToCheck; i++) {
720
+ const argDef = remainingArgDef && i >= def.arguments.length - 1 ? remainingArgDef.definition : def.arguments[i];
721
+ args[i] = checkDefinition(args[i], argDef, `arguments[${i}]`, model.errors, [], true);
722
+ }
723
+
724
+ checkAssertions(args, model, "arguments");
725
+
726
+ let result;
727
+ if (!model.errors.length) {
728
+ result = Reflect.apply(fn, ctx, args);
729
+ if ("return" in def)
730
+ result = checkDefinition(result, def.return, "return value", model.errors, [], true);
731
+ }
732
+ unstackErrors(model);
733
+ return result
734
+ }
735
+ }))
736
+ }
737
+
738
+ extend(FunctionModel, Model, {
739
+ toString(stack = []) {
740
+ let out = `Function(${this.definition.arguments.map(
741
+ argDef => formatDefinition(argDef, [...stack])
742
+ ).join(", ")})`;
743
+
744
+ if ("return" in this.definition) {
745
+ out += " => " + formatDefinition(this.definition.return, stack);
746
+ }
747
+ return out
748
+ },
749
+
750
+ return(def) {
751
+ this.definition.return = def;
752
+ return this
753
+ },
754
+
755
+ [_check](f, path, errors) {
756
+ if (!isFunction(f)) stackError(errors, "Function", f, path);
757
+ }
764
758
  });
765
759
 
766
- const styles = {
767
- list: "list-style-type: none; padding: 0; margin: 0;",
768
- listItem: "padding: 0 0 0 1em;",
769
- model: "color: #3e999f;",
770
- instance: "color: #718c00; font-style: italic",
771
- function: "color: #4271AE",
772
- string: "color: #C41A16",
773
- number: "color: #1C00CF",
774
- boolean: "color: #AA0D91",
775
- property: "color: #8959a8",
776
- private: "color: #C19ED8",
777
- constant: "color: #8959a8; font-weight: bold",
778
- privateConstant: "color: #C19ED8; font-weight: bold",
779
- null: "color: #8e908c",
780
- undeclared: "color: #C0C0C0;",
781
- proto: "color: #B871BD; font-style: italic"
782
- };
783
-
784
- const getModel = (instance) => {
785
- if (instance === undefined || instance === null)
786
- return null
787
-
788
- const proto = getProto(instance);
789
- if (!proto || !proto.constructor || !is(Model, proto.constructor))
790
- return null
791
-
792
- return proto.constructor
793
- };
794
-
795
- const span = (style, ...children) => ["span", { style }, ...children];
796
-
797
- const format = (x, config = {}) => {
798
- if (x === null || x === undefined)
799
- return span(styles.null, "" + x);
800
-
801
- if (typeof x === "boolean")
802
- return span(styles.boolean, x);
803
-
804
- if (typeof x === "number")
805
- return span(styles.number, x);
806
-
807
- if (typeof x === "string")
808
- return span(styles.string, `"${x}"`);
809
-
810
- if (Array.isArray(x) && config.isModelDefinition) {
811
- return span("", ...x.flatMap(part => [format(part, config), " or "]).slice(0, -1))
812
- }
813
-
814
- if (isPlainObject(x))
815
- return formatObject(x, getModel(x), config)
816
-
817
- if (isFunction(x) && !is(Model, x) && config.isModelDefinition)
818
- return span(styles.function, x.name || x.toString());
819
-
820
- return ["object", { object: x, config }]
821
- };
822
-
823
- const formatObject = (o, model, config) => span("",
824
- "{",
825
- ["ol", { style: styles.list }, ...Object.keys(o).map(prop =>
826
- ["li", { style: styles.listItem }, span(styles.property, prop), ": ", format(o[prop], config)])
827
- ],
828
- "}"
829
- );
830
-
831
- const formatModel = model => {
832
- const
833
- cfg = { isModelDefinition: true },
834
- def = model.definition,
835
- formatList = (list, map) => list.flatMap(e => [map(e), ", "]).slice(0, -1);
836
- let parts = [];
837
-
838
- if (is(BasicModel, model)) parts = [format(def, cfg)];
839
- if (is(ArrayModel, model)) parts = ["Array of ", format(def, cfg)];
840
- if (is(SetModel, model)) parts = ["Set of ", format(def, cfg)];
841
- if (is(MapModel, model)) parts = ["Map of ", format(def.key, cfg), " : ", format(def.value, cfg)];
842
- if (is(FunctionModel, model)) {
843
- parts = ["Function(", ...formatList(def.arguments, arg => format(arg, cfg)), ")"];
844
- if ("return" in def) parts.push(" => ", format(def.return, cfg));
845
- }
846
-
847
- if (model.assertions.length > 0) {
848
- parts.push("\n(assertions: ", ...formatList(model.assertions, f => ["object", { object: f }]), ")");
849
- }
850
-
851
- return span(styles.model, ...parts)
852
- };
853
-
854
- const ModelFormatter = {
855
- header(x, config = {}) {
856
- if (x === Any)
857
- return span(styles.model, "Any")
858
-
859
- if (is(Any.remaining, x))
860
- return span(styles.model, "...", format(x.definition, { isModelDefinition: true }))
861
-
862
- if (is(ObjectModel, x))
863
- return span(styles.model, x.name)
864
-
865
- if (is(Model, x)) {
866
- return formatModel(x)
867
- }
868
-
869
- if (config.isModelDefinition && isPlainObject(x))
870
- return format(x, config)
871
-
872
- return null;
873
- },
874
- hasBody(x) {
875
- return is(ObjectModel, x)
876
- },
877
- body(model) {
878
- return span("",
879
- "{",
880
- ["ol", { style: styles.list }, ...Object.keys(model.definition).map(prop => {
881
- const isPrivate = model.conventionForPrivate(prop);
882
- const isConstant = model.conventionForConstant(prop);
883
- const hasDefault = model.default && has(model.default, prop);
884
- let style = styles.property;
885
-
886
- if (isPrivate) {
887
- style = isConstant ? styles.privateConstant : styles.private;
888
- } else if (isConstant) {
889
- style = styles.constant;
890
- }
891
-
892
- return ["li", { style: styles.listItem },
893
- span(style, prop), ": ", format(model.definition[prop], { isModelDefinition: true }),
894
- hasDefault ? span(styles.proto, " = ", format(model.default[prop])) : ""
895
- ]
896
- })],
897
- "}"
898
- )
899
- }
900
- };
901
-
902
- const ModelInstanceFormatter = {
903
- header(x, config = {}) {
904
- if (config.isInstanceProperty && isPlainObject(x)) {
905
- return format(x, config)
906
- }
907
-
908
- const model = getModel(x);
909
- if (is(Model, model)) {
910
- const parts = is(ObjectModel, model) ? [model.name] : [["object", { object: x[_original] }], ` (${model.name})`];
911
- return span(styles.instance, ...parts)
912
- }
913
-
914
- return null;
915
- },
916
- hasBody(x) {
917
- return x && is(ObjectModel, getModel(x))
918
- },
919
- body(x) {
920
- const model = getModel(x);
921
- const o = x[_original] || x;
922
- return span("",
923
- "{",
924
- [
925
- "ol",
926
- { style: styles.list },
927
- ...Object.keys(o).map(prop => {
928
- const isPrivate = model.conventionForPrivate(prop);
929
- const isConstant = model.conventionForConstant(prop);
930
- const isDeclared = prop in model.definition;
931
- let style = styles.property;
932
-
933
- if (!isDeclared) {
934
- style = styles.undeclared;
935
- } else if (isPrivate) {
936
- style = isConstant ? styles.privateConstant : styles.private;
937
- } else if (isConstant) {
938
- style = styles.constant;
939
- }
940
-
941
- return ["li", { style: styles.listItem },
942
- span(style, prop), ": ", format(o[prop], { isInstanceProperty: true })
943
- ]
944
- }),
945
- ["li", { style: styles.listItem },
946
- span(styles.proto, "__proto__", ": ", ["object", { object: getProto(x) }])
947
- ]
948
- ],
949
- "}"
950
- )
951
- }
952
- };
953
-
954
- if (typeof window !== "undefined") {
955
- window.devtoolsFormatters = (window.devtoolsFormatters || [])
956
- .concat(ModelFormatter, ModelInstanceFormatter);
760
+ const styles = {
761
+ list: "list-style-type: none; padding: 0; margin: 0;",
762
+ listItem: "padding: 0 0 0 1em;",
763
+ model: "color: #3e999f;",
764
+ instance: "color: #718c00; font-style: italic",
765
+ function: "color: #4271AE",
766
+ string: "color: #C41A16",
767
+ number: "color: #1C00CF",
768
+ boolean: "color: #AA0D91",
769
+ property: "color: #8959a8",
770
+ private: "color: #C19ED8",
771
+ constant: "color: #8959a8; font-weight: bold",
772
+ privateConstant: "color: #C19ED8; font-weight: bold",
773
+ null: "color: #8e908c",
774
+ undeclared: "color: #C0C0C0;",
775
+ proto: "color: #B871BD; font-style: italic"
776
+ };
777
+
778
+ const getModel = (instance) => {
779
+ if (instance === undefined || instance === null)
780
+ return null
781
+
782
+ const proto = getProto(instance);
783
+ if (!proto || !proto.constructor || !is(Model, proto.constructor))
784
+ return null
785
+
786
+ return proto.constructor
787
+ };
788
+
789
+ const span = (style, ...children) => ["span", { style }, ...children];
790
+
791
+ const format = (x, config = {}) => {
792
+ if (x === null || x === undefined)
793
+ return span(styles.null, "" + x);
794
+
795
+ if (typeof x === "boolean")
796
+ return span(styles.boolean, x);
797
+
798
+ if (typeof x === "number")
799
+ return span(styles.number, x);
800
+
801
+ if (typeof x === "string")
802
+ return span(styles.string, `"${x}"`);
803
+
804
+ if (Array.isArray(x) && config.isModelDefinition) {
805
+ return span("", ...x.flatMap(part => [format(part, config), " or "]).slice(0, -1))
806
+ }
807
+
808
+ if (isPlainObject(x))
809
+ return formatObject(x, getModel(x), config)
810
+
811
+ if (isFunction(x) && !is(Model, x) && config.isModelDefinition)
812
+ return span(styles.function, x.name || x.toString());
813
+
814
+ return ["object", { object: x, config }]
815
+ };
816
+
817
+ const formatObject = (o, model, config) => span("",
818
+ "{",
819
+ ["ol", { style: styles.list }, ...Object.keys(o).map(prop =>
820
+ ["li", { style: styles.listItem }, span(styles.property, prop), ": ", format(o[prop], config)])
821
+ ],
822
+ "}"
823
+ );
824
+
825
+ const formatModel = model => {
826
+ const
827
+ cfg = { isModelDefinition: true },
828
+ def = model.definition,
829
+ formatList = (list, map) => list.flatMap(e => [map(e), ", "]).slice(0, -1);
830
+ let parts = [];
831
+
832
+ if (is(BasicModel, model)) parts = [format(def, cfg)];
833
+ if (is(ArrayModel, model)) parts = ["Array of ", format(def, cfg)];
834
+ if (is(SetModel, model)) parts = ["Set of ", format(def, cfg)];
835
+ if (is(MapModel, model)) parts = ["Map of ", format(def.key, cfg), " : ", format(def.value, cfg)];
836
+ if (is(FunctionModel, model)) {
837
+ parts = ["Function(", ...formatList(def.arguments, arg => format(arg, cfg)), ")"];
838
+ if ("return" in def) parts.push(" => ", format(def.return, cfg));
839
+ }
840
+
841
+ if (model.assertions.length > 0) {
842
+ parts.push("\n(assertions: ", ...formatList(model.assertions, f => ["object", { object: f }]), ")");
843
+ }
844
+
845
+ return span(styles.model, ...parts)
846
+ };
847
+
848
+ const ModelFormatter = {
849
+ header(x, config = {}) {
850
+ if (x === Any)
851
+ return span(styles.model, "Any")
852
+
853
+ if (is(Any.remaining, x))
854
+ return span(styles.model, "...", format(x.definition, { isModelDefinition: true }))
855
+
856
+ if (is(ObjectModel, x))
857
+ return span(styles.model, x.name)
858
+
859
+ if (is(Model, x)) {
860
+ return formatModel(x)
861
+ }
862
+
863
+ if (config.isModelDefinition && isPlainObject(x))
864
+ return format(x, config)
865
+
866
+ return null;
867
+ },
868
+ hasBody(x) {
869
+ return is(ObjectModel, x)
870
+ },
871
+ body(model) {
872
+ return span("",
873
+ "{",
874
+ ["ol", { style: styles.list }, ...Object.keys(model.definition).map(prop => {
875
+ const isPrivate = model.conventionForPrivate(prop);
876
+ const isConstant = model.conventionForConstant(prop);
877
+ const hasDefault = model.default && has(model.default, prop);
878
+ let style = styles.property;
879
+
880
+ if (isPrivate) {
881
+ style = isConstant ? styles.privateConstant : styles.private;
882
+ } else if (isConstant) {
883
+ style = styles.constant;
884
+ }
885
+
886
+ return ["li", { style: styles.listItem },
887
+ span(style, prop), ": ", format(model.definition[prop], { isModelDefinition: true }),
888
+ hasDefault ? span(styles.proto, " = ", format(model.default[prop])) : ""
889
+ ]
890
+ })],
891
+ "}"
892
+ )
893
+ }
894
+ };
895
+
896
+ const ModelInstanceFormatter = {
897
+ header(x, config = {}) {
898
+ if (config.isInstanceProperty && isPlainObject(x)) {
899
+ return format(x, config)
900
+ }
901
+
902
+ const model = getModel(x);
903
+ if (is(Model, model)) {
904
+ const parts = is(ObjectModel, model) ? [model.name] : [["object", { object: x[_original] }], ` (${model.name})`];
905
+ return span(styles.instance, ...parts)
906
+ }
907
+
908
+ return null;
909
+ },
910
+ hasBody(x) {
911
+ return x && is(ObjectModel, getModel(x))
912
+ },
913
+ body(x) {
914
+ const model = getModel(x);
915
+ const o = x[_original] || x;
916
+ return span("",
917
+ "{",
918
+ [
919
+ "ol",
920
+ { style: styles.list },
921
+ ...Object.keys(o).map(prop => {
922
+ const isPrivate = model.conventionForPrivate(prop);
923
+ const isConstant = model.conventionForConstant(prop);
924
+ const isDeclared = prop in model.definition;
925
+ let style = styles.property;
926
+
927
+ if (!isDeclared) {
928
+ style = styles.undeclared;
929
+ } else if (isPrivate) {
930
+ style = isConstant ? styles.privateConstant : styles.private;
931
+ } else if (isConstant) {
932
+ style = styles.constant;
933
+ }
934
+
935
+ return ["li", { style: styles.listItem },
936
+ span(style, prop), ": ", format(o[prop], { isInstanceProperty: true })
937
+ ]
938
+ }),
939
+ ["li", { style: styles.listItem },
940
+ span(styles.proto, "__proto__", ": ", ["object", { object: getProto(x) }])
941
+ ]
942
+ ],
943
+ "}"
944
+ )
945
+ }
946
+ };
947
+
948
+ if (typeof window !== "undefined") {
949
+ window.devtoolsFormatters = (window.devtoolsFormatters || [])
950
+ .concat(ModelFormatter, ModelInstanceFormatter);
957
951
  }
958
952
 
959
953
  ;