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