@expressive/mvc 0.52.1 → 0.53.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/dist/index.d.ts CHANGED
@@ -1,3 +1,30 @@
1
+ /**
2
+ * Update callback function.
3
+ *
4
+ * @param key -
5
+ * - `string` - property which has updated.
6
+ * - `false` - a normal update has completed.
7
+ * - `true` - initial event; instance is ready.
8
+ * - `null` - terminal event; instance is expired.
9
+ * @param source - Instance of Model for which update has occured.
10
+ */
11
+ type OnUpdate<T extends Model = any> = (this: T, key: unknown, source: T) => (() => void) | null | void;
12
+ type OnAccess<T extends Model = any, R = unknown> = (from: T, key: string | number, value: R) => unknown;
13
+ type Effect<T extends Model> = (this: T, proxy: T) => ((update: boolean | null) => void) | Promise<void> | null | void;
14
+ type Event = number | string | null | boolean | symbol;
15
+ declare function addListener<T extends Model>(subject: T, callback: OnUpdate<T>, select?: Event): () => boolean;
16
+ declare function createProxy<T extends Model>(from: T, observer: OnAccess<T>): T;
17
+ /**
18
+ * Create a side-effect which will update whenever values accessed change.
19
+ * Callback is called immediately and if ever values are stale.
20
+ *
21
+ * @param target - Instance of Model to observe.
22
+ * @param callback - Function to invoke when values change.
23
+ * @param requireValues - If `true` will throw if accessing a value which is `undefined`.
24
+ */
25
+ declare function createEffect<T extends Model>(target: T, callback: Effect<Required<T>>, requireValues: true): () => void;
26
+ declare function createEffect<T extends Model>(target: T, callback: Effect<T>, requireValues?: boolean): () => void;
27
+
1
28
  declare namespace Model {
2
29
  /** Any type of Model, using own class constructor as its identifier. */
3
30
  type Type<T extends Model = Model> = (abstract new (...args: any[]) => T) & typeof Model;
@@ -27,7 +54,7 @@ declare namespace Model {
27
54
  /** Value for a property managed by a model. */
28
55
  type Value<T extends Model, K extends Event<T>> = K extends keyof T ? Export<T[K]> : unknown;
29
56
  type OnEvent<T extends Model> = (this: T, key: unknown, source: T) => (() => void) | void | null;
30
- type OnUpdate<T extends Model, K extends Event<T>> = (this: T, value: Value<T, K>, key: K, thisArg: K) => void;
57
+ type OnUpdate<T extends Model, K extends Event<T>> = (this: T, key: K, thisArg: K) => void;
31
58
  /**
32
59
  * Values from current state of given model.
33
60
  * Differs from `Values` as values here will drill
@@ -133,29 +160,18 @@ declare abstract class Model {
133
160
  /**
134
161
  * Get update in progress.
135
162
  *
136
- * @returns Promise which resolves object with updated values. Is `undefined` if there is no update.
163
+ * @returns Promise which resolves object with updated values, `undefined` if there no update is pending.
137
164
  **/
138
165
  set(): PromiseLike<Model.Event<this>[]> | undefined;
139
166
  /**
140
- * Call a function when update occurs.
141
- *
142
- * Given function is called for every assignment (which changes value) or explicit `set`.
143
- *
144
- * To run logic on final value only, callback may return a function. Using the same
145
- * function for one or more events will ensure it is called only when events are settled.
146
- *
147
- * @param callback - Function to call when update occurs.
148
- * @returns Function to remove listener. Will return `true` if removed, `false` if inactive already.
149
- *
150
- */
151
- set(callback: Model.OnEvent<this>): () => boolean;
152
- /**
153
- * Declare an end to updates. This event is final and will freeze state.
154
- * This event can be watched for as well, to run cleanup logic and internally will remove all listeners.
167
+ * Update mulitple properties at once. Merges argument with current state.
168
+ * Properties which are not managed by this model will be ignored.
155
169
  *
156
- * @param status - `null` to end updates.
170
+ * @param assign - Object with properties to update.
171
+ * @param silent - If an update does occur, listeners will not be refreshed automatically.
172
+ * @returns Promise resolving an array of keys updated, `undefined` (immediately) if a noop.
157
173
  */
158
- set(status: null): void;
174
+ set(assign: Model.Assign<this>, silent?: boolean): PromiseLike<Model.Event<this>[]> | undefined;
159
175
  /**
160
176
  * Push an update. This will not change the value of associated property.
161
177
  *
@@ -172,25 +188,28 @@ declare abstract class Model {
172
188
  */
173
189
  set(key: Model.Event<this>): PromiseLike<Model.Event<this>[]>;
174
190
  /**
175
- * Update mulitple properties at once. Merges argument with current state.
176
- * Properties which are not managed by this model will be ignored.
191
+ * Call a function when update occurs.
177
192
  *
178
- * @param assign - Object with properties to update.
179
- * @returns Promise resolving an array of keys updated, `undefined` (immediately) if a noop.
180
- */
181
- set(assign: Model.Assign<this>): PromiseLike<Model.Event<this>[]> | undefined;
193
+ * Given function is called for every assignment (which changes value) or explicit `set`.
194
+ *
195
+ * To run logic on final value only, callback may return a function. Using the same
196
+ * function for one or more events will ensure it is called only when events are settled.
197
+ *
198
+ * @param callback - Function to call when update occurs.
199
+ * @returns Function to remove listener. Will return `true` if removed, `false` if inactive already.
200
+ *
201
+ */
202
+ set(callback: Model.OnEvent<this>): () => boolean;
182
203
  /**
183
- * Update a property with value.
204
+ * Declare an end to updates. This event is final and will freeze state.
205
+ * This event can be watched for as well, to run cleanup logic and internally will remove all listeners.
184
206
  *
185
- * @param key - property to update
186
- * @param value - value to update property with (if the same as current, no update will occur)
187
- * @param silent - if true, will not notify listeners of an update
188
- * @returns Promise resolving an array of keys updated, `undefined` (immediately) if a noop.
207
+ * @param status - `null` to end updates.
189
208
  */
190
- set<K extends string>(key: K, value: Model.Value<this, K>, silent?: boolean): PromiseLike<Model.Event<this>[]> | undefined;
209
+ set(status: null): void;
191
210
  /**
192
211
  * Iterate over managed properties in this instance of Model.
193
- * Yeilds the key and underlying value for each property.
212
+ * Yeilds the key and current value for each property.
194
213
  */
195
214
  [Symbol.iterator](): Iterator<[string, unknown]>;
196
215
  /**
@@ -215,9 +234,10 @@ declare abstract class Model {
215
234
  }
216
235
 
217
236
  declare namespace get {
218
- type Function<T, S = any> = (on: S, key: string) => T;
237
+ type Compute<T, S = any> = (on: S, key: string) => T;
219
238
  type Factory<T, S = any> = (this: S, key: string, thisArg: S) => T;
220
239
  type Source<T extends Model = Model> = (resolve: (x: T) => void) => void;
240
+ type Effect<T> = (model: T, key: string) => (() => void) | void;
221
241
  }
222
242
  /**
223
243
  * Fetches and assigns the controller which spawned this host.
@@ -244,14 +264,14 @@ declare function get<T extends Model>(Type: Model.Type<T>, required?: false): T
244
264
  * @param source - Type of Model to fetch for computation.
245
265
  * @param compute - Compute function. Will update automatically as input values change.
246
266
  */
247
- declare function get<R, T extends Model>(Type: Model.Type<T>, compute: get.Function<R, T>): R;
267
+ declare function get<R, T extends Model>(Type: Model.Type<T>, effect: get.Effect<T>): R;
248
268
  /**
249
269
  * Implement a computed value; output will be generated by provided function.
250
270
  *
251
271
  * @param source - Source model from which computed value will be a subscriber.
252
272
  * @param compute - Compute function. Bound to a subscriber-proxy of source, returns output value. Will update automatically as input values change.
253
273
  */
254
- declare function get<R, T extends Model>(source: T, compute: get.Function<R, T>): R;
274
+ declare function get<R, T extends Model>(source: T, compute: get.Compute<R, T>): R;
255
275
  /**
256
276
  * Implement a computed value; output is returned by function from provided factory.
257
277
  *
@@ -326,10 +346,10 @@ declare namespace set {
326
346
  type Factory<T, S = any> = (this: S, key: string) => Promise<T> | T;
327
347
  }
328
348
  /**
329
- * Set property with a placeholder.
349
+ * Set property as `undefined` but required.
330
350
  *
331
351
  * Property cannot be accessed until it is defined. If accessed while undefined, a hybrid
332
- * `Promise`/`Error` (ala: [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html)) will be thrown.
352
+ * `Promise`/`Error` (aka: [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html)) will be thrown.
333
353
  */
334
354
  declare function set<T = any>(): T;
335
355
  /**
@@ -367,20 +387,12 @@ declare namespace has {
367
387
  declare function has<T extends Model>(type: Model.Type<T>, callback?: has.Callback<T>): readonly T[];
368
388
  declare function has(callback?: has.Callback): readonly Model[];
369
389
 
370
- type Effect<T extends {}> = (this: T, argument: T) => ((update: boolean | null) => void) | Promise<void> | null | void;
371
- /**
372
- * Create a side-effect which will update whenever values accessed change.
373
- * Callback is called immediately and if ever values are stale.
374
- *
375
- * @param target - Instance of Model to observe.
376
- * @param callback - Function to invoke when values change.
377
- * @param requireValues - If `true` will throw if accessing a value which is `undefined`.
378
- */
379
- declare function effect<T extends {}>(target: T, callback: Effect<Required<T>>, requireValues: true): () => void;
380
- declare function effect<T extends {}>(target: T, callback: Effect<T>, requireValues?: boolean): () => void;
381
-
382
390
  declare namespace Context {
383
- type Input = Record<string | number, Model | Model.Init>;
391
+ type Multiple<T extends Model> = {
392
+ [key: string | number]: Model.Init<T> | T;
393
+ };
394
+ type Accept<T extends Model = Model> = T | Model.Init<T> | Multiple<T>;
395
+ type ForEach = (added: Model, explicit: boolean) => void;
384
396
  type Expect = (model: Model) => (() => void) | void;
385
397
  }
386
398
  interface Context {
@@ -392,13 +404,15 @@ declare class Context {
392
404
  id: string;
393
405
  protected layer: Map<string | number, Model | Model.Type<Model>>;
394
406
  protected cleanup: Set<() => void>;
395
- constructor(inputs?: Context.Input);
407
+ constructor(inputs?: Context.Accept);
408
+ /** Run callback when a specified type is registered to a **child** context. */
409
+ has<T extends Model>(Type: Model.Type<T>, callback: (model: T) => void): void;
410
+ /** Find specified type registered to a parent context. Returns undefined if none are found. */
396
411
  get<T extends Model>(Type: Model.Type<T>): T | undefined;
397
- get<T extends Model>(Type: Model.Type<T>, callback: (model: T) => void): void;
398
- push(inputs?: Context.Input): this;
412
+ push(inputs?: Context.Accept): this;
399
413
  pop(): void;
400
- include(inputs: Context.Input, forEach?: (added: Model, explicit: boolean) => void): void;
414
+ include<T extends Model>(inputs: Context.Accept<T>, forEach?: Context.ForEach | Model.Assign<T>): void;
401
415
  protected add<T extends Model>(input: T | Model.Init<T>, implicit?: boolean): T;
402
416
  }
403
417
 
404
- export { Context, Model, Model as default, effect, get, has, ref, set, use };
418
+ export { Context, Model, addListener, createEffect, createProxy, Model as default, get, has, ref, set, use };