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

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$8 = issues({
23
+ const Oops$9 = 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$8.BadEffectCallback();
52
+ throw Oops$9.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$8.BadEffectCallback();
68
+ throw Oops$9.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$7 = issues({
156
+ const Oops$8 = 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
  });
@@ -172,14 +172,14 @@ function prepare(parent, key, source, setter, getter) {
172
172
  }
173
173
  register.set(key, info);
174
174
  const current = getter
175
- ? () => getter.call(subject, state[key], key)
175
+ ? () => getter(parent, key)
176
176
  : () => state[key];
177
177
  function compute(initial) {
178
178
  try {
179
179
  return setter.call(sub.proxy, sub.proxy);
180
180
  }
181
181
  catch (err) {
182
- Oops$7.ComputeFailed(subject, key, !!initial).warn();
182
+ Oops$8.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$7.ComputedEarly(key).warn();
228
+ Oops$8.ComputedEarly(key).warn();
229
229
  throw e;
230
230
  }
231
231
  finally {
@@ -506,6 +506,61 @@ function child(source, name) {
506
506
  }, name || source.name);
507
507
  }
508
508
 
509
+ const Oops$7 = issues({
510
+ NonOptional: (Parent, key) => `Property ${Parent}.${key} is marked as required.`,
511
+ BadFactory: () => `Set instruction can only accept a factory or undefined.`,
512
+ FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
513
+ });
514
+ function lazy(value) {
515
+ return apply(function lazy(key) {
516
+ const source = this.subject;
517
+ source[key] = value;
518
+ defineProperty(this.state, key, {
519
+ get: () => source[key]
520
+ });
521
+ });
522
+ }
523
+ function set(factory, argument) {
524
+ return apply(function set(key) {
525
+ let onSet;
526
+ let onGet;
527
+ const required = argument === true || argument === undefined;
528
+ if (factory === undefined)
529
+ onGet = () => pendingValue(this, key);
530
+ else if (typeof factory !== "function")
531
+ throw Oops$7.BadFactory();
532
+ else {
533
+ onGet = pendingFactory(this, key, factory);
534
+ if (required)
535
+ try {
536
+ onGet();
537
+ }
538
+ catch (err) {
539
+ if (err instanceof Promise)
540
+ ;
541
+ else {
542
+ Oops$7.FactoryFailed(this.subject, key).warn();
543
+ throw err;
544
+ }
545
+ }
546
+ }
547
+ if (typeof argument == "function")
548
+ onSet = createValueEffect(argument);
549
+ else if (required)
550
+ onSet = (value) => {
551
+ if (value === undefined)
552
+ throw Oops$7.NonOptional(this.subject, key);
553
+ };
554
+ return {
555
+ set: this.setter(key, onSet),
556
+ get: onGet
557
+ };
558
+ });
559
+ }
560
+ function on(initial, onUpdate) {
561
+ return set(initial && (() => initial), onUpdate);
562
+ }
563
+
509
564
  const Oops$6 = issues({
510
565
  CantAttachGlobal: (parent, child) => `Singleton '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
511
566
  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.`
@@ -608,10 +663,13 @@ function act(task) {
608
663
  };
609
664
  });
610
665
  }
611
- function from(source, setter, getter) {
666
+ function from(source, setter, argument) {
612
667
  return apply(function from(key) {
613
668
  const { subject } = this;
614
669
  let getSource;
670
+ let getter = argument === true
671
+ ? pendingValue
672
+ : argument || undefined;
615
673
  // Easy mistake, using a peer, will always be unresolved.
616
674
  if (typeof source == "symbol")
617
675
  throw Oops$5.PeerNotAllowed(subject, key);
@@ -626,7 +684,7 @@ function from(source, setter, getter) {
626
684
  // is a peer Model (constructor)
627
685
  else if (Model.isTypeof(source))
628
686
  getSource = pendingAccess(subject, source, key, true);
629
- // Regular function is to ambiguous so not allowed.
687
+ // Regular function is too ambiguous so not allowed.
630
688
  else
631
689
  throw Oops$5.BadComputedSource(subject, key, source);
632
690
  prepare(this, key, getSource, setter, getter);
@@ -636,12 +694,14 @@ function from(source, setter, getter) {
636
694
  const Oops$4 = issues({
637
695
  ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
638
696
  });
697
+ /* deprecated - ignore coverage */
698
+ /* istanbul ignore next */
639
699
  function pending(source, compute) {
640
- return (source === undefined ?
641
- suspendForValue() :
642
- typeof source == "function" && !source.prototype ?
643
- suspendForAsync(source) :
644
- suspendForComputed(source, compute));
700
+ if (source === undefined)
701
+ return set();
702
+ if (typeof source == "function" && !source.prototype)
703
+ return set(source);
704
+ return from(source, compute, true);
645
705
  }
646
706
  /**
647
707
  * Get value, suspend instead if undefined.
@@ -655,6 +715,40 @@ function pendingValue(via, key) {
655
715
  throw suspend(via, key);
656
716
  return value;
657
717
  }
718
+ function pendingFactory(via, key, fn) {
719
+ const { subject, state } = via;
720
+ let waiting;
721
+ let error;
722
+ return () => {
723
+ if (waiting)
724
+ throw waiting;
725
+ if (error)
726
+ throw error;
727
+ if (key in state)
728
+ return state[key];
729
+ let output;
730
+ try {
731
+ output = fn.call(subject, key, subject);
732
+ }
733
+ catch (err) {
734
+ throw error = err;
735
+ }
736
+ if (output instanceof Promise) {
737
+ const issue = Oops$4.ValueNotReady(subject, key);
738
+ output
739
+ .catch(err => error = err)
740
+ .then(out => state[key] = out)
741
+ .finally(() => waiting = undefined);
742
+ throw waiting = Object.assign(output, {
743
+ message: issue.message,
744
+ stack: issue.stack
745
+ });
746
+ }
747
+ else {
748
+ return state[key] = output;
749
+ }
750
+ };
751
+ }
658
752
  function suspend(source, key) {
659
753
  const error = Oops$4.ValueNotReady(source.subject, key);
660
754
  const promise = new Promise(resolve => {
@@ -674,45 +768,6 @@ function suspend(source, key) {
674
768
  message: error.message,
675
769
  stack: error.stack
676
770
  });
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
771
  }
717
772
 
718
773
  function use$1(init) {
@@ -736,12 +791,11 @@ function useWatcher(target, focus, expected) {
736
791
  const sub = new Subscriber(target, () => refresh);
737
792
  if (focus) {
738
793
  const source = sub.proxy;
739
- const key = keys(sub.parent, focus)[0];
740
794
  defineProperty(sub, "proxy", {
741
795
  get() {
742
- const value = source[key];
796
+ const value = source[focus];
743
797
  if (value === undefined && expected)
744
- throw suspend(sub.parent, key);
798
+ throw suspend(sub.parent, focus);
745
799
  return value;
746
800
  }
747
801
  });
@@ -751,6 +805,39 @@ function useWatcher(target, focus, expected) {
751
805
  useLayoutEffect(() => hook.commit(), []);
752
806
  return hook.proxy;
753
807
  }
808
+ function useComputed(target, compute, expected) {
809
+ const hook = use$1(refresh => {
810
+ const sub = new Subscriber(target, () => update);
811
+ const { proxy } = sub;
812
+ let value;
813
+ let retry;
814
+ const update = () => {
815
+ const next = compute.call(proxy, proxy);
816
+ if (value == next)
817
+ return;
818
+ value = next;
819
+ if (retry) {
820
+ retry();
821
+ retry = undefined;
822
+ }
823
+ else
824
+ refresh();
825
+ };
826
+ const access = () => {
827
+ if (value === undefined && expected)
828
+ throw new Promise(res => {
829
+ retry = res;
830
+ });
831
+ return value;
832
+ };
833
+ value = compute.call(proxy, proxy);
834
+ sub.commit();
835
+ defineProperty(sub, "proxy", { get: access });
836
+ return sub;
837
+ });
838
+ useLayoutEffect(() => hook.release, []);
839
+ return hook.proxy;
840
+ }
754
841
  function useModel(Type, callback) {
755
842
  const hook = use$1(refresh => {
756
843
  const instance = new Type();
@@ -914,14 +1001,14 @@ class Model {
914
1001
  });
915
1002
  }
916
1003
  tap(path, expect) {
1004
+ if (typeof path == "function")
1005
+ return useComputed(this, path, expect);
917
1006
  const proxy = useWatcher(this, path, expect);
918
1007
  this.update("willRender", true);
919
1008
  return proxy;
920
1009
  }
921
1010
  tag(id) {
922
- const hook = use$1(refresh => {
923
- return new Subscriber(this, () => refresh);
924
- });
1011
+ const hook = use$1(refresh => (new Subscriber(this, () => refresh)));
925
1012
  useElementLifecycle(hook, id || 0);
926
1013
  return hook.proxy;
927
1014
  }
@@ -969,12 +1056,10 @@ class Model {
969
1056
  invoke();
970
1057
  return this.on(select, invoke, true);
971
1058
  }
972
- else {
973
- const sub = new Subscriber(control, () => invoke);
974
- target = sub.proxy;
975
- invoke();
976
- return sub.commit();
977
- }
1059
+ const sub = new Subscriber(control, () => invoke);
1060
+ target = sub.proxy;
1061
+ invoke();
1062
+ return sub.commit();
978
1063
  }
979
1064
  import(from, subset) {
980
1065
  for (const key of keys(manage(this), subset))
@@ -1069,7 +1154,9 @@ class Model {
1069
1154
  return instance;
1070
1155
  }
1071
1156
  static meta(path) {
1072
- return useWatcher(this, path);
1157
+ return typeof path == "function"
1158
+ ? useComputed(this, path)
1159
+ : useWatcher(this, path);
1073
1160
  }
1074
1161
  static isTypeof(maybe) {
1075
1162
  return (typeof maybe == "function" &&
@@ -1168,31 +1255,6 @@ function parent(Expects, required) {
1168
1255
  });
1169
1256
  }
1170
1257
 
1171
- function on(initial, cb) {
1172
- return apply(function on(key) {
1173
- this.manage(key, initial, cb && createValueEffect(cb));
1174
- });
1175
- }
1176
- function memo(factory, defer) {
1177
- return apply(function memo(key) {
1178
- const source = this.subject;
1179
- const get = () => factory.call(source);
1180
- if (defer)
1181
- defineLazy(source, key, get);
1182
- else
1183
- define(source, key, get());
1184
- });
1185
- }
1186
- function lazy(value) {
1187
- return apply(function lazy(key) {
1188
- const source = this.subject;
1189
- source[key] = value;
1190
- defineProperty(this.state, key, {
1191
- get: () => source[key]
1192
- });
1193
- });
1194
- }
1195
-
1196
1258
  const Oops = issues({
1197
1259
  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.`,
1198
1260
  GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
@@ -1234,5 +1296,5 @@ class Singleton extends Model {
1234
1296
  }
1235
1297
  }
1236
1298
 
1237
- export { Consumer, Model, Provider, Singleton, act, apply, child, Model as default, from, lazy, memo, on, parent, pending, ref, tap, use };
1299
+ export { Consumer, Model, Provider, Singleton, act, apply, child, Model as default, from, lazy, set as memo, on, parent, pending, ref, set, tap, use };
1238
1300
  //# sourceMappingURL=index.esm.js.map