@expressive/mvc 0.9.3 → 0.9.5

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
@@ -8,6 +8,8 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
8
8
 
9
9
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
10
 
11
+ const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
12
+
11
13
  class Issue extends Error {
12
14
  constructor() {
13
15
  super(...arguments);
@@ -25,13 +27,11 @@ function issues(register) {
25
27
  return Library;
26
28
  }
27
29
 
28
- const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
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
  };
@@ -466,7 +466,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
466
466
  });
467
467
  }
468
468
 
469
- const Oops$b = issues({
469
+ const Oops$c = issues({
470
470
  DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
471
471
  });
472
472
  function run(task) {
@@ -474,7 +474,7 @@ function run(task) {
474
474
  let pending = false;
475
475
  const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
476
476
  if (pending)
477
- return Promise.reject(Oops$b.DuplicatePending(key));
477
+ return Promise.reject(Oops$c.DuplicatePending(key));
478
478
  pending = true;
479
479
  this.update(key);
480
480
  try {
@@ -496,7 +496,7 @@ function run(task) {
496
496
  });
497
497
  }
498
498
 
499
- const Oops$a = issues({
499
+ const Oops$b = issues({
500
500
  NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
501
501
  });
502
502
  function factoryMode(self, output, key, required) {
@@ -520,7 +520,7 @@ function factoryMode(self, output, key, required) {
520
520
  const suspend = () => {
521
521
  if (required === false)
522
522
  return undefined;
523
- const issue = Oops$a.NotReady(subject, key);
523
+ const issue = Oops$b.NotReady(subject, key);
524
524
  assign(pending, {
525
525
  message: issue.message,
526
526
  stack: issue.stack
@@ -537,7 +537,7 @@ function factoryMode(self, output, key, required) {
537
537
  };
538
538
  }
539
539
 
540
- const Oops$9 = issues({
540
+ const Oops$a = issues({
541
541
  PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
542
542
  ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
543
543
  Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
@@ -550,7 +550,7 @@ function get(arg0, arg1, arg2) {
550
550
  let getter;
551
551
  // Easy mistake, using a peer, will always be unresolved.
552
552
  if (typeof arg0 == "symbol")
553
- throw Oops$9.PeerNotAllowed(subject, key);
553
+ throw Oops$a.PeerNotAllowed(subject, key);
554
554
  // if(typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
555
555
  // throw Oops.BadSource(subject, key, arg0);
556
556
  this.state.set(key, undefined);
@@ -584,7 +584,7 @@ function get(arg0, arg1, arg2) {
584
584
  init();
585
585
  }
586
586
  catch (err) {
587
- Oops$9.ComputeFailed(subject, key).warn();
587
+ Oops$a.ComputeFailed(subject, key).warn();
588
588
  throw err;
589
589
  }
590
590
  return () => {
@@ -595,7 +595,7 @@ function get(arg0, arg1, arg2) {
595
595
  });
596
596
  }
597
597
 
598
- const Oops$8 = issues({
598
+ const Oops$9 = issues({
599
599
  BadCallback: () => `Callback for effect-callback may only return a function.`
600
600
  });
601
601
  function createEffect(model, callback, keys) {
@@ -609,7 +609,7 @@ function createEffect(model, callback, keys) {
609
609
  if (unSet instanceof Promise)
610
610
  unSet = undefined;
611
611
  if (unSet && typeof unSet !== "function")
612
- throw Oops$8.BadCallback();
612
+ throw Oops$9.BadCallback();
613
613
  }
614
614
  function invoke() {
615
615
  if (busy)
@@ -652,7 +652,7 @@ function createValueEffect(callback) {
652
652
  if (typeof out == "function")
653
653
  unSet = out;
654
654
  else
655
- throw Oops$8.BadCallback();
655
+ throw Oops$9.BadCallback();
656
656
  };
657
657
  }
658
658
 
@@ -850,7 +850,7 @@ function createProxy(emit, watch) {
850
850
  }
851
851
 
852
852
  const Parent = new WeakMap();
853
- const Oops$7 = issues({
853
+ const Oops$8 = issues({
854
854
  BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
855
855
  NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
856
856
  });
@@ -867,7 +867,7 @@ function use$1(input, argument) {
867
867
  input = new input();
868
868
  }
869
869
  else if (input && typeof input !== "object")
870
- throw Oops$7.BadArgument(typeof input);
870
+ throw Oops$8.BadArgument(typeof input);
871
871
  if (input instanceof Map || input instanceof Set)
872
872
  return keyed(this, key, input);
873
873
  const onUpdate = (next) => {
@@ -884,7 +884,7 @@ function use$1(input, argument) {
884
884
  const suspend = () => {
885
885
  if (required === false)
886
886
  return;
887
- const issue = Oops$7.NotReady(subject, key);
887
+ const issue = Oops$8.NotReady(subject, key);
888
888
  assign(pending, {
889
889
  message: issue.message,
890
890
  stack: issue.stack
@@ -929,7 +929,7 @@ function use$1(input, argument) {
929
929
  });
930
930
  }
931
931
 
932
- const Oops$6 = issues({
932
+ const Oops$7 = issues({
933
933
  Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
934
934
  Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
935
935
  });
@@ -940,19 +940,100 @@ function has(Type, required) {
940
940
  const expected = Type.name;
941
941
  if (!value) {
942
942
  if (required !== false)
943
- throw Oops$6.Required(expected, child);
943
+ throw Oops$7.Required(expected, child);
944
944
  }
945
945
  else if (!(value instanceof Type))
946
- throw Oops$6.Unexpected(expected, child, value);
946
+ throw Oops$7.Unexpected(expected, child, value);
947
947
  return { value };
948
948
  });
949
949
  }
950
950
 
951
- const Oops$5 = issues({
951
+ const Oops$6 = issues({
952
952
  Timeout: (keys, timeout) => `No update seen for [${keys}] within ${timeout}.`,
953
953
  KeysExpected: (key) => `Key "${key}" was expected in current update.`,
954
954
  StrictUpdate: () => `Expected update but none in progress.`,
955
- 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({
956
1037
  NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
957
1038
  });
958
1039
  class Model {
@@ -963,82 +1044,7 @@ class Model {
963
1044
  on(arg1, arg2, arg3) {
964
1045
  if (typeof arg1 == "function")
965
1046
  return createEffect(this.is, arg1, arg2);
966
- const single = typeof arg1 == "string";
967
- const keys = typeof arg1 == "string" ? [arg1] :
968
- typeof arg1 == "object" ? arg1 :
969
- undefined;
970
- if (typeof arg2 == "function" && keys)
971
- return Control.for(this, control => {
972
- for (const key of keys)
973
- try {
974
- void this[key];
975
- }
976
- catch (e) { }
977
- const invoke = single
978
- ? () => arg2.call(this, control.state.get(arg1), arg1)
979
- : (frame) => arg2.call(this, frame);
980
- const removeListener = control.addListener(key => {
981
- if (!key && !keys.length)
982
- invoke([]);
983
- if (keys.includes(key)) {
984
- if (arg3)
985
- removeListener();
986
- return invoke;
987
- }
988
- });
989
- return removeListener;
990
- });
991
- return new Promise((resolve, reject) => {
992
- const timeout = (message) => {
993
- const k = keys ? keys.join(", ") : "any";
994
- removeListener();
995
- reject(Oops$5.Timeout(k, message));
996
- };
997
- const removeListener = Control.for(this, control => {
998
- const pending = control.frame;
999
- if (keys === null) {
1000
- if (pending.size)
1001
- reject(Oops$5.StrictNoUpdate());
1002
- else
1003
- resolve(null);
1004
- return;
1005
- }
1006
- if (keys) {
1007
- if (keys.length) {
1008
- if (arg2 === 0 && single && !pending.has(keys[0])) {
1009
- reject(Oops$5.KeysExpected(keys[0]));
1010
- return;
1011
- }
1012
- else
1013
- for (const key of keys)
1014
- try {
1015
- void this[key];
1016
- }
1017
- catch (e) { }
1018
- }
1019
- }
1020
- else if (!pending.size && arg1 === true || arg2 === 0) {
1021
- reject(Oops$5.StrictUpdate());
1022
- return;
1023
- }
1024
- else
1025
- control.waiting.add(resolve);
1026
- return control.addListener(key => {
1027
- if (!key) {
1028
- if (keys && !keys.length)
1029
- resolve([]);
1030
- else
1031
- timeout(`lifetime of ${this}`);
1032
- }
1033
- else if (!keys || keys.includes(key)) {
1034
- removeListener();
1035
- return keys => resolve(single ? control.state.get(key) : keys);
1036
- }
1037
- });
1038
- });
1039
- if (arg2 && typeof arg2 == "number")
1040
- setTimeout(() => timeout(`${arg2}ms`), arg2);
1041
- });
1047
+ return addEventListener(this.is, arg1, arg2, arg3);
1042
1048
  }
1043
1049
  export(subset) {
1044
1050
  const { state } = Control.for(this);
@@ -1291,6 +1297,19 @@ function useValue(source, compute, suspend) {
1291
1297
  else
1292
1298
  refresh();
1293
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
+ }
1294
1313
  if (value instanceof Promise) {
1295
1314
  value.then(set);
1296
1315
  value = undefined;
@@ -1353,43 +1372,6 @@ class MVC extends Model {
1353
1372
  }
1354
1373
  }
1355
1374
 
1356
- const LOCAL = "$debug local";
1357
- const STATE = "$debug state";
1358
- const UPDATE = "$debug update";
1359
- const CONTROL = "$debug controller";
1360
- defineProperties(Model.prototype, {
1361
- [CONTROL]: {
1362
- get() {
1363
- return Control.get(this);
1364
- }
1365
- },
1366
- [LOCAL]: {
1367
- get() {
1368
- return Subscriber.get(this);
1369
- }
1370
- },
1371
- [STATE]: {
1372
- get() {
1373
- const { state } = Control.get(this);
1374
- const output = {};
1375
- state.forEach((value, key) => output[key] = value);
1376
- return output;
1377
- }
1378
- },
1379
- [UPDATE]: {
1380
- get() {
1381
- const source = Subscriber.get(this) || Control.get(this);
1382
- return source && source.latest;
1383
- }
1384
- }
1385
- });
1386
- const Debug = {
1387
- CONTROL,
1388
- LOCAL,
1389
- STATE,
1390
- UPDATE
1391
- };
1392
-
1393
1375
  const Oops$2 = issues({
1394
1376
  BadProps: () => `Provider expects either a render function, 'get' or 'has' props.`
1395
1377
  });
@@ -1519,6 +1501,43 @@ class Global extends MVC {
1519
1501
  }
1520
1502
  Global.keepAlive = true;
1521
1503
 
1504
+ const LOCAL = "$debug local";
1505
+ const STATE = "$debug state";
1506
+ const UPDATE = "$debug update";
1507
+ const CONTROL = "$debug controller";
1508
+ defineProperties(Model.prototype, {
1509
+ [CONTROL]: {
1510
+ get() {
1511
+ return Control.get(this);
1512
+ }
1513
+ },
1514
+ [LOCAL]: {
1515
+ get() {
1516
+ return Subscriber.get(this);
1517
+ }
1518
+ },
1519
+ [STATE]: {
1520
+ get() {
1521
+ const { state } = Control.get(this);
1522
+ const output = {};
1523
+ state.forEach((value, key) => output[key] = value);
1524
+ return output;
1525
+ }
1526
+ },
1527
+ [UPDATE]: {
1528
+ get() {
1529
+ const source = Subscriber.get(this) || Control.get(this);
1530
+ return source && source.latest;
1531
+ }
1532
+ }
1533
+ });
1534
+ const Debug = {
1535
+ CONTROL,
1536
+ LOCAL,
1537
+ STATE,
1538
+ UPDATE
1539
+ };
1540
+
1522
1541
  exports.Consumer = Consumer;
1523
1542
  exports.Debug = Debug;
1524
1543
  exports.Global = Global;