@expressive/mvc 0.20.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -1,19 +1,3 @@
1
- declare namespace Issue {
2
- type Variable = {} | string | number | boolean | null | undefined;
3
- type Variables<T> = T extends (...args: infer T) => any ? T : never;
4
- type Messages = {
5
- [named: string]: (...args: Variable[]) => string;
6
- };
7
- type Output<M extends Messages> = {
8
- readonly [P in keyof M]: (...args: Variables<M[P]>) => Issue;
9
- };
10
- }
11
- declare class Issue extends Error {
12
- stack: string;
13
- warn(): void;
14
- }
15
- declare function issues<M extends Issue.Messages>(register: M): Issue.Output<M>;
16
-
17
1
  type Async<T = any> = (...args: any[]) => Promise<T>;
18
2
  /**
19
3
  * Sets an exotic method with managed ready-state. Property accepts an async function.
@@ -91,7 +75,6 @@ declare class Control<T extends Model = any> {
91
75
  static for: typeof control;
92
76
  static apply: typeof apply;
93
77
  static watch: typeof watch;
94
- parent?: Model;
95
78
  state: {
96
79
  [key: string]: any;
97
80
  };
@@ -242,8 +225,8 @@ declare class Model {
242
225
  get is(): this;
243
226
  on(): Promise<Model.Event<this>[]>;
244
227
  on(timeout?: number): Promise<Model.Event<this>[] | false>;
245
- on<P extends Model.Event<this>>(keys?: P | Iterable<P>, timeout?: number): Promise<P[] | false>;
246
- on<P extends Model.Event<this>>(keys: P | Iterable<P>, listener: Model.OnCallback<this>, once?: boolean): Callback;
228
+ on<P extends Model.Event<this>>(keys?: P | P[], timeout?: number): Promise<P[] | false>;
229
+ on<P extends Model.Event<this>>(keys: P | P[], listener: Model.OnCallback<this>, once?: boolean): Callback;
247
230
  on(effect: Model.Effect<this>): Callback;
248
231
  get(): Model.Export<this>;
249
232
  get<P extends Model.Key<this>>(select: P): this[P];
@@ -251,7 +234,7 @@ declare class Model {
251
234
  get<P extends Model.Key<this>>(select: P, listener: (this: this, value: this[P]) => void): Callback;
252
235
  get<P extends Model.Key<this>>(select: Iterable<P>, listener: (this: this, value: Model.Get<this, P>) => void): Callback;
253
236
  set<T extends Model.Compat<this>>(source: T, select?: (keyof T)[]): Promise<Model.Key<T>[]>;
254
- set<K extends Model.Event<this>>(key: K, value?: Model.ValueOf<this, K>): Promise<readonly Model.Event<this>[]>;
237
+ set<K extends Model.Event<this>>(key: K, value?: Model.ValueOf<this, K>): Promise<Model.Event<this>[] | false>;
255
238
  /** Mark this instance for garbage collection. */
256
239
  null(): void;
257
240
  static get: typeof get$1;
@@ -398,14 +381,20 @@ declare function use<T extends Model>(from: () => Promise<T> | T, callback?: (i:
398
381
  */
399
382
  declare function use<T extends Model>(peer: T, callback?: (i: T) => void): T;
400
383
 
384
+ declare namespace Context {
385
+ type Inputs = {
386
+ [key: string | number]: Model | Model.New;
387
+ };
388
+ }
401
389
  declare class Context {
402
390
  private table;
403
391
  private input;
404
392
  private has;
405
393
  get<T extends Model>(Type: Model.Type<T>): T | undefined;
406
- add<T extends Model>(input: T | Model.New<T>, key?: number | string): T;
394
+ include(inputs: Context.Inputs): Map<Model, boolean>;
395
+ add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
407
396
  push(): this;
408
397
  pop(): void;
409
398
  }
410
399
 
411
- export { Context, Control, Debug, Model, Model as default, get, issues, ref, run, set, use };
400
+ export { Context, Control, Debug, Model, Model as default, get, ref, run, set, use };
package/lib/index.esm.js CHANGED
@@ -379,7 +379,7 @@ class Model {
379
379
  state[key] = arg1[key];
380
380
  controller.update(key);
381
381
  }
382
- return awaitUpdate(this, undefined, 0);
382
+ return this.on(0);
383
383
  }
384
384
  /** Mark this instance for garbage collection. */
385
385
  null() {
@@ -427,6 +427,7 @@ const Oops$5 = issues({
427
427
  const INSTRUCTION = new Map();
428
428
  const REGISTER = new WeakMap();
429
429
  const OBSERVER = new WeakMap();
430
+ const PARENTS = new WeakMap();
430
431
  class Control {
431
432
  constructor(subject, id = random()) {
432
433
  this.subject = subject;
@@ -573,7 +574,7 @@ function setRecursive(on, key, value) {
573
574
  const set = (next) => {
574
575
  if (next instanceof value.constructor) {
575
576
  on.state[key] = next;
576
- control(next).parent = on.subject;
577
+ parent(next, on.subject);
577
578
  control(next, true);
578
579
  return true;
579
580
  }
@@ -582,6 +583,11 @@ function setRecursive(on, key, value) {
582
583
  on.watch(key, { set });
583
584
  set(value);
584
585
  }
586
+ function parent(child, register) {
587
+ if (!register)
588
+ return PARENTS.get(child);
589
+ PARENTS.set(child, register);
590
+ }
585
591
  function watch(on, cb) {
586
592
  if (!on.hasOwnProperty("is"))
587
593
  on = defineProperty(create(on), "is", { value: on });
@@ -649,8 +655,8 @@ function get(arg0, arg1) {
649
655
  if (arg0 instanceof Model)
650
656
  subject = arg0;
651
657
  else if (Model.isTypeof(arg0)) {
652
- const { parent } = control;
653
- if (!parent) {
658
+ const hasParent = parent(subject);
659
+ if (!hasParent) {
654
660
  if (arg1 === true)
655
661
  throw Oops$3.Required(arg0, subject);
656
662
  source = callback => Control.has(arg0, subject, got => {
@@ -660,10 +666,10 @@ function get(arg0, arg1) {
660
666
  throw Oops$3.AmbientRequired(arg0, subject);
661
667
  });
662
668
  }
663
- else if (!arg0 || parent instanceof arg0)
664
- subject = parent;
669
+ else if (!arg0 || hasParent instanceof arg0)
670
+ subject = hasParent;
665
671
  else
666
- throw Oops$3.Unexpected(arg0, subject, parent);
672
+ throw Oops$3.Unexpected(arg0, subject, hasParent);
667
673
  }
668
674
  else if (typeof arg0 == "function")
669
675
  arg1 = arg0.call(subject, key, subject);
@@ -891,7 +897,7 @@ function use(input, argument) {
891
897
  const onUpdate = (next) => {
892
898
  state[key] = next;
893
899
  if (next) {
894
- control(next).parent = subject;
900
+ parent(next, subject);
895
901
  control(next, true);
896
902
  }
897
903
  if (typeof argument == "function")
@@ -947,7 +953,8 @@ function use(input, argument) {
947
953
  }
948
954
 
949
955
  const Oops = issues({
950
- MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
956
+ MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`,
957
+ NewValue: (name) => `Provider already has already defined '${name}' but got new value. This is not yet supported.`
951
958
  });
952
959
  class Context {
953
960
  constructor() {
@@ -968,11 +975,32 @@ class Context {
968
975
  throw Oops.MultipleExist(Type);
969
976
  return result;
970
977
  }
971
- add(input, key) {
972
- if (key && this.input.get(key) === input)
973
- return typeof input == "object"
974
- ? input
975
- : this[this.has(input)];
978
+ include(inputs) {
979
+ const init = new Map();
980
+ for (const key in inputs) {
981
+ const input = inputs[key];
982
+ const exists = this.input.get(key);
983
+ if (exists)
984
+ if (exists !== input)
985
+ throw Oops.NewValue(key);
986
+ else
987
+ continue;
988
+ const instance = this.add(input);
989
+ this.input.set(key, input);
990
+ init.set(instance, true);
991
+ }
992
+ for (const [model] of init) {
993
+ const { state } = control(model, true);
994
+ Object.values(state).forEach(value => {
995
+ if (parent(value) === model) {
996
+ this.add(value, true);
997
+ init.set(value, false);
998
+ }
999
+ });
1000
+ }
1001
+ return init;
1002
+ }
1003
+ add(input, implicit) {
976
1004
  let writable = true;
977
1005
  let T;
978
1006
  let I;
@@ -987,15 +1015,15 @@ class Context {
987
1015
  }
988
1016
  do {
989
1017
  const key = this.has(T);
990
- defineProperty(this, key, {
991
- configurable: true,
992
- value: this.hasOwnProperty(key) && I !== this[key] ? null : I,
993
- writable
994
- });
1018
+ const value = this.hasOwnProperty(key) ? null : I;
1019
+ if (value || I !== this[key] && !implicit)
1020
+ defineProperty(this, key, {
1021
+ configurable: true,
1022
+ value,
1023
+ writable
1024
+ });
995
1025
  T = getPrototypeOf(T);
996
1026
  } while (T !== Model);
997
- if (key !== undefined)
998
- this.input.set(key, input);
999
1027
  return I;
1000
1028
  }
1001
1029
  push() {
@@ -1039,7 +1067,7 @@ defineProperties(Model.prototype, {
1039
1067
  },
1040
1068
  [PARENT]: {
1041
1069
  get() {
1042
- return control(this).parent;
1070
+ return parent(this);
1043
1071
  }
1044
1072
  }
1045
1073
  });
@@ -1050,4 +1078,4 @@ const Debug = {
1050
1078
  PARENT
1051
1079
  };
1052
1080
 
1053
- export { Context, Control, Debug, Model, Model as default, get, issues, ref, run, set, use };
1081
+ export { Context, Control, Debug, Model, Model as default, get, ref, run, set, use };
package/lib/index.js CHANGED
@@ -383,7 +383,7 @@ class Model {
383
383
  state[key] = arg1[key];
384
384
  controller.update(key);
385
385
  }
386
- return awaitUpdate(this, undefined, 0);
386
+ return this.on(0);
387
387
  }
388
388
  /** Mark this instance for garbage collection. */
389
389
  null() {
@@ -431,6 +431,7 @@ const Oops$5 = issues({
431
431
  const INSTRUCTION = new Map();
432
432
  const REGISTER = new WeakMap();
433
433
  const OBSERVER = new WeakMap();
434
+ const PARENTS = new WeakMap();
434
435
  class Control {
435
436
  constructor(subject, id = random()) {
436
437
  this.subject = subject;
@@ -577,7 +578,7 @@ function setRecursive(on, key, value) {
577
578
  const set = (next) => {
578
579
  if (next instanceof value.constructor) {
579
580
  on.state[key] = next;
580
- control(next).parent = on.subject;
581
+ parent(next, on.subject);
581
582
  control(next, true);
582
583
  return true;
583
584
  }
@@ -586,6 +587,11 @@ function setRecursive(on, key, value) {
586
587
  on.watch(key, { set });
587
588
  set(value);
588
589
  }
590
+ function parent(child, register) {
591
+ if (!register)
592
+ return PARENTS.get(child);
593
+ PARENTS.set(child, register);
594
+ }
589
595
  function watch(on, cb) {
590
596
  if (!on.hasOwnProperty("is"))
591
597
  on = defineProperty(create(on), "is", { value: on });
@@ -653,8 +659,8 @@ function get(arg0, arg1) {
653
659
  if (arg0 instanceof Model)
654
660
  subject = arg0;
655
661
  else if (Model.isTypeof(arg0)) {
656
- const { parent } = control;
657
- if (!parent) {
662
+ const hasParent = parent(subject);
663
+ if (!hasParent) {
658
664
  if (arg1 === true)
659
665
  throw Oops$3.Required(arg0, subject);
660
666
  source = callback => Control.has(arg0, subject, got => {
@@ -664,10 +670,10 @@ function get(arg0, arg1) {
664
670
  throw Oops$3.AmbientRequired(arg0, subject);
665
671
  });
666
672
  }
667
- else if (!arg0 || parent instanceof arg0)
668
- subject = parent;
673
+ else if (!arg0 || hasParent instanceof arg0)
674
+ subject = hasParent;
669
675
  else
670
- throw Oops$3.Unexpected(arg0, subject, parent);
676
+ throw Oops$3.Unexpected(arg0, subject, hasParent);
671
677
  }
672
678
  else if (typeof arg0 == "function")
673
679
  arg1 = arg0.call(subject, key, subject);
@@ -895,7 +901,7 @@ function use(input, argument) {
895
901
  const onUpdate = (next) => {
896
902
  state[key] = next;
897
903
  if (next) {
898
- control(next).parent = subject;
904
+ parent(next, subject);
899
905
  control(next, true);
900
906
  }
901
907
  if (typeof argument == "function")
@@ -951,7 +957,8 @@ function use(input, argument) {
951
957
  }
952
958
 
953
959
  const Oops = issues({
954
- MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
960
+ MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`,
961
+ NewValue: (name) => `Provider already has already defined '${name}' but got new value. This is not yet supported.`
955
962
  });
956
963
  class Context {
957
964
  constructor() {
@@ -972,11 +979,32 @@ class Context {
972
979
  throw Oops.MultipleExist(Type);
973
980
  return result;
974
981
  }
975
- add(input, key) {
976
- if (key && this.input.get(key) === input)
977
- return typeof input == "object"
978
- ? input
979
- : this[this.has(input)];
982
+ include(inputs) {
983
+ const init = new Map();
984
+ for (const key in inputs) {
985
+ const input = inputs[key];
986
+ const exists = this.input.get(key);
987
+ if (exists)
988
+ if (exists !== input)
989
+ throw Oops.NewValue(key);
990
+ else
991
+ continue;
992
+ const instance = this.add(input);
993
+ this.input.set(key, input);
994
+ init.set(instance, true);
995
+ }
996
+ for (const [model] of init) {
997
+ const { state } = control(model, true);
998
+ Object.values(state).forEach(value => {
999
+ if (parent(value) === model) {
1000
+ this.add(value, true);
1001
+ init.set(value, false);
1002
+ }
1003
+ });
1004
+ }
1005
+ return init;
1006
+ }
1007
+ add(input, implicit) {
980
1008
  let writable = true;
981
1009
  let T;
982
1010
  let I;
@@ -991,15 +1019,15 @@ class Context {
991
1019
  }
992
1020
  do {
993
1021
  const key = this.has(T);
994
- defineProperty(this, key, {
995
- configurable: true,
996
- value: this.hasOwnProperty(key) && I !== this[key] ? null : I,
997
- writable
998
- });
1022
+ const value = this.hasOwnProperty(key) ? null : I;
1023
+ if (value || I !== this[key] && !implicit)
1024
+ defineProperty(this, key, {
1025
+ configurable: true,
1026
+ value,
1027
+ writable
1028
+ });
999
1029
  T = getPrototypeOf(T);
1000
1030
  } while (T !== Model);
1001
- if (key !== undefined)
1002
- this.input.set(key, input);
1003
1031
  return I;
1004
1032
  }
1005
1033
  push() {
@@ -1043,7 +1071,7 @@ defineProperties(Model.prototype, {
1043
1071
  },
1044
1072
  [PARENT]: {
1045
1073
  get() {
1046
- return control(this).parent;
1074
+ return parent(this);
1047
1075
  }
1048
1076
  }
1049
1077
  });
@@ -1060,7 +1088,6 @@ exports.Debug = Debug;
1060
1088
  exports.Model = Model;
1061
1089
  exports["default"] = Model;
1062
1090
  exports.get = get;
1063
- exports.issues = issues;
1064
1091
  exports.ref = ref;
1065
1092
  exports.run = run;
1066
1093
  exports.set = set;
package/package.json CHANGED
@@ -27,5 +27,5 @@
27
27
  "preversion": "npm run test && npm run build",
28
28
  "postversion": "git push & npm publish"
29
29
  },
30
- "version": "0.20.0"
30
+ "version": "0.21.1"
31
31
  }