@expressive/mvc 1.0.0-beta.18 → 1.0.0-beta.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressive/mvc",
3
- "version": "1.0.0-beta.18",
3
+ "version": "1.0.0-beta.21",
4
4
  "description": "Use classes to define state in React!",
5
5
  "author": {
6
6
  "name": "Gabe Klein",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "keywords": [
16
16
  "react",
17
- "hooks"
17
+ "mvc"
18
18
  ],
19
19
  "main": "lib/index.js",
20
20
  "types": "types/index.d.ts",
@@ -24,14 +24,9 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "build": "rollup --config",
27
- "watch": "rollup --config --sourcemap --watch",
28
- "prebuild": "rm -rf lib/",
29
- "publish:pre": "npm version prerelease --preid=beta",
30
- "preversion": "jest --coverage",
31
- "postversion": "npm run build; npm publish",
32
- "postpublish": "git push; git push --tags; rm -rf lib",
33
- "coverage": "jest --collectCoverage",
34
- "test": "jest --watchAll"
27
+ "watch": "jest --watchAll",
28
+ "test": "jest --collectCoverage",
29
+ "prebuild": "rm -rf lib/"
35
30
  },
36
31
  "peerDependencies": {
37
32
  "react": ">=17.0.2"
package/types/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export {
2
- State,
3
2
  Model,
4
3
  Model as default,
5
4
  Singleton
@@ -1,11 +1,11 @@
1
- import Model, { Selector } from '.';
1
+ import Model from '.';
2
2
  import { Async, Class, InstanceOf, InterceptCallback } from './types';
3
3
 
4
4
  /**
5
5
  * Run instruction as controller sets itself up.
6
6
  * This will specialize the behavior of a given property.
7
7
  **/
8
- export function set <T = any> (instruction: Model.Instruction<T>, name?: string): T;
8
+ export function apply <T = any> (instruction: Model.Instruction<T>, name?: string): T;
9
9
 
10
10
  /**
11
11
  * Creates a new child-instance of specified controller.
@@ -117,14 +117,24 @@ export function on <T = any> (initialValue: undefined, onUpdate: InterceptCallba
117
117
  export function on <T = any> (initialValue: T, onUpdate: InterceptCallback<T>): T;
118
118
 
119
119
  /**
120
- * Creates a ref-compatible property for use with components.
120
+ * Creates an object with references to all managed values.
121
+ * Each property will set value in state when invoked.
122
+ *
123
+ * *Properties are simultaneously a ref-function and ref-object, use as needed.*
124
+ *
125
+ * @param target - Source model from which to reference values.
126
+ */
127
+ export function ref <T = Model> (target: T): { [P in Model.Fields<T>]: Model.Ref<T[P]> };
128
+
129
+ /**
130
+ * Creates a ref-compatible property.
121
131
  * Will persist value, and updates to this are made part of controller event-stream.
122
132
  *
123
133
  * *Output is simultaneously a ref-function and ref-object, use as needed.*
124
134
  *
125
135
  * @param callback - Optional callback to synchronously fire when reference is first set or does update.
126
136
  */
127
- export function ref <T = HTMLElement> (this: any, callback?: InterceptCallback<T>): Model.Ref<T>;
137
+ export function ref <T = HTMLElement> (callback?: InterceptCallback<T>): Model.Ref<T>;
128
138
 
129
139
  /**
130
140
  * Sets an exotic method with managed ready-state. Property accepts an async function.
@@ -141,29 +151,29 @@ export function act <T extends Async> (action: T): T & { active: boolean };
141
151
  /**
142
152
  * Implement a computed value; output is returned by function from provided factory.
143
153
  *
144
- * @param fn - Factory function to generate a getter to subscribe dependancies.
154
+ * @param compute - Factory function to generate a getter to subscribe dependancies.
145
155
  */
146
- export function from <R> (fn: (property: string) => (this: any, state: any) => R): R;
156
+ export function from <R> (compute: (property: string) => (this: any, state: any) => R): R;
147
157
 
148
158
  /**
149
159
  * Implement a computed value; output will be generated by provided function.
150
160
  *
151
161
  * @param source - Source Model to find and subscribe to, for input.
152
162
  *
153
- * @param fn - Compute function. Bound to a subscriber-proxy of source, returns output value.
154
- * Will update automatically as accessed values change.
163
+ * @param compute - Compute function. Bound to a subscriber-proxy of source, returns output value.
164
+ * Will update automatically as input values change.
155
165
  */
156
- export function from <T extends Class, R> (source: T, fn: (this: InstanceOf<T>, on: InstanceOf<T>) => R): R;
166
+ export function from <T extends Class, R> (source: T, compute: (this: InstanceOf<T>, on: InstanceOf<T>) => R): R;
157
167
 
158
168
  /**
159
169
  * Implement a computed value; output will be generated by provided function.
160
170
  *
161
- * @param source - Source model from which computed value will be subscribed.
171
+ * @param source - Source model from which computed value will be a subscriber.
162
172
  *
163
- * @param fn - Compute function. Bound to a subscriber-proxy of source, returns output value.
164
- * Will update automatically as accessed values change.
173
+ * @param compute - Compute function. Bound to a subscriber-proxy of source, returns output value.
174
+ * Will update automatically as input values change.
165
175
  */
166
- export function from <T, R> (source: T, fn: (this: T, on: T) => R): R;
176
+ export function from <T, R> (source: T, compute: (this: T, on: T) => R): R;
167
177
 
168
178
  /**
169
179
  * Memoized value. Computes and stores a value returned by provided factory.
@@ -179,4 +189,31 @@ export function memo <T> (compute: () => T, lazy?: boolean): T;
179
189
  *
180
190
  * @param value - starting value of property.
181
191
  */
182
- export function lazy <T> (value?: T): T;
192
+ export function lazy <T> (value?: T): T;
193
+
194
+ /**
195
+ * Suspend during the execution of given function to obtain value.
196
+ *
197
+ * @param waitFor - Async function to suspend for.
198
+ */
199
+ export function pending (waitFor: () => Promise<void>): undefined;
200
+ export function pending <T> (waitFor: () => Promise<T>): T;
201
+
202
+ /**
203
+ * Suspend for a computed value, returned by syncronous function.
204
+ *
205
+ * If accessed while computing to undefined, will throw a promise. Function is subscribed
206
+ * and will re-evaluate anytime used properties change. Once function returns any value,
207
+ * outstanding promises resolve and are not thrown on subsequent access of this property.
208
+ *
209
+ * Similar to `from`, compute function will only run when inputs change and not upon access.
210
+ *
211
+ * This behavior is recursive. If return value _becomes_ undefined, property
212
+ * access will throw Promises again, awaiting its next value.
213
+ *
214
+ * @param source - Source object, from which computed value will be a subscriber.
215
+ *
216
+ * @param compute - Compute function returns output value. Bound to a subscriber of source.
217
+ * Will re-run automatically as input values change.
218
+ */
219
+ export function pending <T, R> (source: T, compute: (this: T, on: T) => R): Exclude<R, undefined>;
package/types/model.d.ts CHANGED
@@ -1,6 +1,8 @@
1
+ import { Key } from 'react';
2
+
1
3
  import Lifecycle from './lifecycle';
2
4
  import { Select, Selector } from './selector';
3
- import { Class, InstanceOf, Key } from './types';
5
+ import { BunchOf, Callback, Class, InstanceOf, Query, RequestCallback, UpdateCallback } from './types';
4
6
 
5
7
  interface PropertyDescriptor<T> {
6
8
  configurable?: boolean;
@@ -151,7 +153,8 @@ declare const CONTROL: unique symbol;
151
153
  declare const LOCAL: unique symbol;
152
154
  declare const STATE: unique symbol;
153
155
 
154
- export abstract class State {
156
+ export interface Model extends Lifecycle {}
157
+ export abstract class Model {
155
158
  /** Controller for this instance. */
156
159
  [CONTROL]: Model.Controller;
157
160
 
@@ -278,6 +281,50 @@ export abstract class State {
278
281
 
279
282
  tap <K extends Model.SelectField<this>> (key: K, expect?: boolean): ReturnType<K>;
280
283
  tap <K extends Model.SelectField<this>> (key: K, expect: true): Exclude<ReturnType<K>, undefined>;
284
+
285
+ // Keyed
286
+ on <S extends Model.SelectEvents<this>> (via: S, cb: Selector.Callback<S, this>, squash?: false, once?: boolean): Callback;
287
+ on <P extends Model.EventsCompat<this>> (key: P | P[], listener: UpdateCallback<this, P>, squash?: false, once?: boolean): Callback;
288
+ // Squash
289
+ on <S extends Model.SelectEvents<this>> (via: S, cb: (keys: Selector.From<S>[]) => void, squash: true, once?: boolean): Callback;
290
+ on <P extends Model.EventsCompat<this>> (key: P | P[], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
291
+ // Unknown
292
+ on <S extends Model.SelectEvents<this>> (via: S, cb: unknown, squash: boolean, once?: boolean): Callback;
293
+ on <P extends Model.EventsCompat<this>> (key: P | P[], listener: unknown, squash: boolean, once?: boolean): Callback;
294
+
295
+ // Keyed
296
+ once <S extends Model.SelectEvents<this>> (via: S, cb: Selector.Callback<S, this>, squash?: false): Callback;
297
+ once <P extends Model.EventsCompat<this>> (key: P | P[], listener: UpdateCallback<this, P>, squash?: false): Callback;
298
+ // Squash
299
+ once <S extends Model.SelectEvents<this>> (via: S, cb: (keys: Selector.From<S>[]) => void, squash: true): Callback;
300
+ once <P extends Model.EventsCompat<this>> (key: P | P[], listener: (keys: P[]) => void, squash: true): Callback;
301
+ // Promise
302
+ once <S extends Model.SelectEvents<this>> (via: S): Promise<Selector.From<S>[]>;
303
+ once <P extends Model.EventsCompat<this>> (key: P | P[]): Promise<P[]>;
304
+ // Unknown
305
+ once <S extends Model.SelectEvents<this>> (via: S, cb: unknown, squash: boolean): Callback;
306
+ once <P extends Model.EventsCompat<this>> (key: P | P[], listener: unknown, squash: boolean): Callback;
307
+
308
+ effect(callback: (this: this, state: this) => void, select?: Model.SelectFields<this>): Callback;
309
+ effect(callback: (this: this, state: this) => void, select?: (keyof this)[]): Callback;
310
+
311
+ /**
312
+ * **React Hook** - Attach to instance of this controller within ambient component.
313
+ *
314
+ * This method will fire lifecycle events on given controller.
315
+ *
316
+ * @param id - Argument passed to controller-lifecycle methods. Use to identify the consumer.
317
+ */
318
+ tag(id?: any): this;
319
+
320
+ /**
321
+ * **React Hook** - Attach to instance of this controller within ambient component.
322
+ *
323
+ * This method will fire lifecycle events on given controller.
324
+ *
325
+ * @param idFactory - Will be invoked with fetched instance. Use this to register a tag as-needed.
326
+ */
327
+ tag(idFactory: (idFactory: this) => any): this;
281
328
 
282
329
  /** Use symbol to access controller of a model. */
283
330
  static CONTROL: typeof CONTROL;
@@ -385,61 +432,6 @@ export abstract class State {
385
432
  static tap <T extends Class, I extends InstanceOf<T>, K extends Model.Fields<I>> (this: T, key: K, expect: true): Exclude<I[K], undefined>;
386
433
  static tap <T extends Class, I extends InstanceOf<T>, K extends Model.SelectField<I>> (this: T, key: K, expect: true): Exclude<ReturnType<K>, undefined>;
387
434
 
388
- /**
389
- * Static equivalent of `x instanceof this`.
390
- *
391
- * Will determine if provided class is a subtype of this one.
392
- */
393
- static isTypeof <T extends Class>(this: T, subject: any): subject is T;
394
- }
395
-
396
- export interface Model extends Lifecycle {}
397
- export abstract class Model extends State {
398
- // Keyed
399
- on <S extends Model.SelectEvents<this>> (via: S, cb: Selector.Callback<S, this>, squash?: false, once?: boolean): Callback;
400
- on <P extends Model.EventsCompat<this>> (key: P | P[], listener: UpdateCallback<this, P>, squash?: false, once?: boolean): Callback;
401
- // Squash
402
- on <S extends Model.SelectEvents<this>> (via: S, cb: (keys: Selector.From<S>[]) => void, squash: true, once?: boolean): Callback;
403
- on <P extends Model.EventsCompat<this>> (key: P | P[], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
404
- // Unknown
405
- on <S extends Model.SelectEvents<this>> (via: S, cb: unknown, squash: boolean, once?: boolean): Callback;
406
- on <P extends Model.EventsCompat<this>> (key: P | P[], listener: unknown, squash: boolean, once?: boolean): Callback;
407
-
408
- // Keyed
409
- once <S extends Model.SelectEvents<this>> (via: S, cb: Selector.Callback<S, this>, squash?: false): Callback;
410
- once <P extends Model.EventsCompat<this>> (key: P | P[], listener: UpdateCallback<this, P>, squash?: false): Callback;
411
- // Squash
412
- once <S extends Model.SelectEvents<this>> (via: S, cb: (keys: Selector.From<S>[]) => void, squash: true): Callback;
413
- once <P extends Model.EventsCompat<this>> (key: P | P[], listener: (keys: P[]) => void, squash: true): Callback;
414
- // Promise
415
- once <S extends Model.SelectEvents<this>> (via: S): Promise<Selector.From<S>[]>;
416
- once <P extends Model.EventsCompat<this>> (key: P | P[]): Promise<P[]>;
417
- // Unknown
418
- once <S extends Model.SelectEvents<this>> (via: S, cb: unknown, squash: boolean): Callback;
419
- once <P extends Model.EventsCompat<this>> (key: P | P[], listener: unknown, squash: boolean): Callback;
420
-
421
- effect(callback: (this: this, state: this) => void, select?: Model.SelectFields<this>): Callback;
422
- effect(callback: (this: this, state: this) => void, select?: (keyof this)[]): Callback;
423
-
424
- /**
425
- * **React Hook** - Attach to instance of this controller within ambient component.
426
- *
427
- * This method will fire lifecycle events on given controller.
428
- *
429
- * @param id - Argument passed to controller-lifecycle methods. Use to identify the consumer.
430
- */
431
- tag(id?: Key): this;
432
-
433
- /**
434
- * **React Hook** - Attach to instance of this controller within ambient component.
435
- *
436
- * This method will fire lifecycle events on given controller.
437
- *
438
- * @param idFactory - Will be invoked with fetched instance. Use this to register a tag as-needed.
439
- */
440
- tag(idFactory: (idFactory: this) => Key | void): this;
441
-
442
-
443
435
  /**
444
436
  * **React Hook** - Attach to instance of this controller within ambient component.
445
437
  *
@@ -473,6 +465,13 @@ export abstract class Model extends State {
473
465
  * Documentation TBD.
474
466
  */
475
467
  static meta <T extends Class, K extends Model.SelectField<T>> (this: T, key?: K): ReturnType<K>;
468
+
469
+ /**
470
+ * Static equivalent of `x instanceof this`.
471
+ *
472
+ * Will determine if provided class is a subtype of this one.
473
+ */
474
+ static isTypeof <T extends Class>(this: T, subject: any): subject is T;
476
475
  }
477
476
 
478
477
  export class Singleton extends Model {
package/types/types.d.ts CHANGED
@@ -12,4 +12,7 @@ export type EffectCallback<T, A = T> = (this: T, argument: A) => Callback | Prom
12
12
  export type UpdateCallback<T, P> = (this: T, value: IfApplicable<T, P>, changed: P) => void;
13
13
  export type InterceptCallback<T> = (argument: T) => ((next: T) => void) | Promise<any> | void | boolean;
14
14
 
15
- export type RefFunction = (e: HTMLElement | null) => void;
15
+ export type RefFunction = (e: HTMLElement | null) => void;
16
+
17
+ export type Recursive<T> = { [K in keyof T]: Recursive<Omit<T, K>> };
18
+ export type Query = (select: Recursive<{}>) => void;