@expressive/mvc 0.29.2 → 0.30.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 +23 -25
- package/lib/index.esm.js +12 -10
- package/lib/index.js +12 -10
- package/package.json +2 -2
package/lib/index.d.ts
CHANGED
|
@@ -58,15 +58,17 @@ declare global {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
type
|
|
62
|
-
type
|
|
61
|
+
type SelectOne<T, K extends Model.Key<T>> = K;
|
|
62
|
+
type SelectFew<T, K extends Model.Key<T>> = K[];
|
|
63
|
+
type Select<T, K extends Model.Key<T> = Model.Key<T>> = K | K[];
|
|
64
|
+
type Export<T, S> = S extends SelectOne<T, infer P> ? T[P] : S extends SelectFew<T, infer P> ? Model.Export<T, P> : never;
|
|
65
|
+
type OnUpdate<T, S> = (this: T, value: Export<T, S>, updated: Model.Event<T>[]) => void;
|
|
63
66
|
interface Observable {
|
|
64
67
|
get(): Model.Export<this>;
|
|
68
|
+
get<P extends Select<this>>(select: P): Export<this, P>;
|
|
69
|
+
get<P extends Select<this>>(select: P, onUpdate: OnUpdate<this, P>, once?: true): Callback;
|
|
70
|
+
get<P extends Select<this>>(select: P, onUpdate: OnUpdate<this, P>, initial?: false): Callback;
|
|
65
71
|
get(effect: Model.Effect<this>): Callback;
|
|
66
|
-
get<P extends Model.Key<this>>(select: P): this[P];
|
|
67
|
-
get<P extends Model.Key<this>>(select: P, onUpdate: OnValue<this, P>, once?: boolean): Callback;
|
|
68
|
-
get<P extends Model.Key<this>>(select: P[]): Model.Export<this, P>;
|
|
69
|
-
get<P extends Model.Key<this>>(select: P[], onUpdate: OnValues<this, P>, once?: boolean): Callback;
|
|
70
72
|
set(): Promise<Model.Event<this>[]>;
|
|
71
73
|
set(timeout: number): Promise<Model.Event<this>[] | false>;
|
|
72
74
|
set<T extends Model.Values<this>>(source: T, only?: (keyof T)[]): Promise<Model.Event<T>[] | false>;
|
|
@@ -82,34 +84,23 @@ declare namespace Model {
|
|
|
82
84
|
type Type<T extends Model = Model> = abstract new (...args: any[]) => T;
|
|
83
85
|
/** A typeof Model, specifically one which can be created without any arguments. */
|
|
84
86
|
type New<T extends Model = Model> = (new () => T) & typeof Model;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
current: T | null;
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* Subset of `keyof T` which are not methods or defined by base Model U.
|
|
93
|
-
**/
|
|
94
|
-
type Key<T, U = Model> = Extract<Exclude<keyof T, keyof U>, string>;
|
|
87
|
+
/** A callback function which is subscribed to parent and updates when values change. */
|
|
88
|
+
type Effect<T> = (this: T, argument: T) => Callback | Promise<void> | void;
|
|
89
|
+
/** Subset of `keyof T` which are not methods or defined by base Model U. **/
|
|
90
|
+
type Key<T, U = Observable> = Extract<Exclude<keyof T, keyof U>, string>;
|
|
95
91
|
/** Including but not limited to `keyof T` which are not methods or defined by base Model. */
|
|
96
92
|
type Event<T> = Key<T> | (string & {});
|
|
97
|
-
/** Actual value stored in state. */
|
|
98
|
-
type Value<R> = R extends Ref<infer T> ? T : R extends Observable ? Export<R> : R;
|
|
99
93
|
/** Object comperable to data found in T. */
|
|
100
94
|
type Values<T> = {
|
|
101
95
|
[P in Key<T>]?: Value<T[P]>;
|
|
102
96
|
};
|
|
103
97
|
/**
|
|
104
98
|
* Values from current state of given controller.
|
|
105
|
-
*
|
|
106
|
-
* Differs from `Entries` as values here will drill into "real" values held by exotics like ref.
|
|
99
|
+
* Differs from `Values` as values here will drill into "real" values held by exotics like ref.
|
|
107
100
|
*/
|
|
108
101
|
type Export<T, K extends Key<T> = Key<T>> = {
|
|
109
102
|
[P in K]: Value<T[P]>;
|
|
110
103
|
};
|
|
111
|
-
/** Promise thrown by something which is not yet ready. */
|
|
112
|
-
type Suspense = Promise<void> & Error;
|
|
113
104
|
/**
|
|
114
105
|
* Reference to `this` without a subscription.
|
|
115
106
|
* Use to obtain full reference from a destructure.
|
|
@@ -117,6 +108,13 @@ declare namespace Model {
|
|
|
117
108
|
type Focus<T> = T & {
|
|
118
109
|
is: T;
|
|
119
110
|
};
|
|
111
|
+
/** Exotic value, actual value is contained. */
|
|
112
|
+
type Ref<T = any> = {
|
|
113
|
+
(next: T): void;
|
|
114
|
+
current: T | null;
|
|
115
|
+
};
|
|
116
|
+
/** Actual value stored in state. */
|
|
117
|
+
type Value<R> = R extends Ref<infer T> ? T : R extends Observable ? Export<R> : R;
|
|
120
118
|
}
|
|
121
119
|
interface Model extends Observable {
|
|
122
120
|
}
|
|
@@ -346,7 +344,7 @@ declare class Control<T extends {} = any> {
|
|
|
346
344
|
static for: typeof control;
|
|
347
345
|
static apply: typeof apply;
|
|
348
346
|
static watch: typeof watch;
|
|
349
|
-
id
|
|
347
|
+
id: string | number | false;
|
|
350
348
|
subject: T;
|
|
351
349
|
state: {
|
|
352
350
|
[key: string]: any;
|
|
@@ -355,8 +353,8 @@ declare class Control<T extends {} = any> {
|
|
|
355
353
|
frame: Set<string>;
|
|
356
354
|
followers: Set<Observer<any>>;
|
|
357
355
|
observers: Map<string, Set<Observer<any>>>;
|
|
358
|
-
constructor(subject: T, id
|
|
359
|
-
add(key:
|
|
356
|
+
constructor(subject: T, id: string | number | false);
|
|
357
|
+
add(key: string): void;
|
|
360
358
|
watch(key: string, output: Control.PropertyDescriptor<any>): void;
|
|
361
359
|
ref<K extends Model.Key<T>>(key: K, callback?: (this: T, value: T[K]) => boolean | void): (value: any) => void;
|
|
362
360
|
update(key: string): void;
|
package/lib/index.esm.js
CHANGED
|
@@ -292,6 +292,7 @@ function getMethod(argument, callback, once) {
|
|
|
292
292
|
if (typeof callback != "function")
|
|
293
293
|
return extract();
|
|
294
294
|
const select = typeof argument == "string" ? [argument] : argument;
|
|
295
|
+
const invoke = () => callback(extract(), self.latest || []);
|
|
295
296
|
if (select)
|
|
296
297
|
for (const key of select)
|
|
297
298
|
try {
|
|
@@ -302,11 +303,13 @@ function getMethod(argument, callback, once) {
|
|
|
302
303
|
catch (e) {
|
|
303
304
|
// TODO: should this be caught?
|
|
304
305
|
}
|
|
306
|
+
if (once === undefined)
|
|
307
|
+
invoke();
|
|
305
308
|
const remove = self.addListener(key => {
|
|
306
309
|
if (!select || select.includes(key)) {
|
|
307
310
|
if (once)
|
|
308
311
|
remove();
|
|
309
|
-
return
|
|
312
|
+
return invoke;
|
|
310
313
|
}
|
|
311
314
|
});
|
|
312
315
|
return remove;
|
|
@@ -351,7 +354,7 @@ function setMethod(arg1, arg2) {
|
|
|
351
354
|
|
|
352
355
|
class Model {
|
|
353
356
|
constructor(id) {
|
|
354
|
-
new Control(this, id);
|
|
357
|
+
new Control(this, id === undefined ? uid() : id);
|
|
355
358
|
}
|
|
356
359
|
/** Mark this instance for garbage collection. */
|
|
357
360
|
null() {
|
|
@@ -416,7 +419,11 @@ defineProperties(Model.prototype, {
|
|
|
416
419
|
throw new Error("Model.on() is deprecated. Use Model.get or Model.set instead.");
|
|
417
420
|
}
|
|
418
421
|
}
|
|
419
|
-
});
|
|
422
|
+
});
|
|
423
|
+
/** Random alphanumberic of length 6. Will always start with a letter. */
|
|
424
|
+
function uid() {
|
|
425
|
+
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
426
|
+
}
|
|
420
427
|
|
|
421
428
|
const Oops$4 = issues({
|
|
422
429
|
BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
|
|
@@ -432,12 +439,11 @@ class Control {
|
|
|
432
439
|
this.frame = new Set();
|
|
433
440
|
this.followers = new Set();
|
|
434
441
|
this.observers = new Map([["", this.followers]]);
|
|
442
|
+
this.id = id;
|
|
435
443
|
this.subject = subject;
|
|
436
444
|
REGISTER.set(subject, this);
|
|
437
|
-
if (id !== false)
|
|
438
|
-
this.id = id === undefined ? uid() : id;
|
|
445
|
+
if (id !== false)
|
|
439
446
|
PENDING$1.set(this, new Set(Control.ready));
|
|
440
|
-
}
|
|
441
447
|
}
|
|
442
448
|
add(key) {
|
|
443
449
|
const { value } = getOwnPropertyDescriptor(this.subject, key);
|
|
@@ -608,10 +614,6 @@ function apply(instruction) {
|
|
|
608
614
|
onto.watch(key, typeof output == "function" ? { get: output } : output);
|
|
609
615
|
});
|
|
610
616
|
return placeholder;
|
|
611
|
-
}
|
|
612
|
-
/** Random alphanumberic of length 6; will always start with a letter. */
|
|
613
|
-
function uid() {
|
|
614
|
-
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
615
617
|
}
|
|
616
618
|
|
|
617
619
|
const Oops$3 = issues({
|
package/lib/index.js
CHANGED
|
@@ -296,6 +296,7 @@ function getMethod(argument, callback, once) {
|
|
|
296
296
|
if (typeof callback != "function")
|
|
297
297
|
return extract();
|
|
298
298
|
const select = typeof argument == "string" ? [argument] : argument;
|
|
299
|
+
const invoke = () => callback(extract(), self.latest || []);
|
|
299
300
|
if (select)
|
|
300
301
|
for (const key of select)
|
|
301
302
|
try {
|
|
@@ -306,11 +307,13 @@ function getMethod(argument, callback, once) {
|
|
|
306
307
|
catch (e) {
|
|
307
308
|
// TODO: should this be caught?
|
|
308
309
|
}
|
|
310
|
+
if (once === undefined)
|
|
311
|
+
invoke();
|
|
309
312
|
const remove = self.addListener(key => {
|
|
310
313
|
if (!select || select.includes(key)) {
|
|
311
314
|
if (once)
|
|
312
315
|
remove();
|
|
313
|
-
return
|
|
316
|
+
return invoke;
|
|
314
317
|
}
|
|
315
318
|
});
|
|
316
319
|
return remove;
|
|
@@ -355,7 +358,7 @@ function setMethod(arg1, arg2) {
|
|
|
355
358
|
|
|
356
359
|
class Model {
|
|
357
360
|
constructor(id) {
|
|
358
|
-
new Control(this, id);
|
|
361
|
+
new Control(this, id === undefined ? uid() : id);
|
|
359
362
|
}
|
|
360
363
|
/** Mark this instance for garbage collection. */
|
|
361
364
|
null() {
|
|
@@ -420,7 +423,11 @@ defineProperties(Model.prototype, {
|
|
|
420
423
|
throw new Error("Model.on() is deprecated. Use Model.get or Model.set instead.");
|
|
421
424
|
}
|
|
422
425
|
}
|
|
423
|
-
});
|
|
426
|
+
});
|
|
427
|
+
/** Random alphanumberic of length 6. Will always start with a letter. */
|
|
428
|
+
function uid() {
|
|
429
|
+
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
430
|
+
}
|
|
424
431
|
|
|
425
432
|
const Oops$4 = issues({
|
|
426
433
|
BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
|
|
@@ -436,12 +443,11 @@ class Control {
|
|
|
436
443
|
this.frame = new Set();
|
|
437
444
|
this.followers = new Set();
|
|
438
445
|
this.observers = new Map([["", this.followers]]);
|
|
446
|
+
this.id = id;
|
|
439
447
|
this.subject = subject;
|
|
440
448
|
REGISTER.set(subject, this);
|
|
441
|
-
if (id !== false)
|
|
442
|
-
this.id = id === undefined ? uid() : id;
|
|
449
|
+
if (id !== false)
|
|
443
450
|
PENDING$1.set(this, new Set(Control.ready));
|
|
444
|
-
}
|
|
445
451
|
}
|
|
446
452
|
add(key) {
|
|
447
453
|
const { value } = getOwnPropertyDescriptor(this.subject, key);
|
|
@@ -612,10 +618,6 @@ function apply(instruction) {
|
|
|
612
618
|
onto.watch(key, typeof output == "function" ? { get: output } : output);
|
|
613
619
|
});
|
|
614
620
|
return placeholder;
|
|
615
|
-
}
|
|
616
|
-
/** Random alphanumberic of length 6; will always start with a letter. */
|
|
617
|
-
function uid() {
|
|
618
|
-
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
619
621
|
}
|
|
620
622
|
|
|
621
623
|
const Oops$3 = issues({
|
package/package.json
CHANGED