@expressive/mvc 0.9.6 → 0.10.1

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 CHANGED
@@ -4,6 +4,9 @@ type Callback = () => void;
4
4
  type Class = new (...args: any[]) => any;
5
5
  type InstanceOf<T> = T extends { prototype: infer U } ? U : never;
6
6
 
7
+ /** Type may not be undefined - instead will be null. */
8
+ type NoVoid<T> = T extends undefined ? null : T;
9
+
7
10
  declare type Listener = {
8
11
  commit(): void;
9
12
  release(): void;
@@ -22,7 +25,7 @@ declare class Subscriber<T extends {} = any> {
22
25
  dependant: Set<Listener>;
23
26
  watch: Map<any, boolean | (() => true | void)>;
24
27
  constructor(parent: Control<T>, onUpdate: Subscriber.OnEvent);
25
- get using(): Model.Field<T>[];
28
+ get using(): Model.Key<T>[];
26
29
  assign(apply: Model.Compat<T>, keys?: any): void;
27
30
  add(key: any, value?: boolean | Callback): void;
28
31
  commit: () => () => void;
@@ -71,6 +74,7 @@ declare namespace Model {
71
74
  export type Methods<T> = {
72
75
  [K in keyof T]: T[K] extends Ref ? never : T[K] extends Function ? K : never;
73
76
  }[keyof T];
77
+ type BuiltIn = keyof Model | keyof Debug<{}>;
74
78
  /**
75
79
  * Subset of `keyof T` which are not methods or defined by base Model U.
76
80
  *
@@ -78,18 +82,18 @@ declare namespace Model {
78
82
  *
79
83
  * TODO: Should exclude methods
80
84
  **/
81
- export type Field<T, E extends Model = Model> = Exclude<keyof T, keyof E | keyof Debug<{}>> & string;
85
+ export type Key<T> = Exclude<keyof T, BuiltIn> & string;
82
86
  /**
83
87
  * Including but not limited to `keyof T` which are not methods or defined by base Model.
84
88
  **/
85
- export type Event<T, E extends Model = Model> = Extends<Field<T, E>>;
89
+ export type Event<T> = Extends<Key<T>>;
86
90
  /** Object containing managed entries found in T. */
87
- export type Entries<T, E extends Model = Model> = {
88
- [K in Field<T, E>]: T[K];
91
+ export type Entries<T> = {
92
+ [K in Key<T>]: T[K];
89
93
  };
90
94
  /** Object comperable to data found in T. */
91
- export type Compat<T, E extends Model = Model> = {
92
- [K in Field<T, E>]?: T[K];
95
+ export type Compat<T> = {
96
+ [K in Key<T>]?: T[K];
93
97
  };
94
98
  /** Actual value stored in state. */
95
99
  export type Value<R> = R extends Ref<infer T> ? T : R;
@@ -100,11 +104,11 @@ declare namespace Model {
100
104
  *
101
105
  * Differs from `Entries` as values here will drill into "real" values held by exotics like ref.
102
106
  */
103
- export type Values<T, K extends Field<T> = Field<T>> = {
107
+ export type Get<T, K extends Key<T> = Key<T>> = {
104
108
  [P in K]: Value<T[P]>;
105
109
  };
106
110
  export type Export<T, E extends Model = Model> = {
107
- [P in Field<T, E>]: Value<T[P]>;
111
+ [P in Key<T>]: Value<T[P]>;
108
112
  };
109
113
  }
110
114
  declare class Model {
@@ -115,11 +119,8 @@ declare class Model {
115
119
  */
116
120
  is: this;
117
121
  constructor();
118
- on<P extends Model.Event<this>>(key: P, timeout?: number): Promise<Model.ValueOf<this, P>>;
119
- on<P extends Model.Field<this>>(key: P, listener: (this: this, value: this[P], key: P) => void, once?: boolean): Callback;
120
- on<P extends Model.Event<this>>(key: P, listener: (this: this, value: undefined, key: P) => void, once?: boolean): Callback;
121
- on<P extends Model.Event<this>>(keys: P[], timeout?: number): Promise<P[]>;
122
- on<P extends Model.Event<this>>(keys: P[], listener: (keys: P[]) => void, once?: boolean): Callback;
122
+ on<P extends Model.Event<this>>(keys?: P | Iterable<P>, timeout?: number): Promise<P[]>;
123
+ on<P extends Model.Event<this>>(keys: P | Iterable<P>, listener: (this: this, keys: Model.Event<this>[]) => void, once?: boolean): Callback;
123
124
  on(effect: Model.Effect<this>): Callback;
124
125
  on(effect: Model.Effect<this>, watch?: []): Callback;
125
126
  on(effect: Model.Effect<this>, watch?: Model.Event<this>[]): Callback;
@@ -127,17 +128,25 @@ declare class Model {
127
128
  on(current?: boolean): Promise<Model.Event<this>[] | null>;
128
129
  on(current: true): Promise<Model.Event<this>[]>;
129
130
  on(current: null): Promise<null>;
130
- export(): Model.Export<this>;
131
- export<P extends Model.Field<this>>(select: Iterable<P>): Model.Values<this, P>;
132
- update(key: Model.Event<this>): PromiseLike<readonly Model.Event<this>[]>;
133
- update(key: Model.Event<this>, callMethod: boolean): PromiseLike<readonly Model.Event<this>[]>;
134
- update<T>(key: Model.Event<this>, argument: T): PromiseLike<readonly Model.Event<this>[]>;
135
- update<T extends Model.Compat<this>>(source: T, select: (keyof T)[]): PromiseLike<(keyof T)[]>;
136
- update<T extends Model.Compat<this>>(source: T, force?: boolean): PromiseLike<(keyof T)[]>;
131
+ get(): Model.Export<this>;
132
+ get<P extends Model.Key<this>>(property: P): this[P];
133
+ get<P extends Model.Key<this>>(property: P, timeout: number): Promise<this[P]>;
134
+ get<P extends Model.Key<this>>(property: P, onChange: true): Promise<this[P]>;
135
+ get<P extends Model.Key<this>>(property: P, onChange: boolean): this[P] | Promise<this[P]>;
136
+ get<P extends Model.Key<this>>(property: P, listener: (this: this, value: this[P], key: P[]) => void): Callback;
137
+ get<P extends Model.Key<this>>(select: Iterable<P>): Model.Get<this, P>;
138
+ get<P extends Model.Key<this>>(select: Iterable<P>, timeout: number): Promise<Model.Get<this, P>>;
139
+ get<P extends Model.Key<this>>(select: Iterable<P>, onChange: true): Promise<Model.Get<this, P>>;
140
+ get<P extends Model.Key<this>>(select: Iterable<P>, onChange: boolean): Model.Get<this, P> | Promise<Model.Get<this, P>>;
141
+ get<P extends Model.Key<this>>(select: Iterable<P>, listener: (this: this, value: Model.Get<this, P>, key: P[]) => void): Callback;
142
+ set(key: Model.Event<this>): PromiseLike<readonly Model.Event<this>[]>;
143
+ set<K extends Model.Event<this>>(key: Model.Event<this>, value: Model.ValueOf<this, K>): PromiseLike<readonly Model.Event<this>[]>;
144
+ set<T extends Model.Compat<this>>(source: T, select: (keyof T)[]): PromiseLike<(keyof T)[]>;
145
+ set<T extends Model.Compat<this>>(source: T, force?: boolean): PromiseLike<(keyof T)[]>;
137
146
  /**
138
147
  * Clean up side effects and mark this instance for garbage-collection.
139
148
  */
140
- destroy(): void;
149
+ end(): void;
141
150
  /**
142
151
  * Creates a new instance of this controller.
143
152
  *
@@ -180,8 +189,8 @@ declare class Control<T extends {} = any> {
180
189
  subscribe(callback: Subscriber.OnEvent<T>): Model.Subscriber<T>;
181
190
  watch(key: keyof T & string): void;
182
191
  addListener(listener: Control.OnSync<T>): () => void;
183
- ref<K extends Model.Field<T>>(key: K, handler?: (this: T, value: T[K]) => boolean | void): (value: any) => void;
184
- update(key: Model.Field<T>): void;
192
+ ref<K extends Model.Key<T>>(key: K, handler?: (this: T, value: T[K]) => boolean | void): (value: any) => void;
193
+ update(key: Model.Key<T>): void;
185
194
  clear(): void;
186
195
  static get<T extends {}>(from: T): Control<T> | undefined;
187
196
  static for<T extends {}>(subject: T): Control<T>;
@@ -312,10 +321,10 @@ declare namespace ref {
312
321
  }
313
322
  /** Object with references to all managed values of `T`. */
314
323
  type Proxy<T extends Model> = {
315
- [P in Model.Field<T>]-?: Model.Ref<T[P]>;
324
+ [P in Model.Key<T>]-?: Model.Ref<T[P]>;
316
325
  };
317
326
  type CustomProxy<T extends Model, R> = {
318
- [P in Model.Field<T>]-?: R;
327
+ [P in Model.Key<T>]-?: R;
319
328
  };
320
329
  }
321
330
  /**
@@ -335,7 +344,7 @@ declare function ref<T extends Model>(target: T): ref.Proxy<T>;
335
344
  * @param target - Source model from which to reference values.
336
345
  * @param mapper - Function producing the placeholder value for any given property.
337
346
  */
338
- declare function ref<O extends Model, R>(target: O, mapper: (key: Model.Field<O>) => R): ref.CustomProxy<O, R>;
347
+ declare function ref<O extends Model, R>(target: O, mapper: (key: Model.Key<O>) => R): ref.CustomProxy<O, R>;
339
348
  /**
340
349
  * Creates a ref-compatible property.
341
350
  * Will persist value, and updates to this are made part of controller event-stream.
@@ -416,42 +425,54 @@ declare function use<T extends {}>(peer: T, callback?: (i: T) => void): T;
416
425
  declare function has<T extends Model>(Type: Model.Type<T>, required: false): T | undefined;
417
426
  declare function has<T extends Model>(Type: Model.Type<T>, required?: true): T;
418
427
 
428
+ declare namespace MVC {
429
+ type EffectCallback<T = MVC> = (found: T) => Callback | void;
430
+ }
419
431
  declare class MVC extends Model {
432
+ end(force?: boolean): boolean | void;
433
+ static global?: boolean;
434
+ static keepAlive?: boolean;
435
+ /**
436
+ * Create a new instance of this model and activate its managed state.
437
+ *
438
+ * @param args - arguments sent to constructor
439
+ */
440
+ static new<T extends Class>(this: T, ...args: ConstructorParameters<T>): InstanceOf<T>;
420
441
  /**
421
442
  * **React Hook** - Fetch most instance of this controller from context, if it exists.
422
443
  *
423
444
  * @param required - Unless false, will throw where instance cannot be found.
424
445
  */
425
- static get<T extends MVC>(this: Model.Type<T>, required?: boolean): T;
446
+ static get<T extends MVC>(this: Model.Type<T>, required?: boolean, effectCallback?: MVC.EffectCallback<T>): T;
426
447
  /**
427
448
  * **React Hook** - Fetch most instance of this controller from context.
428
449
  *
429
450
  * @param required - If false, may return undefined.
430
451
  */
431
- static get<T extends MVC>(this: Model.Type<T>, required: false): T | undefined;
432
- /**
433
- * **React Hook** - Fetch specific value from instance of this controller in context.
434
- */
435
- static get<I extends MVC, K extends Model.Field<I>>(this: Model.Type<I>, key: K): I[K];
452
+ static get<T extends MVC>(this: Model.Type<T>, required: false, effectCallback?: MVC.EffectCallback<T | undefined>): T | undefined;
436
453
  /**
437
454
  * **React Hook** - Fetch instance.
438
455
  *
439
456
  * Effect callback will run once if found, throw if not found.
440
457
  * Returned function is called on unmount.
441
458
  */
442
- static get<I extends MVC>(this: Model.Type<I>, effect: (found: I) => Callback | void): I;
459
+ static get<I extends MVC>(this: Model.Type<I>, effectCallback: MVC.EffectCallback<I>): I | undefined;
460
+ /**
461
+ * **React Hook** - Fetch specific value from instance of this controller in context.
462
+ */
463
+ static get<I extends MVC, K extends Model.Key<I>>(this: Model.Type<I>, key: K): I[K];
443
464
  /**
444
465
  * **React Hook** - Fetch and subscribe to instance of this controller within ambient component.
445
466
  */
446
467
  static tap<T extends MVC>(this: Model.Type<T>): T;
447
- static tap<T extends MVC, K extends Model.Field<T>>(this: Model.Type<T>, key: K, expect: true): Exclude<T[K], undefined>;
448
- static tap<T extends MVC, K extends Model.Field<T>>(this: Model.Type<T>, key: K, expect?: boolean): T[K];
449
- static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => () => R): R;
450
- static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => (() => R) | null): R | null;
468
+ static tap<T extends MVC, K extends Model.Key<T>>(this: Model.Type<T>, key: K, expect: true): Exclude<T[K], undefined>;
469
+ static tap<T extends MVC, K extends Model.Key<T>>(this: Model.Type<T>, key: K, expect?: boolean): NoVoid<T[K]>;
470
+ static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => () => R): NoVoid<R>;
471
+ static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => (() => R) | null): NoVoid<R> | null;
451
472
  static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R> | R, expect: true): Exclude<R, undefined>;
452
- static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): R | undefined;
453
- static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => R, expect?: boolean): R;
454
- static use<I extends MVC>(this: Model.Type<I>, watch: Model.Field<I>[], callback?: (instance: I) => void): I;
473
+ static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): NoVoid<R> | null;
474
+ static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => R, expect?: boolean): NoVoid<R>;
475
+ static use<I extends MVC>(this: Model.Type<I>, watch: Model.Key<I>[], callback?: (instance: I) => void): I;
455
476
  static use<I extends MVC>(this: Model.Type<I>, callback?: (instance: I) => void): I;
456
477
  static use<I extends MVC>(this: Model.Type<I>, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
457
478
  static meta<T extends Class>(this: T): T;
@@ -463,38 +484,33 @@ declare class MVC extends Model {
463
484
  static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect?: boolean): T;
464
485
  }
465
486
 
466
- declare function useValue<T extends {}, R>(source: (() => T) | T, compute: (this: T, from: T) => R, expect: true): Exclude<R, undefined>;
467
- declare function useValue<T extends {}, R>(source: (() => T) | T, compute: (this: T, from: T) => R, expect?: boolean): R;
468
-
469
487
  declare class Lookup {
470
488
  private table;
471
489
  get local(): Model[];
472
490
  private key;
473
491
  get(T: Model.Type): any;
492
+ add(T: Model.Type, I: Model, writable?: boolean): void;
474
493
  push(): this;
475
- inject(T: Model.Type, I: Model, writable?: boolean): void;
476
494
  pop(): void;
477
495
  }
478
496
  declare function useContext<T extends Model>(Type: Model.Type<T>, required: false): T | undefined;
479
- declare function useContext<T extends Model>(Type: Model.Type<T>, arg?: boolean): T;
480
- declare function useContext<T extends Model>(Type: Model.Type<T>, effect: (found: T) => Callback | void): T;
481
- declare function useContext<T extends Model, K extends Model.Field<T>>(Type: Model.Type<T>, key: K): T[K];
497
+ declare function useContext<T extends Model>(Type: Model.Type<T>, required?: boolean): T;
482
498
 
483
- declare function useModel<T extends Model>(source: Model.Type<T> | (() => T), callback?: (instance: T) => void): T;
484
- declare function useModel<T extends Model>(source: Model.Type<T> | (() => T), watch: Model.Field<T>[], callback?: (instance: T) => void): T;
485
- declare function useModel<T extends Model>(source: Model.Type<T> | (() => T), apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
499
+ declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), callback?: (instance: T) => void): T;
500
+ declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), watch: Model.Key<T>[], callback?: (instance: T) => void): T;
501
+ declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
486
502
 
487
503
  declare namespace useTap {
488
504
  type Source<T extends Model> = T | Model.Type<T> | (() => T | Model.Type<T>);
489
505
  }
490
506
  declare function useTap<T extends Model>(source: useTap.Source<T>): T;
491
- declare function useTap<T extends Model, K extends Model.Field<T>>(source: useTap.Source<T>, path: K, expect: true): Exclude<T[K], undefined>;
492
- declare function useTap<T extends Model, K extends Model.Field<T>>(source: useTap.Source<T>, path: K, expect?: boolean): T[K];
493
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => () => R): R;
494
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => (() => R) | null): R | null;
507
+ declare function useTap<T extends Model, K extends Model.Key<T>>(source: useTap.Source<T>, path: K, expect: true): Exclude<T[K], undefined>;
508
+ declare function useTap<T extends Model, K extends Model.Key<T>>(source: useTap.Source<T>, path: K, expect?: boolean): NoVoid<T[K]>;
509
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => () => R): NoVoid<R>;
510
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => (() => R) | null): NoVoid<R> | null;
495
511
  declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => Promise<R> | R, expect: true): Exclude<R, undefined>;
496
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): R | undefined;
497
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => R, expect?: boolean): R;
512
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): NoVoid<R> | null;
513
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => R, expect?: boolean): NoVoid<R>;
498
514
 
499
515
  declare namespace Consumer {
500
516
  type HasProps<E extends Class> = {
@@ -538,48 +554,24 @@ declare namespace Provider {
538
554
  type Multiple<T extends Item = Item> = T[] | {
539
555
  [key: string]: T;
540
556
  };
541
- type Existent<E> = E extends Class ? InstanceType<E> : E extends Model ? E : never;
542
- type NormalProps<E, I = Existent<E>> = {
557
+ type Instance<E> = E extends Class ? InstanceType<E> : E extends Model ? E : never;
558
+ type NormalProps<E, I = Instance<E>> = {
543
559
  for: E;
544
560
  children?: React.ReactNode | ((instance: I) => React.ReactNode);
545
- } & Model.Compat<I>;
561
+ and?: Model.Compat<I>;
562
+ };
546
563
  type MultipleProps<T extends Item> = {
547
564
  for: Multiple<T>;
548
565
  children?: React.ReactNode | (() => React.ReactNode);
549
- } & Model.Compat<Existent<T>>;
566
+ and?: Model.Compat<Instance<T>>;
567
+ };
550
568
  type Props<T extends Item> = MultipleProps<T> | NormalProps<T>;
551
569
  }
552
570
  declare function Provider<T extends Provider.Item>(props: Provider.Props<T>): React.FunctionComponentElement<React.ProviderProps<Lookup>>;
553
571
 
554
572
  declare class Global extends MVC {
555
- constructor();
556
- destroy(force?: boolean): boolean;
573
+ static global: boolean;
557
574
  static keepAlive: boolean;
558
- static new<T extends Class>(this: T, ...args: ConstructorParameters<T>): InstanceOf<T>;
559
- /**
560
- * Update the active instance of this class.
561
- * Returns a thenable; resolves after successful update.
562
- * If instance does not already exist, one will be created.
563
- */
564
- static set<T extends typeof Global>(this: T, values: Model.Compat<InstanceOf<T>, Global>): PromiseLike<Model.Field<InstanceOf<T>, Global>[]>;
565
- /**
566
- * **React Hook** - Fetch most instance of this controller from context, if it exists.
567
- *
568
- * @param required - If false, may return undefined.
569
- */
570
- static get<T extends Global>(this: Model.Type<T>, required: false): T | undefined;
571
- /**
572
- * **React Hook** - Fetch most instance of this controller from context.
573
- *
574
- * @param required - Unless false, will throw where instance cannot be found.
575
- */
576
- static get<T extends Global>(this: Model.Type<T>, required?: boolean): T;
577
- /**
578
- * **React Hook** - Fetch specific value from instance of this controller in context.
579
- */
580
- static get<T extends Global, K extends Model.Field<T, Global>>(this: Model.Type<T>, key: K): T[K];
581
- /** Destroy current instance of Global, if it exists. */
582
- static reset(): void;
583
575
  }
584
576
 
585
577
  /**
@@ -607,4 +599,4 @@ declare function tap<T extends Model>(Type: Model.Type<T>, callback?: (instance?
607
599
  declare function tap<T extends Model>(Type: Model.Type<T>, required: true): T;
608
600
  declare function tap<T extends Model>(Type: Model.Type<T>, required?: boolean): T | undefined;
609
601
 
610
- export { Consumer, Debug, Global, MVC, MVC as Model, Provider, add, MVC as default, get, has, ref, run, set, tap, use, useContext, useModel, useTap, useValue };
602
+ export { Consumer, Debug, Global, MVC, MVC as Model, Provider, add, MVC as default, get, has, ref, run, set, tap, use, useContext, useNew, useTap };