@expressive/mvc 0.29.2 → 0.30.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/lib/index.d.ts CHANGED
@@ -58,15 +58,17 @@ declare global {
58
58
  }
59
59
  }
60
60
 
61
- type OnValue<T, P extends Model.Key<T>> = (this: T, value: T[P], updated: Model.Event<T>[]) => void;
62
- type OnValues<T, P extends Model.Key<T>> = (this: T, value: Model.Export<T, P>, updated: Model.Event<T>[]) => void;
61
+ type SelectOne<T, K extends Model.Key<T>> = K;
62
+ type SelectFew<T, K extends Model.Key<T>> = K[];
63
+ type Select<T, K extends Model.Key<T> = Model.Key<T>> = K | K[];
64
+ type Export<T, S> = S extends SelectOne<T, infer P> ? T[P] : S extends SelectFew<T, infer P> ? Model.Export<T, P> : never;
65
+ type OnUpdate<T, S> = (this: T, value: Export<T, S>, updated: Model.Event<T>[]) => void;
63
66
  interface Observable {
64
67
  get(): Model.Export<this>;
68
+ get<P extends Select<this>>(select: P): Export<this, P>;
69
+ get<P extends Select<this>>(select: P, onUpdate: OnUpdate<this, P>, once?: true): Callback;
70
+ get<P extends Select<this>>(select: P, onUpdate: OnUpdate<this, P>, initial?: false): Callback;
65
71
  get(effect: Model.Effect<this>): Callback;
66
- get<P extends Model.Key<this>>(select: P): this[P];
67
- get<P extends Model.Key<this>>(select: P, onUpdate: OnValue<this, P>, once?: boolean): Callback;
68
- get<P extends Model.Key<this>>(select: P[]): Model.Export<this, P>;
69
- get<P extends Model.Key<this>>(select: P[], onUpdate: OnValues<this, P>, once?: boolean): Callback;
70
72
  set(): Promise<Model.Event<this>[]>;
71
73
  set(timeout: number): Promise<Model.Event<this>[] | false>;
72
74
  set<T extends Model.Values<this>>(source: T, only?: (keyof T)[]): Promise<Model.Event<T>[] | false>;
@@ -82,34 +84,23 @@ declare namespace Model {
82
84
  type Type<T extends Model = Model> = abstract new (...args: any[]) => T;
83
85
  /** A typeof Model, specifically one which can be created without any arguments. */
84
86
  type New<T extends Model = Model> = (new () => T) & typeof Model;
85
- type Effect<T> = (this: T, argument: T) => Callback | Promise<any> | void;
86
- /** Exotic value, actual value is contained. */
87
- type Ref<T = any> = {
88
- (next: T): void;
89
- current: T | null;
90
- };
91
- /**
92
- * Subset of `keyof T` which are not methods or defined by base Model U.
93
- **/
94
- type Key<T, U = Model> = Extract<Exclude<keyof T, keyof U>, string>;
87
+ /** A callback function which is subscribed to parent and updates when values change. */
88
+ type Effect<T> = (this: T, argument: T) => Callback | Promise<void> | void;
89
+ /** Subset of `keyof T` which are not methods or defined by base Model U. **/
90
+ type Key<T, U = Observable> = Extract<Exclude<keyof T, keyof U>, string>;
95
91
  /** Including but not limited to `keyof T` which are not methods or defined by base Model. */
96
92
  type Event<T> = Key<T> | (string & {});
97
- /** Actual value stored in state. */
98
- type Value<R> = R extends Ref<infer T> ? T : R extends Observable ? Export<R> : R;
99
93
  /** Object comperable to data found in T. */
100
94
  type Values<T> = {
101
95
  [P in Key<T>]?: Value<T[P]>;
102
96
  };
103
97
  /**
104
98
  * Values from current state of given controller.
105
- *
106
- * Differs from `Entries` as values here will drill into "real" values held by exotics like ref.
99
+ * Differs from `Values` as values here will drill into "real" values held by exotics like ref.
107
100
  */
108
101
  type Export<T, K extends Key<T> = Key<T>> = {
109
102
  [P in K]: Value<T[P]>;
110
103
  };
111
- /** Promise thrown by something which is not yet ready. */
112
- type Suspense = Promise<void> & Error;
113
104
  /**
114
105
  * Reference to `this` without a subscription.
115
106
  * Use to obtain full reference from a destructure.
@@ -117,6 +108,13 @@ declare namespace Model {
117
108
  type Focus<T> = T & {
118
109
  is: T;
119
110
  };
111
+ /** Exotic value, actual value is contained. */
112
+ type Ref<T = any> = {
113
+ (next: T): void;
114
+ current: T | null;
115
+ };
116
+ /** Actual value stored in state. */
117
+ type Value<R> = R extends Ref<infer T> ? T : R extends Observable ? Export<R> : R;
120
118
  }
121
119
  interface Model extends Observable {
122
120
  }
@@ -346,7 +344,7 @@ declare class Control<T extends {} = any> {
346
344
  static for: typeof control;
347
345
  static apply: typeof apply;
348
346
  static watch: typeof watch;
349
- id?: string | number;
347
+ id: string | number | false;
350
348
  subject: T;
351
349
  state: {
352
350
  [key: string]: any;
@@ -355,8 +353,8 @@ declare class Control<T extends {} = any> {
355
353
  frame: Set<string>;
356
354
  followers: Set<Observer<any>>;
357
355
  observers: Map<string, Set<Observer<any>>>;
358
- constructor(subject: T, id?: string | number | false);
359
- add(key: Extract<keyof T, string>): void;
356
+ constructor(subject: T, id: string | number | false);
357
+ add(key: string): void;
360
358
  watch(key: string, output: Control.PropertyDescriptor<any>): void;
361
359
  ref<K extends Model.Key<T>>(key: K, callback?: (this: T, value: T[K]) => boolean | void): (value: any) => void;
362
360
  update(key: string): void;
package/lib/index.esm.js CHANGED
@@ -292,6 +292,7 @@ function getMethod(argument, callback, once) {
292
292
  if (typeof callback != "function")
293
293
  return extract();
294
294
  const select = typeof argument == "string" ? [argument] : argument;
295
+ const invoke = () => callback(extract(), self.latest || []);
295
296
  if (select)
296
297
  for (const key of select)
297
298
  try {
@@ -302,11 +303,13 @@ function getMethod(argument, callback, once) {
302
303
  catch (e) {
303
304
  // TODO: should this be caught?
304
305
  }
306
+ if (once === undefined)
307
+ invoke();
305
308
  const remove = self.addListener(key => {
306
309
  if (!select || select.includes(key)) {
307
310
  if (once)
308
311
  remove();
309
- return () => callback(extract(), self.latest);
312
+ return invoke;
310
313
  }
311
314
  });
312
315
  return remove;
@@ -351,7 +354,7 @@ function setMethod(arg1, arg2) {
351
354
 
352
355
  class Model {
353
356
  constructor(id) {
354
- new Control(this, id);
357
+ new Control(this, id === undefined ? uid() : id);
355
358
  }
356
359
  /** Mark this instance for garbage collection. */
357
360
  null() {
@@ -416,7 +419,11 @@ defineProperties(Model.prototype, {
416
419
  throw new Error("Model.on() is deprecated. Use Model.get or Model.set instead.");
417
420
  }
418
421
  }
419
- });
422
+ });
423
+ /** Random alphanumberic of length 6. Will always start with a letter. */
424
+ function uid() {
425
+ return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
426
+ }
420
427
 
421
428
  const Oops$4 = issues({
422
429
  BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
@@ -432,12 +439,11 @@ class Control {
432
439
  this.frame = new Set();
433
440
  this.followers = new Set();
434
441
  this.observers = new Map([["", this.followers]]);
442
+ this.id = id;
435
443
  this.subject = subject;
436
444
  REGISTER.set(subject, this);
437
- if (id !== false) {
438
- this.id = id === undefined ? uid() : id;
445
+ if (id !== false)
439
446
  PENDING$1.set(this, new Set(Control.ready));
440
- }
441
447
  }
442
448
  add(key) {
443
449
  const { value } = getOwnPropertyDescriptor(this.subject, key);
@@ -608,10 +614,6 @@ function apply(instruction) {
608
614
  onto.watch(key, typeof output == "function" ? { get: output } : output);
609
615
  });
610
616
  return placeholder;
611
- }
612
- /** Random alphanumberic of length 6; will always start with a letter. */
613
- function uid() {
614
- return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
615
617
  }
616
618
 
617
619
  const Oops$3 = issues({
package/lib/index.js CHANGED
@@ -296,6 +296,7 @@ function getMethod(argument, callback, once) {
296
296
  if (typeof callback != "function")
297
297
  return extract();
298
298
  const select = typeof argument == "string" ? [argument] : argument;
299
+ const invoke = () => callback(extract(), self.latest || []);
299
300
  if (select)
300
301
  for (const key of select)
301
302
  try {
@@ -306,11 +307,13 @@ function getMethod(argument, callback, once) {
306
307
  catch (e) {
307
308
  // TODO: should this be caught?
308
309
  }
310
+ if (once === undefined)
311
+ invoke();
309
312
  const remove = self.addListener(key => {
310
313
  if (!select || select.includes(key)) {
311
314
  if (once)
312
315
  remove();
313
- return () => callback(extract(), self.latest);
316
+ return invoke;
314
317
  }
315
318
  });
316
319
  return remove;
@@ -355,7 +358,7 @@ function setMethod(arg1, arg2) {
355
358
 
356
359
  class Model {
357
360
  constructor(id) {
358
- new Control(this, id);
361
+ new Control(this, id === undefined ? uid() : id);
359
362
  }
360
363
  /** Mark this instance for garbage collection. */
361
364
  null() {
@@ -420,7 +423,11 @@ defineProperties(Model.prototype, {
420
423
  throw new Error("Model.on() is deprecated. Use Model.get or Model.set instead.");
421
424
  }
422
425
  }
423
- });
426
+ });
427
+ /** Random alphanumberic of length 6. Will always start with a letter. */
428
+ function uid() {
429
+ return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
430
+ }
424
431
 
425
432
  const Oops$4 = issues({
426
433
  BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
@@ -436,12 +443,11 @@ class Control {
436
443
  this.frame = new Set();
437
444
  this.followers = new Set();
438
445
  this.observers = new Map([["", this.followers]]);
446
+ this.id = id;
439
447
  this.subject = subject;
440
448
  REGISTER.set(subject, this);
441
- if (id !== false) {
442
- this.id = id === undefined ? uid() : id;
449
+ if (id !== false)
443
450
  PENDING$1.set(this, new Set(Control.ready));
444
- }
445
451
  }
446
452
  add(key) {
447
453
  const { value } = getOwnPropertyDescriptor(this.subject, key);
@@ -612,10 +618,6 @@ function apply(instruction) {
612
618
  onto.watch(key, typeof output == "function" ? { get: output } : output);
613
619
  });
614
620
  return placeholder;
615
- }
616
- /** Random alphanumberic of length 6; will always start with a letter. */
617
- function uid() {
618
- return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
619
621
  }
620
622
 
621
623
  const Oops$3 = issues({
package/package.json CHANGED
@@ -26,6 +26,6 @@
26
26
  "prebuild": "rm -rf lib/",
27
27
  "preversion": "npm run test && npm run build"
28
28
  },
29
- "version": "0.29.2",
30
- "gitHead": "a10efcc0deba6e634d9b194ceda506573e981719"
29
+ "version": "0.30.0",
30
+ "gitHead": "8e2ed856c216a18e350494fef186adbee3c20f73"
31
31
  }