@expressive/mvc 0.10.0 → 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 Get<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 {
@@ -125,16 +129,16 @@ declare class Model {
125
129
  on(current: true): Promise<Model.Event<this>[]>;
126
130
  on(current: null): Promise<null>;
127
131
  get(): Model.Export<this>;
128
- get<P extends Model.Field<this>>(property: P): this[P];
129
- get<P extends Model.Field<this>>(property: P, timeout: number): Promise<this[P]>;
130
- get<P extends Model.Field<this>>(property: P, onChange: true): Promise<this[P]>;
131
- get<P extends Model.Field<this>>(property: P, onChange: boolean): this[P] | Promise<this[P]>;
132
- get<P extends Model.Field<this>>(property: P, listener: (this: this, value: this[P], key: P[]) => void): Callback;
133
- get<P extends Model.Field<this>>(select: Iterable<P>): Model.Get<this, P>;
134
- get<P extends Model.Field<this>>(select: Iterable<P>, timeout: number): Promise<Model.Get<this, P>>;
135
- get<P extends Model.Field<this>>(select: Iterable<P>, onChange: true): Promise<Model.Get<this, P>>;
136
- get<P extends Model.Field<this>>(select: Iterable<P>, onChange: boolean): Model.Get<this, P> | Promise<Model.Get<this, P>>;
137
- get<P extends Model.Field<this>>(select: Iterable<P>, listener: (this: this, value: Model.Get<this, P>, key: P[]) => void): Callback;
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;
138
142
  set(key: Model.Event<this>): PromiseLike<readonly Model.Event<this>[]>;
139
143
  set<K extends Model.Event<this>>(key: Model.Event<this>, value: Model.ValueOf<this, K>): PromiseLike<readonly Model.Event<this>[]>;
140
144
  set<T extends Model.Compat<this>>(source: T, select: (keyof T)[]): PromiseLike<(keyof T)[]>;
@@ -185,8 +189,8 @@ declare class Control<T extends {} = any> {
185
189
  subscribe(callback: Subscriber.OnEvent<T>): Model.Subscriber<T>;
186
190
  watch(key: keyof T & string): void;
187
191
  addListener(listener: Control.OnSync<T>): () => void;
188
- ref<K extends Model.Field<T>>(key: K, handler?: (this: T, value: T[K]) => boolean | void): (value: any) => void;
189
- 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;
190
194
  clear(): void;
191
195
  static get<T extends {}>(from: T): Control<T> | undefined;
192
196
  static for<T extends {}>(subject: T): Control<T>;
@@ -317,10 +321,10 @@ declare namespace ref {
317
321
  }
318
322
  /** Object with references to all managed values of `T`. */
319
323
  type Proxy<T extends Model> = {
320
- [P in Model.Field<T>]-?: Model.Ref<T[P]>;
324
+ [P in Model.Key<T>]-?: Model.Ref<T[P]>;
321
325
  };
322
326
  type CustomProxy<T extends Model, R> = {
323
- [P in Model.Field<T>]-?: R;
327
+ [P in Model.Key<T>]-?: R;
324
328
  };
325
329
  }
326
330
  /**
@@ -340,7 +344,7 @@ declare function ref<T extends Model>(target: T): ref.Proxy<T>;
340
344
  * @param target - Source model from which to reference values.
341
345
  * @param mapper - Function producing the placeholder value for any given property.
342
346
  */
343
- 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>;
344
348
  /**
345
349
  * Creates a ref-compatible property.
346
350
  * Will persist value, and updates to this are made part of controller event-stream.
@@ -456,19 +460,19 @@ declare class MVC extends Model {
456
460
  /**
457
461
  * **React Hook** - Fetch specific value from instance of this controller in context.
458
462
  */
459
- static get<I extends MVC, K extends Model.Field<I>>(this: Model.Type<I>, key: K): I[K];
463
+ static get<I extends MVC, K extends Model.Key<I>>(this: Model.Type<I>, key: K): I[K];
460
464
  /**
461
465
  * **React Hook** - Fetch and subscribe to instance of this controller within ambient component.
462
466
  */
463
467
  static tap<T extends MVC>(this: Model.Type<T>): T;
464
- static tap<T extends MVC, K extends Model.Field<T>>(this: Model.Type<T>, key: K, expect: true): Exclude<T[K], undefined>;
465
- static tap<T extends MVC, K extends Model.Field<T>>(this: Model.Type<T>, key: K, expect?: boolean): T[K];
466
- static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => () => R): R;
467
- 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;
468
472
  static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R> | R, expect: true): Exclude<R, undefined>;
469
- static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): R | undefined;
470
- static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => R, expect?: boolean): R;
471
- 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;
472
476
  static use<I extends MVC>(this: Model.Type<I>, callback?: (instance: I) => void): I;
473
477
  static use<I extends MVC>(this: Model.Type<I>, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
474
478
  static meta<T extends Class>(this: T): T;
@@ -493,20 +497,20 @@ declare function useContext<T extends Model>(Type: Model.Type<T>, required: fals
493
497
  declare function useContext<T extends Model>(Type: Model.Type<T>, required?: boolean): T;
494
498
 
495
499
  declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), callback?: (instance: T) => void): T;
496
- declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), watch: Model.Field<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;
497
501
  declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
498
502
 
499
503
  declare namespace useTap {
500
504
  type Source<T extends Model> = T | Model.Type<T> | (() => T | Model.Type<T>);
501
505
  }
502
506
  declare function useTap<T extends Model>(source: useTap.Source<T>): T;
503
- declare function useTap<T extends Model, K extends Model.Field<T>>(source: useTap.Source<T>, path: K, expect: true): Exclude<T[K], undefined>;
504
- declare function useTap<T extends Model, K extends Model.Field<T>>(source: useTap.Source<T>, path: K, expect?: boolean): T[K];
505
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => () => R): R;
506
- 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;
507
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>;
508
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): R | undefined;
509
- 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>;
510
514
 
511
515
  declare namespace Consumer {
512
516
  type HasProps<E extends Class> = {
package/lib/index.esm.js CHANGED
@@ -1324,9 +1324,11 @@ function useValue(source, compute, suspend) {
1324
1324
  }
1325
1325
  defineProperty(sub, "proxy", {
1326
1326
  get() {
1327
- if (value === undefined && suspend)
1327
+ if (value !== undefined)
1328
+ return value;
1329
+ if (suspend)
1328
1330
  throw new Promise(res => retry = res);
1329
- return value;
1331
+ return null;
1330
1332
  }
1331
1333
  });
1332
1334
  return sub;