@expressive/mvc 0.9.2 → 0.9.4

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.js CHANGED
@@ -27,11 +27,11 @@ function issues(register) {
27
27
 
28
28
  const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
29
29
 
30
- const Oops$d = issues({
30
+ const Oops$e = issues({
31
31
  NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
32
32
  });
33
33
  function suspend(source, key) {
34
- const error = Oops$d.NotReady(source.subject, key);
34
+ const error = Oops$e.NotReady(source.subject, key);
35
35
  const promise = new Promise(resolve => {
36
36
  const release = source.addListener(forKey => {
37
37
  if (forKey == key)
@@ -71,7 +71,7 @@ function mayRetry(fn) {
71
71
  return compute();
72
72
  }
73
73
 
74
- const Oops$c = issues({
74
+ const Oops$d = issues({
75
75
  Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
76
76
  });
77
77
  const INFO = new WeakMap();
@@ -91,7 +91,7 @@ function computeMode(self, source, setter, key, required) {
91
91
  return setter.call(sub.proxy, sub.proxy);
92
92
  }
93
93
  catch (err) {
94
- Oops$c.Failed(subject, key, initial).warn();
94
+ Oops$d.Failed(subject, key, initial).warn();
95
95
  throw err;
96
96
  }
97
97
  };
@@ -118,6 +118,7 @@ function computeMode(self, source, setter, key, required) {
118
118
  else
119
119
  pending.add(refresh);
120
120
  });
121
+ sub.watch.set(key, false);
121
122
  try {
122
123
  const value = compute(true);
123
124
  state.set(key, value);
@@ -465,7 +466,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
465
466
  });
466
467
  }
467
468
 
468
- const Oops$b = issues({
469
+ const Oops$c = issues({
469
470
  DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
470
471
  });
471
472
  function run(task) {
@@ -473,7 +474,7 @@ function run(task) {
473
474
  let pending = false;
474
475
  const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
475
476
  if (pending)
476
- return Promise.reject(Oops$b.DuplicatePending(key));
477
+ return Promise.reject(Oops$c.DuplicatePending(key));
477
478
  pending = true;
478
479
  this.update(key);
479
480
  try {
@@ -495,7 +496,7 @@ function run(task) {
495
496
  });
496
497
  }
497
498
 
498
- const Oops$a = issues({
499
+ const Oops$b = issues({
499
500
  NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
500
501
  });
501
502
  function factoryMode(self, output, key, required) {
@@ -519,7 +520,7 @@ function factoryMode(self, output, key, required) {
519
520
  const suspend = () => {
520
521
  if (required === false)
521
522
  return undefined;
522
- const issue = Oops$a.NotReady(subject, key);
523
+ const issue = Oops$b.NotReady(subject, key);
523
524
  assign(pending, {
524
525
  message: issue.message,
525
526
  stack: issue.stack
@@ -536,7 +537,7 @@ function factoryMode(self, output, key, required) {
536
537
  };
537
538
  }
538
539
 
539
- const Oops$9 = issues({
540
+ const Oops$a = issues({
540
541
  PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
541
542
  ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
542
543
  Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
@@ -549,7 +550,7 @@ function get(arg0, arg1, arg2) {
549
550
  let getter;
550
551
  // Easy mistake, using a peer, will always be unresolved.
551
552
  if (typeof arg0 == "symbol")
552
- throw Oops$9.PeerNotAllowed(subject, key);
553
+ throw Oops$a.PeerNotAllowed(subject, key);
553
554
  // if(typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
554
555
  // throw Oops.BadSource(subject, key, arg0);
555
556
  this.state.set(key, undefined);
@@ -583,7 +584,7 @@ function get(arg0, arg1, arg2) {
583
584
  init();
584
585
  }
585
586
  catch (err) {
586
- Oops$9.ComputeFailed(subject, key).warn();
587
+ Oops$a.ComputeFailed(subject, key).warn();
587
588
  throw err;
588
589
  }
589
590
  return () => {
@@ -594,7 +595,7 @@ function get(arg0, arg1, arg2) {
594
595
  });
595
596
  }
596
597
 
597
- const Oops$8 = issues({
598
+ const Oops$9 = issues({
598
599
  BadCallback: () => `Callback for effect-callback may only return a function.`
599
600
  });
600
601
  function createEffect(model, callback, keys) {
@@ -608,7 +609,7 @@ function createEffect(model, callback, keys) {
608
609
  if (unSet instanceof Promise)
609
610
  unSet = undefined;
610
611
  if (unSet && typeof unSet !== "function")
611
- throw Oops$8.BadCallback();
612
+ throw Oops$9.BadCallback();
612
613
  }
613
614
  function invoke() {
614
615
  if (busy)
@@ -651,7 +652,7 @@ function createValueEffect(callback) {
651
652
  if (typeof out == "function")
652
653
  unSet = out;
653
654
  else
654
- throw Oops$8.BadCallback();
655
+ throw Oops$9.BadCallback();
655
656
  };
656
657
  }
657
658
 
@@ -849,7 +850,7 @@ function createProxy(emit, watch) {
849
850
  }
850
851
 
851
852
  const Parent = new WeakMap();
852
- const Oops$7 = issues({
853
+ const Oops$8 = issues({
853
854
  BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
854
855
  NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
855
856
  });
@@ -866,7 +867,7 @@ function use$1(input, argument) {
866
867
  input = new input();
867
868
  }
868
869
  else if (input && typeof input !== "object")
869
- throw Oops$7.BadArgument(typeof input);
870
+ throw Oops$8.BadArgument(typeof input);
870
871
  if (input instanceof Map || input instanceof Set)
871
872
  return keyed(this, key, input);
872
873
  const onUpdate = (next) => {
@@ -883,7 +884,7 @@ function use$1(input, argument) {
883
884
  const suspend = () => {
884
885
  if (required === false)
885
886
  return;
886
- const issue = Oops$7.NotReady(subject, key);
887
+ const issue = Oops$8.NotReady(subject, key);
887
888
  assign(pending, {
888
889
  message: issue.message,
889
890
  stack: issue.stack
@@ -928,7 +929,7 @@ function use$1(input, argument) {
928
929
  });
929
930
  }
930
931
 
931
- const Oops$6 = issues({
932
+ const Oops$7 = issues({
932
933
  Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
933
934
  Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
934
935
  });
@@ -939,19 +940,100 @@ function has(Type, required) {
939
940
  const expected = Type.name;
940
941
  if (!value) {
941
942
  if (required !== false)
942
- throw Oops$6.Required(expected, child);
943
+ throw Oops$7.Required(expected, child);
943
944
  }
944
945
  else if (!(value instanceof Type))
945
- throw Oops$6.Unexpected(expected, child, value);
946
+ throw Oops$7.Unexpected(expected, child, value);
946
947
  return { value };
947
948
  });
948
949
  }
949
950
 
950
- const Oops$5 = issues({
951
+ const Oops$6 = issues({
951
952
  Timeout: (keys, timeout) => `No update seen for [${keys}] within ${timeout}.`,
952
953
  KeysExpected: (key) => `Key "${key}" was expected in current update.`,
953
954
  StrictUpdate: () => `Expected update but none in progress.`,
954
- StrictNoUpdate: () => `Update is not expected but one is in progress!`,
955
+ StrictNoUpdate: () => `Update is not expected but one is in progress!`
956
+ });
957
+ function addEventListener(source, arg1, arg2, arg3) {
958
+ const single = typeof arg1 == "string";
959
+ const keys = typeof arg1 == "string" ? [arg1] :
960
+ typeof arg1 == "object" ? arg1 :
961
+ undefined;
962
+ if (typeof arg2 == "function" && keys)
963
+ return Control.for(source, control => {
964
+ for (const key of keys)
965
+ try {
966
+ void source[key];
967
+ }
968
+ catch (e) { }
969
+ const invoke = single
970
+ ? () => arg2.call(source, control.state.get(arg1), arg1)
971
+ : (frame) => arg2.call(source, frame);
972
+ const removeListener = control.addListener(key => {
973
+ if (!key && !keys.length)
974
+ invoke([]);
975
+ if (keys.includes(key)) {
976
+ if (arg3)
977
+ removeListener();
978
+ return invoke;
979
+ }
980
+ });
981
+ return removeListener;
982
+ });
983
+ return new Promise((resolve, reject) => {
984
+ const timeout = (message) => {
985
+ const k = keys ? keys.join(", ") : "any";
986
+ removeListener();
987
+ reject(Oops$6.Timeout(k, message));
988
+ };
989
+ const removeListener = Control.for(source, control => {
990
+ const pending = control.frame;
991
+ if (keys === null) {
992
+ if (pending.size)
993
+ reject(Oops$6.StrictNoUpdate());
994
+ else
995
+ resolve(null);
996
+ return;
997
+ }
998
+ if (keys) {
999
+ if (keys.length) {
1000
+ if (arg2 === 0 && single && !pending.has(keys[0])) {
1001
+ reject(Oops$6.KeysExpected(keys[0]));
1002
+ return;
1003
+ }
1004
+ else
1005
+ for (const key of keys)
1006
+ try {
1007
+ void source[key];
1008
+ }
1009
+ catch (e) { }
1010
+ }
1011
+ }
1012
+ else if (!pending.size && arg1 === true || arg2 === 0) {
1013
+ reject(Oops$6.StrictUpdate());
1014
+ return;
1015
+ }
1016
+ else
1017
+ control.waiting.add(resolve);
1018
+ return control.addListener(key => {
1019
+ if (!key) {
1020
+ if (keys && !keys.length)
1021
+ resolve([]);
1022
+ else
1023
+ timeout(`lifetime of ${source}`);
1024
+ }
1025
+ else if (!keys || keys.includes(key)) {
1026
+ removeListener();
1027
+ return keys => resolve(single ? control.state.get(key) : keys);
1028
+ }
1029
+ });
1030
+ });
1031
+ if (arg2 && typeof arg2 == "number")
1032
+ setTimeout(() => timeout(`${arg2}ms`), arg2);
1033
+ });
1034
+ }
1035
+
1036
+ const Oops$5 = issues({
955
1037
  NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
956
1038
  });
957
1039
  class Model {
@@ -962,82 +1044,7 @@ class Model {
962
1044
  on(arg1, arg2, arg3) {
963
1045
  if (typeof arg1 == "function")
964
1046
  return createEffect(this.is, arg1, arg2);
965
- const single = typeof arg1 == "string";
966
- const keys = typeof arg1 == "string" ? [arg1] :
967
- typeof arg1 == "object" ? arg1 :
968
- undefined;
969
- if (typeof arg2 == "function" && keys)
970
- return Control.for(this, control => {
971
- for (const key of keys)
972
- try {
973
- void this[key];
974
- }
975
- catch (e) { }
976
- const invoke = single
977
- ? () => arg2.call(this, control.state.get(arg1), arg1)
978
- : (frame) => arg2.call(this, frame);
979
- const removeListener = control.addListener(key => {
980
- if (!key && !keys.length)
981
- invoke([]);
982
- if (keys.includes(key)) {
983
- if (arg3)
984
- removeListener();
985
- return invoke;
986
- }
987
- });
988
- return removeListener;
989
- });
990
- return new Promise((resolve, reject) => {
991
- const timeout = (message) => {
992
- const k = keys ? keys.join(", ") : "any";
993
- removeListener();
994
- reject(Oops$5.Timeout(k, message));
995
- };
996
- const removeListener = Control.for(this, control => {
997
- const pending = control.frame;
998
- if (keys === null) {
999
- if (pending.size)
1000
- reject(Oops$5.StrictNoUpdate());
1001
- else
1002
- resolve(null);
1003
- return;
1004
- }
1005
- if (keys) {
1006
- if (keys.length) {
1007
- if (arg2 === 0 && single && !pending.has(keys[0])) {
1008
- reject(Oops$5.KeysExpected(keys[0]));
1009
- return;
1010
- }
1011
- else
1012
- for (const key of keys)
1013
- try {
1014
- void this[key];
1015
- }
1016
- catch (e) { }
1017
- }
1018
- }
1019
- else if (!pending.size && arg1 === true || arg2 === 0) {
1020
- reject(Oops$5.StrictUpdate());
1021
- return;
1022
- }
1023
- else
1024
- control.waiting.add(resolve);
1025
- return control.addListener(key => {
1026
- if (!key) {
1027
- if (keys && !keys.length)
1028
- resolve([]);
1029
- else
1030
- timeout(`lifetime of ${this}`);
1031
- }
1032
- else if (!keys || keys.includes(key)) {
1033
- removeListener();
1034
- return keys => resolve(single ? control.state.get(key) : keys);
1035
- }
1036
- });
1037
- });
1038
- if (arg2 && typeof arg2 == "number")
1039
- setTimeout(() => timeout(`${arg2}ms`), arg2);
1040
- });
1047
+ return addEventListener(this.is, arg1, arg2, arg3);
1041
1048
  }
1042
1049
  export(subset) {
1043
1050
  const { state } = Control.for(this);
@@ -1290,6 +1297,19 @@ function useValue(source, compute, suspend) {
1290
1297
  else
1291
1298
  refresh();
1292
1299
  };
1300
+ if (value === null) {
1301
+ sub.watch.clear();
1302
+ return {
1303
+ proxy: null,
1304
+ release: () => { }
1305
+ };
1306
+ }
1307
+ if (typeof value == "function") {
1308
+ const get = value;
1309
+ sub.watch.clear();
1310
+ compute = () => get();
1311
+ value = get();
1312
+ }
1293
1313
  if (value instanceof Promise) {
1294
1314
  value.then(set);
1295
1315
  value = undefined;