@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 +154 -92
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +155 -92
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/types/instructions.d.ts +92 -6
- package/types/model.d.ts +4 -4
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$9 = 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$9.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$9.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$8 = 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
|
});
|
|
@@ -176,14 +176,14 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
176
176
|
}
|
|
177
177
|
register.set(key, info);
|
|
178
178
|
const current = getter
|
|
179
|
-
? () => getter
|
|
179
|
+
? () => getter(parent, key)
|
|
180
180
|
: () => state[key];
|
|
181
181
|
function compute(initial) {
|
|
182
182
|
try {
|
|
183
183
|
return setter.call(sub.proxy, sub.proxy);
|
|
184
184
|
}
|
|
185
185
|
catch (err) {
|
|
186
|
-
Oops$
|
|
186
|
+
Oops$8.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$8.ComputedEarly(key).warn();
|
|
233
233
|
throw e;
|
|
234
234
|
}
|
|
235
235
|
finally {
|
|
@@ -510,6 +510,61 @@ function child(source, name) {
|
|
|
510
510
|
}, name || source.name);
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
+
const Oops$7 = issues({
|
|
514
|
+
NonOptional: (Parent, key) => `Property ${Parent}.${key} is marked as required.`,
|
|
515
|
+
BadFactory: () => `Set instruction can only accept a factory or undefined.`,
|
|
516
|
+
FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
|
|
517
|
+
});
|
|
518
|
+
function lazy(value) {
|
|
519
|
+
return apply(function lazy(key) {
|
|
520
|
+
const source = this.subject;
|
|
521
|
+
source[key] = value;
|
|
522
|
+
defineProperty(this.state, key, {
|
|
523
|
+
get: () => source[key]
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
function set(factory, argument) {
|
|
528
|
+
return apply(function set(key) {
|
|
529
|
+
let onSet;
|
|
530
|
+
let onGet;
|
|
531
|
+
const required = argument === true || argument === undefined;
|
|
532
|
+
if (factory === undefined)
|
|
533
|
+
onGet = () => pendingValue(this, key);
|
|
534
|
+
else if (typeof factory !== "function")
|
|
535
|
+
throw Oops$7.BadFactory();
|
|
536
|
+
else {
|
|
537
|
+
onGet = pendingFactory(this, key, factory);
|
|
538
|
+
if (required)
|
|
539
|
+
try {
|
|
540
|
+
onGet();
|
|
541
|
+
}
|
|
542
|
+
catch (err) {
|
|
543
|
+
if (err instanceof Promise)
|
|
544
|
+
;
|
|
545
|
+
else {
|
|
546
|
+
Oops$7.FactoryFailed(this.subject, key).warn();
|
|
547
|
+
throw err;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (typeof argument == "function")
|
|
552
|
+
onSet = createValueEffect(argument);
|
|
553
|
+
else if (required)
|
|
554
|
+
onSet = (value) => {
|
|
555
|
+
if (value === undefined)
|
|
556
|
+
throw Oops$7.NonOptional(this.subject, key);
|
|
557
|
+
};
|
|
558
|
+
return {
|
|
559
|
+
set: this.setter(key, onSet),
|
|
560
|
+
get: onGet
|
|
561
|
+
};
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
function on(initial, onUpdate) {
|
|
565
|
+
return set(initial && (() => initial), onUpdate);
|
|
566
|
+
}
|
|
567
|
+
|
|
513
568
|
const Oops$6 = issues({
|
|
514
569
|
CantAttachGlobal: (parent, child) => `Singleton '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
|
|
515
570
|
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.`
|
|
@@ -612,10 +667,13 @@ function act(task) {
|
|
|
612
667
|
};
|
|
613
668
|
});
|
|
614
669
|
}
|
|
615
|
-
function from(source, setter,
|
|
670
|
+
function from(source, setter, argument) {
|
|
616
671
|
return apply(function from(key) {
|
|
617
672
|
const { subject } = this;
|
|
618
673
|
let getSource;
|
|
674
|
+
let getter = argument === true
|
|
675
|
+
? pendingValue
|
|
676
|
+
: argument || undefined;
|
|
619
677
|
// Easy mistake, using a peer, will always be unresolved.
|
|
620
678
|
if (typeof source == "symbol")
|
|
621
679
|
throw Oops$5.PeerNotAllowed(subject, key);
|
|
@@ -630,7 +688,7 @@ function from(source, setter, getter) {
|
|
|
630
688
|
// is a peer Model (constructor)
|
|
631
689
|
else if (Model.isTypeof(source))
|
|
632
690
|
getSource = pendingAccess(subject, source, key, true);
|
|
633
|
-
// Regular function is
|
|
691
|
+
// Regular function is too ambiguous so not allowed.
|
|
634
692
|
else
|
|
635
693
|
throw Oops$5.BadComputedSource(subject, key, source);
|
|
636
694
|
prepare(this, key, getSource, setter, getter);
|
|
@@ -640,12 +698,14 @@ function from(source, setter, getter) {
|
|
|
640
698
|
const Oops$4 = issues({
|
|
641
699
|
ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
642
700
|
});
|
|
701
|
+
/* deprecated - ignore coverage */
|
|
702
|
+
/* istanbul ignore next */
|
|
643
703
|
function pending(source, compute) {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
704
|
+
if (source === undefined)
|
|
705
|
+
return set();
|
|
706
|
+
if (typeof source == "function" && !source.prototype)
|
|
707
|
+
return set(source);
|
|
708
|
+
return from(source, compute, true);
|
|
649
709
|
}
|
|
650
710
|
/**
|
|
651
711
|
* Get value, suspend instead if undefined.
|
|
@@ -659,6 +719,40 @@ function pendingValue(via, key) {
|
|
|
659
719
|
throw suspend(via, key);
|
|
660
720
|
return value;
|
|
661
721
|
}
|
|
722
|
+
function pendingFactory(via, key, fn) {
|
|
723
|
+
const { subject, state } = via;
|
|
724
|
+
let waiting;
|
|
725
|
+
let error;
|
|
726
|
+
return () => {
|
|
727
|
+
if (waiting)
|
|
728
|
+
throw waiting;
|
|
729
|
+
if (error)
|
|
730
|
+
throw error;
|
|
731
|
+
if (key in state)
|
|
732
|
+
return state[key];
|
|
733
|
+
let output;
|
|
734
|
+
try {
|
|
735
|
+
output = fn.call(subject, key, subject);
|
|
736
|
+
}
|
|
737
|
+
catch (err) {
|
|
738
|
+
throw error = err;
|
|
739
|
+
}
|
|
740
|
+
if (output instanceof Promise) {
|
|
741
|
+
const issue = Oops$4.ValueNotReady(subject, key);
|
|
742
|
+
output
|
|
743
|
+
.catch(err => error = err)
|
|
744
|
+
.then(out => state[key] = out)
|
|
745
|
+
.finally(() => waiting = undefined);
|
|
746
|
+
throw waiting = Object.assign(output, {
|
|
747
|
+
message: issue.message,
|
|
748
|
+
stack: issue.stack
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
return state[key] = output;
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
}
|
|
662
756
|
function suspend(source, key) {
|
|
663
757
|
const error = Oops$4.ValueNotReady(source.subject, key);
|
|
664
758
|
const promise = new Promise(resolve => {
|
|
@@ -678,45 +772,6 @@ function suspend(source, key) {
|
|
|
678
772
|
message: error.message,
|
|
679
773
|
stack: error.stack
|
|
680
774
|
});
|
|
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
775
|
}
|
|
721
776
|
|
|
722
777
|
function use$1(init) {
|
|
@@ -740,12 +795,11 @@ function useWatcher(target, focus, expected) {
|
|
|
740
795
|
const sub = new Subscriber(target, () => refresh);
|
|
741
796
|
if (focus) {
|
|
742
797
|
const source = sub.proxy;
|
|
743
|
-
const key = keys(sub.parent, focus)[0];
|
|
744
798
|
defineProperty(sub, "proxy", {
|
|
745
799
|
get() {
|
|
746
|
-
const value = source[
|
|
800
|
+
const value = source[focus];
|
|
747
801
|
if (value === undefined && expected)
|
|
748
|
-
throw suspend(sub.parent,
|
|
802
|
+
throw suspend(sub.parent, focus);
|
|
749
803
|
return value;
|
|
750
804
|
}
|
|
751
805
|
});
|
|
@@ -755,6 +809,39 @@ function useWatcher(target, focus, expected) {
|
|
|
755
809
|
react.useLayoutEffect(() => hook.commit(), []);
|
|
756
810
|
return hook.proxy;
|
|
757
811
|
}
|
|
812
|
+
function useComputed(target, compute, expected) {
|
|
813
|
+
const hook = use$1(refresh => {
|
|
814
|
+
const sub = new Subscriber(target, () => update);
|
|
815
|
+
const { proxy } = sub;
|
|
816
|
+
let value;
|
|
817
|
+
let retry;
|
|
818
|
+
const update = () => {
|
|
819
|
+
const next = compute.call(proxy, proxy);
|
|
820
|
+
if (value == next)
|
|
821
|
+
return;
|
|
822
|
+
value = next;
|
|
823
|
+
if (retry) {
|
|
824
|
+
retry();
|
|
825
|
+
retry = undefined;
|
|
826
|
+
}
|
|
827
|
+
else
|
|
828
|
+
refresh();
|
|
829
|
+
};
|
|
830
|
+
const access = () => {
|
|
831
|
+
if (value === undefined && expected)
|
|
832
|
+
throw new Promise(res => {
|
|
833
|
+
retry = res;
|
|
834
|
+
});
|
|
835
|
+
return value;
|
|
836
|
+
};
|
|
837
|
+
value = compute.call(proxy, proxy);
|
|
838
|
+
sub.commit();
|
|
839
|
+
defineProperty(sub, "proxy", { get: access });
|
|
840
|
+
return sub;
|
|
841
|
+
});
|
|
842
|
+
react.useLayoutEffect(() => hook.release, []);
|
|
843
|
+
return hook.proxy;
|
|
844
|
+
}
|
|
758
845
|
function useModel(Type, callback) {
|
|
759
846
|
const hook = use$1(refresh => {
|
|
760
847
|
const instance = new Type();
|
|
@@ -918,14 +1005,14 @@ class Model {
|
|
|
918
1005
|
});
|
|
919
1006
|
}
|
|
920
1007
|
tap(path, expect) {
|
|
1008
|
+
if (typeof path == "function")
|
|
1009
|
+
return useComputed(this, path, expect);
|
|
921
1010
|
const proxy = useWatcher(this, path, expect);
|
|
922
1011
|
this.update("willRender", true);
|
|
923
1012
|
return proxy;
|
|
924
1013
|
}
|
|
925
1014
|
tag(id) {
|
|
926
|
-
const hook = use$1(refresh =>
|
|
927
|
-
return new Subscriber(this, () => refresh);
|
|
928
|
-
});
|
|
1015
|
+
const hook = use$1(refresh => (new Subscriber(this, () => refresh)));
|
|
929
1016
|
useElementLifecycle(hook, id || 0);
|
|
930
1017
|
return hook.proxy;
|
|
931
1018
|
}
|
|
@@ -973,12 +1060,10 @@ class Model {
|
|
|
973
1060
|
invoke();
|
|
974
1061
|
return this.on(select, invoke, true);
|
|
975
1062
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
return sub.commit();
|
|
981
|
-
}
|
|
1063
|
+
const sub = new Subscriber(control, () => invoke);
|
|
1064
|
+
target = sub.proxy;
|
|
1065
|
+
invoke();
|
|
1066
|
+
return sub.commit();
|
|
982
1067
|
}
|
|
983
1068
|
import(from, subset) {
|
|
984
1069
|
for (const key of keys(manage(this), subset))
|
|
@@ -1073,7 +1158,9 @@ class Model {
|
|
|
1073
1158
|
return instance;
|
|
1074
1159
|
}
|
|
1075
1160
|
static meta(path) {
|
|
1076
|
-
return
|
|
1161
|
+
return typeof path == "function"
|
|
1162
|
+
? useComputed(this, path)
|
|
1163
|
+
: useWatcher(this, path);
|
|
1077
1164
|
}
|
|
1078
1165
|
static isTypeof(maybe) {
|
|
1079
1166
|
return (typeof maybe == "function" &&
|
|
@@ -1172,31 +1259,6 @@ function parent(Expects, required) {
|
|
|
1172
1259
|
});
|
|
1173
1260
|
}
|
|
1174
1261
|
|
|
1175
|
-
function on(initial, cb) {
|
|
1176
|
-
return apply(function on(key) {
|
|
1177
|
-
this.manage(key, initial, cb && createValueEffect(cb));
|
|
1178
|
-
});
|
|
1179
|
-
}
|
|
1180
|
-
function memo(factory, defer) {
|
|
1181
|
-
return apply(function memo(key) {
|
|
1182
|
-
const source = this.subject;
|
|
1183
|
-
const get = () => factory.call(source);
|
|
1184
|
-
if (defer)
|
|
1185
|
-
defineLazy(source, key, get);
|
|
1186
|
-
else
|
|
1187
|
-
define(source, key, get());
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
function lazy(value) {
|
|
1191
|
-
return apply(function lazy(key) {
|
|
1192
|
-
const source = this.subject;
|
|
1193
|
-
source[key] = value;
|
|
1194
|
-
defineProperty(this.state, key, {
|
|
1195
|
-
get: () => source[key]
|
|
1196
|
-
});
|
|
1197
|
-
});
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
1262
|
const Oops = issues({
|
|
1201
1263
|
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.`,
|
|
1202
1264
|
GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
|
|
@@ -1248,11 +1310,12 @@ exports.child = child;
|
|
|
1248
1310
|
exports["default"] = Model;
|
|
1249
1311
|
exports.from = from;
|
|
1250
1312
|
exports.lazy = lazy;
|
|
1251
|
-
exports.memo =
|
|
1313
|
+
exports.memo = set;
|
|
1252
1314
|
exports.on = on;
|
|
1253
1315
|
exports.parent = parent;
|
|
1254
1316
|
exports.pending = pending;
|
|
1255
1317
|
exports.ref = ref;
|
|
1318
|
+
exports.set = set;
|
|
1256
1319
|
exports.tap = tap;
|
|
1257
1320
|
exports.use = use;
|
|
1258
1321
|
//# sourceMappingURL=index.js.map
|