@expressive/mvc 0.15.1 → 0.16.0
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.d.ts +16 -8
- package/lib/index.esm.js +36 -20
- package/lib/index.js +36 -20
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -17,13 +17,14 @@ declare namespace Subscriber {
|
|
|
17
17
|
declare class Subscriber<T extends {} = any> {
|
|
18
18
|
parent: Control<T>;
|
|
19
19
|
onUpdate: Subscriber.OnEvent;
|
|
20
|
+
suspend?: boolean | undefined;
|
|
20
21
|
proxy: T;
|
|
21
22
|
release: Callback;
|
|
22
23
|
latest?: Model.Event<T>[];
|
|
23
24
|
active: boolean;
|
|
24
25
|
dependant: Set<Listener>;
|
|
25
26
|
watch: Map<any, boolean | (() => true | void)>;
|
|
26
|
-
constructor(parent: Control<T>, onUpdate: Subscriber.OnEvent);
|
|
27
|
+
constructor(parent: Control<T>, onUpdate: Subscriber.OnEvent, suspend?: boolean | undefined);
|
|
27
28
|
get using(): Model.Key<T>[];
|
|
28
29
|
add(key: any, value?: boolean | Callback): void;
|
|
29
30
|
commit(): () => void;
|
|
@@ -62,7 +63,7 @@ declare namespace Model {
|
|
|
62
63
|
/** Including but not limited to T. */
|
|
63
64
|
type Extends<T> = T | (string & Record<never, never>);
|
|
64
65
|
/** Any typeof Model, using class constructor as the reference. */
|
|
65
|
-
export type Type<T extends Model = Model> =
|
|
66
|
+
export type Type<T extends Model = Model> = abstract new (...args: any[]) => T;
|
|
66
67
|
/** A typeof Model, specifically one which may be created without arguments. */
|
|
67
68
|
export type New<T extends Model = Model> = (new () => T) & typeof Model;
|
|
68
69
|
export type Effect<T> = (this: T, argument: T) => Callback | Promise<any> | void;
|
|
@@ -474,13 +475,16 @@ declare class MVC extends Model {
|
|
|
474
475
|
* **React Hook** - Fetch and subscribe to instance of this controller within ambient component.
|
|
475
476
|
*/
|
|
476
477
|
static tap<T extends MVC>(this: Model.Type<T>): T;
|
|
477
|
-
static tap<T extends MVC,
|
|
478
|
-
static tap<T extends MVC,
|
|
479
|
-
static tap<T extends MVC, R>(this: Model.Type<T>,
|
|
480
|
-
static tap<T extends MVC, R>(this: Model.Type<T>, connect: MVC.TapCallback<T, (() => R) | null>): NoVoid<R> | null;
|
|
478
|
+
static tap<T extends MVC, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: MVC.TapCallback<T, R | (() => R)>, expect?: boolean): R;
|
|
479
|
+
static tap<T extends MVC, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: MVC.TapCallback<T, Promise<R> | (() => R) | null>, expect?: boolean): R | null;
|
|
480
|
+
static tap<T extends MVC, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: MVC.TapCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
|
481
481
|
static tap<T extends MVC, R>(this: Model.Type<T>, compute: MVC.TapCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
|
482
482
|
static tap<T extends MVC, R>(this: Model.Type<T>, compute: MVC.TapCallback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
|
|
483
483
|
static tap<T extends MVC, R>(this: Model.Type<T>, compute: MVC.TapCallback<T, R>, expect?: boolean): NoVoid<R>;
|
|
484
|
+
static tap<T extends MVC, R>(this: Model.Type<T>, init: MVC.TapCallback<T, () => R>): NoVoid<R>;
|
|
485
|
+
static tap<T extends MVC, R>(this: Model.Type<T>, init: MVC.TapCallback<T, (() => R) | null>): NoVoid<R> | null;
|
|
486
|
+
static tap<T extends MVC, K extends Model.Key<T>>(this: Model.Type<T>, key: K, expect: true): Exclude<T[K], undefined>;
|
|
487
|
+
static tap<T extends MVC, K extends Model.Key<T>>(this: Model.Type<T>, key: K, expect?: boolean): NoVoid<T[K]>;
|
|
484
488
|
static use<I extends MVC>(this: Model.Type<I>, watch: Model.Key<I>[], callback?: (instance: I) => void): I;
|
|
485
489
|
static use<I extends MVC>(this: Model.Type<I>, callback?: (instance: I) => void): I;
|
|
486
490
|
static use<I extends MVC>(this: Model.Type<I>, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
|
|
@@ -505,8 +509,12 @@ declare namespace useTap {
|
|
|
505
509
|
type Callback<T extends Model, R> = (this: T, model: T, update: MVC.ForceUpdate) => R;
|
|
506
510
|
}
|
|
507
511
|
declare function useTap<T extends Model>(source: useTap.Source<T>): T;
|
|
508
|
-
declare function useTap<T extends Model
|
|
509
|
-
|
|
512
|
+
declare function useTap<T extends Model>(source: useTap.Source<T>, expect: true): {
|
|
513
|
+
[P in Model.Key<T>]: Exclude<T[P], undefined>;
|
|
514
|
+
};
|
|
515
|
+
declare function useTap<T extends Model>(source: useTap.Source<T>, expect?: boolean): {
|
|
516
|
+
[P in Model.Key<T>]: T[P] | undefined;
|
|
517
|
+
};
|
|
510
518
|
declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: useTap.Callback<T, () => R>): NoVoid<R>;
|
|
511
519
|
declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: useTap.Callback<T, (() => R) | null>): NoVoid<R> | null;
|
|
512
520
|
declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: useTap.Callback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
package/lib/index.esm.js
CHANGED
|
@@ -314,9 +314,10 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
314
314
|
|
|
315
315
|
const REGISTER$1 = new WeakMap();
|
|
316
316
|
class Subscriber {
|
|
317
|
-
constructor(parent, onUpdate) {
|
|
317
|
+
constructor(parent, onUpdate, suspend) {
|
|
318
318
|
this.parent = parent;
|
|
319
319
|
this.onUpdate = onUpdate;
|
|
320
|
+
this.suspend = suspend;
|
|
320
321
|
this.active = false;
|
|
321
322
|
this.dependant = new Set();
|
|
322
323
|
this.watch = new Map();
|
|
@@ -506,9 +507,13 @@ class Control {
|
|
|
506
507
|
set: this.ref(key),
|
|
507
508
|
get() {
|
|
508
509
|
const sub = subscriber(this);
|
|
509
|
-
|
|
510
|
+
const value = state.get(key);
|
|
511
|
+
if (sub) {
|
|
510
512
|
sub.add(key);
|
|
511
|
-
|
|
513
|
+
if (value === undefined && sub.suspend)
|
|
514
|
+
throw suspend(this, key);
|
|
515
|
+
}
|
|
516
|
+
return value;
|
|
512
517
|
}
|
|
513
518
|
});
|
|
514
519
|
}
|
|
@@ -698,11 +703,22 @@ function add(instruction, label) {
|
|
|
698
703
|
if (!state.has(key) && shouldSuspend)
|
|
699
704
|
throw suspend(control, key);
|
|
700
705
|
const local = subscriber(this);
|
|
706
|
+
const required = local && local.suspend;
|
|
701
707
|
if (local)
|
|
702
708
|
local.add(key);
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
709
|
+
try {
|
|
710
|
+
const value = onGet
|
|
711
|
+
? onGet(local)
|
|
712
|
+
: state.get(key);
|
|
713
|
+
if (value === undefined && required === true)
|
|
714
|
+
throw suspend(control, key);
|
|
715
|
+
return value;
|
|
716
|
+
}
|
|
717
|
+
catch (err) {
|
|
718
|
+
if (err instanceof Promise && required === false)
|
|
719
|
+
return;
|
|
720
|
+
throw err;
|
|
721
|
+
}
|
|
706
722
|
}
|
|
707
723
|
});
|
|
708
724
|
}
|
|
@@ -828,7 +844,7 @@ function get(arg0, arg1, arg2) {
|
|
|
828
844
|
let source = this;
|
|
829
845
|
let setter;
|
|
830
846
|
if (typeof arg0 == "function") {
|
|
831
|
-
|
|
847
|
+
const result = mayRetry(arg0.bind(subject, key, subject));
|
|
832
848
|
if (typeof result == "function")
|
|
833
849
|
setter = result;
|
|
834
850
|
else {
|
|
@@ -1396,7 +1412,7 @@ function useCompute(source, compute, suspend) {
|
|
|
1396
1412
|
sub.commit();
|
|
1397
1413
|
update = () => {
|
|
1398
1414
|
const next = make();
|
|
1399
|
-
if (value
|
|
1415
|
+
if (notEqual(value, next))
|
|
1400
1416
|
reassign(next);
|
|
1401
1417
|
};
|
|
1402
1418
|
}
|
|
@@ -1415,7 +1431,12 @@ function useCompute(source, compute, suspend) {
|
|
|
1415
1431
|
return null;
|
|
1416
1432
|
React.useLayoutEffect(() => local.release, deps);
|
|
1417
1433
|
return local.proxy;
|
|
1418
|
-
}
|
|
1434
|
+
}
|
|
1435
|
+
/** Values are not equal for purposes of a refresh. */
|
|
1436
|
+
const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
1437
|
+
!Array.isArray(b) ||
|
|
1438
|
+
a.length !== b.length ||
|
|
1439
|
+
a.some((x, i) => x !== b[i])));
|
|
1419
1440
|
|
|
1420
1441
|
function useTap(source, arg1, arg2) {
|
|
1421
1442
|
const instance = typeof source == "object"
|
|
@@ -1425,18 +1446,13 @@ function useTap(source, arg1, arg2) {
|
|
|
1425
1446
|
: useContext(source);
|
|
1426
1447
|
return typeof arg1 == "function"
|
|
1427
1448
|
? useCompute(instance, arg1, arg2)
|
|
1428
|
-
: useSubscribe(instance, arg1
|
|
1449
|
+
: useSubscribe(instance, arg1);
|
|
1429
1450
|
}
|
|
1430
|
-
function useSubscribe(source,
|
|
1451
|
+
function useSubscribe(source, expect) {
|
|
1431
1452
|
const deps = [uid(source)];
|
|
1432
|
-
const local = use(refresh => (control(source)
|
|
1453
|
+
const local = use(refresh => (new Subscriber(control(source), () => refresh, expect)), deps);
|
|
1433
1454
|
React.useLayoutEffect(() => local.commit(), deps);
|
|
1434
|
-
|
|
1435
|
-
return local.proxy;
|
|
1436
|
-
const value = local.proxy[path];
|
|
1437
|
-
if (value === undefined && expect)
|
|
1438
|
-
throw suspend(local.parent, path);
|
|
1439
|
-
return value;
|
|
1455
|
+
return local.proxy;
|
|
1440
1456
|
}
|
|
1441
1457
|
|
|
1442
1458
|
const Global$1 = new WeakMap();
|
|
@@ -1497,7 +1513,7 @@ class MVC extends Model {
|
|
|
1497
1513
|
const instance = this.get();
|
|
1498
1514
|
return typeof arg1 == "function"
|
|
1499
1515
|
? useCompute(instance, arg1, arg2)
|
|
1500
|
-
: useSubscribe(instance, arg1
|
|
1516
|
+
: useSubscribe(instance, arg1);
|
|
1501
1517
|
}
|
|
1502
1518
|
static use(a, b) {
|
|
1503
1519
|
return useNew(this, a, b);
|
|
@@ -1505,7 +1521,7 @@ class MVC extends Model {
|
|
|
1505
1521
|
static meta(arg1, arg2) {
|
|
1506
1522
|
return typeof arg1 == "function"
|
|
1507
1523
|
? useCompute(this, arg1, arg2)
|
|
1508
|
-
: useSubscribe(this, arg1
|
|
1524
|
+
: useSubscribe(this, arg1);
|
|
1509
1525
|
}
|
|
1510
1526
|
}
|
|
1511
1527
|
|
package/lib/index.js
CHANGED
|
@@ -322,9 +322,10 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
322
322
|
|
|
323
323
|
const REGISTER$1 = new WeakMap();
|
|
324
324
|
class Subscriber {
|
|
325
|
-
constructor(parent, onUpdate) {
|
|
325
|
+
constructor(parent, onUpdate, suspend) {
|
|
326
326
|
this.parent = parent;
|
|
327
327
|
this.onUpdate = onUpdate;
|
|
328
|
+
this.suspend = suspend;
|
|
328
329
|
this.active = false;
|
|
329
330
|
this.dependant = new Set();
|
|
330
331
|
this.watch = new Map();
|
|
@@ -514,9 +515,13 @@ class Control {
|
|
|
514
515
|
set: this.ref(key),
|
|
515
516
|
get() {
|
|
516
517
|
const sub = subscriber(this);
|
|
517
|
-
|
|
518
|
+
const value = state.get(key);
|
|
519
|
+
if (sub) {
|
|
518
520
|
sub.add(key);
|
|
519
|
-
|
|
521
|
+
if (value === undefined && sub.suspend)
|
|
522
|
+
throw suspend(this, key);
|
|
523
|
+
}
|
|
524
|
+
return value;
|
|
520
525
|
}
|
|
521
526
|
});
|
|
522
527
|
}
|
|
@@ -706,11 +711,22 @@ function add(instruction, label) {
|
|
|
706
711
|
if (!state.has(key) && shouldSuspend)
|
|
707
712
|
throw suspend(control, key);
|
|
708
713
|
const local = subscriber(this);
|
|
714
|
+
const required = local && local.suspend;
|
|
709
715
|
if (local)
|
|
710
716
|
local.add(key);
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
717
|
+
try {
|
|
718
|
+
const value = onGet
|
|
719
|
+
? onGet(local)
|
|
720
|
+
: state.get(key);
|
|
721
|
+
if (value === undefined && required === true)
|
|
722
|
+
throw suspend(control, key);
|
|
723
|
+
return value;
|
|
724
|
+
}
|
|
725
|
+
catch (err) {
|
|
726
|
+
if (err instanceof Promise && required === false)
|
|
727
|
+
return;
|
|
728
|
+
throw err;
|
|
729
|
+
}
|
|
714
730
|
}
|
|
715
731
|
});
|
|
716
732
|
}
|
|
@@ -836,7 +852,7 @@ function get(arg0, arg1, arg2) {
|
|
|
836
852
|
let source = this;
|
|
837
853
|
let setter;
|
|
838
854
|
if (typeof arg0 == "function") {
|
|
839
|
-
|
|
855
|
+
const result = mayRetry(arg0.bind(subject, key, subject));
|
|
840
856
|
if (typeof result == "function")
|
|
841
857
|
setter = result;
|
|
842
858
|
else {
|
|
@@ -1404,7 +1420,7 @@ function useCompute(source, compute, suspend) {
|
|
|
1404
1420
|
sub.commit();
|
|
1405
1421
|
update = () => {
|
|
1406
1422
|
const next = make();
|
|
1407
|
-
if (value
|
|
1423
|
+
if (notEqual(value, next))
|
|
1408
1424
|
reassign(next);
|
|
1409
1425
|
};
|
|
1410
1426
|
}
|
|
@@ -1423,7 +1439,12 @@ function useCompute(source, compute, suspend) {
|
|
|
1423
1439
|
return null;
|
|
1424
1440
|
React__default["default"].useLayoutEffect(() => local.release, deps);
|
|
1425
1441
|
return local.proxy;
|
|
1426
|
-
}
|
|
1442
|
+
}
|
|
1443
|
+
/** Values are not equal for purposes of a refresh. */
|
|
1444
|
+
const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
1445
|
+
!Array.isArray(b) ||
|
|
1446
|
+
a.length !== b.length ||
|
|
1447
|
+
a.some((x, i) => x !== b[i])));
|
|
1427
1448
|
|
|
1428
1449
|
function useTap(source, arg1, arg2) {
|
|
1429
1450
|
const instance = typeof source == "object"
|
|
@@ -1433,18 +1454,13 @@ function useTap(source, arg1, arg2) {
|
|
|
1433
1454
|
: useContext(source);
|
|
1434
1455
|
return typeof arg1 == "function"
|
|
1435
1456
|
? useCompute(instance, arg1, arg2)
|
|
1436
|
-
: useSubscribe(instance, arg1
|
|
1457
|
+
: useSubscribe(instance, arg1);
|
|
1437
1458
|
}
|
|
1438
|
-
function useSubscribe(source,
|
|
1459
|
+
function useSubscribe(source, expect) {
|
|
1439
1460
|
const deps = [uid(source)];
|
|
1440
|
-
const local = use(refresh => (control(source)
|
|
1461
|
+
const local = use(refresh => (new Subscriber(control(source), () => refresh, expect)), deps);
|
|
1441
1462
|
React__default["default"].useLayoutEffect(() => local.commit(), deps);
|
|
1442
|
-
|
|
1443
|
-
return local.proxy;
|
|
1444
|
-
const value = local.proxy[path];
|
|
1445
|
-
if (value === undefined && expect)
|
|
1446
|
-
throw suspend(local.parent, path);
|
|
1447
|
-
return value;
|
|
1463
|
+
return local.proxy;
|
|
1448
1464
|
}
|
|
1449
1465
|
|
|
1450
1466
|
const Global$1 = new WeakMap();
|
|
@@ -1505,7 +1521,7 @@ class MVC extends Model {
|
|
|
1505
1521
|
const instance = this.get();
|
|
1506
1522
|
return typeof arg1 == "function"
|
|
1507
1523
|
? useCompute(instance, arg1, arg2)
|
|
1508
|
-
: useSubscribe(instance, arg1
|
|
1524
|
+
: useSubscribe(instance, arg1);
|
|
1509
1525
|
}
|
|
1510
1526
|
static use(a, b) {
|
|
1511
1527
|
return useNew(this, a, b);
|
|
@@ -1513,7 +1529,7 @@ class MVC extends Model {
|
|
|
1513
1529
|
static meta(arg1, arg2) {
|
|
1514
1530
|
return typeof arg1 == "function"
|
|
1515
1531
|
? useCompute(this, arg1, arg2)
|
|
1516
|
-
: useSubscribe(this, arg1
|
|
1532
|
+
: useSubscribe(this, arg1);
|
|
1517
1533
|
}
|
|
1518
1534
|
}
|
|
1519
1535
|
|
package/package.json
CHANGED