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

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,214 @@ 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.`
511
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
+ setAlias(invoke, `run ${key}`);
601
+ defineProperty(invoke, "active", {
602
+ get: () => pending
603
+ });
604
+ return {
605
+ value: invoke,
606
+ writable: false
607
+ };
608
+ });
609
+ }
610
+ function from(source, setter, getter) {
611
+ return apply(function from(key) {
612
+ const { subject } = this;
613
+ let getSource;
614
+ // Easy mistake, using a peer, will always be unresolved.
615
+ if (typeof source == "symbol")
616
+ throw Oops$5.PeerNotAllowed(subject, key);
617
+ // replace source controller in-case different
618
+ if (typeof source == "object")
619
+ getSource = () => manage(source);
620
+ // specifically an arrow function (getter factory)
621
+ else if (!source.prototype) {
622
+ setter = source.call(subject, key);
623
+ getSource = () => this;
624
+ }
625
+ // is a peer Model (constructor)
626
+ else if (Model.isTypeof(source))
627
+ getSource = pendingAccess(subject, source, key, true);
628
+ // Regular function is to ambiguous so not allowed.
629
+ else
630
+ throw Oops$5.BadComputedSource(subject, key, source);
631
+ prepare(this, key, getSource, setter, getter);
632
+ });
633
+ }
634
+
635
+ const Oops$4 = issues({
636
+ ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
637
+ });
638
+ function pending(source, compute) {
639
+ return (source === undefined ?
640
+ suspendForValue() :
641
+ typeof source == "function" && !source.prototype ?
642
+ suspendForAsync(source) :
643
+ suspendForComputed(source, compute));
644
+ }
645
+ /**
646
+ * Get value, suspend instead if undefined.
647
+ *
648
+ * Throws suspense promise also interpretable as an error.
649
+ * React could handle it but other contexts probably not.
650
+ */
651
+ function pendingValue(via, key) {
652
+ const value = via.state[key];
653
+ if (value === undefined)
654
+ throw suspend(via, key);
655
+ return value;
656
+ }
657
+ function suspend(source, key) {
658
+ const error = Oops$4.ValueNotReady(source.subject, key);
659
+ const promise = new Promise(resolve => {
660
+ const release = source.addListener(forKey => {
661
+ if (forKey == key)
662
+ return () => {
663
+ if (source.state[key] !== undefined) {
664
+ release();
665
+ resolve();
666
+ }
667
+ };
668
+ });
669
+ });
670
+ return Object.assign(promise, {
671
+ toString: () => String(error),
672
+ name: "Suspense",
673
+ message: error.message,
674
+ stack: error.stack
675
+ });
676
+ }
677
+ function suspendForComputed(source, compute) {
678
+ function getter(_value, key) {
679
+ return pendingValue(manage(this), key);
680
+ }
681
+ return from(source, compute, getter);
682
+ }
683
+ function suspendForValue() {
684
+ return apply(function pending(key) {
685
+ this.state[key] = undefined;
686
+ return {
687
+ set: this.setter(key),
688
+ get: () => pendingValue(this, key)
689
+ };
690
+ });
691
+ }
692
+ function suspendForAsync(source) {
693
+ return apply(function suspense(key) {
694
+ const subject = this.subject;
695
+ let waiting = true;
696
+ let value;
697
+ let error;
698
+ return () => {
699
+ if (error)
700
+ throw error;
701
+ if (!waiting)
702
+ return value;
703
+ const issue = Oops$4.ValueNotReady(subject, key);
704
+ let suspend = source
705
+ .call(subject, key)
706
+ .catch(err => error = err)
707
+ .then(out => value = out)
708
+ .finally(() => waiting = false);
709
+ throw Object.assign(suspend, {
710
+ message: issue.message,
711
+ stack: issue.stack
712
+ });
713
+ };
714
+ });
715
+ }
716
+
512
717
  function use$1(init) {
513
718
  const [state, update] = useState(() => [
514
719
  init(() => update(state.concat()))
@@ -529,13 +734,14 @@ function useWatcher(target, focus, expected) {
529
734
  const hook = use$1(refresh => {
530
735
  const sub = new Subscriber(target, () => refresh);
531
736
  if (focus) {
532
- const src = sub.proxy;
737
+ const source = sub.proxy;
533
738
  const key = keys(sub.parent, focus)[0];
534
739
  defineProperty(sub, "proxy", {
535
740
  get() {
536
- if (src[key] === undefined && expected)
537
- throw Oops$7.HasPropertyUndefined(target, key);
538
- return src[key];
741
+ const value = source[key];
742
+ if (value === undefined && expected)
743
+ throw suspend(sub.parent, key);
744
+ return value;
539
745
  }
540
746
  });
541
747
  }
@@ -563,56 +769,6 @@ function useModel(Type, callback) {
563
769
  return hook.proxy;
564
770
  }
565
771
 
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
772
  class Lookup {
617
773
  constructor() {
618
774
  this.table = new Map();
@@ -668,7 +824,7 @@ class Lookup {
668
824
  }
669
825
  }
670
826
 
671
- const Oops$5 = issues({
827
+ const Oops$3 = issues({
672
828
  NoProviderType: () => `Provider 'of' prop must be Model, typeof Model or a collection of them.`,
673
829
  NothingInContext: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`,
674
830
  BadConsumerProps: () => `Provider expects either a render function, 'get' or 'has' props.`
@@ -678,7 +834,7 @@ const useLookup = () => useContext(LookupContext);
678
834
  function useFromContext(Type, strict) {
679
835
  const instance = useLookup().get(Type);
680
836
  if (!instance && strict)
681
- throw Oops$5.NothingInContext(Type.name);
837
+ throw Oops$3.NothingInContext(Type.name);
682
838
  return instance;
683
839
  }
684
840
  function Consumer(props) {
@@ -689,13 +845,13 @@ function Consumer(props) {
689
845
  if (typeof callback == "function")
690
846
  callback(Control.get(!!has));
691
847
  else
692
- throw Oops$5.BadConsumerProps();
848
+ throw Oops$3.BadConsumerProps();
693
849
  return null;
694
850
  }
695
851
  function useNewContext(from, inject) {
696
852
  return useMemo(() => {
697
853
  if (!inject)
698
- throw Oops$5.NoProviderType();
854
+ throw Oops$3.NoProviderType();
699
855
  const context = from.push(inject);
700
856
  for (const instance of context.local)
701
857
  for (const apply of getPending(instance))
@@ -738,7 +894,7 @@ function Provider(props) {
738
894
  : render);
739
895
  }
740
896
 
741
- const Oops$4 = issues({
897
+ const Oops$2 = issues({
742
898
  StrictUpdate: (expected) => `Strict update() did ${expected ? "not " : ""}find pending updates.`,
743
899
  NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
744
900
  });
@@ -837,7 +993,7 @@ class Model {
837
993
  arg = select(this, arg);
838
994
  if (typeof arg == "boolean") {
839
995
  if (!control.pending === arg)
840
- return Promise.reject(Oops$4.StrictUpdate(arg));
996
+ return Promise.reject(Oops$2.StrictUpdate(arg));
841
997
  }
842
998
  else if (arg) {
843
999
  control.update(arg);
@@ -858,7 +1014,7 @@ class Model {
858
1014
  else
859
1015
  callback(false);
860
1016
  else
861
- throw Oops$4.NoChaining();
1017
+ throw Oops$2.NoChaining();
862
1018
  }
863
1019
  };
864
1020
  }
@@ -939,7 +1095,7 @@ function defer(on, method) {
939
1095
  }
940
1096
 
941
1097
  const Parent = new WeakMap();
942
- const Oops$3 = issues({
1098
+ const Oops$1 = issues({
943
1099
  ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
944
1100
  UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
945
1101
  UndefinedNotAllowed: (key) => `Child property ${key} may not be undefined.`,
@@ -964,7 +1120,7 @@ function use(input, argument) {
964
1120
  let current;
965
1121
  const onUpdate = (next, initial) => {
966
1122
  if (mode === true && !initial)
967
- throw Oops$3.IsReadOnly(subject, key);
1123
+ throw Oops$1.IsReadOnly(subject, key);
968
1124
  if (next) {
969
1125
  current = next instanceof Model
970
1126
  ? next : bootstrap(next);
@@ -972,7 +1128,7 @@ function use(input, argument) {
972
1128
  manage(current);
973
1129
  }
974
1130
  else if (mode === undefined)
975
- throw Oops$3.UndefinedNotAllowed(key);
1131
+ throw Oops$1.UndefinedNotAllowed(key);
976
1132
  else
977
1133
  current = undefined;
978
1134
  if (typeof argument == "function")
@@ -984,11 +1140,11 @@ function use(input, argument) {
984
1140
  input instanceof Model ? input :
985
1141
  typeof input === "function" ? input() :
986
1142
  typeof input === "object" ? bootstrap(input) :
987
- Oops$3.BadArgument(typeof input).throw();
1143
+ Oops$1.BadArgument(typeof input).throw();
988
1144
  if (current)
989
1145
  mode = onUpdate(current, true) || mode;
990
1146
  else if (mode == true)
991
- throw Oops$3.MustBeDefined(subject, key);
1147
+ throw Oops$1.MustBeDefined(subject, key);
992
1148
  }
993
1149
  else
994
1150
  mode = false;
@@ -1003,10 +1159,10 @@ function parent(Expects, required) {
1003
1159
  const value = Parent.get(this.subject);
1004
1160
  if (!value) {
1005
1161
  if (required)
1006
- throw Oops$3.ParentRequired(expected, child);
1162
+ throw Oops$1.ParentRequired(expected, child);
1007
1163
  }
1008
1164
  else if (!(value instanceof Expects))
1009
- throw Oops$3.UnexpectedParent(expected, child, value);
1165
+ throw Oops$1.UnexpectedParent(expected, child, value);
1010
1166
  return { value };
1011
1167
  });
1012
1168
  }
@@ -1036,160 +1192,6 @@ function lazy(value) {
1036
1192
  });
1037
1193
  }
1038
1194
 
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
1195
  const Oops = issues({
1194
1196
  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
1197
  GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`