@expressive/mvc 1.0.0-beta.27 → 1.0.0-beta.30

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
@@ -24,7 +24,7 @@ function issues(register) {
24
24
  return Library;
25
25
  }
26
26
 
27
- const Oops$9 = issues({
27
+ const Oops$8 = issues({
28
28
  BadEffectCallback: () => `Callback for effect-callback may only return a function.`
29
29
  });
30
30
  const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertyDescriptors, getOwnPropertySymbols, keys: keys$1, values } = Object;
@@ -53,7 +53,7 @@ function createEffect(callback) {
53
53
  if (unSet instanceof Promise)
54
54
  unSet = undefined;
55
55
  if (unSet && typeof unSet !== "function")
56
- throw Oops$9.BadEffectCallback();
56
+ throw Oops$8.BadEffectCallback();
57
57
  };
58
58
  }
59
59
  function createValueEffect(callback) {
@@ -69,7 +69,7 @@ function createValueEffect(callback) {
69
69
  if (typeof out == "function")
70
70
  unSet = out;
71
71
  else
72
- throw Oops$9.BadEffectCallback();
72
+ throw Oops$8.BadEffectCallback();
73
73
  };
74
74
  }
75
75
  function select(source, select) {
@@ -157,7 +157,7 @@ class Subscriber {
157
157
  }
158
158
  }
159
159
 
160
- const Oops$8 = issues({
160
+ const Oops$7 = issues({
161
161
  ComputeFailed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
162
162
  ComputedEarly: (property) => `Note: Computed values don't run until accessed, except when subscribed to. '${property}' getter may have run earlier than intended.`
163
163
  });
@@ -183,7 +183,7 @@ function prepare(parent, key, source, setter, getter) {
183
183
  return setter.call(sub.proxy, sub.proxy);
184
184
  }
185
185
  catch (err) {
186
- Oops$8.ComputeFailed(subject, key, !!initial).warn();
186
+ Oops$7.ComputeFailed(subject, key, !!initial).warn();
187
187
  throw err;
188
188
  }
189
189
  }
@@ -229,7 +229,7 @@ function prepare(parent, key, source, setter, getter) {
229
229
  }
230
230
  catch (e) {
231
231
  if (early)
232
- Oops$8.ComputedEarly(key).warn();
232
+ Oops$7.ComputedEarly(key).warn();
233
233
  throw e;
234
234
  }
235
235
  finally {
@@ -510,9 +510,215 @@ function child(source, name) {
510
510
  }, name || source.name);
511
511
  }
512
512
 
513
- const Oops$7 = issues({
514
- HasPropertyUndefined: (control, property) => `${control}.${property} is marked as required for this render.`
513
+ const Oops$6 = issues({
514
+ CantAttachGlobal: (parent, child) => `Singleton '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
515
+ AmbientRequired: (requested, requester, key) => `Attempted to find an instance of ${requested} in context. It is required for [${requester}.${key}], but one could not be found.`
516
+ });
517
+ const PendingContext = new WeakMap();
518
+ const ContextWasUsed = new WeakMap();
519
+ function tap(type, argument) {
520
+ return child(function tap(key) {
521
+ return pendingAccess(this.subject, type, key, argument);
522
+ });
523
+ }
524
+ function pendingAccess(from, type, key, argument) {
525
+ if ("current" in type)
526
+ return () => type.current;
527
+ if ("current" in from.constructor)
528
+ throw Oops$6.CantAttachGlobal(from, type.name);
529
+ let instance;
530
+ getPending(from).push(context => {
531
+ instance = context.get(type);
532
+ if (typeof argument == "function") {
533
+ if (argument(instance) === false)
534
+ instance = undefined;
535
+ }
536
+ else if (!instance && argument)
537
+ throw Oops$6.AmbientRequired(type.name, from, key);
538
+ });
539
+ return () => instance;
540
+ }
541
+ function usePeerContext(subject) {
542
+ if (ContextWasUsed.has(subject)) {
543
+ if (ContextWasUsed.get(subject))
544
+ useLookup();
545
+ return;
546
+ }
547
+ const pending = PendingContext.get(subject);
548
+ if (pending) {
549
+ const local = useLookup();
550
+ for (const init of pending)
551
+ init(local);
552
+ PendingContext.delete(subject);
553
+ }
554
+ ContextWasUsed.set(subject, !!pending);
555
+ }
556
+ function getPending(subject) {
557
+ let pending = PendingContext.get(subject);
558
+ if (!pending)
559
+ PendingContext.set(subject, pending = []);
560
+ return pending;
561
+ }
562
+
563
+ const Oops$5 = issues({
564
+ DuplicateAction: (key) => `Invoked action ${key} but one is already active.`,
565
+ BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
566
+ PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`
567
+ });
568
+ function createRef(key, cb) {
569
+ const refObjectFunction = this.setter(key, cb && createValueEffect(cb));
570
+ defineProperty(refObjectFunction, "current", {
571
+ set: refObjectFunction,
572
+ get: () => this.state[key]
573
+ });
574
+ return refObjectFunction;
575
+ }
576
+ function ref(arg) {
577
+ return apply(function ref(key) {
578
+ let value = {};
579
+ if (typeof arg == "object") {
580
+ const source = manage(arg);
581
+ for (const key in source.state)
582
+ defineLazy(value, key, createRef.bind(source, key));
583
+ }
584
+ else
585
+ value = createRef.call(this, key, arg);
586
+ return { value };
587
+ });
588
+ }
589
+ function act(task) {
590
+ return apply(function act(key) {
591
+ let pending = false;
592
+ const invoke = (...args) => {
593
+ if (pending)
594
+ return Promise.reject(Oops$5.DuplicateAction(key));
595
+ pending = true;
596
+ this.update(key);
597
+ return new Promise(res => {
598
+ res(task.apply(this.subject, args));
599
+ }).finally(() => {
600
+ pending = false;
601
+ this.update(key);
602
+ });
603
+ };
604
+ this.state[key] = undefined;
605
+ setAlias(invoke, `run ${key}`);
606
+ defineProperty(invoke, "active", {
607
+ get: () => pending
608
+ });
609
+ return {
610
+ value: invoke,
611
+ writable: false
612
+ };
613
+ });
614
+ }
615
+ function from(source, setter, getter) {
616
+ return apply(function from(key) {
617
+ const { subject } = this;
618
+ let getSource;
619
+ // Easy mistake, using a peer, will always be unresolved.
620
+ if (typeof source == "symbol")
621
+ throw Oops$5.PeerNotAllowed(subject, key);
622
+ // replace source controller in-case different
623
+ if (typeof source == "object")
624
+ getSource = () => manage(source);
625
+ // specifically an arrow function (getter factory)
626
+ else if (!source.prototype) {
627
+ setter = source.call(subject, key);
628
+ getSource = () => this;
629
+ }
630
+ // is a peer Model (constructor)
631
+ else if (Model.isTypeof(source))
632
+ getSource = pendingAccess(subject, source, key, true);
633
+ // Regular function is to ambiguous so not allowed.
634
+ else
635
+ throw Oops$5.BadComputedSource(subject, key, source);
636
+ prepare(this, key, getSource, setter, getter);
637
+ });
638
+ }
639
+
640
+ const Oops$4 = issues({
641
+ ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
515
642
  });
643
+ function pending(source, compute) {
644
+ return (source === undefined ?
645
+ suspendForValue() :
646
+ typeof source == "function" && !source.prototype ?
647
+ suspendForAsync(source) :
648
+ suspendForComputed(source, compute));
649
+ }
650
+ /**
651
+ * Get value, suspend instead if undefined.
652
+ *
653
+ * Throws suspense promise also interpretable as an error.
654
+ * React could handle it but other contexts probably not.
655
+ */
656
+ function pendingValue(via, key) {
657
+ const value = via.state[key];
658
+ if (value === undefined)
659
+ throw suspend(via, key);
660
+ return value;
661
+ }
662
+ function suspend(source, key) {
663
+ const error = Oops$4.ValueNotReady(source.subject, key);
664
+ const promise = new Promise(resolve => {
665
+ const release = source.addListener(forKey => {
666
+ if (forKey == key)
667
+ return () => {
668
+ if (source.state[key] !== undefined) {
669
+ release();
670
+ resolve();
671
+ }
672
+ };
673
+ });
674
+ });
675
+ return Object.assign(promise, {
676
+ toString: () => String(error),
677
+ name: "Suspense",
678
+ message: error.message,
679
+ stack: error.stack
680
+ });
681
+ }
682
+ function suspendForComputed(source, compute) {
683
+ function getter(_value, key) {
684
+ return pendingValue(manage(this), key);
685
+ }
686
+ return from(source, compute, getter);
687
+ }
688
+ function suspendForValue() {
689
+ return apply(function pending(key) {
690
+ this.state[key] = undefined;
691
+ return {
692
+ set: this.setter(key),
693
+ get: () => pendingValue(this, key)
694
+ };
695
+ });
696
+ }
697
+ function suspendForAsync(source) {
698
+ return apply(function suspense(key) {
699
+ const subject = this.subject;
700
+ let waiting = true;
701
+ let value;
702
+ let error;
703
+ return () => {
704
+ if (error)
705
+ throw error;
706
+ if (!waiting)
707
+ return value;
708
+ const issue = Oops$4.ValueNotReady(subject, key);
709
+ let suspend = source
710
+ .call(subject, key)
711
+ .catch(err => error = err)
712
+ .then(out => value = out)
713
+ .finally(() => waiting = false);
714
+ throw Object.assign(suspend, {
715
+ message: issue.message,
716
+ stack: issue.stack
717
+ });
718
+ };
719
+ });
720
+ }
721
+
516
722
  function use$1(init) {
517
723
  const [state, update] = react.useState(() => [
518
724
  init(() => update(state.concat()))
@@ -533,13 +739,14 @@ function useWatcher(target, focus, expected) {
533
739
  const hook = use$1(refresh => {
534
740
  const sub = new Subscriber(target, () => refresh);
535
741
  if (focus) {
536
- const src = sub.proxy;
742
+ const source = sub.proxy;
537
743
  const key = keys(sub.parent, focus)[0];
538
744
  defineProperty(sub, "proxy", {
539
745
  get() {
540
- if (src[key] === undefined && expected)
541
- throw Oops$7.HasPropertyUndefined(target, key);
542
- return src[key];
746
+ const value = source[key];
747
+ if (value === undefined && expected)
748
+ throw suspend(sub.parent, key);
749
+ return value;
543
750
  }
544
751
  });
545
752
  }
@@ -567,56 +774,6 @@ function useModel(Type, callback) {
567
774
  return hook.proxy;
568
775
  }
569
776
 
570
- const Oops$6 = issues({
571
- CantAttachGlobal: (parent, child) => `Singleton '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
572
- AmbientRequired: (requested, requester, key) => `Attempted to find an instance of ${requested} in context. It is required for [${requester}.${key}], but one could not be found.`
573
- });
574
- const PendingContext = new WeakMap();
575
- const ContextWasUsed = new WeakMap();
576
- function tap(type, argument) {
577
- return child(function tap(key) {
578
- return pendingAccess(this.subject, type, key, argument);
579
- });
580
- }
581
- function pendingAccess(from, type, key, argument) {
582
- if ("current" in type)
583
- return () => type.current;
584
- if ("current" in from.constructor)
585
- throw Oops$6.CantAttachGlobal(from, type.name);
586
- let instance;
587
- getPending(from).push(context => {
588
- instance = context.get(type);
589
- if (typeof argument == "function") {
590
- if (argument(instance) === false)
591
- instance = undefined;
592
- }
593
- else if (!instance && argument)
594
- throw Oops$6.AmbientRequired(type.name, from, key);
595
- });
596
- return () => instance;
597
- }
598
- function usePeerContext(subject) {
599
- if (ContextWasUsed.has(subject)) {
600
- if (ContextWasUsed.get(subject))
601
- useLookup();
602
- return;
603
- }
604
- const pending = PendingContext.get(subject);
605
- if (pending) {
606
- const local = useLookup();
607
- for (const init of pending)
608
- init(local);
609
- PendingContext.delete(subject);
610
- }
611
- ContextWasUsed.set(subject, !!pending);
612
- }
613
- function getPending(subject) {
614
- let pending = PendingContext.get(subject);
615
- if (!pending)
616
- PendingContext.set(subject, pending = []);
617
- return pending;
618
- }
619
-
620
777
  class Lookup {
621
778
  constructor() {
622
779
  this.table = new Map();
@@ -672,7 +829,7 @@ class Lookup {
672
829
  }
673
830
  }
674
831
 
675
- const Oops$5 = issues({
832
+ const Oops$3 = issues({
676
833
  NoProviderType: () => `Provider 'of' prop must be Model, typeof Model or a collection of them.`,
677
834
  NothingInContext: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`,
678
835
  BadConsumerProps: () => `Provider expects either a render function, 'get' or 'has' props.`
@@ -682,7 +839,7 @@ const useLookup = () => react.useContext(LookupContext);
682
839
  function useFromContext(Type, strict) {
683
840
  const instance = useLookup().get(Type);
684
841
  if (!instance && strict)
685
- throw Oops$5.NothingInContext(Type.name);
842
+ throw Oops$3.NothingInContext(Type.name);
686
843
  return instance;
687
844
  }
688
845
  function Consumer(props) {
@@ -693,13 +850,13 @@ function Consumer(props) {
693
850
  if (typeof callback == "function")
694
851
  callback(Control.get(!!has));
695
852
  else
696
- throw Oops$5.BadConsumerProps();
853
+ throw Oops$3.BadConsumerProps();
697
854
  return null;
698
855
  }
699
856
  function useNewContext(from, inject) {
700
857
  return react.useMemo(() => {
701
858
  if (!inject)
702
- throw Oops$5.NoProviderType();
859
+ throw Oops$3.NoProviderType();
703
860
  const context = from.push(inject);
704
861
  for (const instance of context.local)
705
862
  for (const apply of getPending(instance))
@@ -742,7 +899,7 @@ function Provider(props) {
742
899
  : render);
743
900
  }
744
901
 
745
- const Oops$4 = issues({
902
+ const Oops$2 = issues({
746
903
  StrictUpdate: (expected) => `Strict update() did ${expected ? "not " : ""}find pending updates.`,
747
904
  NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
748
905
  });
@@ -841,7 +998,7 @@ class Model {
841
998
  arg = select(this, arg);
842
999
  if (typeof arg == "boolean") {
843
1000
  if (!control.pending === arg)
844
- return Promise.reject(Oops$4.StrictUpdate(arg));
1001
+ return Promise.reject(Oops$2.StrictUpdate(arg));
845
1002
  }
846
1003
  else if (arg) {
847
1004
  control.update(arg);
@@ -862,7 +1019,7 @@ class Model {
862
1019
  else
863
1020
  callback(false);
864
1021
  else
865
- throw Oops$4.NoChaining();
1022
+ throw Oops$2.NoChaining();
866
1023
  }
867
1024
  };
868
1025
  }
@@ -943,7 +1100,7 @@ function defer(on, method) {
943
1100
  }
944
1101
 
945
1102
  const Parent = new WeakMap();
946
- const Oops$3 = issues({
1103
+ const Oops$1 = issues({
947
1104
  ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
948
1105
  UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
949
1106
  UndefinedNotAllowed: (key) => `Child property ${key} may not be undefined.`,
@@ -968,7 +1125,7 @@ function use(input, argument) {
968
1125
  let current;
969
1126
  const onUpdate = (next, initial) => {
970
1127
  if (mode === true && !initial)
971
- throw Oops$3.IsReadOnly(subject, key);
1128
+ throw Oops$1.IsReadOnly(subject, key);
972
1129
  if (next) {
973
1130
  current = next instanceof Model
974
1131
  ? next : bootstrap(next);
@@ -976,7 +1133,7 @@ function use(input, argument) {
976
1133
  manage(current);
977
1134
  }
978
1135
  else if (mode === undefined)
979
- throw Oops$3.UndefinedNotAllowed(key);
1136
+ throw Oops$1.UndefinedNotAllowed(key);
980
1137
  else
981
1138
  current = undefined;
982
1139
  if (typeof argument == "function")
@@ -988,11 +1145,11 @@ function use(input, argument) {
988
1145
  input instanceof Model ? input :
989
1146
  typeof input === "function" ? input() :
990
1147
  typeof input === "object" ? bootstrap(input) :
991
- Oops$3.BadArgument(typeof input).throw();
1148
+ Oops$1.BadArgument(typeof input).throw();
992
1149
  if (current)
993
1150
  mode = onUpdate(current, true) || mode;
994
1151
  else if (mode == true)
995
- throw Oops$3.MustBeDefined(subject, key);
1152
+ throw Oops$1.MustBeDefined(subject, key);
996
1153
  }
997
1154
  else
998
1155
  mode = false;
@@ -1007,10 +1164,10 @@ function parent(Expects, required) {
1007
1164
  const value = Parent.get(this.subject);
1008
1165
  if (!value) {
1009
1166
  if (required)
1010
- throw Oops$3.ParentRequired(expected, child);
1167
+ throw Oops$1.ParentRequired(expected, child);
1011
1168
  }
1012
1169
  else if (!(value instanceof Expects))
1013
- throw Oops$3.UnexpectedParent(expected, child, value);
1170
+ throw Oops$1.UnexpectedParent(expected, child, value);
1014
1171
  return { value };
1015
1172
  });
1016
1173
  }
@@ -1040,160 +1197,6 @@ function lazy(value) {
1040
1197
  });
1041
1198
  }
1042
1199
 
1043
- const Oops$2 = issues({
1044
- DuplicateAction: (key) => `Invoked action ${key} but one is already active.`,
1045
- BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
1046
- PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`
1047
- });
1048
- function createRef(key, cb) {
1049
- const refObjectFunction = this.setter(key, cb && createValueEffect(cb));
1050
- defineProperty(refObjectFunction, "current", {
1051
- set: refObjectFunction,
1052
- get: () => this.state[key]
1053
- });
1054
- return refObjectFunction;
1055
- }
1056
- function ref(arg) {
1057
- return apply(function ref(key) {
1058
- let value = {};
1059
- if (typeof arg == "object") {
1060
- const source = manage(arg);
1061
- for (const key in source.state)
1062
- defineLazy(value, key, createRef.bind(source, key));
1063
- }
1064
- else
1065
- value = createRef.call(this, key, arg);
1066
- return { value };
1067
- });
1068
- }
1069
- function act(task) {
1070
- return apply(function act(key) {
1071
- let pending = false;
1072
- const invoke = (...args) => {
1073
- if (pending)
1074
- return Promise.reject(Oops$2.DuplicateAction(key));
1075
- pending = true;
1076
- this.update(key);
1077
- return new Promise(res => {
1078
- res(task.apply(this.subject, args));
1079
- }).finally(() => {
1080
- pending = false;
1081
- this.update(key);
1082
- });
1083
- };
1084
- setAlias(invoke, `run ${key}`);
1085
- defineProperty(invoke, "active", {
1086
- get: () => pending
1087
- });
1088
- return {
1089
- value: invoke,
1090
- writable: false
1091
- };
1092
- });
1093
- }
1094
- function from(source, setter, getter) {
1095
- return apply(function from(key) {
1096
- const { subject } = this;
1097
- let getSource;
1098
- // Easy mistake, using a peer, will always be unresolved.
1099
- if (typeof source == "symbol")
1100
- throw Oops$2.PeerNotAllowed(subject, key);
1101
- // replace source controller in-case different
1102
- if (typeof source == "object")
1103
- getSource = () => manage(source);
1104
- // specifically an arrow function (getter factory)
1105
- else if (!source.prototype) {
1106
- setter = source.call(subject, key);
1107
- getSource = () => this;
1108
- }
1109
- // is a peer Model (constructor)
1110
- else if (Model.isTypeof(source))
1111
- getSource = pendingAccess(subject, source, key, true);
1112
- // Regular function is to ambiguous so not allowed.
1113
- else
1114
- throw Oops$2.BadComputedSource(subject, key, source);
1115
- prepare(this, key, getSource, setter, getter);
1116
- });
1117
- }
1118
-
1119
- const Oops$1 = issues({
1120
- ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
1121
- });
1122
- function pending(source, compute) {
1123
- return (source === undefined ?
1124
- suspendForValue() :
1125
- typeof source == "function" && !source.prototype ?
1126
- suspendForAsync(source) :
1127
- suspendForComputed(source, compute));
1128
- }
1129
- /**
1130
- * Get value, suspend instead if undefined.
1131
- *
1132
- * Throws suspense promise also interpretable as an error.
1133
- * React could handle it but other contexts probably not.
1134
- */
1135
- function pendingValue(via, key) {
1136
- const value = via.state[key];
1137
- if (value !== undefined)
1138
- return value;
1139
- const error = Oops$1.ValueNotReady(via.subject, key);
1140
- const promise = new Promise(resolve => {
1141
- const release = via.addListener(forKey => {
1142
- if (forKey == key)
1143
- return () => {
1144
- if (via.state[key] !== undefined) {
1145
- release();
1146
- resolve();
1147
- }
1148
- };
1149
- });
1150
- });
1151
- throw Object.assign(promise, {
1152
- toString: () => String(error),
1153
- message: error.message,
1154
- stack: error.stack
1155
- });
1156
- }
1157
- function suspendForComputed(source, compute) {
1158
- function getter(_value, key) {
1159
- return pendingValue(manage(this), key);
1160
- }
1161
- return from(source, compute, getter);
1162
- }
1163
- function suspendForValue() {
1164
- return apply(function pending(key) {
1165
- this.state[key] = undefined;
1166
- return {
1167
- set: this.setter(key),
1168
- get: () => pendingValue(this, key)
1169
- };
1170
- });
1171
- }
1172
- function suspendForAsync(source) {
1173
- return apply(function suspense(key) {
1174
- const subject = this.subject;
1175
- let waiting = true;
1176
- let value;
1177
- let error;
1178
- return () => {
1179
- if (error)
1180
- throw error;
1181
- if (!waiting)
1182
- return value;
1183
- const issue = Oops$1.ValueNotReady(subject, key);
1184
- let suspend = source
1185
- .call(subject, key)
1186
- .catch(err => error = err)
1187
- .then(out => value = out)
1188
- .finally(() => waiting = false);
1189
- throw Object.assign(suspend, {
1190
- message: issue.message,
1191
- stack: issue.stack
1192
- });
1193
- };
1194
- });
1195
- }
1196
-
1197
1200
  const Oops = issues({
1198
1201
  GlobalDoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.create() before attempting to access, or consider using ${name}.use() instead.`,
1199
1202
  GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`