@expressive/mvc 0.24.0 → 0.24.2

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
@@ -22,15 +22,12 @@ declare namespace Context {
22
22
  };
23
23
  }
24
24
  declare class Context {
25
- /** Use */
26
25
  key: string;
27
26
  private table;
28
27
  private layer;
29
28
  private has;
30
29
  get<T extends Model>(Type: Model.Type<T>): T | undefined;
31
30
  include(inputs: Context.Inputs): Map<Model, boolean>;
32
- /** Context must force-reset becasue inputs are no longer safe. */
33
- private bailout;
34
31
  add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
35
32
  push(): this;
36
33
  pop(): void;
@@ -69,7 +66,7 @@ declare namespace Control {
69
66
  * Callback for Controller.for() static method.
70
67
  * Returned callback is forwarded.
71
68
  */
72
- type OnReady<T extends Model> = (control: Control<T>) => Callback | void;
69
+ type OnReady<T extends {}> = (control: Control<T>) => Callback | void;
73
70
  type RequestRefresh = (update: (tick: number) => number) => void;
74
71
  type GetContext = (target: Model) => (callback: (got: Context) => void) => void;
75
72
  type GetAdapter<T> = (refresh: RequestRefresh, context: Context) => {
@@ -84,7 +81,7 @@ declare namespace Control {
84
81
  };
85
82
  type UseHook = <T extends Model, R>(adapter: UseAdapter<T, R>) => R;
86
83
  }
87
- declare class Control<T extends Model = any> {
84
+ declare class Control<T extends {} = any> {
88
85
  subject: T;
89
86
  id: string | number;
90
87
  static after: Set<Callback>;
@@ -113,7 +110,7 @@ declare class Control<T extends Model = any> {
113
110
  }
114
111
  declare function control<T extends Model>(subject: T, ready: Control.OnReady<T>): Callback;
115
112
  declare function control<T extends Model>(subject: T, ready?: boolean): Control<T>;
116
- declare function watch<T extends Model>(on: T, cb: Observer): T;
113
+ declare function watch<T extends {}>(on: T, cb: Observer): T;
117
114
  declare function apply<T = any>(instruction: Control.Instruction<T>): T;
118
115
 
119
116
  declare const STATE = "__state";
@@ -156,7 +153,7 @@ type Debug<T extends Model = Model> = T & {
156
153
  };
157
154
 
158
155
  /** Type may not be undefined - instead will be null. */
159
- type NoVoid<T> = T extends undefined ? null : T;
156
+ type NoVoid<T> = T extends undefined | void ? null : T;
160
157
  declare function get$1<T extends Model>(this: Model.Type<T>): T;
161
158
  /** Fetch instance of this class in passive mode. Will not subscribe to events. */
162
159
  declare function get$1<T extends Model>(this: Model.Type<T>, ignoreUpdates?: true): T;
@@ -387,11 +384,12 @@ declare function use<T extends Model>(): T | undefined;
387
384
  /** Create a new child instance of model. */
388
385
  declare function use<T extends Model>(Type: Model.New<T>, callback?: (i: T) => void): T;
389
386
  /** Assign the result of a factory as a child model. */
390
- declare function use<T extends Model>(from: () => Promise<T> | T, required?: true): T;
387
+ declare function use<T extends {}>(from: () => Promise<T> | T, required?: true): T;
391
388
  /** Assign the result of a factory as a child model. */
392
- declare function use<T extends Model>(from: () => Promise<T> | T, required: boolean): T | undefined;
389
+ declare function use<T extends {}>(from: () => Promise<T> | T, required: boolean): T | undefined;
393
390
  /** Create a managed child from factory function. */
394
- declare function use<T extends Model>(from: () => Promise<T> | T, callback?: (i: T) => void): T;
391
+ declare function use<T extends {}>(from: () => Promise<T> | T, callback?: (i: T) => void): T;
392
+ declare function use<T extends {}>(data: T): T;
395
393
  /**
396
394
  * Create child-instance relationship with provided model.
397
395
  *
package/lib/index.esm.js CHANGED
@@ -226,9 +226,6 @@ function get$1(arg1, arg2) {
226
226
  const found = context.get(this);
227
227
  if (!found)
228
228
  throw Oops$6.NotFound(this);
229
- proxy = Control.watch(found, () => factory ? null : onUpdate);
230
- getValue = () => compute.call(proxy, proxy, forceUpdate);
231
- value = getValue();
232
229
  function forceUpdate(action) {
233
230
  if (typeof action == "function")
234
231
  action = action();
@@ -239,6 +236,18 @@ function get$1(arg1, arg2) {
239
236
  if (action)
240
237
  return action.finally(refresh);
241
238
  }
239
+ function didUpdate(got) {
240
+ value = got;
241
+ if (suspense) {
242
+ suspense();
243
+ suspense = undefined;
244
+ }
245
+ else
246
+ refresh();
247
+ }
248
+ proxy = Control.watch(found, () => factory ? null : onUpdate);
249
+ getValue = () => compute.call(proxy, proxy, forceUpdate);
250
+ value = getValue();
242
251
  if (value === null) {
243
252
  getValue = undefined;
244
253
  onUpdate = null;
@@ -251,15 +260,6 @@ function get$1(arg1, arg2) {
251
260
  compute = () => get();
252
261
  value = get();
253
262
  }
254
- const didUpdate = (got) => {
255
- value = got;
256
- if (suspense) {
257
- suspense();
258
- suspense = undefined;
259
- }
260
- else
261
- refresh();
262
- };
263
263
  if (value instanceof Promise) {
264
264
  onUpdate = null;
265
265
  value.then(didUpdate);
@@ -444,7 +444,7 @@ class Control {
444
444
  const instruction = INSTRUCTION.get(value);
445
445
  if (typeof instruction == "function") {
446
446
  INSTRUCTION.delete(value);
447
- instruction(key, this);
447
+ instruction(this, key);
448
448
  }
449
449
  else if (value instanceof Model)
450
450
  setRecursive(this, key, value);
@@ -453,7 +453,7 @@ class Control {
453
453
  }
454
454
  watch(key, output) {
455
455
  const { state } = this;
456
- const { get, set, enumerable = true } = output;
456
+ const { set, enumerable = true } = output;
457
457
  const subs = new Set();
458
458
  this.observers.set(key, subs);
459
459
  if ("value" in output)
@@ -467,8 +467,9 @@ class Control {
467
467
  const event = OBSERVER.get(this);
468
468
  if (event)
469
469
  subs.add(event);
470
- const value = get ? get(this) : state[key];
471
- return event && value instanceof Model
470
+ const value = output.get
471
+ ? output.get(this) : state[key];
472
+ return event && REGISTER.has(value)
472
473
  ? watch(value, event)
473
474
  : value;
474
475
  }
@@ -598,7 +599,7 @@ function watch(on, cb) {
598
599
  }
599
600
  function apply(instruction) {
600
601
  const placeholder = Symbol("instruction");
601
- INSTRUCTION.set(placeholder, (key, onto) => {
602
+ INSTRUCTION.set(placeholder, (onto, key) => {
602
603
  delete onto.subject[key];
603
604
  const output = instruction.call(onto, key, onto);
604
605
  if (output)
@@ -900,69 +901,63 @@ function use(input, argument) {
900
901
  return apply((key, source) => {
901
902
  const { state, subject } = source;
902
903
  const required = argument !== false;
903
- let pending;
904
- let error;
905
904
  if (typeof input === "function") {
906
905
  if ("prototype" in input && input === input.prototype.constructor)
907
906
  input = new input();
908
907
  }
909
908
  else if (input && typeof input !== "object")
910
909
  throw Oops$1.BadArgument(typeof input);
911
- const onUpdate = (next) => {
912
- state[key] = next;
913
- if (next) {
914
- parent(next, subject);
915
- control(next, true);
916
- }
917
- if (typeof argument == "function")
918
- argument(next);
919
- return true;
920
- };
921
- const suspend = () => {
922
- if (required === false)
923
- return;
924
- const issue = Oops$1.NotReady(subject, key);
925
- assign(pending, {
926
- message: issue.message,
927
- stack: issue.stack
928
- });
929
- throw pending;
930
- };
931
- const initialize = () => {
932
- const output = typeof input == "function" ?
910
+ function init() {
911
+ const result = typeof input == "function" ?
933
912
  mayRetry(() => input.call(subject, subject)) :
934
913
  input;
935
- if (output instanceof Promise) {
936
- pending = output
937
- .then(val => {
938
- onUpdate(val);
939
- return val;
914
+ if (result instanceof Promise) {
915
+ const pending = result
916
+ .then(value => {
917
+ output.get = undefined;
918
+ set(value);
919
+ return value;
920
+ })
921
+ .catch(err => {
922
+ output.get = () => { throw err; };
940
923
  })
941
- .catch(err => error = err)
942
924
  .finally(() => {
943
- pending = undefined;
944
925
  source.update(key);
945
926
  });
946
- return;
927
+ if (required !== false)
928
+ output.get = () => {
929
+ throw assign(pending, Oops$1.NotReady(subject, key));
930
+ };
947
931
  }
948
- onUpdate(output);
949
- };
950
- if (input !== undefined && required)
951
- initialize();
952
- return {
953
- set: onUpdate,
954
- get() {
955
- if (pending)
956
- return suspend();
957
- if (error)
958
- throw error;
959
- if (!(key in state))
960
- initialize();
961
- if (pending)
962
- return suspend();
963
- return state[key];
932
+ else
933
+ set(result);
934
+ }
935
+ function set(next) {
936
+ if (next instanceof Model) {
937
+ parent(next, subject);
938
+ control(next, true);
964
939
  }
965
- };
940
+ else if (next) {
941
+ const control = new Control(create(next));
942
+ control.state = next;
943
+ for (const key in next)
944
+ control.watch(key, {});
945
+ next = control.subject;
946
+ }
947
+ state[key] = next;
948
+ if (typeof argument == "function")
949
+ argument(next);
950
+ return true;
951
+ }
952
+ const output = { set };
953
+ if (required)
954
+ init();
955
+ else
956
+ output.get = () => {
957
+ init();
958
+ return state[key];
959
+ };
960
+ return output;
966
961
  });
967
962
  }
968
963
 
@@ -998,8 +993,12 @@ class Context {
998
993
  this.layer.set(key, input);
999
994
  init.set(instance, true);
1000
995
  }
1001
- else if (exists !== input)
1002
- return this.bailout(inputs);
996
+ // Context must force-reset becasue inputs are no longer safe.
997
+ else if (exists !== input) {
998
+ this.pop();
999
+ this.key = uid();
1000
+ return this.include(inputs);
1001
+ }
1003
1002
  }
1004
1003
  for (const [model] of init) {
1005
1004
  const { state } = control(model, true);
@@ -1012,12 +1011,6 @@ class Context {
1012
1011
  }
1013
1012
  return init;
1014
1013
  }
1015
- /** Context must force-reset becasue inputs are no longer safe. */
1016
- bailout(inputs) {
1017
- this.pop();
1018
- this.key = uid();
1019
- return this.include(inputs);
1020
- }
1021
1014
  add(input, implicit) {
1022
1015
  let writable = true;
1023
1016
  let T;
package/lib/index.js CHANGED
@@ -230,9 +230,6 @@ function get$1(arg1, arg2) {
230
230
  const found = context.get(this);
231
231
  if (!found)
232
232
  throw Oops$6.NotFound(this);
233
- proxy = Control.watch(found, () => factory ? null : onUpdate);
234
- getValue = () => compute.call(proxy, proxy, forceUpdate);
235
- value = getValue();
236
233
  function forceUpdate(action) {
237
234
  if (typeof action == "function")
238
235
  action = action();
@@ -243,6 +240,18 @@ function get$1(arg1, arg2) {
243
240
  if (action)
244
241
  return action.finally(refresh);
245
242
  }
243
+ function didUpdate(got) {
244
+ value = got;
245
+ if (suspense) {
246
+ suspense();
247
+ suspense = undefined;
248
+ }
249
+ else
250
+ refresh();
251
+ }
252
+ proxy = Control.watch(found, () => factory ? null : onUpdate);
253
+ getValue = () => compute.call(proxy, proxy, forceUpdate);
254
+ value = getValue();
246
255
  if (value === null) {
247
256
  getValue = undefined;
248
257
  onUpdate = null;
@@ -255,15 +264,6 @@ function get$1(arg1, arg2) {
255
264
  compute = () => get();
256
265
  value = get();
257
266
  }
258
- const didUpdate = (got) => {
259
- value = got;
260
- if (suspense) {
261
- suspense();
262
- suspense = undefined;
263
- }
264
- else
265
- refresh();
266
- };
267
267
  if (value instanceof Promise) {
268
268
  onUpdate = null;
269
269
  value.then(didUpdate);
@@ -448,7 +448,7 @@ class Control {
448
448
  const instruction = INSTRUCTION.get(value);
449
449
  if (typeof instruction == "function") {
450
450
  INSTRUCTION.delete(value);
451
- instruction(key, this);
451
+ instruction(this, key);
452
452
  }
453
453
  else if (value instanceof Model)
454
454
  setRecursive(this, key, value);
@@ -457,7 +457,7 @@ class Control {
457
457
  }
458
458
  watch(key, output) {
459
459
  const { state } = this;
460
- const { get, set, enumerable = true } = output;
460
+ const { set, enumerable = true } = output;
461
461
  const subs = new Set();
462
462
  this.observers.set(key, subs);
463
463
  if ("value" in output)
@@ -471,8 +471,9 @@ class Control {
471
471
  const event = OBSERVER.get(this);
472
472
  if (event)
473
473
  subs.add(event);
474
- const value = get ? get(this) : state[key];
475
- return event && value instanceof Model
474
+ const value = output.get
475
+ ? output.get(this) : state[key];
476
+ return event && REGISTER.has(value)
476
477
  ? watch(value, event)
477
478
  : value;
478
479
  }
@@ -602,7 +603,7 @@ function watch(on, cb) {
602
603
  }
603
604
  function apply(instruction) {
604
605
  const placeholder = Symbol("instruction");
605
- INSTRUCTION.set(placeholder, (key, onto) => {
606
+ INSTRUCTION.set(placeholder, (onto, key) => {
606
607
  delete onto.subject[key];
607
608
  const output = instruction.call(onto, key, onto);
608
609
  if (output)
@@ -904,69 +905,63 @@ function use(input, argument) {
904
905
  return apply((key, source) => {
905
906
  const { state, subject } = source;
906
907
  const required = argument !== false;
907
- let pending;
908
- let error;
909
908
  if (typeof input === "function") {
910
909
  if ("prototype" in input && input === input.prototype.constructor)
911
910
  input = new input();
912
911
  }
913
912
  else if (input && typeof input !== "object")
914
913
  throw Oops$1.BadArgument(typeof input);
915
- const onUpdate = (next) => {
916
- state[key] = next;
917
- if (next) {
918
- parent(next, subject);
919
- control(next, true);
920
- }
921
- if (typeof argument == "function")
922
- argument(next);
923
- return true;
924
- };
925
- const suspend = () => {
926
- if (required === false)
927
- return;
928
- const issue = Oops$1.NotReady(subject, key);
929
- assign(pending, {
930
- message: issue.message,
931
- stack: issue.stack
932
- });
933
- throw pending;
934
- };
935
- const initialize = () => {
936
- const output = typeof input == "function" ?
914
+ function init() {
915
+ const result = typeof input == "function" ?
937
916
  mayRetry(() => input.call(subject, subject)) :
938
917
  input;
939
- if (output instanceof Promise) {
940
- pending = output
941
- .then(val => {
942
- onUpdate(val);
943
- return val;
918
+ if (result instanceof Promise) {
919
+ const pending = result
920
+ .then(value => {
921
+ output.get = undefined;
922
+ set(value);
923
+ return value;
924
+ })
925
+ .catch(err => {
926
+ output.get = () => { throw err; };
944
927
  })
945
- .catch(err => error = err)
946
928
  .finally(() => {
947
- pending = undefined;
948
929
  source.update(key);
949
930
  });
950
- return;
931
+ if (required !== false)
932
+ output.get = () => {
933
+ throw assign(pending, Oops$1.NotReady(subject, key));
934
+ };
951
935
  }
952
- onUpdate(output);
953
- };
954
- if (input !== undefined && required)
955
- initialize();
956
- return {
957
- set: onUpdate,
958
- get() {
959
- if (pending)
960
- return suspend();
961
- if (error)
962
- throw error;
963
- if (!(key in state))
964
- initialize();
965
- if (pending)
966
- return suspend();
967
- return state[key];
936
+ else
937
+ set(result);
938
+ }
939
+ function set(next) {
940
+ if (next instanceof Model) {
941
+ parent(next, subject);
942
+ control(next, true);
968
943
  }
969
- };
944
+ else if (next) {
945
+ const control = new Control(create(next));
946
+ control.state = next;
947
+ for (const key in next)
948
+ control.watch(key, {});
949
+ next = control.subject;
950
+ }
951
+ state[key] = next;
952
+ if (typeof argument == "function")
953
+ argument(next);
954
+ return true;
955
+ }
956
+ const output = { set };
957
+ if (required)
958
+ init();
959
+ else
960
+ output.get = () => {
961
+ init();
962
+ return state[key];
963
+ };
964
+ return output;
970
965
  });
971
966
  }
972
967
 
@@ -1002,8 +997,12 @@ class Context {
1002
997
  this.layer.set(key, input);
1003
998
  init.set(instance, true);
1004
999
  }
1005
- else if (exists !== input)
1006
- return this.bailout(inputs);
1000
+ // Context must force-reset becasue inputs are no longer safe.
1001
+ else if (exists !== input) {
1002
+ this.pop();
1003
+ this.key = uid();
1004
+ return this.include(inputs);
1005
+ }
1007
1006
  }
1008
1007
  for (const [model] of init) {
1009
1008
  const { state } = control(model, true);
@@ -1016,12 +1015,6 @@ class Context {
1016
1015
  }
1017
1016
  return init;
1018
1017
  }
1019
- /** Context must force-reset becasue inputs are no longer safe. */
1020
- bailout(inputs) {
1021
- this.pop();
1022
- this.key = uid();
1023
- return this.include(inputs);
1024
- }
1025
1018
  add(input, implicit) {
1026
1019
  let writable = true;
1027
1020
  let T;
package/package.json CHANGED
@@ -22,8 +22,10 @@
22
22
  "scripts": {
23
23
  "build": "rollup --config",
24
24
  "watch": "jest --watchAll",
25
- "test": "jest --collectCoverage"
25
+ "test": "jest --collectCoverage",
26
+ "prebuild": "rm -rf lib/",
27
+ "preversion": "npm run test && npm run build"
26
28
  },
27
- "version": "0.24.0",
28
- "gitHead": "a2dc690ceb816497268b2affe5b83951d993c6f2"
29
+ "version": "0.24.2",
30
+ "gitHead": "97e6daffcf793d8aa1152d553b4c427546e90dbc"
29
31
  }