@expressive/mvc 0.18.1 → 0.19.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 +68 -48
- package/lib/index.esm.js +49 -70
- package/lib/index.js +49 -69
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -1,13 +1,43 @@
|
|
|
1
|
-
declare
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
declare namespace Issue {
|
|
2
|
+
type Variable = {} | string | number | boolean | null | undefined;
|
|
3
|
+
type Variables<T> = T extends (...args: infer T) => any ? T : never;
|
|
4
|
+
type Messages = {
|
|
5
|
+
[named: string]: (...args: Variable[]) => string;
|
|
6
|
+
};
|
|
7
|
+
type Output<M extends Messages> = {
|
|
8
|
+
readonly [P in keyof M]: (...args: Variables<M[P]>) => Issue;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
declare class Issue extends Error {
|
|
12
|
+
stack: string;
|
|
13
|
+
warn(): void;
|
|
14
|
+
}
|
|
15
|
+
declare function issues<M extends Issue.Messages>(register: M): Issue.Output<M>;
|
|
16
|
+
|
|
17
|
+
declare const LOCAL = "__local";
|
|
18
|
+
declare const STATE = "__state";
|
|
19
|
+
declare const UPDATE = "__update";
|
|
20
|
+
declare const CONTROL = "__control";
|
|
5
21
|
declare const Debug: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
22
|
+
/** Use to access Model's local Subscriber (if exists). */
|
|
23
|
+
LOCAL: "__local";
|
|
24
|
+
/** Use to access snapshot of Model's current state. */
|
|
25
|
+
STATE: "__state";
|
|
26
|
+
/**
|
|
27
|
+
* Use to access snapshot of Model's latest update.
|
|
28
|
+
*
|
|
29
|
+
* Note: If used within a Subscriber, update will be narrowed to the specific keys
|
|
30
|
+
* which triggered a refresh (if one did).
|
|
31
|
+
*/
|
|
32
|
+
UPDATE: "__update";
|
|
33
|
+
/** Use to access a Model's controller. */
|
|
34
|
+
CONTROL: "__control";
|
|
10
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* Generic will declare debug properties on a given Model.
|
|
38
|
+
*
|
|
39
|
+
* These properties always exist at runtime, however are hidden unless you cast your Model as `Debug<T>`.
|
|
40
|
+
*/
|
|
11
41
|
type Debug<T extends Model> = T & {
|
|
12
42
|
/** Controller for this instance. */
|
|
13
43
|
[CONTROL]?: Control<T>;
|
|
@@ -28,24 +58,19 @@ type Callback = () => void;
|
|
|
28
58
|
type Class = new (...args: any[]) => any;
|
|
29
59
|
type InstanceOf<T> = T extends { prototype: infer U } ? U : never;
|
|
30
60
|
|
|
61
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
62
|
+
|
|
31
63
|
/** Type may not be undefined - instead will be null. */
|
|
32
64
|
type NoVoid<T> = T extends undefined ? null : T;
|
|
33
65
|
|
|
34
|
-
type OptionalValues<T extends {}> = {
|
|
35
|
-
[P in Model.Key<T>]: T[P] | undefined;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
type NonOptionalValues<T extends {}> = {
|
|
39
|
-
[P in Model.Key<T>]: Exclude<T[P], undefined>;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
66
|
declare namespace Model {
|
|
43
67
|
export { Control };
|
|
44
68
|
export { Subscriber };
|
|
45
69
|
/** Including but not limited to T. */
|
|
46
70
|
type Extends<T> = T | (string & Record<never, never>);
|
|
47
71
|
/** Any typeof Model, using class constructor as the reference. */
|
|
48
|
-
export type Type<T extends Model = Model> =
|
|
72
|
+
export type Type<T extends Model = Model> = abstract new () => T;
|
|
73
|
+
export type Class<T extends Model> = (abstract new () => T) & typeof Model;
|
|
49
74
|
/** A typeof Model, specifically one which may be created without arguments. */
|
|
50
75
|
export type New<T extends Model = Model> = (new () => T) & typeof Model;
|
|
51
76
|
export type Effect<T> = (this: T, argument: T) => Callback | Promise<any> | void;
|
|
@@ -95,7 +120,7 @@ declare namespace Model {
|
|
|
95
120
|
[P in Key<T>]: Value<T[P]>;
|
|
96
121
|
};
|
|
97
122
|
export type FindFunction = <T extends Model>(type: Model.Type<T>, relativeTo: Model, required: boolean) => (_refresh: (x: T) => void) => T | undefined;
|
|
98
|
-
export type
|
|
123
|
+
export type GetCallback<T extends Model, R> = (this: T, model: T, update: ForceUpdate) => R;
|
|
99
124
|
type ForceUpdate = {
|
|
100
125
|
/** Force an update in current component. */
|
|
101
126
|
(): void;
|
|
@@ -119,7 +144,9 @@ declare class Model {
|
|
|
119
144
|
* Use to obtain full reference from a destructure.
|
|
120
145
|
*/
|
|
121
146
|
is: this;
|
|
122
|
-
|
|
147
|
+
/** Unique identifier for Model instance. */
|
|
148
|
+
id: string;
|
|
149
|
+
constructor(id?: string);
|
|
123
150
|
on<P extends Model.Event<this>>(keys?: P | Iterable<P>, timeout?: number): Promise<P[]>;
|
|
124
151
|
on<P extends Model.Event<this>>(keys: P | Iterable<P>, listener: (this: this, keys: Model.Event<this>[]) => void, once?: boolean): Callback;
|
|
125
152
|
on(effect: Model.Effect<this>): Callback;
|
|
@@ -130,15 +157,15 @@ declare class Model {
|
|
|
130
157
|
on(current: true): Promise<Model.Event<this>[]>;
|
|
131
158
|
on(current: null): Promise<null>;
|
|
132
159
|
get(): Model.Export<this>;
|
|
133
|
-
get<P extends Model.Key<this>>(
|
|
134
|
-
get<P extends Model.Key<this>>(property: P, timeout: number): Promise<this[P]>;
|
|
135
|
-
get<P extends Model.Key<this>>(property: P, onChange: true): Promise<this[P]>;
|
|
136
|
-
get<P extends Model.Key<this>>(property: P, onChange: boolean): this[P] | Promise<this[P]>;
|
|
137
|
-
get<P extends Model.Key<this>>(property: P, listener: (this: this, value: this[P], key: P[]) => void): Callback;
|
|
160
|
+
get<P extends Model.Key<this>>(select: P): this[P];
|
|
138
161
|
get<P extends Model.Key<this>>(select: Iterable<P>): Model.Get<this, P>;
|
|
162
|
+
get<P extends Model.Key<this>>(select: P, timeout: number): Promise<this[P]>;
|
|
139
163
|
get<P extends Model.Key<this>>(select: Iterable<P>, timeout: number): Promise<Model.Get<this, P>>;
|
|
164
|
+
get<P extends Model.Key<this>>(select: P, onChange: true): Promise<this[P]>;
|
|
140
165
|
get<P extends Model.Key<this>>(select: Iterable<P>, onChange: true): Promise<Model.Get<this, P>>;
|
|
141
|
-
get<P extends Model.Key<this>>(select:
|
|
166
|
+
get<P extends Model.Key<this>>(select: P, onChange: boolean): MaybePromise<this[P]>;
|
|
167
|
+
get<P extends Model.Key<this>>(select: Iterable<P>, onChange: boolean): MaybePromise<Model.Get<this, P>>;
|
|
168
|
+
get<P extends Model.Key<this>>(select: P, listener: (this: this, value: this[P], key: P[]) => void): Callback;
|
|
142
169
|
get<P extends Model.Key<this>>(select: Iterable<P>, listener: (this: this, value: Model.Get<this, P>, key: P[]) => void): Callback;
|
|
143
170
|
set(key: Model.Event<this>): PromiseLike<readonly Model.Event<this>[]>;
|
|
144
171
|
set<K extends Model.Event<this>>(key: Model.Event<this>, value: Model.ValueOf<this, K>): PromiseLike<readonly Model.Event<this>[]>;
|
|
@@ -154,29 +181,22 @@ declare class Model {
|
|
|
154
181
|
* @param args - arguments sent to constructor
|
|
155
182
|
*/
|
|
156
183
|
static new<T extends Class>(this: T, ...args: ConstructorParameters<T>): InstanceOf<T>;
|
|
184
|
+
static find<T extends Model>(this: Model.Type<T>, required?: boolean): T;
|
|
185
|
+
static find<T extends Model>(this: Model.Type<T>, required: false): T | undefined;
|
|
186
|
+
static get<T extends Model>(this: Model.Type<T>): T;
|
|
187
|
+
static get<T extends Model>(this: Model.Type<T>, passive: true): T;
|
|
188
|
+
static get<T extends Model>(this: Model.Type<T>, required: false): T | undefined;
|
|
189
|
+
static get<T extends Model, R extends []>(this: Model.Type<T>, compute: Model.GetCallback<T, R | (() => R)>, expect?: boolean): R;
|
|
190
|
+
static get<T extends Model, R extends []>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R> | (() => R) | null>, expect?: boolean): R | null;
|
|
191
|
+
static get<T extends Model, R extends []>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
|
192
|
+
static get<T extends Model, R>(this: Model.Type<T>, init: Model.GetCallback<T, () => R>): NoVoid<R>;
|
|
193
|
+
static get<T extends Model, R>(this: Model.Type<T>, init: Model.GetCallback<T, (() => R) | null>): NoVoid<R> | null;
|
|
194
|
+
static get<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
|
195
|
+
static get<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
|
|
196
|
+
static get<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, R>, expect?: boolean): NoVoid<R>;
|
|
157
197
|
static use<I extends Model>(this: Model.Type<I>, watch: Model.Key<I>[], callback?: (instance: I) => void): I;
|
|
158
198
|
static use<I extends Model>(this: Model.Type<I>, callback?: (instance: I) => void): I;
|
|
159
199
|
static use<I extends Model>(this: Model.Type<I>, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
|
|
160
|
-
static get<T extends Model>(this: Model.Type<T>, required?: boolean): T;
|
|
161
|
-
static get<T extends Model>(this: Model.Type<T>, required: false): T | undefined;
|
|
162
|
-
static tap<T extends Model>(this: Model.Type<T>): T;
|
|
163
|
-
static tap<T extends Model, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: Model.TapCallback<T, R | (() => R)>, expect?: boolean): R;
|
|
164
|
-
static tap<T extends Model, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: Model.TapCallback<T, Promise<R> | (() => R) | null>, expect?: boolean): R | null;
|
|
165
|
-
static tap<T extends Model, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: Model.TapCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
|
166
|
-
static tap<T extends Model, R>(this: Model.Type<T>, init: Model.TapCallback<T, () => R>): NoVoid<R>;
|
|
167
|
-
static tap<T extends Model, R>(this: Model.Type<T>, init: Model.TapCallback<T, (() => R) | null>): NoVoid<R> | null;
|
|
168
|
-
static tap<T extends Model, R>(this: Model.Type<T>, compute: Model.TapCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
|
169
|
-
static tap<T extends Model, R>(this: Model.Type<T>, compute: Model.TapCallback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
|
|
170
|
-
static tap<T extends Model, R>(this: Model.Type<T>, compute: Model.TapCallback<T, R>, expect?: boolean): NoVoid<R>;
|
|
171
|
-
static tap<T extends Model>(this: Model.Type<T>, expect: true): NonOptionalValues<T>;
|
|
172
|
-
static tap<T extends Model>(this: Model.Type<T>, expect?: boolean): OptionalValues<T>;
|
|
173
|
-
protected static meta<T extends Class>(this: T): T;
|
|
174
|
-
protected static meta<T extends Class>(this: T, expect: true): NonOptionalValues<T>;
|
|
175
|
-
protected static meta<T extends Class>(this: T, expect?: boolean): OptionalValues<T>;
|
|
176
|
-
protected static meta<T, M extends Class>(this: M, from: (this: M, state: M) => Promise<T>, expect: true): Exclude<T, undefined>;
|
|
177
|
-
protected static meta<T, M extends Class>(this: M, from: (this: M, state: M) => Promise<T>, expect?: boolean): T;
|
|
178
|
-
protected static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect: true): Exclude<T, undefined>;
|
|
179
|
-
protected static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect?: boolean): T;
|
|
180
200
|
/**
|
|
181
201
|
* Static equivalent of `x instanceof this`.
|
|
182
202
|
*
|
|
@@ -272,7 +292,7 @@ declare namespace control {
|
|
|
272
292
|
declare function control<T extends Model>(subject: T): Control<T>;
|
|
273
293
|
declare function control<T extends Model>(subject: T, cb: control.OnReady<T>): Callback;
|
|
274
294
|
|
|
275
|
-
declare function getParent<T extends Model>(from: Model, type?: Model.
|
|
295
|
+
declare function getParent<T extends Model>(from: Model, type?: Model.Class<T>): T;
|
|
276
296
|
|
|
277
297
|
type Async<T = any> = (...args: any[]) => Promise<T>;
|
|
278
298
|
/**
|
|
@@ -295,7 +315,7 @@ declare function run<S>(action: Async<S>): typeof action & {
|
|
|
295
315
|
declare namespace get {
|
|
296
316
|
type Function<T, S = any> = (this: S, on: S) => T;
|
|
297
317
|
type Factory<R, T> = (this: T, property: string, on: T) => Function<R, T>;
|
|
298
|
-
type FindFunction<T extends Model = Model> = (type:
|
|
318
|
+
type FindFunction<T extends Model = Model> = (type: Model.Class<T>, relativeTo: Model, required: boolean) => Source<T>;
|
|
299
319
|
type Source<T extends Model = Model> = (callback: (x: T) => void) => void;
|
|
300
320
|
/** Assign fetch algorithm for get instruction. */
|
|
301
321
|
let using: (fn: FindFunction) => typeof get;
|
|
@@ -479,4 +499,4 @@ declare const Internal: {
|
|
|
479
499
|
getParent: typeof getParent;
|
|
480
500
|
};
|
|
481
501
|
|
|
482
|
-
export { Control, Debug, Internal, Model, Register, Subscriber, add, Model as default, get, ref, run, set, use };
|
|
502
|
+
export { Control, Debug, Internal, Model, Register, Subscriber, add, Model as default, get, issues, ref, run, set, use };
|
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
1
|
+
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
2
|
+
/** Random alphanumberic of length 6; will always start with a letter. */
|
|
3
|
+
function random() {
|
|
4
|
+
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
5
|
+
}
|
|
2
6
|
|
|
3
7
|
class Issue extends Error {
|
|
4
8
|
constructor() {
|
|
@@ -281,9 +285,10 @@ const Oops$5 = issues({
|
|
|
281
285
|
NoAdapter: (method) => `Can't call Model.${method} without an adapter.`
|
|
282
286
|
});
|
|
283
287
|
class Model {
|
|
284
|
-
constructor() {
|
|
288
|
+
constructor(id) {
|
|
285
289
|
new Control(this);
|
|
286
290
|
defineProperty(this, "is", { value: this });
|
|
291
|
+
defineProperty(this, "id", { value: id || random() });
|
|
287
292
|
}
|
|
288
293
|
on(arg1, arg2, arg3) {
|
|
289
294
|
if (typeof arg1 == "function")
|
|
@@ -313,14 +318,7 @@ class Model {
|
|
|
313
318
|
set(arg1, arg2) {
|
|
314
319
|
const controller = control(this);
|
|
315
320
|
const { state } = controller;
|
|
316
|
-
if (typeof arg1 == "
|
|
317
|
-
for (const key in arg1) {
|
|
318
|
-
if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
|
|
319
|
-
state.set(key, arg1[key]);
|
|
320
|
-
controller.update(key);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
else if (typeof arg1 == "string") {
|
|
321
|
+
if (typeof arg1 == "string") {
|
|
324
322
|
controller.update(arg1);
|
|
325
323
|
if (1 in arguments) {
|
|
326
324
|
if (state.has(arg1))
|
|
@@ -332,6 +330,12 @@ class Model {
|
|
|
332
330
|
}
|
|
333
331
|
}
|
|
334
332
|
}
|
|
333
|
+
else if (typeof arg1 == "object")
|
|
334
|
+
for (const key in arg1)
|
|
335
|
+
if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
|
|
336
|
+
state.set(key, arg1[key]);
|
|
337
|
+
controller.update(key);
|
|
338
|
+
}
|
|
335
339
|
return {
|
|
336
340
|
then: (callback) => {
|
|
337
341
|
if (!callback)
|
|
@@ -356,17 +360,14 @@ class Model {
|
|
|
356
360
|
control(instance);
|
|
357
361
|
return instance;
|
|
358
362
|
}
|
|
359
|
-
static
|
|
360
|
-
throw Oops$5.NoAdapter("
|
|
363
|
+
static find() {
|
|
364
|
+
throw Oops$5.NoAdapter("find");
|
|
361
365
|
}
|
|
362
366
|
static get() {
|
|
363
367
|
throw Oops$5.NoAdapter("get");
|
|
364
368
|
}
|
|
365
|
-
static
|
|
366
|
-
throw Oops$5.NoAdapter("
|
|
367
|
-
}
|
|
368
|
-
static meta() {
|
|
369
|
-
throw Oops$5.NoAdapter("meta");
|
|
369
|
+
static use() {
|
|
370
|
+
throw Oops$5.NoAdapter("use");
|
|
370
371
|
}
|
|
371
372
|
/**
|
|
372
373
|
* Static equivalent of `x instanceof this`.
|
|
@@ -379,8 +380,14 @@ class Model {
|
|
|
379
380
|
}
|
|
380
381
|
}
|
|
381
382
|
defineProperty(Model.prototype, "toString", {
|
|
383
|
+
configurable: true,
|
|
382
384
|
value() {
|
|
383
|
-
return this.constructor.name
|
|
385
|
+
return `${this.constructor.name}-${this.id}`;
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
defineProperty(Model, "toString", {
|
|
389
|
+
value() {
|
|
390
|
+
return this.name;
|
|
384
391
|
}
|
|
385
392
|
});
|
|
386
393
|
|
|
@@ -418,7 +425,7 @@ function add(instruction, label) {
|
|
|
418
425
|
|
|
419
426
|
const Oops$4 = issues({
|
|
420
427
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
|
|
421
|
-
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"}
|
|
428
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} ${parent}.${property}.`,
|
|
422
429
|
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
423
430
|
});
|
|
424
431
|
function get(arg0, arg1) {
|
|
@@ -435,8 +442,8 @@ function get(arg0, arg1) {
|
|
|
435
442
|
else if (typeof arg0 == "function")
|
|
436
443
|
arg1 = arg0.call(subject, key, subject);
|
|
437
444
|
return typeof arg1 == "function"
|
|
438
|
-
?
|
|
439
|
-
:
|
|
445
|
+
? computed(this, key, source, arg1)
|
|
446
|
+
: recursive(this, key, source, arg1);
|
|
440
447
|
});
|
|
441
448
|
}
|
|
442
449
|
function getParentForGetInstruction(type, relativeTo, required) {
|
|
@@ -445,54 +452,26 @@ function getParentForGetInstruction(type, relativeTo, required) {
|
|
|
445
452
|
if (item)
|
|
446
453
|
callback(item);
|
|
447
454
|
else if (required)
|
|
448
|
-
throw Oops$4.Required(type
|
|
455
|
+
throw Oops$4.Required(type, relativeTo.constructor);
|
|
449
456
|
};
|
|
450
457
|
}
|
|
451
|
-
function
|
|
452
|
-
const
|
|
453
|
-
const { state } = parent;
|
|
458
|
+
function recursive(parent, key, source, required) {
|
|
459
|
+
const getter = getRecursive(key, parent);
|
|
454
460
|
let waiting;
|
|
455
461
|
source((got) => {
|
|
456
|
-
state.set(key, got);
|
|
462
|
+
parent.state.set(key, got);
|
|
457
463
|
if (waiting)
|
|
458
464
|
parent.update(key);
|
|
459
465
|
});
|
|
460
466
|
waiting = true;
|
|
461
|
-
function create(local) {
|
|
462
|
-
let reset;
|
|
463
|
-
local.follow(key, init);
|
|
464
|
-
init();
|
|
465
|
-
function init() {
|
|
466
|
-
if (reset)
|
|
467
|
-
reset();
|
|
468
|
-
const value = state.get(key);
|
|
469
|
-
if (value && controller(value)) {
|
|
470
|
-
const child = new Subscriber(value, local.onUpdate);
|
|
471
|
-
if (local.active)
|
|
472
|
-
child.commit();
|
|
473
|
-
local.dependant.add(child);
|
|
474
|
-
context.set(local, child.proxy);
|
|
475
|
-
reset = () => {
|
|
476
|
-
child.release();
|
|
477
|
-
local.dependant.delete(child);
|
|
478
|
-
context.set(local, undefined);
|
|
479
|
-
reset = undefined;
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
467
|
return (local) => {
|
|
485
|
-
const value = state.get(key);
|
|
468
|
+
const value = parent.state.get(key);
|
|
486
469
|
if (!value && required !== false)
|
|
487
470
|
parent.waitFor(key);
|
|
488
|
-
|
|
489
|
-
return value;
|
|
490
|
-
if (!context.has(local))
|
|
491
|
-
create(local);
|
|
492
|
-
return context.get(local);
|
|
471
|
+
return local ? getter(local) : value;
|
|
493
472
|
};
|
|
494
473
|
}
|
|
495
|
-
function
|
|
474
|
+
function computed(parent, key, source, setter) {
|
|
496
475
|
const { state } = parent;
|
|
497
476
|
let local;
|
|
498
477
|
let active;
|
|
@@ -553,7 +532,7 @@ function getComputed(key, parent, source, setter) {
|
|
|
553
532
|
const INFO = new WeakMap();
|
|
554
533
|
const KEYS = new WeakMap();
|
|
555
534
|
const ORDER = new WeakMap();
|
|
556
|
-
function
|
|
535
|
+
function flushComputed(control) {
|
|
557
536
|
const pending = KEYS.get(control);
|
|
558
537
|
if (!pending || !pending.size)
|
|
559
538
|
return;
|
|
@@ -647,7 +626,7 @@ class Control {
|
|
|
647
626
|
return;
|
|
648
627
|
else if (!frame.size)
|
|
649
628
|
setTimeout(() => {
|
|
650
|
-
|
|
629
|
+
flushComputed(this);
|
|
651
630
|
const keys = this.latest = Array.from(frame);
|
|
652
631
|
setTimeout(() => this.latest = undefined, 0);
|
|
653
632
|
frame.clear();
|
|
@@ -706,21 +685,19 @@ function control(subject, cb) {
|
|
|
706
685
|
|
|
707
686
|
const Parent = new WeakMap();
|
|
708
687
|
const Oops$3 = issues({
|
|
709
|
-
BadAssignment: (parent, expected, got) =>
|
|
688
|
+
BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
|
|
710
689
|
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
711
690
|
});
|
|
712
691
|
function getParent(from, type) {
|
|
713
692
|
const value = Parent.get(from);
|
|
714
693
|
if (value && type && !(value instanceof type))
|
|
715
|
-
throw Oops$3.Unexpected(type
|
|
694
|
+
throw Oops$3.Unexpected(type, from, value);
|
|
716
695
|
return value;
|
|
717
696
|
}
|
|
718
697
|
function getRecursive(key, from) {
|
|
719
698
|
const context = new WeakMap();
|
|
720
699
|
const { state } = from;
|
|
721
700
|
return (local) => {
|
|
722
|
-
if (!local)
|
|
723
|
-
return state.get(key);
|
|
724
701
|
if (!context.has(local)) {
|
|
725
702
|
let reset;
|
|
726
703
|
const init = () => {
|
|
@@ -754,8 +731,9 @@ function setRecursive(controller, key, initial) {
|
|
|
754
731
|
const onUpdate = (next) => {
|
|
755
732
|
state.set(key, next);
|
|
756
733
|
if (!(next instanceof Type))
|
|
757
|
-
throw Oops$3.BadAssignment(`${subject}.${key}`, Type
|
|
758
|
-
|
|
734
|
+
throw Oops$3.BadAssignment(`${subject}.${key}`, Type, String(next));
|
|
735
|
+
const getter = getRecursive(key, controller);
|
|
736
|
+
get = (local) => local ? getter(local) : state.get(key);
|
|
759
737
|
Parent.set(next, subject);
|
|
760
738
|
control(next);
|
|
761
739
|
return true;
|
|
@@ -1107,7 +1085,8 @@ function use(input, argument) {
|
|
|
1107
1085
|
const onUpdate = (next) => {
|
|
1108
1086
|
state.set(key, next);
|
|
1109
1087
|
if (next) {
|
|
1110
|
-
|
|
1088
|
+
const getter = getRecursive(key, this);
|
|
1089
|
+
get = (local) => local ? getter(local) : state.get(key);
|
|
1111
1090
|
Parent.set(next, subject);
|
|
1112
1091
|
control(next);
|
|
1113
1092
|
}
|
|
@@ -1163,10 +1142,10 @@ function use(input, argument) {
|
|
|
1163
1142
|
});
|
|
1164
1143
|
}
|
|
1165
1144
|
|
|
1166
|
-
const LOCAL = "
|
|
1167
|
-
const STATE = "
|
|
1168
|
-
const UPDATE = "
|
|
1169
|
-
const CONTROL = "
|
|
1145
|
+
const LOCAL = "__local";
|
|
1146
|
+
const STATE = "__state";
|
|
1147
|
+
const UPDATE = "__update";
|
|
1148
|
+
const CONTROL = "__control";
|
|
1170
1149
|
defineProperties(Model.prototype, {
|
|
1171
1150
|
[CONTROL]: {
|
|
1172
1151
|
get() {
|
|
@@ -1262,4 +1241,4 @@ const Internal = {
|
|
|
1262
1241
|
getParent
|
|
1263
1242
|
};
|
|
1264
1243
|
|
|
1265
|
-
export { Control, Debug, Internal, Model, Register, Subscriber, add, Model as default, get, ref, run, set, use };
|
|
1244
|
+
export { Control, Debug, Internal, Model, Register, Subscriber, add, Model as default, get, issues, ref, run, set, use };
|
package/lib/index.js
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
5
|
+
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
6
|
+
/** Random alphanumberic of length 6; will always start with a letter. */
|
|
7
|
+
function random() {
|
|
8
|
+
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
9
|
+
}
|
|
6
10
|
|
|
7
11
|
class Issue extends Error {
|
|
8
12
|
constructor() {
|
|
@@ -285,9 +289,10 @@ const Oops$5 = issues({
|
|
|
285
289
|
NoAdapter: (method) => `Can't call Model.${method} without an adapter.`
|
|
286
290
|
});
|
|
287
291
|
class Model {
|
|
288
|
-
constructor() {
|
|
292
|
+
constructor(id) {
|
|
289
293
|
new Control(this);
|
|
290
294
|
defineProperty(this, "is", { value: this });
|
|
295
|
+
defineProperty(this, "id", { value: id || random() });
|
|
291
296
|
}
|
|
292
297
|
on(arg1, arg2, arg3) {
|
|
293
298
|
if (typeof arg1 == "function")
|
|
@@ -317,14 +322,7 @@ class Model {
|
|
|
317
322
|
set(arg1, arg2) {
|
|
318
323
|
const controller = control(this);
|
|
319
324
|
const { state } = controller;
|
|
320
|
-
if (typeof arg1 == "
|
|
321
|
-
for (const key in arg1) {
|
|
322
|
-
if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
|
|
323
|
-
state.set(key, arg1[key]);
|
|
324
|
-
controller.update(key);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
else if (typeof arg1 == "string") {
|
|
325
|
+
if (typeof arg1 == "string") {
|
|
328
326
|
controller.update(arg1);
|
|
329
327
|
if (1 in arguments) {
|
|
330
328
|
if (state.has(arg1))
|
|
@@ -336,6 +334,12 @@ class Model {
|
|
|
336
334
|
}
|
|
337
335
|
}
|
|
338
336
|
}
|
|
337
|
+
else if (typeof arg1 == "object")
|
|
338
|
+
for (const key in arg1)
|
|
339
|
+
if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
|
|
340
|
+
state.set(key, arg1[key]);
|
|
341
|
+
controller.update(key);
|
|
342
|
+
}
|
|
339
343
|
return {
|
|
340
344
|
then: (callback) => {
|
|
341
345
|
if (!callback)
|
|
@@ -360,17 +364,14 @@ class Model {
|
|
|
360
364
|
control(instance);
|
|
361
365
|
return instance;
|
|
362
366
|
}
|
|
363
|
-
static
|
|
364
|
-
throw Oops$5.NoAdapter("
|
|
367
|
+
static find() {
|
|
368
|
+
throw Oops$5.NoAdapter("find");
|
|
365
369
|
}
|
|
366
370
|
static get() {
|
|
367
371
|
throw Oops$5.NoAdapter("get");
|
|
368
372
|
}
|
|
369
|
-
static
|
|
370
|
-
throw Oops$5.NoAdapter("
|
|
371
|
-
}
|
|
372
|
-
static meta() {
|
|
373
|
-
throw Oops$5.NoAdapter("meta");
|
|
373
|
+
static use() {
|
|
374
|
+
throw Oops$5.NoAdapter("use");
|
|
374
375
|
}
|
|
375
376
|
/**
|
|
376
377
|
* Static equivalent of `x instanceof this`.
|
|
@@ -383,8 +384,14 @@ class Model {
|
|
|
383
384
|
}
|
|
384
385
|
}
|
|
385
386
|
defineProperty(Model.prototype, "toString", {
|
|
387
|
+
configurable: true,
|
|
386
388
|
value() {
|
|
387
|
-
return this.constructor.name
|
|
389
|
+
return `${this.constructor.name}-${this.id}`;
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
defineProperty(Model, "toString", {
|
|
393
|
+
value() {
|
|
394
|
+
return this.name;
|
|
388
395
|
}
|
|
389
396
|
});
|
|
390
397
|
|
|
@@ -422,7 +429,7 @@ function add(instruction, label) {
|
|
|
422
429
|
|
|
423
430
|
const Oops$4 = issues({
|
|
424
431
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
|
|
425
|
-
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"}
|
|
432
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} ${parent}.${property}.`,
|
|
426
433
|
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
427
434
|
});
|
|
428
435
|
function get(arg0, arg1) {
|
|
@@ -439,8 +446,8 @@ function get(arg0, arg1) {
|
|
|
439
446
|
else if (typeof arg0 == "function")
|
|
440
447
|
arg1 = arg0.call(subject, key, subject);
|
|
441
448
|
return typeof arg1 == "function"
|
|
442
|
-
?
|
|
443
|
-
:
|
|
449
|
+
? computed(this, key, source, arg1)
|
|
450
|
+
: recursive(this, key, source, arg1);
|
|
444
451
|
});
|
|
445
452
|
}
|
|
446
453
|
function getParentForGetInstruction(type, relativeTo, required) {
|
|
@@ -449,54 +456,26 @@ function getParentForGetInstruction(type, relativeTo, required) {
|
|
|
449
456
|
if (item)
|
|
450
457
|
callback(item);
|
|
451
458
|
else if (required)
|
|
452
|
-
throw Oops$4.Required(type
|
|
459
|
+
throw Oops$4.Required(type, relativeTo.constructor);
|
|
453
460
|
};
|
|
454
461
|
}
|
|
455
|
-
function
|
|
456
|
-
const
|
|
457
|
-
const { state } = parent;
|
|
462
|
+
function recursive(parent, key, source, required) {
|
|
463
|
+
const getter = getRecursive(key, parent);
|
|
458
464
|
let waiting;
|
|
459
465
|
source((got) => {
|
|
460
|
-
state.set(key, got);
|
|
466
|
+
parent.state.set(key, got);
|
|
461
467
|
if (waiting)
|
|
462
468
|
parent.update(key);
|
|
463
469
|
});
|
|
464
470
|
waiting = true;
|
|
465
|
-
function create(local) {
|
|
466
|
-
let reset;
|
|
467
|
-
local.follow(key, init);
|
|
468
|
-
init();
|
|
469
|
-
function init() {
|
|
470
|
-
if (reset)
|
|
471
|
-
reset();
|
|
472
|
-
const value = state.get(key);
|
|
473
|
-
if (value && controller(value)) {
|
|
474
|
-
const child = new Subscriber(value, local.onUpdate);
|
|
475
|
-
if (local.active)
|
|
476
|
-
child.commit();
|
|
477
|
-
local.dependant.add(child);
|
|
478
|
-
context.set(local, child.proxy);
|
|
479
|
-
reset = () => {
|
|
480
|
-
child.release();
|
|
481
|
-
local.dependant.delete(child);
|
|
482
|
-
context.set(local, undefined);
|
|
483
|
-
reset = undefined;
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
471
|
return (local) => {
|
|
489
|
-
const value = state.get(key);
|
|
472
|
+
const value = parent.state.get(key);
|
|
490
473
|
if (!value && required !== false)
|
|
491
474
|
parent.waitFor(key);
|
|
492
|
-
|
|
493
|
-
return value;
|
|
494
|
-
if (!context.has(local))
|
|
495
|
-
create(local);
|
|
496
|
-
return context.get(local);
|
|
475
|
+
return local ? getter(local) : value;
|
|
497
476
|
};
|
|
498
477
|
}
|
|
499
|
-
function
|
|
478
|
+
function computed(parent, key, source, setter) {
|
|
500
479
|
const { state } = parent;
|
|
501
480
|
let local;
|
|
502
481
|
let active;
|
|
@@ -557,7 +536,7 @@ function getComputed(key, parent, source, setter) {
|
|
|
557
536
|
const INFO = new WeakMap();
|
|
558
537
|
const KEYS = new WeakMap();
|
|
559
538
|
const ORDER = new WeakMap();
|
|
560
|
-
function
|
|
539
|
+
function flushComputed(control) {
|
|
561
540
|
const pending = KEYS.get(control);
|
|
562
541
|
if (!pending || !pending.size)
|
|
563
542
|
return;
|
|
@@ -651,7 +630,7 @@ class Control {
|
|
|
651
630
|
return;
|
|
652
631
|
else if (!frame.size)
|
|
653
632
|
setTimeout(() => {
|
|
654
|
-
|
|
633
|
+
flushComputed(this);
|
|
655
634
|
const keys = this.latest = Array.from(frame);
|
|
656
635
|
setTimeout(() => this.latest = undefined, 0);
|
|
657
636
|
frame.clear();
|
|
@@ -710,21 +689,19 @@ function control(subject, cb) {
|
|
|
710
689
|
|
|
711
690
|
const Parent = new WeakMap();
|
|
712
691
|
const Oops$3 = issues({
|
|
713
|
-
BadAssignment: (parent, expected, got) =>
|
|
692
|
+
BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
|
|
714
693
|
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
715
694
|
});
|
|
716
695
|
function getParent(from, type) {
|
|
717
696
|
const value = Parent.get(from);
|
|
718
697
|
if (value && type && !(value instanceof type))
|
|
719
|
-
throw Oops$3.Unexpected(type
|
|
698
|
+
throw Oops$3.Unexpected(type, from, value);
|
|
720
699
|
return value;
|
|
721
700
|
}
|
|
722
701
|
function getRecursive(key, from) {
|
|
723
702
|
const context = new WeakMap();
|
|
724
703
|
const { state } = from;
|
|
725
704
|
return (local) => {
|
|
726
|
-
if (!local)
|
|
727
|
-
return state.get(key);
|
|
728
705
|
if (!context.has(local)) {
|
|
729
706
|
let reset;
|
|
730
707
|
const init = () => {
|
|
@@ -758,8 +735,9 @@ function setRecursive(controller, key, initial) {
|
|
|
758
735
|
const onUpdate = (next) => {
|
|
759
736
|
state.set(key, next);
|
|
760
737
|
if (!(next instanceof Type))
|
|
761
|
-
throw Oops$3.BadAssignment(`${subject}.${key}`, Type
|
|
762
|
-
|
|
738
|
+
throw Oops$3.BadAssignment(`${subject}.${key}`, Type, String(next));
|
|
739
|
+
const getter = getRecursive(key, controller);
|
|
740
|
+
get = (local) => local ? getter(local) : state.get(key);
|
|
763
741
|
Parent.set(next, subject);
|
|
764
742
|
control(next);
|
|
765
743
|
return true;
|
|
@@ -1111,7 +1089,8 @@ function use(input, argument) {
|
|
|
1111
1089
|
const onUpdate = (next) => {
|
|
1112
1090
|
state.set(key, next);
|
|
1113
1091
|
if (next) {
|
|
1114
|
-
|
|
1092
|
+
const getter = getRecursive(key, this);
|
|
1093
|
+
get = (local) => local ? getter(local) : state.get(key);
|
|
1115
1094
|
Parent.set(next, subject);
|
|
1116
1095
|
control(next);
|
|
1117
1096
|
}
|
|
@@ -1167,10 +1146,10 @@ function use(input, argument) {
|
|
|
1167
1146
|
});
|
|
1168
1147
|
}
|
|
1169
1148
|
|
|
1170
|
-
const LOCAL = "
|
|
1171
|
-
const STATE = "
|
|
1172
|
-
const UPDATE = "
|
|
1173
|
-
const CONTROL = "
|
|
1149
|
+
const LOCAL = "__local";
|
|
1150
|
+
const STATE = "__state";
|
|
1151
|
+
const UPDATE = "__update";
|
|
1152
|
+
const CONTROL = "__control";
|
|
1174
1153
|
defineProperties(Model.prototype, {
|
|
1175
1154
|
[CONTROL]: {
|
|
1176
1155
|
get() {
|
|
@@ -1275,6 +1254,7 @@ exports.Subscriber = Subscriber;
|
|
|
1275
1254
|
exports.add = add;
|
|
1276
1255
|
exports["default"] = Model;
|
|
1277
1256
|
exports.get = get;
|
|
1257
|
+
exports.issues = issues;
|
|
1278
1258
|
exports.ref = ref;
|
|
1279
1259
|
exports.run = run;
|
|
1280
1260
|
exports.set = set;
|
package/package.json
CHANGED