objectmodel 4.3.1 → 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 (53) 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.js +13 -13
  7. package/build/bundle-entry.dev.js +2 -2
  8. package/build/bundle-entry.js +11 -11
  9. package/dist/object-model.cjs +462 -469
  10. package/dist/object-model.js +462 -469
  11. package/dist/object-model.js.map +1 -1
  12. package/dist/object-model.min.js +2 -2
  13. package/dist/object-model.min.js.map +1 -1
  14. package/index.html +4 -4
  15. package/package.json +9 -3
  16. package/rollup.config.js +13 -13
  17. package/src/array-model.d.ts +16 -0
  18. package/src/array-model.js +68 -68
  19. package/src/devtool-formatter.js +198 -198
  20. package/src/function-model.d.ts +24 -0
  21. package/src/function-model.js +58 -65
  22. package/src/helpers.js +43 -43
  23. package/src/index.js +4 -4
  24. package/src/list-model.js +43 -43
  25. package/src/map-model.d.ts +18 -0
  26. package/src/map-model.js +48 -48
  27. package/src/object-model.d.ts +74 -0
  28. package/src/set-model.d.ts +16 -0
  29. package/src/set-model.js +41 -41
  30. package/test/array-model.spec.cjs +291 -291
  31. package/test/array-model.test-d.ts +24 -0
  32. package/test/basic-model.spec.cjs +263 -263
  33. package/test/basic-model.test-d.ts +30 -0
  34. package/test/bench/array.html +51 -51
  35. package/test/bench/bench-lib.js +49 -49
  36. package/test/bench/map-no-cast.html +53 -53
  37. package/test/bench/map-set.html +52 -52
  38. package/test/bench/map.html +51 -51
  39. package/test/bench/object-models.html +87 -87
  40. package/test/function-model.spec.cjs +161 -162
  41. package/test/function-model.test-d.ts +18 -0
  42. package/test/index.cjs +13 -13
  43. package/test/map-model.spec.cjs +224 -224
  44. package/test/map-model.test-d.ts +21 -0
  45. package/test/model.spec.cjs +30 -30
  46. package/test/object-model.spec.cjs +1345 -1346
  47. package/test/object-model.test-d.ts +53 -0
  48. package/test/set-model.spec.cjs +213 -213
  49. package/test/set-model.test-d.ts +17 -0
  50. package/test/umd.html +25 -25
  51. package/types/definitions.d.ts +43 -0
  52. package/types/helpers.d.ts +4 -0
  53. package/types/index.d.ts +6 -128
@@ -1,48 +1,48 @@
1
- // ObjectModel v4.3.1 - 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
@@ -520,441 +520,434 @@ extend(Any.remaining, Any, {
520
520
  });
521
521
  Any[Symbol.iterator] = function* () { yield new Any.remaining(this.definition); };
522
522
 
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))
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))
562
562
  };
563
563
 
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
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
625
625
  };
626
626
 
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
- }
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
+ }
661
661
  });
662
662
 
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
- }
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
+ }
704
704
  });
705
705
 
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
- extend(newArgs, newReturns) {
756
- const args = this.definition.arguments,
757
- mixedArgs = newArgs.map((a, i) => extendDefinition(i in args ? args[i] : [], newArgs[i])),
758
- mixedReturns = extendDefinition(this.definition.return, newReturns);
759
- return extendModel(new FunctionModel(...mixedArgs).return(mixedReturns), this)
760
- },
761
-
762
- [_check](f, path, errors) {
763
- if (!isFunction(f)) stackError(errors, "Function", f, path);
764
- }
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
+ }
765
758
  });
766
759
 
767
- const styles = {
768
- list: "list-style-type: none; padding: 0; margin: 0;",
769
- listItem: "padding: 0 0 0 1em;",
770
- model: "color: #3e999f;",
771
- instance: "color: #718c00; font-style: italic",
772
- function: "color: #4271AE",
773
- string: "color: #C41A16",
774
- number: "color: #1C00CF",
775
- boolean: "color: #AA0D91",
776
- property: "color: #8959a8",
777
- private: "color: #C19ED8",
778
- constant: "color: #8959a8; font-weight: bold",
779
- privateConstant: "color: #C19ED8; font-weight: bold",
780
- null: "color: #8e908c",
781
- undeclared: "color: #C0C0C0;",
782
- proto: "color: #B871BD; font-style: italic"
783
- };
784
-
785
- const getModel = (instance) => {
786
- if (instance === undefined || instance === null)
787
- return null
788
-
789
- const proto = getProto(instance);
790
- if (!proto || !proto.constructor || !is(Model, proto.constructor))
791
- return null
792
-
793
- return proto.constructor
794
- };
795
-
796
- const span = (style, ...children) => ["span", { style }, ...children];
797
-
798
- const format = (x, config = {}) => {
799
- if (x === null || x === undefined)
800
- return span(styles.null, "" + x);
801
-
802
- if (typeof x === "boolean")
803
- return span(styles.boolean, x);
804
-
805
- if (typeof x === "number")
806
- return span(styles.number, x);
807
-
808
- if (typeof x === "string")
809
- return span(styles.string, `"${x}"`);
810
-
811
- if (Array.isArray(x) && config.isModelDefinition) {
812
- return span("", ...x.flatMap(part => [format(part, config), " or "]).slice(0, -1))
813
- }
814
-
815
- if (isPlainObject(x))
816
- return formatObject(x, getModel(x), config)
817
-
818
- if (isFunction(x) && !is(Model, x) && config.isModelDefinition)
819
- return span(styles.function, x.name || x.toString());
820
-
821
- return ["object", { object: x, config }]
822
- };
823
-
824
- const formatObject = (o, model, config) => span("",
825
- "{",
826
- ["ol", { style: styles.list }, ...Object.keys(o).map(prop =>
827
- ["li", { style: styles.listItem }, span(styles.property, prop), ": ", format(o[prop], config)])
828
- ],
829
- "}"
830
- );
831
-
832
- const formatModel = model => {
833
- const
834
- cfg = { isModelDefinition: true },
835
- def = model.definition,
836
- formatList = (list, map) => list.flatMap(e => [map(e), ", "]).slice(0, -1);
837
- let parts = [];
838
-
839
- if (is(BasicModel, model)) parts = [format(def, cfg)];
840
- if (is(ArrayModel, model)) parts = ["Array of ", format(def, cfg)];
841
- if (is(SetModel, model)) parts = ["Set of ", format(def, cfg)];
842
- if (is(MapModel, model)) parts = ["Map of ", format(def.key, cfg), " : ", format(def.value, cfg)];
843
- if (is(FunctionModel, model)) {
844
- parts = ["Function(", ...formatList(def.arguments, arg => format(arg, cfg)), ")"];
845
- if ("return" in def) parts.push(" => ", format(def.return, cfg));
846
- }
847
-
848
- if (model.assertions.length > 0) {
849
- parts.push("\n(assertions: ", ...formatList(model.assertions, f => ["object", { object: f }]), ")");
850
- }
851
-
852
- return span(styles.model, ...parts)
853
- };
854
-
855
- const ModelFormatter = {
856
- header(x, config = {}) {
857
- if (x === Any)
858
- return span(styles.model, "Any")
859
-
860
- if (is(Any.remaining, x))
861
- return span(styles.model, "...", format(x.definition, { isModelDefinition: true }))
862
-
863
- if (is(ObjectModel, x))
864
- return span(styles.model, x.name)
865
-
866
- if (is(Model, x)) {
867
- return formatModel(x)
868
- }
869
-
870
- if (config.isModelDefinition && isPlainObject(x))
871
- return format(x, config)
872
-
873
- return null;
874
- },
875
- hasBody(x) {
876
- return is(ObjectModel, x)
877
- },
878
- body(model) {
879
- return span("",
880
- "{",
881
- ["ol", { style: styles.list }, ...Object.keys(model.definition).map(prop => {
882
- const isPrivate = model.conventionForPrivate(prop);
883
- const isConstant = model.conventionForConstant(prop);
884
- const hasDefault = model.default && has(model.default, prop);
885
- let style = styles.property;
886
-
887
- if (isPrivate) {
888
- style = isConstant ? styles.privateConstant : styles.private;
889
- } else if (isConstant) {
890
- style = styles.constant;
891
- }
892
-
893
- return ["li", { style: styles.listItem },
894
- span(style, prop), ": ", format(model.definition[prop], { isModelDefinition: true }),
895
- hasDefault ? span(styles.proto, " = ", format(model.default[prop])) : ""
896
- ]
897
- })],
898
- "}"
899
- )
900
- }
901
- };
902
-
903
- const ModelInstanceFormatter = {
904
- header(x, config = {}) {
905
- if (config.isInstanceProperty && isPlainObject(x)) {
906
- return format(x, config)
907
- }
908
-
909
- const model = getModel(x);
910
- if (is(Model, model)) {
911
- const parts = is(ObjectModel, model) ? [model.name] : [["object", { object: x[_original] }], ` (${model.name})`];
912
- return span(styles.instance, ...parts)
913
- }
914
-
915
- return null;
916
- },
917
- hasBody(x) {
918
- return x && is(ObjectModel, getModel(x))
919
- },
920
- body(x) {
921
- const model = getModel(x);
922
- const o = x[_original] || x;
923
- return span("",
924
- "{",
925
- [
926
- "ol",
927
- { style: styles.list },
928
- ...Object.keys(o).map(prop => {
929
- const isPrivate = model.conventionForPrivate(prop);
930
- const isConstant = model.conventionForConstant(prop);
931
- const isDeclared = prop in model.definition;
932
- let style = styles.property;
933
-
934
- if (!isDeclared) {
935
- style = styles.undeclared;
936
- } else if (isPrivate) {
937
- style = isConstant ? styles.privateConstant : styles.private;
938
- } else if (isConstant) {
939
- style = styles.constant;
940
- }
941
-
942
- return ["li", { style: styles.listItem },
943
- span(style, prop), ": ", format(o[prop], { isInstanceProperty: true })
944
- ]
945
- }),
946
- ["li", { style: styles.listItem },
947
- span(styles.proto, "__proto__", ": ", ["object", { object: getProto(x) }])
948
- ]
949
- ],
950
- "}"
951
- )
952
- }
953
- };
954
-
955
- if (typeof window !== "undefined") {
956
- window.devtoolsFormatters = (window.devtoolsFormatters || [])
957
- .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);
958
951
  }
959
952
 
960
953
  ;