@expressive/mvc 0.21.2 → 0.21.7
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 +26 -21
- package/lib/index.esm.js +55 -47
- package/lib/index.js +55 -47
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -16,6 +16,26 @@ declare function run<S>(action: Async<S>): typeof action & {
|
|
|
16
16
|
active: boolean;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
declare namespace Context {
|
|
20
|
+
type Inputs = {
|
|
21
|
+
[key: string | number]: Model | Model.New;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
declare class Context {
|
|
25
|
+
/** Use */
|
|
26
|
+
key: string;
|
|
27
|
+
private table;
|
|
28
|
+
private layer;
|
|
29
|
+
private has;
|
|
30
|
+
get<T extends Model>(Type: Model.Type<T>): T | undefined;
|
|
31
|
+
include(inputs: Context.Inputs): Map<Model, boolean>;
|
|
32
|
+
/** Context must force-reset becasue inputs are no longer safe. */
|
|
33
|
+
private bailout;
|
|
34
|
+
add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
|
|
35
|
+
push(): this;
|
|
36
|
+
pop(): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
19
39
|
type Callback = () => void;
|
|
20
40
|
|
|
21
41
|
declare global {
|
|
@@ -50,18 +70,19 @@ declare namespace Control {
|
|
|
50
70
|
* Returned callback is forwarded.
|
|
51
71
|
*/
|
|
52
72
|
type OnReady<T extends Model> = (control: Control<T>) => Callback | void;
|
|
53
|
-
type
|
|
73
|
+
type RequestRefresh = (update: (tick: number) => number) => void;
|
|
74
|
+
type GetContext = (target: Model) => (callback: (got: Context) => void) => void;
|
|
75
|
+
type GetAdapter<T> = (refresh: RequestRefresh, context: Context) => {
|
|
54
76
|
mount: () => (() => void) | void;
|
|
55
77
|
render: () => T;
|
|
56
78
|
} | void;
|
|
57
|
-
type GetHook = <T
|
|
58
|
-
type UseAdapter<T extends Model> = (
|
|
79
|
+
type GetHook = <T>(adapter: GetAdapter<T>) => T | null;
|
|
80
|
+
type UseAdapter<T extends Model> = (refresh: RequestRefresh) => {
|
|
59
81
|
instance: T;
|
|
60
82
|
mount: () => (() => void) | void;
|
|
61
83
|
render: (props: Model.Compat<T>) => T;
|
|
62
84
|
};
|
|
63
85
|
type UseHook = <T extends Model>(adapter: UseAdapter<T>) => (props: Model.Compat<T>) => T;
|
|
64
|
-
type HasHook = (type: typeof Model, relativeTo: Model, callback: (got: Model | undefined) => void) => void;
|
|
65
86
|
}
|
|
66
87
|
declare class Control<T extends Model = any> {
|
|
67
88
|
subject: T;
|
|
@@ -71,7 +92,7 @@ declare class Control<T extends Model = any> {
|
|
|
71
92
|
static pending: Set<Callback>;
|
|
72
93
|
static get: Control.GetHook;
|
|
73
94
|
static use: Control.UseHook;
|
|
74
|
-
static has: Control.
|
|
95
|
+
static has: Control.GetContext;
|
|
75
96
|
static for: typeof control;
|
|
76
97
|
static apply: typeof apply;
|
|
77
98
|
static watch: typeof watch;
|
|
@@ -381,20 +402,4 @@ declare function use<T extends Model>(from: () => Promise<T> | T, callback?: (i:
|
|
|
381
402
|
*/
|
|
382
403
|
declare function use<T extends Model>(peer: T, callback?: (i: T) => void): T;
|
|
383
404
|
|
|
384
|
-
declare namespace Context {
|
|
385
|
-
type Inputs = {
|
|
386
|
-
[key: string | number]: Model | Model.New;
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
declare class Context {
|
|
390
|
-
private table;
|
|
391
|
-
private layer;
|
|
392
|
-
private has;
|
|
393
|
-
get<T extends Model>(Type: Model.Type<T>): T | undefined;
|
|
394
|
-
include(inputs: Context.Inputs): Map<Model, boolean>;
|
|
395
|
-
add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
|
|
396
|
-
push(): this;
|
|
397
|
-
pop(): void;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
405
|
export { Context, Control, Debug, Model, Model as default, get, ref, run, set, use };
|
package/lib/index.esm.js
CHANGED
|
@@ -198,18 +198,18 @@ const Oops$6 = issues({
|
|
|
198
198
|
NotFound: (name) => `Could not find ${name} in context.`
|
|
199
199
|
});
|
|
200
200
|
function get$1(arg1, arg2) {
|
|
201
|
-
return Control.get(
|
|
201
|
+
return Control.get((dispatch, context) => {
|
|
202
|
+
const refresh = () => dispatch(x => x + 1);
|
|
202
203
|
let onUpdate;
|
|
203
204
|
let value;
|
|
204
205
|
if (typeof arg1 !== "function") {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
});
|
|
206
|
+
const got = context.get(this);
|
|
207
|
+
if (got)
|
|
208
|
+
value = arg1 === undefined
|
|
209
|
+
? Control.watch(got, k => k ? onUpdate : undefined)
|
|
210
|
+
: got;
|
|
211
|
+
else if (arg1 !== false)
|
|
212
|
+
throw Oops$6.NotFound(this);
|
|
213
213
|
return {
|
|
214
214
|
mount() {
|
|
215
215
|
onUpdate = refresh;
|
|
@@ -223,23 +223,22 @@ function get$1(arg1, arg2) {
|
|
|
223
223
|
let getValue;
|
|
224
224
|
let factory;
|
|
225
225
|
let proxy;
|
|
226
|
-
context(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
});
|
|
226
|
+
const found = context.get(this);
|
|
227
|
+
if (!found)
|
|
228
|
+
throw Oops$6.NotFound(this);
|
|
229
|
+
proxy = Control.watch(found, () => factory ? null : onUpdate);
|
|
230
|
+
getValue = () => compute.call(proxy, proxy, forceUpdate);
|
|
231
|
+
value = getValue();
|
|
232
|
+
function forceUpdate(action) {
|
|
233
|
+
if (typeof action == "function")
|
|
234
|
+
action = action();
|
|
235
|
+
if (getValue)
|
|
236
|
+
didUpdate(getValue());
|
|
237
|
+
else
|
|
238
|
+
refresh();
|
|
239
|
+
if (action)
|
|
240
|
+
return action.finally(refresh);
|
|
241
|
+
}
|
|
243
242
|
if (value === null) {
|
|
244
243
|
getValue = undefined;
|
|
245
244
|
onUpdate = null;
|
|
@@ -295,11 +294,12 @@ const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
|
295
294
|
a.some((x, i) => x !== b[i])));
|
|
296
295
|
|
|
297
296
|
function use$1(arg1, arg2) {
|
|
298
|
-
const render = Control.use(
|
|
299
|
-
let onUpdate;
|
|
300
|
-
let applyProps = typeof arg1 === "object";
|
|
297
|
+
const render = Control.use(dispatch => {
|
|
301
298
|
const instance = this.new();
|
|
302
299
|
const proxy = Control.watch(instance, () => onUpdate);
|
|
300
|
+
const refresh = () => dispatch(x => x + 1);
|
|
301
|
+
let onUpdate;
|
|
302
|
+
let applyProps = typeof arg1 === "object";
|
|
303
303
|
if (typeof arg1 == "function")
|
|
304
304
|
arg1(instance);
|
|
305
305
|
return {
|
|
@@ -429,7 +429,7 @@ const REGISTER = new WeakMap();
|
|
|
429
429
|
const OBSERVER = new WeakMap();
|
|
430
430
|
const PARENTS = new WeakMap();
|
|
431
431
|
class Control {
|
|
432
|
-
constructor(subject, id =
|
|
432
|
+
constructor(subject, id = uid()) {
|
|
433
433
|
this.subject = subject;
|
|
434
434
|
this.id = id;
|
|
435
435
|
this.frame = new Set();
|
|
@@ -605,7 +605,7 @@ function apply(instruction) {
|
|
|
605
605
|
return placeholder;
|
|
606
606
|
}
|
|
607
607
|
/** Random alphanumberic of length 6; will always start with a letter. */
|
|
608
|
-
function
|
|
608
|
+
function uid() {
|
|
609
609
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
610
610
|
}
|
|
611
611
|
|
|
@@ -659,12 +659,16 @@ function get(arg0, arg1) {
|
|
|
659
659
|
if (!hasParent) {
|
|
660
660
|
if (arg1 === true)
|
|
661
661
|
throw Oops$3.Required(arg0, subject);
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
662
|
+
const fetch = Control.has(subject);
|
|
663
|
+
source = got => {
|
|
664
|
+
fetch(context => {
|
|
665
|
+
const model = context.get(arg0);
|
|
666
|
+
if (model)
|
|
667
|
+
got(model);
|
|
668
|
+
else if (arg1 !== false)
|
|
669
|
+
throw Oops$3.AmbientRequired(arg0, subject);
|
|
670
|
+
});
|
|
671
|
+
};
|
|
668
672
|
}
|
|
669
673
|
else if (!arg0 || hasParent instanceof arg0)
|
|
670
674
|
subject = hasParent;
|
|
@@ -953,8 +957,7 @@ function use(input, argument) {
|
|
|
953
957
|
}
|
|
954
958
|
|
|
955
959
|
const Oops = issues({
|
|
956
|
-
MultipleExist: (name) => `Did find ${name} in context, but multiple were defined
|
|
957
|
-
NewValue: (name) => `Provider already has already defined '${name}' but got new value. This is not yet supported.`
|
|
960
|
+
MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
|
|
958
961
|
});
|
|
959
962
|
class Context {
|
|
960
963
|
constructor() {
|
|
@@ -980,14 +983,13 @@ class Context {
|
|
|
980
983
|
for (const key in inputs) {
|
|
981
984
|
const input = inputs[key];
|
|
982
985
|
const exists = this.layer.get(key);
|
|
983
|
-
if (exists)
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
init.set(instance, true);
|
|
986
|
+
if (!exists) {
|
|
987
|
+
const instance = this.add(input);
|
|
988
|
+
this.layer.set(key, input);
|
|
989
|
+
init.set(instance, true);
|
|
990
|
+
}
|
|
991
|
+
else if (exists !== input)
|
|
992
|
+
return this.bailout(inputs);
|
|
991
993
|
}
|
|
992
994
|
for (const [model] of init) {
|
|
993
995
|
const { state } = control(model, true);
|
|
@@ -1000,6 +1002,12 @@ class Context {
|
|
|
1000
1002
|
}
|
|
1001
1003
|
return init;
|
|
1002
1004
|
}
|
|
1005
|
+
/** Context must force-reset becasue inputs are no longer safe. */
|
|
1006
|
+
bailout(inputs) {
|
|
1007
|
+
this.pop();
|
|
1008
|
+
this.key = uid();
|
|
1009
|
+
return this.include(inputs);
|
|
1010
|
+
}
|
|
1003
1011
|
add(input, implicit) {
|
|
1004
1012
|
let writable = true;
|
|
1005
1013
|
let T;
|
package/lib/index.js
CHANGED
|
@@ -202,18 +202,18 @@ const Oops$6 = issues({
|
|
|
202
202
|
NotFound: (name) => `Could not find ${name} in context.`
|
|
203
203
|
});
|
|
204
204
|
function get$1(arg1, arg2) {
|
|
205
|
-
return Control.get(
|
|
205
|
+
return Control.get((dispatch, context) => {
|
|
206
|
+
const refresh = () => dispatch(x => x + 1);
|
|
206
207
|
let onUpdate;
|
|
207
208
|
let value;
|
|
208
209
|
if (typeof arg1 !== "function") {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
});
|
|
210
|
+
const got = context.get(this);
|
|
211
|
+
if (got)
|
|
212
|
+
value = arg1 === undefined
|
|
213
|
+
? Control.watch(got, k => k ? onUpdate : undefined)
|
|
214
|
+
: got;
|
|
215
|
+
else if (arg1 !== false)
|
|
216
|
+
throw Oops$6.NotFound(this);
|
|
217
217
|
return {
|
|
218
218
|
mount() {
|
|
219
219
|
onUpdate = refresh;
|
|
@@ -227,23 +227,22 @@ function get$1(arg1, arg2) {
|
|
|
227
227
|
let getValue;
|
|
228
228
|
let factory;
|
|
229
229
|
let proxy;
|
|
230
|
-
context(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
});
|
|
230
|
+
const found = context.get(this);
|
|
231
|
+
if (!found)
|
|
232
|
+
throw Oops$6.NotFound(this);
|
|
233
|
+
proxy = Control.watch(found, () => factory ? null : onUpdate);
|
|
234
|
+
getValue = () => compute.call(proxy, proxy, forceUpdate);
|
|
235
|
+
value = getValue();
|
|
236
|
+
function forceUpdate(action) {
|
|
237
|
+
if (typeof action == "function")
|
|
238
|
+
action = action();
|
|
239
|
+
if (getValue)
|
|
240
|
+
didUpdate(getValue());
|
|
241
|
+
else
|
|
242
|
+
refresh();
|
|
243
|
+
if (action)
|
|
244
|
+
return action.finally(refresh);
|
|
245
|
+
}
|
|
247
246
|
if (value === null) {
|
|
248
247
|
getValue = undefined;
|
|
249
248
|
onUpdate = null;
|
|
@@ -299,11 +298,12 @@ const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
|
299
298
|
a.some((x, i) => x !== b[i])));
|
|
300
299
|
|
|
301
300
|
function use$1(arg1, arg2) {
|
|
302
|
-
const render = Control.use(
|
|
303
|
-
let onUpdate;
|
|
304
|
-
let applyProps = typeof arg1 === "object";
|
|
301
|
+
const render = Control.use(dispatch => {
|
|
305
302
|
const instance = this.new();
|
|
306
303
|
const proxy = Control.watch(instance, () => onUpdate);
|
|
304
|
+
const refresh = () => dispatch(x => x + 1);
|
|
305
|
+
let onUpdate;
|
|
306
|
+
let applyProps = typeof arg1 === "object";
|
|
307
307
|
if (typeof arg1 == "function")
|
|
308
308
|
arg1(instance);
|
|
309
309
|
return {
|
|
@@ -433,7 +433,7 @@ const REGISTER = new WeakMap();
|
|
|
433
433
|
const OBSERVER = new WeakMap();
|
|
434
434
|
const PARENTS = new WeakMap();
|
|
435
435
|
class Control {
|
|
436
|
-
constructor(subject, id =
|
|
436
|
+
constructor(subject, id = uid()) {
|
|
437
437
|
this.subject = subject;
|
|
438
438
|
this.id = id;
|
|
439
439
|
this.frame = new Set();
|
|
@@ -609,7 +609,7 @@ function apply(instruction) {
|
|
|
609
609
|
return placeholder;
|
|
610
610
|
}
|
|
611
611
|
/** Random alphanumberic of length 6; will always start with a letter. */
|
|
612
|
-
function
|
|
612
|
+
function uid() {
|
|
613
613
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
614
614
|
}
|
|
615
615
|
|
|
@@ -663,12 +663,16 @@ function get(arg0, arg1) {
|
|
|
663
663
|
if (!hasParent) {
|
|
664
664
|
if (arg1 === true)
|
|
665
665
|
throw Oops$3.Required(arg0, subject);
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
666
|
+
const fetch = Control.has(subject);
|
|
667
|
+
source = got => {
|
|
668
|
+
fetch(context => {
|
|
669
|
+
const model = context.get(arg0);
|
|
670
|
+
if (model)
|
|
671
|
+
got(model);
|
|
672
|
+
else if (arg1 !== false)
|
|
673
|
+
throw Oops$3.AmbientRequired(arg0, subject);
|
|
674
|
+
});
|
|
675
|
+
};
|
|
672
676
|
}
|
|
673
677
|
else if (!arg0 || hasParent instanceof arg0)
|
|
674
678
|
subject = hasParent;
|
|
@@ -957,8 +961,7 @@ function use(input, argument) {
|
|
|
957
961
|
}
|
|
958
962
|
|
|
959
963
|
const Oops = issues({
|
|
960
|
-
MultipleExist: (name) => `Did find ${name} in context, but multiple were defined
|
|
961
|
-
NewValue: (name) => `Provider already has already defined '${name}' but got new value. This is not yet supported.`
|
|
964
|
+
MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
|
|
962
965
|
});
|
|
963
966
|
class Context {
|
|
964
967
|
constructor() {
|
|
@@ -984,14 +987,13 @@ class Context {
|
|
|
984
987
|
for (const key in inputs) {
|
|
985
988
|
const input = inputs[key];
|
|
986
989
|
const exists = this.layer.get(key);
|
|
987
|
-
if (exists)
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
init.set(instance, true);
|
|
990
|
+
if (!exists) {
|
|
991
|
+
const instance = this.add(input);
|
|
992
|
+
this.layer.set(key, input);
|
|
993
|
+
init.set(instance, true);
|
|
994
|
+
}
|
|
995
|
+
else if (exists !== input)
|
|
996
|
+
return this.bailout(inputs);
|
|
995
997
|
}
|
|
996
998
|
for (const [model] of init) {
|
|
997
999
|
const { state } = control(model, true);
|
|
@@ -1004,6 +1006,12 @@ class Context {
|
|
|
1004
1006
|
}
|
|
1005
1007
|
return init;
|
|
1006
1008
|
}
|
|
1009
|
+
/** Context must force-reset becasue inputs are no longer safe. */
|
|
1010
|
+
bailout(inputs) {
|
|
1011
|
+
this.pop();
|
|
1012
|
+
this.key = uid();
|
|
1013
|
+
return this.include(inputs);
|
|
1014
|
+
}
|
|
1007
1015
|
add(input, implicit) {
|
|
1008
1016
|
let writable = true;
|
|
1009
1017
|
let T;
|
package/package.json
CHANGED