@expressive/mvc 0.18.0 → 0.19.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
@@ -1,13 +1,43 @@
1
- declare const LOCAL = "$debug local";
2
- declare const STATE = "$debug state";
3
- declare const UPDATE = "$debug update";
4
- declare const CONTROL = "$debug controller";
1
+ declare namespace Issue {
2
+ type Variable = {} | string | number | boolean | null | undefined;
3
+ type Variables<T> = T extends (...args: infer T) => any ? T : never;
4
+ type Messages = {
5
+ [named: string]: (...args: Variable[]) => string;
6
+ };
7
+ type Output<M extends Messages> = {
8
+ readonly [P in keyof M]: (...args: Variables<M[P]>) => Issue;
9
+ };
10
+ }
11
+ declare class Issue extends Error {
12
+ stack: string;
13
+ warn(): void;
14
+ }
15
+ declare function issues<M extends Issue.Messages>(register: M): Issue.Output<M>;
16
+
17
+ declare const LOCAL = "__local";
18
+ declare const STATE = "__state";
19
+ declare const UPDATE = "__update";
20
+ declare const CONTROL = "__control";
5
21
  declare const Debug: {
6
- readonly CONTROL: "$debug controller";
7
- readonly LOCAL: "$debug local";
8
- readonly STATE: "$debug state";
9
- readonly UPDATE: "$debug update";
22
+ /** Use to access Model's local Subscriber (if exists). */
23
+ LOCAL: "__local";
24
+ /** Use to access snapshot of Model's current state. */
25
+ STATE: "__state";
26
+ /**
27
+ * Use to access snapshot of Model's latest update.
28
+ *
29
+ * Note: If used within a Subscriber, update will be narrowed to the specific keys
30
+ * which triggered a refresh (if one did).
31
+ */
32
+ UPDATE: "__update";
33
+ /** Use to access a Model's controller. */
34
+ CONTROL: "__control";
10
35
  };
36
+ /**
37
+ * Generic will declare debug properties on a given Model.
38
+ *
39
+ * These properties always exist at runtime, however are hidden unless you cast your Model as `Debug<T>`.
40
+ */
11
41
  type Debug<T extends Model> = T & {
12
42
  /** Controller for this instance. */
13
43
  [CONTROL]?: Control<T>;
@@ -28,24 +58,19 @@ type Callback = () => void;
28
58
  type Class = new (...args: any[]) => any;
29
59
  type InstanceOf<T> = T extends { prototype: infer U } ? U : never;
30
60
 
61
+ type MaybePromise<T> = T | Promise<T>;
62
+
31
63
  /** Type may not be undefined - instead will be null. */
32
64
  type NoVoid<T> = T extends undefined ? null : T;
33
65
 
34
- type OptionalValues<T extends {}> = {
35
- [P in Model.Key<T>]: T[P] | undefined;
36
- }
37
-
38
- type NonOptionalValues<T extends {}> = {
39
- [P in Model.Key<T>]: Exclude<T[P], undefined>;
40
- };
41
-
42
66
  declare namespace Model {
43
67
  export { Control };
44
68
  export { Subscriber };
45
69
  /** Including but not limited to T. */
46
70
  type Extends<T> = T | (string & Record<never, never>);
47
71
  /** Any typeof Model, using class constructor as the reference. */
48
- export type Type<T extends Model = Model> = (abstract new (...args: any[]) => T);
72
+ export type Type<T extends Model = Model> = abstract new () => T;
73
+ export type Class<T extends Model> = (abstract new () => T) & typeof Model;
49
74
  /** A typeof Model, specifically one which may be created without arguments. */
50
75
  export type New<T extends Model = Model> = (new () => T) & typeof Model;
51
76
  export type Effect<T> = (this: T, argument: T) => Callback | Promise<any> | void;
@@ -95,7 +120,7 @@ declare namespace Model {
95
120
  [P in Key<T>]: Value<T[P]>;
96
121
  };
97
122
  export type FindFunction = <T extends Model>(type: Model.Type<T>, relativeTo: Model, required: boolean) => (_refresh: (x: T) => void) => T | undefined;
98
- export type TapCallback<T extends Model, R> = (this: T, model: T, update: ForceUpdate) => R;
123
+ export type GetCallback<T extends Model, R> = (this: T, model: T, update: ForceUpdate) => R;
99
124
  type ForceUpdate = {
100
125
  /** Force an update in current component. */
101
126
  (): void;
@@ -119,7 +144,9 @@ declare class Model {
119
144
  * Use to obtain full reference from a destructure.
120
145
  */
121
146
  is: this;
122
- constructor();
147
+ /** Unique identifier for Model instance. */
148
+ id: string;
149
+ constructor(id?: string);
123
150
  on<P extends Model.Event<this>>(keys?: P | Iterable<P>, timeout?: number): Promise<P[]>;
124
151
  on<P extends Model.Event<this>>(keys: P | Iterable<P>, listener: (this: this, keys: Model.Event<this>[]) => void, once?: boolean): Callback;
125
152
  on(effect: Model.Effect<this>): Callback;
@@ -130,15 +157,15 @@ declare class Model {
130
157
  on(current: true): Promise<Model.Event<this>[]>;
131
158
  on(current: null): Promise<null>;
132
159
  get(): Model.Export<this>;
133
- get<P extends Model.Key<this>>(property: P): this[P];
134
- get<P extends Model.Key<this>>(property: P, timeout: number): Promise<this[P]>;
135
- get<P extends Model.Key<this>>(property: P, onChange: true): Promise<this[P]>;
136
- get<P extends Model.Key<this>>(property: P, onChange: boolean): this[P] | Promise<this[P]>;
137
- get<P extends Model.Key<this>>(property: P, listener: (this: this, value: this[P], key: P[]) => void): Callback;
160
+ get<P extends Model.Key<this>>(select: P): this[P];
138
161
  get<P extends Model.Key<this>>(select: Iterable<P>): Model.Get<this, P>;
162
+ get<P extends Model.Key<this>>(select: P, timeout: number): Promise<this[P]>;
139
163
  get<P extends Model.Key<this>>(select: Iterable<P>, timeout: number): Promise<Model.Get<this, P>>;
164
+ get<P extends Model.Key<this>>(select: P, onChange: true): Promise<this[P]>;
140
165
  get<P extends Model.Key<this>>(select: Iterable<P>, onChange: true): Promise<Model.Get<this, P>>;
141
- get<P extends Model.Key<this>>(select: Iterable<P>, onChange: boolean): Model.Get<this, P> | Promise<Model.Get<this, P>>;
166
+ get<P extends Model.Key<this>>(select: P, onChange: boolean): MaybePromise<this[P]>;
167
+ get<P extends Model.Key<this>>(select: Iterable<P>, onChange: boolean): MaybePromise<Model.Get<this, P>>;
168
+ get<P extends Model.Key<this>>(select: P, listener: (this: this, value: this[P], key: P[]) => void): Callback;
142
169
  get<P extends Model.Key<this>>(select: Iterable<P>, listener: (this: this, value: Model.Get<this, P>, key: P[]) => void): Callback;
143
170
  set(key: Model.Event<this>): PromiseLike<readonly Model.Event<this>[]>;
144
171
  set<K extends Model.Event<this>>(key: Model.Event<this>, value: Model.ValueOf<this, K>): PromiseLike<readonly Model.Event<this>[]>;
@@ -154,29 +181,22 @@ declare class Model {
154
181
  * @param args - arguments sent to constructor
155
182
  */
156
183
  static new<T extends Class>(this: T, ...args: ConstructorParameters<T>): InstanceOf<T>;
184
+ static find<T extends Model>(this: Model.Type<T>, required?: boolean): T;
185
+ static find<T extends Model>(this: Model.Type<T>, required: false): T | undefined;
186
+ static get<T extends Model>(this: Model.Type<T>): T;
187
+ static get<T extends Model>(this: Model.Type<T>, passive: true): T;
188
+ static get<T extends Model>(this: Model.Type<T>, required: false): T | undefined;
189
+ static get<T extends Model, R extends []>(this: Model.Type<T>, compute: Model.GetCallback<T, R | (() => R)>, expect?: boolean): R;
190
+ static get<T extends Model, R extends []>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R> | (() => R) | null>, expect?: boolean): R | null;
191
+ static get<T extends Model, R extends []>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
192
+ static get<T extends Model, R>(this: Model.Type<T>, init: Model.GetCallback<T, () => R>): NoVoid<R>;
193
+ static get<T extends Model, R>(this: Model.Type<T>, init: Model.GetCallback<T, (() => R) | null>): NoVoid<R> | null;
194
+ static get<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
195
+ static get<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
196
+ static get<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, R>, expect?: boolean): NoVoid<R>;
157
197
  static use<I extends Model>(this: Model.Type<I>, watch: Model.Key<I>[], callback?: (instance: I) => void): I;
158
198
  static use<I extends Model>(this: Model.Type<I>, callback?: (instance: I) => void): I;
159
199
  static use<I extends Model>(this: Model.Type<I>, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
160
- static get<T extends Model>(this: Model.Type<T>, required?: boolean): T;
161
- static get<T extends Model>(this: Model.Type<T>, required: false): T | undefined;
162
- static tap<T extends Model>(this: Model.Type<T>): T;
163
- static tap<T extends Model, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: Model.TapCallback<T, R | (() => R)>, expect?: boolean): R;
164
- static tap<T extends Model, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: Model.TapCallback<T, Promise<R> | (() => R) | null>, expect?: boolean): R | null;
165
- static tap<T extends Model, R extends readonly unknown[] | []>(this: Model.Type<T>, compute: Model.TapCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
166
- static tap<T extends Model, R>(this: Model.Type<T>, init: Model.TapCallback<T, () => R>): NoVoid<R>;
167
- static tap<T extends Model, R>(this: Model.Type<T>, init: Model.TapCallback<T, (() => R) | null>): NoVoid<R> | null;
168
- static tap<T extends Model, R>(this: Model.Type<T>, compute: Model.TapCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
169
- static tap<T extends Model, R>(this: Model.Type<T>, compute: Model.TapCallback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
170
- static tap<T extends Model, R>(this: Model.Type<T>, compute: Model.TapCallback<T, R>, expect?: boolean): NoVoid<R>;
171
- static tap<T extends Model>(this: Model.Type<T>, expect: true): NonOptionalValues<T>;
172
- static tap<T extends Model>(this: Model.Type<T>, expect?: boolean): OptionalValues<T>;
173
- protected static meta<T extends Class>(this: T): T;
174
- protected static meta<T extends Class>(this: T, expect: true): NonOptionalValues<T>;
175
- protected static meta<T extends Class>(this: T, expect?: boolean): OptionalValues<T>;
176
- protected static meta<T, M extends Class>(this: M, from: (this: M, state: M) => Promise<T>, expect: true): Exclude<T, undefined>;
177
- protected static meta<T, M extends Class>(this: M, from: (this: M, state: M) => Promise<T>, expect?: boolean): T;
178
- protected static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect: true): Exclude<T, undefined>;
179
- protected static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect?: boolean): T;
180
200
  /**
181
201
  * Static equivalent of `x instanceof this`.
182
202
  *
@@ -272,7 +292,7 @@ declare namespace control {
272
292
  declare function control<T extends Model>(subject: T): Control<T>;
273
293
  declare function control<T extends Model>(subject: T, cb: control.OnReady<T>): Callback;
274
294
 
275
- declare function getParent<T extends Model>(from: Model, type?: Model.Type<T>): T;
295
+ declare function getParent<T extends Model>(from: Model, type?: Model.Class<T>): T;
276
296
 
277
297
  type Async<T = any> = (...args: any[]) => Promise<T>;
278
298
  /**
@@ -295,7 +315,7 @@ declare function run<S>(action: Async<S>): typeof action & {
295
315
  declare namespace get {
296
316
  type Function<T, S = any> = (this: S, on: S) => T;
297
317
  type Factory<R, T> = (this: T, property: string, on: T) => Function<R, T>;
298
- type FindFunction<T extends Model = Model> = (type: typeof Model, relativeTo: Model, required: boolean) => Source<T>;
318
+ type FindFunction<T extends Model = Model> = (type: Model.Class<T>, relativeTo: Model, required: boolean) => Source<T>;
299
319
  type Source<T extends Model = Model> = (callback: (x: T) => void) => void;
300
320
  /** Assign fetch algorithm for get instruction. */
301
321
  let using: (fn: FindFunction) => typeof get;
@@ -479,4 +499,4 @@ declare const Internal: {
479
499
  getParent: typeof getParent;
480
500
  };
481
501
 
482
- export { Control, Debug, Internal, Model, Register, Subscriber, add, get, ref, run, set, use };
502
+ export { Control, Debug, Internal, Model, Register, Subscriber, add, Model as default, get, issues, ref, run, set, use };
package/lib/index.esm.js CHANGED
@@ -1,4 +1,8 @@
1
- const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
1
+ const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
2
+ /** Random alphanumberic of length 6; will always start with a letter. */
3
+ function random() {
4
+ return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
5
+ }
2
6
 
3
7
  class Issue extends Error {
4
8
  constructor() {
@@ -281,9 +285,10 @@ const Oops$5 = issues({
281
285
  NoAdapter: (method) => `Can't call Model.${method} without an adapter.`
282
286
  });
283
287
  class Model {
284
- constructor() {
288
+ constructor(id) {
285
289
  new Control(this);
286
290
  defineProperty(this, "is", { value: this });
291
+ defineProperty(this, "id", { value: id || random() });
287
292
  }
288
293
  on(arg1, arg2, arg3) {
289
294
  if (typeof arg1 == "function")
@@ -313,14 +318,7 @@ class Model {
313
318
  set(arg1, arg2) {
314
319
  const controller = control(this);
315
320
  const { state } = controller;
316
- if (typeof arg1 == "object")
317
- for (const key in arg1) {
318
- if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
319
- state.set(key, arg1[key]);
320
- controller.update(key);
321
- }
322
- }
323
- else if (typeof arg1 == "string") {
321
+ if (typeof arg1 == "string") {
324
322
  controller.update(arg1);
325
323
  if (1 in arguments) {
326
324
  if (state.has(arg1))
@@ -332,6 +330,12 @@ class Model {
332
330
  }
333
331
  }
334
332
  }
333
+ else if (typeof arg1 == "object")
334
+ for (const key in arg1)
335
+ if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
336
+ state.set(key, arg1[key]);
337
+ controller.update(key);
338
+ }
335
339
  return {
336
340
  then: (callback) => {
337
341
  if (!callback)
@@ -356,17 +360,14 @@ class Model {
356
360
  control(instance);
357
361
  return instance;
358
362
  }
359
- static use() {
360
- throw Oops$5.NoAdapter("use");
363
+ static find() {
364
+ throw Oops$5.NoAdapter("find");
361
365
  }
362
366
  static get() {
363
367
  throw Oops$5.NoAdapter("get");
364
368
  }
365
- static tap() {
366
- throw Oops$5.NoAdapter("tap");
367
- }
368
- static meta() {
369
- throw Oops$5.NoAdapter("meta");
369
+ static use() {
370
+ throw Oops$5.NoAdapter("use");
370
371
  }
371
372
  /**
372
373
  * Static equivalent of `x instanceof this`.
@@ -379,8 +380,14 @@ class Model {
379
380
  }
380
381
  }
381
382
  defineProperty(Model.prototype, "toString", {
383
+ configurable: true,
382
384
  value() {
383
- return this.constructor.name;
385
+ return `${this.constructor.name}-${this.id}`;
386
+ }
387
+ });
388
+ defineProperty(Model, "toString", {
389
+ value() {
390
+ return this.name;
384
391
  }
385
392
  });
386
393
 
@@ -418,7 +425,7 @@ function add(instruction, label) {
418
425
 
419
426
  const Oops$4 = issues({
420
427
  PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
421
- Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
428
+ Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} ${parent}.${property}.`,
422
429
  Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
423
430
  });
424
431
  function get(arg0, arg1) {
@@ -435,8 +442,8 @@ function get(arg0, arg1) {
435
442
  else if (typeof arg0 == "function")
436
443
  arg1 = arg0.call(subject, key, subject);
437
444
  return typeof arg1 == "function"
438
- ? getComputed(key, this, source, arg1)
439
- : getRecursive$1(key, this, source, arg1);
445
+ ? computed(this, key, source, arg1)
446
+ : recursive(this, key, source, arg1);
440
447
  });
441
448
  }
442
449
  function getParentForGetInstruction(type, relativeTo, required) {
@@ -445,54 +452,26 @@ function getParentForGetInstruction(type, relativeTo, required) {
445
452
  if (item)
446
453
  callback(item);
447
454
  else if (required)
448
- throw Oops$4.Required(type.name, relativeTo);
455
+ throw Oops$4.Required(type, relativeTo.constructor);
449
456
  };
450
457
  }
451
- function getRecursive$1(key, parent, source, required) {
452
- const context = new WeakMap();
453
- const { state } = parent;
458
+ function recursive(parent, key, source, required) {
459
+ const getter = getRecursive(key, parent);
454
460
  let waiting;
455
461
  source((got) => {
456
- state.set(key, got);
462
+ parent.state.set(key, got);
457
463
  if (waiting)
458
464
  parent.update(key);
459
465
  });
460
466
  waiting = true;
461
- function create(local) {
462
- let reset;
463
- local.follow(key, init);
464
- init();
465
- function init() {
466
- if (reset)
467
- reset();
468
- const value = state.get(key);
469
- if (value && controller(value)) {
470
- const child = new Subscriber(value, local.onUpdate);
471
- if (local.active)
472
- child.commit();
473
- local.dependant.add(child);
474
- context.set(local, child.proxy);
475
- reset = () => {
476
- child.release();
477
- local.dependant.delete(child);
478
- context.set(local, undefined);
479
- reset = undefined;
480
- };
481
- }
482
- }
483
- }
484
467
  return (local) => {
485
- const value = state.get(key);
468
+ const value = parent.state.get(key);
486
469
  if (!value && required !== false)
487
470
  parent.waitFor(key);
488
- if (!local)
489
- return value;
490
- if (!context.has(local))
491
- create(local);
492
- return context.get(local);
471
+ return local ? getter(local) : value;
493
472
  };
494
473
  }
495
- function getComputed(key, parent, source, setter) {
474
+ function computed(parent, key, source, setter) {
496
475
  const { state } = parent;
497
476
  let local;
498
477
  let active;
@@ -553,7 +532,7 @@ function getComputed(key, parent, source, setter) {
553
532
  const INFO = new WeakMap();
554
533
  const KEYS = new WeakMap();
555
534
  const ORDER = new WeakMap();
556
- function flush(control) {
535
+ function flushComputed(control) {
557
536
  const pending = KEYS.get(control);
558
537
  if (!pending || !pending.size)
559
538
  return;
@@ -647,7 +626,7 @@ class Control {
647
626
  return;
648
627
  else if (!frame.size)
649
628
  setTimeout(() => {
650
- flush(this);
629
+ flushComputed(this);
651
630
  const keys = this.latest = Array.from(frame);
652
631
  setTimeout(() => this.latest = undefined, 0);
653
632
  frame.clear();
@@ -706,21 +685,19 @@ function control(subject, cb) {
706
685
 
707
686
  const Parent = new WeakMap();
708
687
  const Oops$3 = issues({
709
- BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`,
688
+ BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
710
689
  Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
711
690
  });
712
691
  function getParent(from, type) {
713
692
  const value = Parent.get(from);
714
693
  if (value && type && !(value instanceof type))
715
- throw Oops$3.Unexpected(type.name, from, value);
694
+ throw Oops$3.Unexpected(type, from, value);
716
695
  return value;
717
696
  }
718
697
  function getRecursive(key, from) {
719
698
  const context = new WeakMap();
720
699
  const { state } = from;
721
700
  return (local) => {
722
- if (!local)
723
- return state.get(key);
724
701
  if (!context.has(local)) {
725
702
  let reset;
726
703
  const init = () => {
@@ -754,8 +731,9 @@ function setRecursive(controller, key, initial) {
754
731
  const onUpdate = (next) => {
755
732
  state.set(key, next);
756
733
  if (!(next instanceof Type))
757
- throw Oops$3.BadAssignment(`${subject}.${key}`, Type.name, String(next));
758
- get = getRecursive(key, controller);
734
+ throw Oops$3.BadAssignment(`${subject}.${key}`, Type, String(next));
735
+ const getter = getRecursive(key, controller);
736
+ get = (local) => local ? getter(local) : state.get(key);
759
737
  Parent.set(next, subject);
760
738
  control(next);
761
739
  return true;
@@ -1107,7 +1085,8 @@ function use(input, argument) {
1107
1085
  const onUpdate = (next) => {
1108
1086
  state.set(key, next);
1109
1087
  if (next) {
1110
- get = getRecursive(key, this);
1088
+ const getter = getRecursive(key, this);
1089
+ get = (local) => local ? getter(local) : state.get(key);
1111
1090
  Parent.set(next, subject);
1112
1091
  control(next);
1113
1092
  }
@@ -1163,10 +1142,10 @@ function use(input, argument) {
1163
1142
  });
1164
1143
  }
1165
1144
 
1166
- const LOCAL = "$debug local";
1167
- const STATE = "$debug state";
1168
- const UPDATE = "$debug update";
1169
- const CONTROL = "$debug controller";
1145
+ const LOCAL = "__local";
1146
+ const STATE = "__state";
1147
+ const UPDATE = "__update";
1148
+ const CONTROL = "__control";
1170
1149
  defineProperties(Model.prototype, {
1171
1150
  [CONTROL]: {
1172
1151
  get() {
@@ -1262,4 +1241,4 @@ const Internal = {
1262
1241
  getParent
1263
1242
  };
1264
1243
 
1265
- export { Control, Debug, Internal, Model, Register, Subscriber, add, get, ref, run, set, use };
1244
+ export { Control, Debug, Internal, Model, Register, Subscriber, add, Model as default, get, issues, ref, run, set, use };
package/lib/index.js CHANGED
@@ -2,7 +2,11 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
5
+ const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
6
+ /** Random alphanumberic of length 6; will always start with a letter. */
7
+ function random() {
8
+ return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
9
+ }
6
10
 
7
11
  class Issue extends Error {
8
12
  constructor() {
@@ -285,9 +289,10 @@ const Oops$5 = issues({
285
289
  NoAdapter: (method) => `Can't call Model.${method} without an adapter.`
286
290
  });
287
291
  class Model {
288
- constructor() {
292
+ constructor(id) {
289
293
  new Control(this);
290
294
  defineProperty(this, "is", { value: this });
295
+ defineProperty(this, "id", { value: id || random() });
291
296
  }
292
297
  on(arg1, arg2, arg3) {
293
298
  if (typeof arg1 == "function")
@@ -317,14 +322,7 @@ class Model {
317
322
  set(arg1, arg2) {
318
323
  const controller = control(this);
319
324
  const { state } = controller;
320
- if (typeof arg1 == "object")
321
- for (const key in arg1) {
322
- if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
323
- state.set(key, arg1[key]);
324
- controller.update(key);
325
- }
326
- }
327
- else if (typeof arg1 == "string") {
325
+ if (typeof arg1 == "string") {
328
326
  controller.update(arg1);
329
327
  if (1 in arguments) {
330
328
  if (state.has(arg1))
@@ -336,6 +334,12 @@ class Model {
336
334
  }
337
335
  }
338
336
  }
337
+ else if (typeof arg1 == "object")
338
+ for (const key in arg1)
339
+ if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
340
+ state.set(key, arg1[key]);
341
+ controller.update(key);
342
+ }
339
343
  return {
340
344
  then: (callback) => {
341
345
  if (!callback)
@@ -360,17 +364,14 @@ class Model {
360
364
  control(instance);
361
365
  return instance;
362
366
  }
363
- static use() {
364
- throw Oops$5.NoAdapter("use");
367
+ static find() {
368
+ throw Oops$5.NoAdapter("find");
365
369
  }
366
370
  static get() {
367
371
  throw Oops$5.NoAdapter("get");
368
372
  }
369
- static tap() {
370
- throw Oops$5.NoAdapter("tap");
371
- }
372
- static meta() {
373
- throw Oops$5.NoAdapter("meta");
373
+ static use() {
374
+ throw Oops$5.NoAdapter("use");
374
375
  }
375
376
  /**
376
377
  * Static equivalent of `x instanceof this`.
@@ -383,8 +384,14 @@ class Model {
383
384
  }
384
385
  }
385
386
  defineProperty(Model.prototype, "toString", {
387
+ configurable: true,
386
388
  value() {
387
- return this.constructor.name;
389
+ return `${this.constructor.name}-${this.id}`;
390
+ }
391
+ });
392
+ defineProperty(Model, "toString", {
393
+ value() {
394
+ return this.name;
388
395
  }
389
396
  });
390
397
 
@@ -422,7 +429,7 @@ function add(instruction, label) {
422
429
 
423
430
  const Oops$4 = issues({
424
431
  PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
425
- Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
432
+ Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} ${parent}.${property}.`,
426
433
  Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
427
434
  });
428
435
  function get(arg0, arg1) {
@@ -439,8 +446,8 @@ function get(arg0, arg1) {
439
446
  else if (typeof arg0 == "function")
440
447
  arg1 = arg0.call(subject, key, subject);
441
448
  return typeof arg1 == "function"
442
- ? getComputed(key, this, source, arg1)
443
- : getRecursive$1(key, this, source, arg1);
449
+ ? computed(this, key, source, arg1)
450
+ : recursive(this, key, source, arg1);
444
451
  });
445
452
  }
446
453
  function getParentForGetInstruction(type, relativeTo, required) {
@@ -449,54 +456,26 @@ function getParentForGetInstruction(type, relativeTo, required) {
449
456
  if (item)
450
457
  callback(item);
451
458
  else if (required)
452
- throw Oops$4.Required(type.name, relativeTo);
459
+ throw Oops$4.Required(type, relativeTo.constructor);
453
460
  };
454
461
  }
455
- function getRecursive$1(key, parent, source, required) {
456
- const context = new WeakMap();
457
- const { state } = parent;
462
+ function recursive(parent, key, source, required) {
463
+ const getter = getRecursive(key, parent);
458
464
  let waiting;
459
465
  source((got) => {
460
- state.set(key, got);
466
+ parent.state.set(key, got);
461
467
  if (waiting)
462
468
  parent.update(key);
463
469
  });
464
470
  waiting = true;
465
- function create(local) {
466
- let reset;
467
- local.follow(key, init);
468
- init();
469
- function init() {
470
- if (reset)
471
- reset();
472
- const value = state.get(key);
473
- if (value && controller(value)) {
474
- const child = new Subscriber(value, local.onUpdate);
475
- if (local.active)
476
- child.commit();
477
- local.dependant.add(child);
478
- context.set(local, child.proxy);
479
- reset = () => {
480
- child.release();
481
- local.dependant.delete(child);
482
- context.set(local, undefined);
483
- reset = undefined;
484
- };
485
- }
486
- }
487
- }
488
471
  return (local) => {
489
- const value = state.get(key);
472
+ const value = parent.state.get(key);
490
473
  if (!value && required !== false)
491
474
  parent.waitFor(key);
492
- if (!local)
493
- return value;
494
- if (!context.has(local))
495
- create(local);
496
- return context.get(local);
475
+ return local ? getter(local) : value;
497
476
  };
498
477
  }
499
- function getComputed(key, parent, source, setter) {
478
+ function computed(parent, key, source, setter) {
500
479
  const { state } = parent;
501
480
  let local;
502
481
  let active;
@@ -557,7 +536,7 @@ function getComputed(key, parent, source, setter) {
557
536
  const INFO = new WeakMap();
558
537
  const KEYS = new WeakMap();
559
538
  const ORDER = new WeakMap();
560
- function flush(control) {
539
+ function flushComputed(control) {
561
540
  const pending = KEYS.get(control);
562
541
  if (!pending || !pending.size)
563
542
  return;
@@ -651,7 +630,7 @@ class Control {
651
630
  return;
652
631
  else if (!frame.size)
653
632
  setTimeout(() => {
654
- flush(this);
633
+ flushComputed(this);
655
634
  const keys = this.latest = Array.from(frame);
656
635
  setTimeout(() => this.latest = undefined, 0);
657
636
  frame.clear();
@@ -710,21 +689,19 @@ function control(subject, cb) {
710
689
 
711
690
  const Parent = new WeakMap();
712
691
  const Oops$3 = issues({
713
- BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`,
692
+ BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
714
693
  Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
715
694
  });
716
695
  function getParent(from, type) {
717
696
  const value = Parent.get(from);
718
697
  if (value && type && !(value instanceof type))
719
- throw Oops$3.Unexpected(type.name, from, value);
698
+ throw Oops$3.Unexpected(type, from, value);
720
699
  return value;
721
700
  }
722
701
  function getRecursive(key, from) {
723
702
  const context = new WeakMap();
724
703
  const { state } = from;
725
704
  return (local) => {
726
- if (!local)
727
- return state.get(key);
728
705
  if (!context.has(local)) {
729
706
  let reset;
730
707
  const init = () => {
@@ -758,8 +735,9 @@ function setRecursive(controller, key, initial) {
758
735
  const onUpdate = (next) => {
759
736
  state.set(key, next);
760
737
  if (!(next instanceof Type))
761
- throw Oops$3.BadAssignment(`${subject}.${key}`, Type.name, String(next));
762
- get = getRecursive(key, controller);
738
+ throw Oops$3.BadAssignment(`${subject}.${key}`, Type, String(next));
739
+ const getter = getRecursive(key, controller);
740
+ get = (local) => local ? getter(local) : state.get(key);
763
741
  Parent.set(next, subject);
764
742
  control(next);
765
743
  return true;
@@ -1111,7 +1089,8 @@ function use(input, argument) {
1111
1089
  const onUpdate = (next) => {
1112
1090
  state.set(key, next);
1113
1091
  if (next) {
1114
- get = getRecursive(key, this);
1092
+ const getter = getRecursive(key, this);
1093
+ get = (local) => local ? getter(local) : state.get(key);
1115
1094
  Parent.set(next, subject);
1116
1095
  control(next);
1117
1096
  }
@@ -1167,10 +1146,10 @@ function use(input, argument) {
1167
1146
  });
1168
1147
  }
1169
1148
 
1170
- const LOCAL = "$debug local";
1171
- const STATE = "$debug state";
1172
- const UPDATE = "$debug update";
1173
- const CONTROL = "$debug controller";
1149
+ const LOCAL = "__local";
1150
+ const STATE = "__state";
1151
+ const UPDATE = "__update";
1152
+ const CONTROL = "__control";
1174
1153
  defineProperties(Model.prototype, {
1175
1154
  [CONTROL]: {
1176
1155
  get() {
@@ -1273,7 +1252,9 @@ exports.Model = Model;
1273
1252
  exports.Register = Register;
1274
1253
  exports.Subscriber = Subscriber;
1275
1254
  exports.add = add;
1255
+ exports["default"] = Model;
1276
1256
  exports.get = get;
1257
+ exports.issues = issues;
1277
1258
  exports.ref = ref;
1278
1259
  exports.run = run;
1279
1260
  exports.set = set;
package/package.json CHANGED
@@ -37,5 +37,5 @@
37
37
  "tslib": "^2.3.0",
38
38
  "typescript": "^4.9.5"
39
39
  },
40
- "version": "0.18.0"
40
+ "version": "0.19.0"
41
41
  }