@expressive/mvc 0.34.0 → 0.35.0-alpha.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.
@@ -14,44 +14,29 @@ type Async<T = any, Y extends any[] = any> = {
14
14
  */
15
15
  declare function run<T, Y extends any[]>(action: (...args: Y) => T | Promise<T>): Async<T, Y>;
16
16
 
17
- type Callback = () => void;
18
-
19
- declare global {
20
- namespace jest {
21
- interface Matchers<R> {
22
- /** Assert model does have one or more updates pending. */
23
- toUpdate(): Promise<R>;
24
-
25
- /** Assert model did update with keys specified. */
26
- toHaveUpdated<R>(...keys: string[]): Promise<R>;
27
- }
28
- }
29
- }
30
-
31
- type InstanceOf<T> = T extends {
32
- prototype: infer U;
33
- } ? U : never;
34
- type Class = new (...args: any[]) => any;
35
17
  type Predicate = (key: string) => boolean | void;
36
18
  declare namespace Model {
37
- /** Any typeof Model, using class constructor as the reference. */
19
+ /** Any type of Model, using own class constructor as its identifier. */
38
20
  type Type<T extends Model = Model> = abstract new (...args: any[]) => T;
39
- /** A typeof Model, specifically one which can be created without any arguments. */
21
+ /** A type of Model which may be created without constructor arguments. */
40
22
  type New<T extends Model = Model> = (new () => T) & typeof Model;
41
23
  /** Subset of `keyof T` which are not methods or defined by base Model U. **/
42
24
  type Key<T> = Exclude<keyof T, keyof Model> & string;
25
+ type Any<T> = Exclude<keyof T, keyof Model> | (string & {});
43
26
  /** Actual value stored in state. */
44
27
  type Value<R> = R extends Ref<infer T> ? T : R extends Model ? Export<R> : R;
45
- /** Object comperable to data found in T. */
46
- type Values<T> = {
47
- [P in Key<T>]?: Value<T[P]>;
48
- };
28
+ type ValueOf<T extends Model, K extends Any<T>> = K extends keyof T ? T[K] extends Ref<infer V> ? V : T[K] : unknown;
49
29
  /**
50
30
  * Values from current state of given controller.
51
- * Differs from `Values` as values here will drill into "real" values held by exotics like ref.
31
+ * Differs from `Values` as values here will drill
32
+ * into "real" values held by exotics like ref.
52
33
  */
53
34
  type Export<T> = {
54
- [P in keyof T]: Value<T[P]>;
35
+ [P in Key<T>]: Value<T[P]>;
36
+ };
37
+ /** Object comperable to data found in T. */
38
+ type Values<T> = {
39
+ [P in Key<T>]?: Value<T[P]>;
55
40
  };
56
41
  /** Exotic value, where actual value is contained within. */
57
42
  type Ref<T = any> = {
@@ -59,29 +44,55 @@ declare namespace Model {
59
44
  current: T | null;
60
45
  };
61
46
  /** A callback function which is subscribed to parent and updates when values change. */
62
- type Effect<T> = (this: T, argument: T) => Callback | Promise<void> | void;
47
+ type Effect<T> = (this: T, argument: T) => Callback | Promise<void> | null | void;
63
48
  type Event = (key: string) => Callback | void;
49
+ namespace Instruction {
50
+ type Getter<T> = (source: Model) => T;
51
+ type Setter<T> = (value: T, previous: T) => boolean | void | (() => T);
52
+ type Descriptor<T = any> = {
53
+ get?: Getter<T> | boolean;
54
+ set?: Setter<T> | false;
55
+ enumerable?: boolean;
56
+ value?: T;
57
+ };
58
+ }
59
+ /**
60
+ * Property initializer, will run upon instance creation.
61
+ * Optional returned callback will run when once upon first access.
62
+ */
63
+ type Instruction<T = any, M extends Model = any> = (this: M, key: Model.Key<M>, thisArg: M, state: Model.Export<M>) => Instruction.Descriptor<T> | Instruction.Getter<T> | void;
64
64
  }
65
- declare class Model {
65
+ interface Model {
66
+ /**
67
+ * Loopback to instance of this model. This is useful when in a subscribed context,
68
+ * to keep write access to `this` after a destructure. You can use it to read variables silently as well.
69
+ **/
66
70
  is: this;
71
+ }
72
+ declare class Model {
67
73
  constructor(id?: string | number);
68
74
  /** Pull current values from state. Flattens all models and exotic values amongst properties. */
69
75
  get(): Model.Export<this>;
70
- /** Run a function which will automatically run again when accessed properties change. */
76
+ /** Run a function which will run automatically when accessed values change. */
71
77
  get(effect: Model.Effect<this>): Callback;
72
- /** Assert update is in progress. Returns a promise which resolves updated keys. */
78
+ get<T extends string>(key: T, required: true): Exclude<Model.ValueOf<this, T>, undefined>;
79
+ get<T extends string>(key: T, required?: boolean): Model.ValueOf<this, T>;
80
+ /**
81
+ * Check if update is in progress.
82
+ * Returns a promise which resolves updated keys. If no update, will resolve `false`.
83
+ **/
73
84
  set(): Promise<Model.Values<this> | false>;
74
85
  /**
75
- * Expect an update to state within timeout.
86
+ * Expect an update to state within a set timeout.
76
87
  *
77
88
  * @param timeout - milliseconds to wait for update
78
- * @param predicate - optional function to filter updates. If returns true, update is accepted.
89
+ * @param predicate - optional function to filter for specific updates. If returns true, update is accepted.
79
90
  *
80
- * @returns a promise which resolves full update.
91
+ * @returns a promise to resolve when next accepted update has occured.
81
92
  */
82
93
  set(timeout: number, predicate?: Predicate): Promise<Model.Values<this>>;
83
94
  /**
84
- * Call a function when an update to state has occured.
95
+ * Call a function whenever an update to state has occured.
85
96
  *
86
97
  * @param callback - Function to call when any update occurs.
87
98
  * Note: This will be called for every assignment which changes the value.
@@ -89,11 +100,26 @@ declare class Model {
89
100
  * Returning the same function for the same (or multiple for that matter)
90
101
  * will ensure it is only called once.
91
102
  *
92
- * @returns a function to remove listener
103
+ * @returns a function to remove listener. Will return true if listener did exist.
93
104
  */
94
- set(callback: Model.Event): Callback;
95
- /** Mark this instance for garbage collection. */
96
- null(): void;
105
+ set(callback: Model.Event): () => boolean;
106
+ /**
107
+ * Push an update without changing the value of associated property.
108
+ *
109
+ * This is useful where a property value internally has changed, but the object remains the same.
110
+ * For example: an array which has pushed a new value, or change to nested properties.
111
+ */
112
+ set(key: string | null): void;
113
+ /**
114
+ * Update a property programatically within state.
115
+ *
116
+ * @param key - property to update
117
+ * @param value - value to update property with (if the same as current, no update will occur)
118
+ * @param silent - if true, will not notify listeners of an update
119
+ */
120
+ set<K extends string>(key: K, value?: Model.ValueOf<this, K>, silent?: boolean): void;
121
+ /** Iterate over managed properties in this instance of Model. */
122
+ [Symbol.iterator](): Iterator<[string, unknown]>;
97
123
  /**
98
124
  * Creates a new instance of this controller.
99
125
  *
@@ -101,7 +127,7 @@ declare class Model {
101
127
  *
102
128
  * @param args - arguments sent to constructor
103
129
  */
104
- static new<T extends Class>(this: T, ...args: ConstructorParameters<T>): InstanceOf<T>;
130
+ static new<T extends typeof Model>(this: T, ...args: ConstructorParameters<T>): InstanceType<T>;
105
131
  /**
106
132
  * Static equivalent of `x instanceof this`.
107
133
  * Determines if provided class is a subtype of this one.
@@ -110,29 +136,12 @@ declare class Model {
110
136
  */
111
137
  static is<T extends Model.Type>(this: T, maybe: any): maybe is T;
112
138
  }
113
-
114
- declare namespace Context {
115
- type Inputs = {
116
- [key: string | number]: Model | Model.New;
117
- };
118
- }
119
- declare class Context {
120
- key: string;
121
- private table;
122
- private layer;
123
- private has;
124
- get<T extends Model>(Type: Model.Type<T>): T | undefined;
125
- include(inputs: Context.Inputs): Map<Model, boolean>;
126
- add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
127
- push(): this;
128
- pop(): void;
129
- }
139
+ declare function add<T = any, M extends Model = any>(instruction: Model.Instruction): T;
130
140
 
131
141
  declare namespace get {
132
142
  type Function<T, S = any> = (this: S, on: S) => T;
133
143
  type Factory<R, T> = (this: T, property: string, on: T) => Function<R, T>;
134
144
  type Source<T extends Model = Model> = (resolve: (x: T) => void) => void;
135
- function from(target: Model): (resolve: (got: Context) => void) => void;
136
145
  }
137
146
  /**
138
147
  * Fetches and assigns the controller which spawned this host.
@@ -281,93 +290,23 @@ declare function use<T extends Model>(model: T, ready?: (i: T) => void): T;
281
290
  /** Create a managed object with observable entries. */
282
291
  declare function use<T extends {}, O = use.Object<T>>(data: T, ready?: (object: O) => void): O;
283
292
 
284
- declare namespace Control {
285
- /**
286
- * Property initializer, will run upon instance creation.
287
- * Optional returned callback will run when once upon first access.
288
- */
289
- type Instruction<T> = (this: Control, key: string, thisArg: Control) => PropertyDescriptor<T> | Getter<T> | void;
290
- type Getter<T> = (source: Model) => T;
291
- type Setter<T> = (value: T, previous: T) => boolean | void;
292
- type PropertyDescriptor<T = any> = {
293
- get?: Getter<T>;
294
- set?: Setter<T> | false;
295
- enumerable?: boolean;
296
- value?: T;
293
+ declare namespace Context {
294
+ type Inputs = {
295
+ [key: string | number]: Model | Model.New;
297
296
  };
298
- type Callback = (control: Control) => void;
299
- /**
300
- * Callback for Controller.for() static method.
301
- * Returned callback is forwarded.
302
- */
303
- type OnReady<T extends {}> = (control: Control<T>) => (() => void) | void;
304
- type OnUpdate<T extends {} = any> = (key: Model.Key<T> | null | undefined, source: T) => (() => void) | null | void;
305
- type OnChange = (this: {}, next: unknown, previous: unknown) => boolean | void;
306
297
  }
307
- declare class Control<T extends {} = any> {
308
- static watch: typeof watch;
309
- static for: typeof control;
310
- static add: typeof add;
311
- static on(event: "ready", callback: Control.Callback): Callback;
312
- static on(event: "update" | "didUpdate", callback: Callback): Callback;
313
- id: string;
314
- subject: T;
315
- state: {
316
- [property: string]: unknown;
317
- };
318
- frame: {
319
- [property: string]: unknown;
320
- };
321
- listeners: Map<Control.OnUpdate, Set<string> | undefined>;
322
- constructor(subject: T, id?: string | number | false);
323
- watch(key: string, output: Control.PropertyDescriptor<any>): void;
324
- update(key: string, value?: unknown): void;
325
- fetch(key: string, required?: boolean): () => unknown;
326
- addListener<T extends Model>(fn: Control.OnUpdate<T>): () => boolean;
327
- clear(): void;
298
+ declare class Context {
299
+ static resolve(from: Model, callback: (context: Context) => void): void;
300
+ constructor(inputs?: Context.Inputs);
301
+ key: string;
302
+ private table;
303
+ private layer;
304
+ private has;
305
+ get<T extends Model>(Type: Model.Type<T>): T | undefined;
306
+ include(inputs: Context.Inputs): Map<Model, boolean>;
307
+ protected add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
308
+ push(): this;
309
+ pop(): void;
328
310
  }
329
- declare function control<T extends Model>(subject: T, ready: Control.OnReady<T>): Callback;
330
- declare function control<T extends Model>(subject: T, ready?: boolean): Control<T>;
331
- declare function watch<T extends {}>(value: T, argument: Control.OnUpdate): T;
332
- declare function add<T = any>(instruction: Control.Instruction<T>): T;
333
-
334
- declare const STATE = "__state";
335
- declare const UPDATE = "__update";
336
- declare const CONTROL = "__control";
337
- declare const PARENT = "__parent";
338
- declare const Debug: {
339
- /** Use to access snapshot of Model's current state. */
340
- STATE: "__state";
341
- /**
342
- * Use to access snapshot of Model's latest update.
343
- */
344
- UPDATE: "__update";
345
- /** Use to access a Model's controller. */
346
- CONTROL: "__control";
347
- /** Use to access a Model's parent, if exists. */
348
- PARENT: "__parent";
349
- };
350
- /**
351
- * Generic will declare debug properties on a given Model.
352
- *
353
- * These properties always exist at runtime, however are hidden unless you cast your Model as `Debug<T>`.
354
- */
355
- type Debug<T extends Model = Model> = T & {
356
- /** Controller for this instance. */
357
- [CONTROL]?: Control<T>;
358
- /** Current state of this instance. */
359
- [STATE]?: Model.Export<T>;
360
- /**
361
- * Last update causing a refresh to subscribers.
362
- *
363
- * If accessed directly, will contain all keys from last push.
364
- * If within a subscribed function, will contain only keys which explicitly caused a refresh.
365
- */
366
- [UPDATE]?: Model.Values<T>;
367
- /**
368
- * Parent currently assigned to parent. Usually the model which this one is a property of.
369
- */
370
- [PARENT]?: Model;
371
- };
372
311
 
373
- export { Context, Control, Debug, Model, Model as default, get, ref, run, set, use };
312
+ export { Context, Model, add, Model as default, get, ref, run, set, use };