@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 +233 -230
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +233 -230
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -24,7 +24,7 @@ function issues(register) {
|
|
|
24
24
|
return Library;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const Oops$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
514
|
-
|
|
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
|
|
742
|
+
const source = sub.proxy;
|
|
537
743
|
const key = keys(sub.parent, focus)[0];
|
|
538
744
|
defineProperty(sub, "proxy", {
|
|
539
745
|
get() {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
1167
|
+
throw Oops$1.ParentRequired(expected, child);
|
|
1011
1168
|
}
|
|
1012
1169
|
else if (!(value instanceof Expects))
|
|
1013
|
-
throw Oops$
|
|
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.`
|