@expressive/mvc 1.0.0-beta.33 → 1.0.0-beta.36

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.
@@ -1,5 +1,5 @@
1
1
  import Model from '.';
2
- import { Async, Class, InstanceOf, InterceptCallback } from './types';
2
+ import { Async, Class, InstanceOf } from './types';
3
3
 
4
4
  /**
5
5
  * Run instruction as controller sets itself up.
@@ -15,57 +15,22 @@ export function use <T extends Model> (): T | undefined;
15
15
  /**
16
16
  * Create a new child instance of model.
17
17
  */
18
- export function use <T extends Class> (Type: T): InstanceOf<T>;
19
-
20
- /**
21
- * Create a new child-instance of specified controller, in readonly mode.
22
- * Will prevent assignment of new value.
23
- *
24
- * **Note:** This is only enforced at runtime. Use
25
- * [`readonly`](https://www.typescriptlang.org/docs/handbook/2/classes.html#readonly), if writing in typescript.
26
- */
27
- export function use <T extends Class> (Type: T, readonly: true): InstanceOf<T>;
28
- export function use <T extends Model> (from: () => T, readonly: true): T;
29
-
30
- /**
31
- * Create a new child-instance of specified controller, in optional mode.
32
- * Will allow assignment of undefined, and likewise should be checked before usage.
33
- */
34
- export function use <T extends Class> (Type: T, required: false): InstanceOf<T> | undefined;
35
- export function use <T extends Model> (from: () => T | undefined, required: false): T | undefined;
36
-
37
- /**
38
- * Create a new child-instance of specified controller.
39
- *
40
- * By default, property is non-nullable. If callback returns `true` the first time, will be in readonly mode.
41
- * If callback returns false, property may also be set to undefined, as needed.
42
- */
43
- export function use <T extends Class> (Type: T, callback: (i: InstanceOf<T>) => true): InstanceOf<T>;
44
- export function use <T extends Class> (Type: T, callback: (i: InstanceOf<T>) => false): InstanceOf<T> | undefined;
45
- export function use <T extends Class> (Type: T, callback: (i: InstanceOf<T>) => void): InstanceOf<T>;
18
+ export function use <T extends Class> (Type: T, callback?: (i: InstanceOf<T>) => void): InstanceOf<T>;
46
19
 
47
20
  /**
48
21
  * Create a new child-instance from factory function.
49
22
  */
50
- export function use <T extends Model> (from: () => T): T;
51
- export function use <T extends Model> (from: () => T, callback: (i: T) => true): T;
52
- export function use <T extends Model> (from: () => T | undefined, callback: (i: T) => false): T | undefined;
53
- export function use <T extends Model> (from: () => T, callback: (i: T) => void): T;
23
+ export function use <T extends Model> (from: () => T, callback?: (i: T) => void): T;
54
24
 
55
25
  /**
56
- * Createa child-instance relationship with provided model.
26
+ * Create child-instance relationship with provided model.
57
27
  *
58
28
  * Note: If `peer` is not already initialized before parent is
59
29
  * (created with `new` as opposed to create method), that model will
60
30
  * attach this via `parent()` instruction. It will not, if
61
31
  * already active.
62
32
  */
63
- export function use <T extends Model> (peer: T): T;
64
- export function use <T extends Model> (peer: T, readonly: true): T;
65
- export function use <T extends Model> (peer: T, required: false): T | undefined;
66
- export function use <T extends Model> (peer: T, callback: (i: T) => true): T;
67
- export function use <T extends Model> (peer: T, callback: (i: T) => false): T | undefined;
68
- export function use <T extends Model> (peer: T, callback: (i: T) => void): T;
33
+ export function use <T extends Model> (peer: T, callback?: (i: T) => void): T;
69
34
 
70
35
  /**
71
36
  * Generate a child controller from specified object. Object's values are be trackable, as would be for a full-model.
@@ -74,12 +39,19 @@ export function use <T extends Model> (peer: T, callback: (i: T) => void): T;
74
39
  */
75
40
  export function use <T extends {}> (object: T): T;
76
41
 
42
+ export namespace child {
43
+ type Instruction<T> = (this: Model.Controller, key: string) => {
44
+ get: () => T | undefined,
45
+ set?: (value: T | undefined) => void
46
+ }
47
+ }
48
+
77
49
  /**
78
50
  * Generic instruction used by `use()` and `tap()` for recursive subscription.
79
51
  *
80
52
  * @param from - Instruction body is run upon parent create. Return function to fetch current value of field.
81
53
  */
82
- export function child <T extends Model> (from: (this: Model.Controller, key: string) => () => T | undefined): T;
54
+ export function child <T extends Model> (from: child.Instruction<T>): T;
83
55
 
84
56
  /**
85
57
  * Fetches and assigns the controller which spawned this host.
@@ -117,6 +89,11 @@ export function tap <T extends typeof Model> (Type: T, callback?: (instance?: In
117
89
  */
118
90
  export function tap <T extends Class> (Type: T, required?: boolean): InstanceOf<T>;
119
91
 
92
+ export namespace on {
93
+ type Callback<T, S = any> = (this: S, argument: T) =>
94
+ ((next: T) => void) | Promise<any> | void | boolean;
95
+ }
96
+
120
97
  /**
121
98
  * Cause property to synchronously run effect upon update.
122
99
  *
@@ -132,14 +109,19 @@ export function tap <T extends Class> (Type: T, required?: boolean): InstanceOf<
132
109
  *
133
110
  * @deprecated will be removed in favor of `set`
134
111
  */
135
- export function on <T> (initialValue: undefined, onUpdate: InterceptCallback<T>): T | undefined;
136
- export function on <T> (initialValue: T, onUpdate: InterceptCallback<T>): T;
137
- export function on <T, S> (initialValue: undefined, onUpdate: InterceptCallback<T, S>): T | undefined;
138
- export function on <T, S> (initialValue: T, onUpdate: InterceptCallback<T, S>): T;
112
+ export function on <T> (initialValue: undefined, onUpdate: on.Callback<T>): T | undefined;
113
+ export function on <T> (initialValue: T, onUpdate: on.Callback<T>): T;
114
+ export function on <T, S> (initialValue: undefined, onUpdate: on.Callback<T, S>): T | undefined;
115
+ export function on <T, S> (initialValue: T, onUpdate: on.Callback<T, S>): T;
139
116
 
140
117
  /** Object with references to all managed values of `T`. */
141
118
  export type Refs <T extends Model> = { [P in Model.Fields<T>]: Model.Ref<T[P]> };
142
119
 
120
+ export namespace ref {
121
+ type Callback<T, S = any> = (this: S, argument: T) =>
122
+ ((next: T) => void) | Promise<any> | void | boolean;
123
+ }
124
+
143
125
  /**
144
126
  * Creates an object with references to all managed values.
145
127
  * Each property will set value in state when invoked.
@@ -158,8 +140,8 @@ export function ref <T extends Model> (target: T): Refs<T>;
158
140
  *
159
141
  * @param callback - Optional callback to synchronously fire when reference is first set or does update.
160
142
  */
161
- export function ref <T = HTMLElement> (callback?: InterceptCallback<T>): Model.Ref<T>;
162
- export function ref <T, S> (callback?: InterceptCallback<T, S>): Model.Ref<T>;
143
+ export function ref <T = HTMLElement> (callback?: ref.Callback<T>): Model.Ref<T>;
144
+ export function ref <T, S> (callback?: ref.Callback<T, S>): Model.Ref<T>;
163
145
 
164
146
  /**
165
147
  * Sets an exotic method with managed ready-state. Property accepts an async function.
@@ -267,7 +249,12 @@ export function pending <R, T> (waitFor: (this: T) => Promise<R>): R;
267
249
  */
268
250
  export function pending <R, T> (source: T, compute: (this: T, on: T) => R): R; // ✅
269
251
 
270
- type FactoryFunction<T, S = unknown> = (this: S, key: string, subject: S) => T;
252
+ export namespace set {
253
+ type Factory<T, S = unknown> = (this: S, key: string, subject: S) => T;
254
+
255
+ type Callback<T, S = any> = (this: S, argument: T) =>
256
+ ((next: T) => void) | Promise<any> | void | boolean;
257
+ }
271
258
 
272
259
  /**
273
260
  * Set property with a placeholder.
@@ -289,8 +276,8 @@ type FactoryFunction<T, S = unknown> = (this: S, key: string, subject: S) => T;
289
276
  export function set <T> (value: undefined, required: false): T | undefined;
290
277
  export function set <T> (value: undefined, required?: boolean): T;
291
278
 
292
- export function set <T> (value: undefined, onUpdate: InterceptCallback<T>): T | undefined;
293
- export function set <T, S> (value: undefined, onUpdate: InterceptCallback<T, S>): T | undefined;
279
+ export function set <T> (value: undefined, onUpdate: set.Callback<T>): T | undefined;
280
+ export function set <T, S> (value: undefined, onUpdate: set.Callback<T, S>): T | undefined;
294
281
 
295
282
  /**
296
283
  * Set property with an async function.
@@ -307,14 +294,14 @@ type FactoryFunction<T, S = unknown> = (this: S, key: string, subject: S) => T;
307
294
  * @param factory - Callback run to derrive property value.
308
295
  * @param required - (default: true) Run factory immediately on creation, otherwise on access.
309
296
  */
310
- export function set <T>(factory: FactoryFunction<Promise<T>>, required: false): T | undefined;
311
- export function set <T, S>(factory: FactoryFunction<Promise<T>, S>, required: false): T | undefined;
297
+ export function set <T>(factory: set.Factory<Promise<T>>, required: false): T | undefined;
298
+ export function set <T, S>(factory: set.Factory<Promise<T>, S>, required: false): T | undefined;
312
299
 
313
- export function set <T>(factory: FactoryFunction<Promise<T>>, required?: boolean): T;
314
- export function set <T, S>(factory: FactoryFunction<Promise<T>, S>, required?: boolean): T;
300
+ export function set <T>(factory: set.Factory<Promise<T>>, required?: boolean): T;
301
+ export function set <T, S>(factory: set.Factory<Promise<T>, S>, required?: boolean): T;
315
302
 
316
- export function set <T> (value: FactoryFunction<Promise<T>>, onUpdate: InterceptCallback<T>): T;
317
- export function set <T, S> (value: FactoryFunction<Promise<T>, S>, onUpdate: InterceptCallback<T, S>): T;
303
+ export function set <T> (value: set.Factory<Promise<T>>, onUpdate: set.Callback<T>): T;
304
+ export function set <T, S> (value: set.Factory<Promise<T>, S>, onUpdate: set.Callback<T, S>): T;
318
305
 
319
306
  /**
320
307
  * Set property with a factory function.
@@ -328,12 +315,12 @@ type FactoryFunction<T, S = unknown> = (this: S, key: string, subject: S) => T;
328
315
  * @param factory - Callback run to derrive property value.
329
316
  * @param required - (default: true) Run factory immediately on creation, otherwise on access.
330
317
  */
331
- export function set <T>(factory: FactoryFunction<T>, required: false): T | undefined;
332
- export function set <T, S>(factory: FactoryFunction<T, S>, required: false): T | undefined;
318
+ export function set <T>(factory: set.Factory<T>, required: false): T | undefined;
319
+ export function set <T, S>(factory: set.Factory<T, S>, required: false): T | undefined;
333
320
 
334
- export function set <T>(factory: FactoryFunction<T>, required?: boolean): T;
335
- export function set <T, S>(factory: FactoryFunction<T, S>, required?: boolean): T;
321
+ export function set <T>(factory: set.Factory<T>, required?: boolean): T;
322
+ export function set <T, S>(factory: set.Factory<T, S>, required?: boolean): T;
336
323
 
337
- export function set <T> (value: FactoryFunction<T>, onUpdate: InterceptCallback<T>): T;
338
- export function set <T, S> (value: FactoryFunction<T, S>, onUpdate: InterceptCallback<T, S>): T;
324
+ export function set <T> (value: set.Factory<T>, onUpdate: set.Callback<T>): T;
325
+ export function set <T, S> (value: set.Factory<T, S>, onUpdate: set.Callback<T, S>): T;
339
326
 
@@ -1,4 +1,6 @@
1
- import { Key } from "./types";
1
+ declare namespace Lifecycle {
2
+ type Key = string | symbol | number;
3
+ }
2
4
 
3
5
  /**
4
6
  * Model-Component Lifecycle
@@ -8,17 +10,17 @@ import { Key } from "./types";
8
10
  * call these respectively to that component's lifecycle.
9
11
  */
10
12
  interface Lifecycle {
11
- didMount?(tag?: Key): void;
12
- willRender?(tag?: Key): void;
13
- willUpdate?(tag?: Key): void;
14
- willMount?(tag?: Key): void;
15
- willUnmount?(tag?: Key): void;
13
+ didMount?(tag?: Lifecycle.Key): void;
14
+ willRender?(tag?: Lifecycle.Key): void;
15
+ willUpdate?(tag?: Lifecycle.Key): void;
16
+ willMount?(tag?: Lifecycle.Key): void;
17
+ willUnmount?(tag?: Lifecycle.Key): void;
16
18
 
17
- elementDidMount?(tag: Key): void;
18
- elementWillRender?(tag: Key): void;
19
- elementWillUpdate?(tag: Key): void;
20
- elementWillMount?(tag: Key): void;
21
- elementWillUnmount?(tag: Key): void;
19
+ elementDidMount?(tag: Lifecycle.Key): void;
20
+ elementWillRender?(tag: Lifecycle.Key): void;
21
+ elementWillUpdate?(tag: Lifecycle.Key): void;
22
+ elementWillMount?(tag: Lifecycle.Key): void;
23
+ elementWillUnmount?(tag: Lifecycle.Key): void;
22
24
 
23
25
  componentDidMount?(): void;
24
26
  componentWillRender?(): void;
package/types/model.d.ts CHANGED
@@ -1,19 +1,12 @@
1
1
  import { Key } from 'react';
2
2
 
3
3
  import Lifecycle from './lifecycle';
4
- import { Select, Selector } from './selector';
5
- import { BunchOf, Callback, Class, InstanceOf, Query, RequestCallback, UpdateCallback } from './types';
6
-
7
- interface PropertyDescriptor<T> {
8
- configurable?: boolean;
9
- enumerable?: boolean;
10
- value?: T;
11
- writable?: boolean;
12
- get?(): T;
13
- set?(v: T): void;
14
- }
4
+ import { BunchOf, Class, InstanceOf } from './types';
15
5
 
6
+ type Callback = () => void;
16
7
  type Argument<T> = T extends (arg: infer U) => any ? U : never;
8
+ type IfApplicable<T extends {}, K> = K extends keyof T ? T[K] : undefined;
9
+ type Including<T> = T | (string & Record<never, never>);
17
10
 
18
11
  type Thenable<T> = {
19
12
  then(onFulfilled: (arg: T) => void): void;
@@ -26,17 +19,29 @@ export namespace Model {
26
19
  current: T | null;
27
20
  }
28
21
 
29
- type GetFunction<T> = (within?: Subscriber) => T;
22
+ type UpdateCallback<T, P> = (this: T, value: IfApplicable<T, P>, changed: P) => void;
23
+
24
+ type EffectCallback<T> = (this: T, argument: T) => Callback | Promise<any> | void;
30
25
 
31
26
  /**
32
27
  * Property initializer, will run upon instance creation.
33
28
  * Optional returned callback will run when once upon first access.
34
29
  */
35
30
  type Instruction<T> = (this: Controller, key: string, thisArg: Controller) =>
36
- void | GetFunction<T> | PropertyDescriptor<T>;
37
-
38
- /** Shallow replacement given all entries of Model */
39
- type Overlay<T, R> = { [K in keyof Entries<T>]: R };
31
+ void | Instruction.Getter<T> | Instruction.Descriptor<T>;
32
+
33
+ namespace Instruction {
34
+ interface Descriptor<T> {
35
+ configurable?: boolean;
36
+ enumerable?: boolean;
37
+ value?: T;
38
+ writable?: boolean;
39
+ get?(current: T | undefined, within?: Subscriber): T;
40
+ set?(value: T, state: any): boolean | void;
41
+ }
42
+
43
+ type Getter<T> = (state: T | undefined, within?: Subscriber) => T;
44
+ }
40
45
 
41
46
  /** Subset of `keyof T` excluding keys defined by base Model */
42
47
  type Fields<T, E = Model> = Exclude<keyof T, keyof E>;
@@ -52,87 +57,48 @@ export namespace Model {
52
57
  [P in K]: Value<T[P]>;
53
58
  }
54
59
 
55
- /** Object comperable to data which may be found in T. */
56
- type Data<T, E = Model> = Partial<Entries<T, E>>;
60
+ /** Object comperable to data found in T. */
61
+ type Compat<T, Exclude = Model> = Partial<Entries<T, Exclude>>;
57
62
 
58
63
  /** Subset of `keyof T` excluding keys defined by base Model, except lifecycle. */
59
64
  type Events<T> = Omit<T, Exclude<keyof Model, keyof Lifecycle>>;
60
65
 
61
- type EventsCompat<T> = keyof T | keyof Lifecycle;
62
-
63
- /**
64
- * Field selector which includes Model-Lifecycle events.
65
- * Can select for any tracked-property on a specified controller.
66
- *
67
- * Function `SelectEvent<T>` is a preferred alterative to string `keyof T`.
68
- *
69
- * ---
70
- *
71
- * ```js
72
- * Model.on(x => x.foo.bar.didMountComponent, cb)
73
- * ```
74
- * is equivalent to, while also more robust than:
75
- * ```js
76
- * Model.on(["foo", "bar", "didMountComponent"], cb)
77
- * ```
78
- */
79
- type SelectEvents<T> = Selector.Function<Events<T>>;
80
-
81
- /**
82
- * Field selector function you provide. Argument is a representation of controller specified.
83
- * *When used as an argument*, return a chain of properties desired for a given operation.
84
- *
85
- * Allows for refactor safe selection of properties belonging to a controller.
86
- * Using selectors is generally recommended to prevent unexpected behavior to be caused by bundling of your code.
87
- *
88
- * ---
89
- *
90
- * **Selector used to update specific properties:**
91
- *
92
- * ```js
93
- * Model.update(x => x.foo.bar.baz)
94
- * ```
95
- *
96
- * is equivalent to, while more robust than:
97
- *
98
- * ```js
99
- * Model.update(["foo", "bar", "baz"])
100
- * ```
101
- */
102
- type SelectFields<T> = Selector.Function<Omit<T, keyof Model>>;
103
-
104
- type SelectField<T> = (arg: Omit<T, keyof Model>) => any;
105
-
106
- type SelectFieldKey<T> = Select.Key<Fields<T>>;
66
+ type EventsCompat<T> = Including<keyof T | keyof Lifecycle>;
107
67
 
108
68
  type Typeof<T, ST, X extends keyof T = Exclude<keyof T, keyof Model>> = {
109
69
  [Key in X]: T[Key] extends ST ? Key : never;
110
70
  }[X];
111
71
 
112
- type SelectTypeof<T, ST> = Select.Key<Typeof<T, ST>>;
113
-
114
- type HandleValue = (value: any) => boolean | void;
115
-
116
72
  export namespace Controller {
117
- export type Listen = (key: string, source: Controller) =>
73
+ type RequestCallback = (keys: readonly string[]) => void;
74
+
75
+ type OnEvent = (key: string, source: Controller) =>
118
76
  RequestCallback | undefined;
77
+
78
+ type OnValue = <T>(this: T, value: any, state: T) => boolean | void;
119
79
  }
120
80
 
121
81
  export class Controller {
122
82
  state: BunchOf<any>;
123
83
  subject: {};
124
- waiting: Set<RequestCallback>;
84
+ waiting: Set<Controller.RequestCallback>;
85
+ frame: Set<string>;
125
86
 
126
- /** Add property to managed state. */
127
- manage(key: string, initial: any, effect?: HandleValue): void;
87
+ start(): this;
128
88
 
129
- select(using?: Query): string[];
89
+ manage(key: string, effect?: Controller.OnValue): void;
130
90
 
131
- setter(key: string, effect?: HandleValue): (value: any) => boolean | void;
91
+ setter(key: string, effect?: Controller.OnValue): (value: any) => boolean | void;
132
92
 
133
- addListener(listener: Controller.Listen): Callback;
93
+ addListener(listener: Controller.OnEvent): Callback;
134
94
 
135
95
  update(key: string, value?: any): void;
96
+
97
+ requestUpdate(): PromiseLike<readonly string[] | false>;
98
+ requestUpdate(strict: true): Promise<readonly string[]>;
99
+ requestUpdate(strict: false): Promise<false>;
100
+ requestUpdate(strict: boolean): Promise<readonly string[] | false>;
101
+ requestUpdate(callback: Controller.RequestCallback): void;
136
102
  }
137
103
 
138
104
  export class Subscriber {
@@ -140,13 +106,13 @@ export namespace Model {
140
106
  source: any;
141
107
  parent: Controller;
142
108
  active: boolean;
143
- listen: Controller.Listen;
109
+ listen: Controller.OnEvent;
144
110
  dependant: Set<{
145
111
  commit(): void;
146
112
  release(): void;
147
113
  }>;
148
114
 
149
- follow(key: string, cb?: RequestCallback | undefined): void;
115
+ follow(key: string, cb?: Controller.RequestCallback | undefined): void;
150
116
  commit(): Callback;
151
117
  release(): Callback;
152
118
  onUpdate(): void;
@@ -154,7 +120,7 @@ export namespace Model {
154
120
  }
155
121
 
156
122
  declare const CONTROL: unique symbol;
157
- declare const UPDATE: unique symbol;
123
+ declare const WHY: unique symbol;
158
124
  declare const LOCAL: unique symbol;
159
125
  declare const STATE: unique symbol;
160
126
 
@@ -175,7 +141,7 @@ export abstract class Model {
175
141
  * If accessed directly, will contain all keys from last push.
176
142
  * If within a subscribed function, will contain only keys which explicitly caused a refresh.
177
143
  **/
178
- [UPDATE]?: readonly string[];
144
+ [WHY]?: readonly string[];
179
145
 
180
146
  /**
181
147
  * Circular reference to `this` controller.
@@ -236,25 +202,19 @@ export abstract class Model {
236
202
  */
237
203
  set: this;
238
204
 
239
- import <O extends Model.Data<this>> (via: O, select?: string[] | Model.SelectFields<this>): void;
205
+ import <O extends Model.Compat<this>> (via: O, select?: string[]): void;
240
206
 
241
207
  export(): Model.State<this>;
242
208
  export <P extends Model.Fields<this>> (select: P[]): Model.State<this, P>;
243
- export <S extends Model.SelectFields<this>> (select: S): Model.State<this, Selector.From<S>>;
244
209
 
245
210
  update(): PromiseLike<readonly string[] | false>;
246
211
  update(strict: true): Promise<readonly string[]>;
247
212
  update(strict: false): Promise<false>;
248
213
  update(strict: boolean): Promise<readonly string[] | false>;
249
214
 
250
- update(keys: Model.Fields<this>): Thenable<readonly string[]>;
251
- update(keys: Model.SelectFieldKey<this>): Thenable<readonly string[]>;
252
-
253
- update(keys: Model.Fields<this>, callMethod: boolean): PromiseLike<readonly string[]>;
254
- update(keys: Model.SelectFields<this>, callMethod: boolean): PromiseLike<readonly string[]>;
255
-
256
- update<T>(keys: Model.Fields<this>, argument: T): PromiseLike<readonly string[]>;
257
- update<T>(keys: Model.SelectFields<this>, argument: T): PromiseLike<readonly string[]>;
215
+ update(keys: Including<Model.Fields<this>>): Thenable<readonly string[]>;
216
+ update(keys: Including<Model.Fields<this>>, callMethod: boolean): PromiseLike<readonly string[]>;
217
+ update<T>(keys: Including<Model.Fields<this>>, argument: T): PromiseLike<readonly string[]>;
258
218
 
259
219
  /*
260
220
  Issue with self-reference, using fallback.
@@ -289,45 +249,41 @@ export abstract class Model {
289
249
  tap(): this;
290
250
 
291
251
  /** Tracks specific key of this controller within a component. */
292
- tap <K extends Model.Fields<this>> (key: K, expect?: boolean): this[K];
293
252
  tap <K extends Model.Fields<this>> (key: K, expect: true): Exclude<this[K], undefined>;
253
+ tap <K extends Model.Fields<this>> (key: K, expect?: boolean): this[K];
254
+
255
+ tap <T> (from: (this: this, state: this) => Promise<T>, expect: true): Exclude<T, undefined>;
256
+ tap <T> (from: (this: this, state: this) => Promise<T>, expect?: boolean): T | undefined;
294
257
 
295
- tap <T> (from: (this: this, state: this) => T, expect?: boolean): T;
296
258
  tap <T> (from: (this: this, state: this) => T, expect: true): Exclude<T, undefined>;
259
+ tap <T> (from: (this: this, state: this) => T, expect?: boolean): T;
297
260
 
298
261
  // Keyed
299
- on <S extends Model.SelectEvents<this>> (via: S, cb: Selector.Callback<S, this>, squash?: false, once?: boolean): Callback;
300
- on <P = Model.EventsCompat<this>> (keys: [], listener: UpdateCallback<this, P>, squash?: false, once?: boolean): Callback;
301
- on <P extends Model.EventsCompat<this>> (key: P | P[], listener: UpdateCallback<this, P>, squash?: false, once?: boolean): Callback;
262
+ on <P = Model.EventsCompat<this>> (keys: [], listener: Model.UpdateCallback<this, P>, squash?: false, once?: boolean): Callback;
263
+ on <P extends Model.EventsCompat<this>> (key: P | P[], listener: Model.UpdateCallback<this, P>, squash?: false, once?: boolean): Callback;
302
264
  // Squash
303
- on <S extends Model.SelectEvents<this>> (via: S, cb: (keys: Selector.From<S>[]) => void, squash: true, once?: boolean): Callback;
304
265
  on <P = Model.EventsCompat<this>> (keys: [], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
305
266
  on <P extends Model.EventsCompat<this>> (key: P | P[], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
306
267
  // Unknown
307
- on <S extends Model.SelectEvents<this>> (via: S, cb: unknown, squash: boolean, once?: boolean): Callback;
308
268
  on (keys: [], listener: unknown, squash: boolean, once?: boolean): Callback;
309
269
  on <P extends Model.EventsCompat<this>> (key: P | P[], listener: unknown, squash: boolean, once?: boolean): Callback;
310
270
 
311
271
  // Keyed
312
- once <S extends Model.SelectEvents<this>> (via: S, cb: Selector.Callback<S, this>, squash?: false): Callback;
313
- once <P = Model.EventsCompat<this>> (keys: [], listener: UpdateCallback<this, P>, squash?: false, once?: boolean): Callback;
314
- once <P extends Model.EventsCompat<this>> (key: P | P[], listener: UpdateCallback<this, P>, squash?: false): Callback;
272
+ once <P = Model.EventsCompat<this>> (keys: [], listener: Model.UpdateCallback<this, P>, squash?: false, once?: boolean): Callback;
273
+ once <P extends Model.EventsCompat<this>> (key: P | P[], listener: Model.UpdateCallback<this, P>, squash?: false): Callback;
315
274
  // Squash
316
- once <S extends Model.SelectEvents<this>> (via: S, cb: (keys: Selector.From<S>[]) => void, squash: true): Callback;
317
275
  once <P = Model.EventsCompat<this>> (keys: [], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
318
276
  once <P extends Model.EventsCompat<this>> (key: P | P[], listener: (keys: P[]) => void, squash: true): Callback;
319
277
  // Promise
320
- once <S extends Model.SelectEvents<this>> (via: S): Promise<Selector.From<S>[]>;
321
278
  once <P = Model.EventsCompat<this>> (keys: [], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
322
279
  once <P extends Model.EventsCompat<this>> (key: P | P[]): Promise<P[]>;
323
280
  // Unknown
324
- once <S extends Model.SelectEvents<this>> (via: S, cb: unknown, squash: boolean): Callback;
325
281
  once (keys: [], listener: unknown, squash: boolean, once?: boolean): Callback;
326
282
  once <P extends Model.EventsCompat<this>> (key: P | P[], listener: unknown, squash: boolean): Callback;
327
283
 
328
- effect(callback: (this: this, state: this) => void, select?: Model.SelectFields<this>): Callback;
329
- effect(callback: (this: this, state: this) => void, select?: []): Callback;
330
- effect(callback: (this: this, state: this) => void, select?: (keyof this)[]): Callback;
284
+ effect(callback: Model.EffectCallback<this>): Callback;
285
+ effect(callback: Model.EffectCallback<this>, select: []): Callback;
286
+ effect(callback: Model.EffectCallback<this>, select: (keyof this)[]): Callback;
331
287
 
332
288
  /**
333
289
  * **React Hook** - Attach to instance of this controller within a component.
@@ -366,7 +322,7 @@ export abstract class Model {
366
322
  static LOCAL: typeof LOCAL;
367
323
 
368
324
  /** Use symbol to access keys affected by last update. */
369
- static WHY: typeof UPDATE;
325
+ static WHY: typeof WHY;
370
326
 
371
327
  /**
372
328
  * Creates a new instance of this controller.
@@ -413,36 +369,25 @@ export abstract class Model {
413
369
  */
414
370
  static using <T extends Class, I extends InstanceOf<T>, D extends Partial<I>> (this: T, data: D, only?: (keyof D)[]): I;
415
371
 
416
- /**
417
- * **React Hook** - Locate most relevant instance of this type in context.
418
- */
419
- static find <T extends Class>(this: T, strict: true): InstanceOf<T>;
420
- static find <T extends Class>(this: T, strict?: boolean): InstanceOf<T> | undefined;
421
-
422
372
  /**
423
373
  * **React Hook** - Fetch most instance of this controller from context, if it exists.
424
374
  *
425
- * @param expect - If true, will throw where controller cannot be found. Otherwise, may return undefined.
375
+ * @param required - If false, may return undefined.
426
376
  */
427
- static get <T extends Class> (this: T, expect?: boolean): InstanceOf<T> | undefined;
377
+ static get <T extends Class> (this: T, required?: true): InstanceOf<T>;
428
378
 
429
379
  /**
430
380
  * **React Hook** - Fetch most instance of this controller from context.
431
381
  *
432
- * @param expect - Will throw if controller cannot be found.
382
+ * @param required - Unless false, will throw where instance cannot be found.
433
383
  */
434
- static get <T extends Class> (this: T, expect: true): InstanceOf<T>;
384
+ static get <T extends Class> (this: T, required: boolean): InstanceOf<T> | undefined;
435
385
 
436
386
  /**
437
387
  * **React Hook** - Fetch specific value from instance of this controller in context.
438
388
  */
439
389
  static get <T extends Class, I extends InstanceOf<T>, K extends Model.Fields<I>> (this: T, key: K): I[K];
440
390
 
441
- /**
442
- * **React Hook** - Fetch specific value from instance of this controller in context.
443
- */
444
- static get <T extends Class, I extends InstanceOf<T>, K extends Model.SelectField<I>> (this: T, key?: K): ReturnType<K>;
445
-
446
391
  /**
447
392
  * **React Hook** - Fetch and subscribe to instance of this controller within ambient component.
448
393
  */
@@ -451,17 +396,14 @@ export abstract class Model {
451
396
  /**
452
397
  * **React Hook** - Fetch and subscribe to a value on applicable instance within ambient component.
453
398
  */
399
+ static tap <T extends Class, I extends InstanceOf<T>, K extends Model.Fields<I>> (this: T, key: K, expect: true): Exclude<I[K], undefined>;
454
400
  static tap <T extends Class, I extends InstanceOf<T>, K extends Model.Fields<I>> (this: T, key: K, expect?: boolean): I[K];
455
- static tap <T, M extends Class, I extends InstanceOf<M>> (this: M, from: (this: I, state: I) => T, expect?: boolean): T;
456
401
 
457
- /**
458
- * **React Hook** - Fetch and subscribe to a value on applicable instance within ambient component.
459
- *
460
- * **(In Expect Mode)** - Will throw of value is undefined.
461
- * This makes return type non-nullable and convenient to use without optional chaining.
462
- */
463
- static tap <T extends Class, I extends InstanceOf<T>, K extends Model.Fields<I>> (this: T, key: K, expect: true): Exclude<I[K], undefined>;
402
+ static tap <T, M extends Class, I extends InstanceOf<M>> (this: M, from: (this: I, state: I) => Promise<T>, expect: true): Exclude<T, undefined>;
403
+ static tap <T, M extends Class, I extends InstanceOf<M>> (this: M, from: (this: I, state: I) => Promise<T>, expect?: boolean): T | undefined;
404
+
464
405
  static tap <T, M extends Class, I extends InstanceOf<M>> (this: M, from: (this: I, state: I) => T, expect: true): Exclude<T, undefined>;
406
+ static tap <T, M extends Class, I extends InstanceOf<M>> (this: M, from: (this: I, state: I) => T, expect?: boolean): T;
465
407
 
466
408
  /**
467
409
  * **React Hook** - Attach to instance of this controller within ambient component.
@@ -481,21 +423,16 @@ export abstract class Model {
481
423
  */
482
424
  static tag <T extends Class, I extends InstanceOf<T>> (this: T, idFactory: (on: I) => Key | void): I;
483
425
 
484
- /**
485
- * **React Hook** - Fetch and subscribe to *class itself* within a component.
486
- *
487
- * This allows you to do pretty meta stuff.
488
- *
489
- * Documentation TBD.
490
- */
491
426
  static meta <T extends Class>(this: T): T;
492
427
 
493
- /**
494
- * **React Hook** - Fetch and subscribe to value defined on class itself using selectors.
495
- *
496
- * Documentation TBD.
497
- */
498
- static meta <T extends Class, K extends Model.SelectField<T>> (this: T, key?: K): ReturnType<K>;
428
+ static meta <T extends Class, K extends keyof T> (this: T, key: K, expect: true): Exclude<T[K], undefined>;
429
+ static meta <T extends Class, K extends keyof T> (this: T, key: K, expect?: boolean): T[K];
430
+
431
+ static meta <T, M extends Class> (this: M, from: (this: M, state: M) => Promise<T>, expect: true): Exclude<T, undefined>;
432
+ static meta <T, M extends Class> (this: M, from: (this: M, state: M) => Promise<T>, expect?: boolean): T | undefined;
433
+
434
+ static meta <T, M extends Class> (this: M, from: (this: M, state: M) => T, expect: true): Exclude<T, undefined>;
435
+ static meta <T, M extends Class> (this: M, from: (this: M, state: M) => T, expect?: boolean): T;
499
436
 
500
437
  /**
501
438
  * Static equivalent of `x instanceof this`.
@@ -506,16 +443,13 @@ export abstract class Model {
506
443
  }
507
444
 
508
445
  export class Singleton extends Model {
509
- /** Get current instance of this singleton. Will throw if one does not exist. */
510
- static is<T extends Class>(this: T): InstanceOf<T>;
511
-
512
446
  /**
513
447
  * Update the active instance of this class.
514
448
  * Returns a thenable; resolves after successful update.
515
449
  * If instance does not already exist, one will be created.
516
450
  **/
517
- static update<T extends Class>(
518
- this: T, updates: Model.Data<InstanceOf<T>>
451
+ static set<T extends Class>(
452
+ this: T, updates: Model.Compat<InstanceOf<T>>
519
453
  ): PromiseLike<string[] | false>;
520
454
 
521
455
  /** Destroy current instance of Singleton, if it exists. */