@expressive/mvc 0.21.2 → 0.21.7

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
@@ -16,6 +16,26 @@ declare function run<S>(action: Async<S>): typeof action & {
16
16
  active: boolean;
17
17
  };
18
18
 
19
+ declare namespace Context {
20
+ type Inputs = {
21
+ [key: string | number]: Model | Model.New;
22
+ };
23
+ }
24
+ declare class Context {
25
+ /** Use */
26
+ key: string;
27
+ private table;
28
+ private layer;
29
+ private has;
30
+ get<T extends Model>(Type: Model.Type<T>): T | undefined;
31
+ include(inputs: Context.Inputs): Map<Model, boolean>;
32
+ /** Context must force-reset becasue inputs are no longer safe. */
33
+ private bailout;
34
+ add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
35
+ push(): this;
36
+ pop(): void;
37
+ }
38
+
19
39
  type Callback = () => void;
20
40
 
21
41
  declare global {
@@ -50,18 +70,19 @@ declare namespace Control {
50
70
  * Returned callback is forwarded.
51
71
  */
52
72
  type OnReady<T extends Model> = (control: Control<T>) => Callback | void;
53
- type GetAdapter<T> = (update: () => void, source: (request: (got: Model | undefined) => void) => void) => {
73
+ type RequestRefresh = (update: (tick: number) => number) => void;
74
+ type GetContext = (target: Model) => (callback: (got: Context) => void) => void;
75
+ type GetAdapter<T> = (refresh: RequestRefresh, context: Context) => {
54
76
  mount: () => (() => void) | void;
55
77
  render: () => T;
56
78
  } | void;
57
- type GetHook = <T extends Model, R>(type: Model.Type<T>, adapter: GetAdapter<R>) => R | null;
58
- type UseAdapter<T extends Model> = (update: () => void) => {
79
+ type GetHook = <T>(adapter: GetAdapter<T>) => T | null;
80
+ type UseAdapter<T extends Model> = (refresh: RequestRefresh) => {
59
81
  instance: T;
60
82
  mount: () => (() => void) | void;
61
83
  render: (props: Model.Compat<T>) => T;
62
84
  };
63
85
  type UseHook = <T extends Model>(adapter: UseAdapter<T>) => (props: Model.Compat<T>) => T;
64
- type HasHook = (type: typeof Model, relativeTo: Model, callback: (got: Model | undefined) => void) => void;
65
86
  }
66
87
  declare class Control<T extends Model = any> {
67
88
  subject: T;
@@ -71,7 +92,7 @@ declare class Control<T extends Model = any> {
71
92
  static pending: Set<Callback>;
72
93
  static get: Control.GetHook;
73
94
  static use: Control.UseHook;
74
- static has: Control.HasHook;
95
+ static has: Control.GetContext;
75
96
  static for: typeof control;
76
97
  static apply: typeof apply;
77
98
  static watch: typeof watch;
@@ -381,20 +402,4 @@ declare function use<T extends Model>(from: () => Promise<T> | T, callback?: (i:
381
402
  */
382
403
  declare function use<T extends Model>(peer: T, callback?: (i: T) => void): T;
383
404
 
384
- declare namespace Context {
385
- type Inputs = {
386
- [key: string | number]: Model | Model.New;
387
- };
388
- }
389
- declare class Context {
390
- private table;
391
- private layer;
392
- private has;
393
- get<T extends Model>(Type: Model.Type<T>): T | undefined;
394
- include(inputs: Context.Inputs): Map<Model, boolean>;
395
- add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
396
- push(): this;
397
- pop(): void;
398
- }
399
-
400
405
  export { Context, Control, Debug, Model, Model as default, get, ref, run, set, use };
package/lib/index.esm.js CHANGED
@@ -198,18 +198,18 @@ const Oops$6 = issues({
198
198
  NotFound: (name) => `Could not find ${name} in context.`
199
199
  });
200
200
  function get$1(arg1, arg2) {
201
- return Control.get(this, (refresh, context) => {
201
+ return Control.get((dispatch, context) => {
202
+ const refresh = () => dispatch(x => x + 1);
202
203
  let onUpdate;
203
204
  let value;
204
205
  if (typeof arg1 !== "function") {
205
- context(got => {
206
- if (got)
207
- value = arg1 === undefined
208
- ? Control.watch(got, () => onUpdate)
209
- : got;
210
- else if (arg1 !== false)
211
- throw Oops$6.NotFound(this);
212
- });
206
+ const got = context.get(this);
207
+ if (got)
208
+ value = arg1 === undefined
209
+ ? Control.watch(got, k => k ? onUpdate : undefined)
210
+ : got;
211
+ else if (arg1 !== false)
212
+ throw Oops$6.NotFound(this);
213
213
  return {
214
214
  mount() {
215
215
  onUpdate = refresh;
@@ -223,23 +223,22 @@ function get$1(arg1, arg2) {
223
223
  let getValue;
224
224
  let factory;
225
225
  let proxy;
226
- context(got => {
227
- if (!got)
228
- throw Oops$6.NotFound(this);
229
- proxy = Control.watch(got, () => factory ? null : onUpdate);
230
- getValue = () => compute.call(proxy, proxy, forceUpdate);
231
- value = getValue();
232
- function forceUpdate(action) {
233
- if (typeof action == "function")
234
- action = action();
235
- if (getValue)
236
- didUpdate(getValue());
237
- else
238
- refresh();
239
- if (action)
240
- return action.finally(refresh);
241
- }
242
- });
226
+ const found = context.get(this);
227
+ if (!found)
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
+ function forceUpdate(action) {
233
+ if (typeof action == "function")
234
+ action = action();
235
+ if (getValue)
236
+ didUpdate(getValue());
237
+ else
238
+ refresh();
239
+ if (action)
240
+ return action.finally(refresh);
241
+ }
243
242
  if (value === null) {
244
243
  getValue = undefined;
245
244
  onUpdate = null;
@@ -295,11 +294,12 @@ const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
295
294
  a.some((x, i) => x !== b[i])));
296
295
 
297
296
  function use$1(arg1, arg2) {
298
- const render = Control.use((refresh) => {
299
- let onUpdate;
300
- let applyProps = typeof arg1 === "object";
297
+ const render = Control.use(dispatch => {
301
298
  const instance = this.new();
302
299
  const proxy = Control.watch(instance, () => onUpdate);
300
+ const refresh = () => dispatch(x => x + 1);
301
+ let onUpdate;
302
+ let applyProps = typeof arg1 === "object";
303
303
  if (typeof arg1 == "function")
304
304
  arg1(instance);
305
305
  return {
@@ -429,7 +429,7 @@ const REGISTER = new WeakMap();
429
429
  const OBSERVER = new WeakMap();
430
430
  const PARENTS = new WeakMap();
431
431
  class Control {
432
- constructor(subject, id = random()) {
432
+ constructor(subject, id = uid()) {
433
433
  this.subject = subject;
434
434
  this.id = id;
435
435
  this.frame = new Set();
@@ -605,7 +605,7 @@ function apply(instruction) {
605
605
  return placeholder;
606
606
  }
607
607
  /** Random alphanumberic of length 6; will always start with a letter. */
608
- function random() {
608
+ function uid() {
609
609
  return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
610
610
  }
611
611
 
@@ -659,12 +659,16 @@ function get(arg0, arg1) {
659
659
  if (!hasParent) {
660
660
  if (arg1 === true)
661
661
  throw Oops$3.Required(arg0, subject);
662
- source = callback => Control.has(arg0, subject, got => {
663
- if (got)
664
- callback(got);
665
- else if (arg1 !== false)
666
- throw Oops$3.AmbientRequired(arg0, subject);
667
- });
662
+ const fetch = Control.has(subject);
663
+ source = got => {
664
+ fetch(context => {
665
+ const model = context.get(arg0);
666
+ if (model)
667
+ got(model);
668
+ else if (arg1 !== false)
669
+ throw Oops$3.AmbientRequired(arg0, subject);
670
+ });
671
+ };
668
672
  }
669
673
  else if (!arg0 || hasParent instanceof arg0)
670
674
  subject = hasParent;
@@ -953,8 +957,7 @@ function use(input, argument) {
953
957
  }
954
958
 
955
959
  const Oops = issues({
956
- MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`,
957
- NewValue: (name) => `Provider already has already defined '${name}' but got new value. This is not yet supported.`
960
+ MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
958
961
  });
959
962
  class Context {
960
963
  constructor() {
@@ -980,14 +983,13 @@ class Context {
980
983
  for (const key in inputs) {
981
984
  const input = inputs[key];
982
985
  const exists = this.layer.get(key);
983
- if (exists)
984
- if (exists !== input)
985
- throw Oops.NewValue(key);
986
- else
987
- continue;
988
- const instance = this.add(input);
989
- this.layer.set(key, input);
990
- init.set(instance, true);
986
+ if (!exists) {
987
+ const instance = this.add(input);
988
+ this.layer.set(key, input);
989
+ init.set(instance, true);
990
+ }
991
+ else if (exists !== input)
992
+ return this.bailout(inputs);
991
993
  }
992
994
  for (const [model] of init) {
993
995
  const { state } = control(model, true);
@@ -1000,6 +1002,12 @@ class Context {
1000
1002
  }
1001
1003
  return init;
1002
1004
  }
1005
+ /** Context must force-reset becasue inputs are no longer safe. */
1006
+ bailout(inputs) {
1007
+ this.pop();
1008
+ this.key = uid();
1009
+ return this.include(inputs);
1010
+ }
1003
1011
  add(input, implicit) {
1004
1012
  let writable = true;
1005
1013
  let T;
package/lib/index.js CHANGED
@@ -202,18 +202,18 @@ const Oops$6 = issues({
202
202
  NotFound: (name) => `Could not find ${name} in context.`
203
203
  });
204
204
  function get$1(arg1, arg2) {
205
- return Control.get(this, (refresh, context) => {
205
+ return Control.get((dispatch, context) => {
206
+ const refresh = () => dispatch(x => x + 1);
206
207
  let onUpdate;
207
208
  let value;
208
209
  if (typeof arg1 !== "function") {
209
- context(got => {
210
- if (got)
211
- value = arg1 === undefined
212
- ? Control.watch(got, () => onUpdate)
213
- : got;
214
- else if (arg1 !== false)
215
- throw Oops$6.NotFound(this);
216
- });
210
+ const got = context.get(this);
211
+ if (got)
212
+ value = arg1 === undefined
213
+ ? Control.watch(got, k => k ? onUpdate : undefined)
214
+ : got;
215
+ else if (arg1 !== false)
216
+ throw Oops$6.NotFound(this);
217
217
  return {
218
218
  mount() {
219
219
  onUpdate = refresh;
@@ -227,23 +227,22 @@ function get$1(arg1, arg2) {
227
227
  let getValue;
228
228
  let factory;
229
229
  let proxy;
230
- context(got => {
231
- if (!got)
232
- throw Oops$6.NotFound(this);
233
- proxy = Control.watch(got, () => factory ? null : onUpdate);
234
- getValue = () => compute.call(proxy, proxy, forceUpdate);
235
- value = getValue();
236
- function forceUpdate(action) {
237
- if (typeof action == "function")
238
- action = action();
239
- if (getValue)
240
- didUpdate(getValue());
241
- else
242
- refresh();
243
- if (action)
244
- return action.finally(refresh);
245
- }
246
- });
230
+ const found = context.get(this);
231
+ if (!found)
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
+ function forceUpdate(action) {
237
+ if (typeof action == "function")
238
+ action = action();
239
+ if (getValue)
240
+ didUpdate(getValue());
241
+ else
242
+ refresh();
243
+ if (action)
244
+ return action.finally(refresh);
245
+ }
247
246
  if (value === null) {
248
247
  getValue = undefined;
249
248
  onUpdate = null;
@@ -299,11 +298,12 @@ const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
299
298
  a.some((x, i) => x !== b[i])));
300
299
 
301
300
  function use$1(arg1, arg2) {
302
- const render = Control.use((refresh) => {
303
- let onUpdate;
304
- let applyProps = typeof arg1 === "object";
301
+ const render = Control.use(dispatch => {
305
302
  const instance = this.new();
306
303
  const proxy = Control.watch(instance, () => onUpdate);
304
+ const refresh = () => dispatch(x => x + 1);
305
+ let onUpdate;
306
+ let applyProps = typeof arg1 === "object";
307
307
  if (typeof arg1 == "function")
308
308
  arg1(instance);
309
309
  return {
@@ -433,7 +433,7 @@ const REGISTER = new WeakMap();
433
433
  const OBSERVER = new WeakMap();
434
434
  const PARENTS = new WeakMap();
435
435
  class Control {
436
- constructor(subject, id = random()) {
436
+ constructor(subject, id = uid()) {
437
437
  this.subject = subject;
438
438
  this.id = id;
439
439
  this.frame = new Set();
@@ -609,7 +609,7 @@ function apply(instruction) {
609
609
  return placeholder;
610
610
  }
611
611
  /** Random alphanumberic of length 6; will always start with a letter. */
612
- function random() {
612
+ function uid() {
613
613
  return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
614
614
  }
615
615
 
@@ -663,12 +663,16 @@ function get(arg0, arg1) {
663
663
  if (!hasParent) {
664
664
  if (arg1 === true)
665
665
  throw Oops$3.Required(arg0, subject);
666
- source = callback => Control.has(arg0, subject, got => {
667
- if (got)
668
- callback(got);
669
- else if (arg1 !== false)
670
- throw Oops$3.AmbientRequired(arg0, subject);
671
- });
666
+ const fetch = Control.has(subject);
667
+ source = got => {
668
+ fetch(context => {
669
+ const model = context.get(arg0);
670
+ if (model)
671
+ got(model);
672
+ else if (arg1 !== false)
673
+ throw Oops$3.AmbientRequired(arg0, subject);
674
+ });
675
+ };
672
676
  }
673
677
  else if (!arg0 || hasParent instanceof arg0)
674
678
  subject = hasParent;
@@ -957,8 +961,7 @@ function use(input, argument) {
957
961
  }
958
962
 
959
963
  const Oops = issues({
960
- MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`,
961
- NewValue: (name) => `Provider already has already defined '${name}' but got new value. This is not yet supported.`
964
+ MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
962
965
  });
963
966
  class Context {
964
967
  constructor() {
@@ -984,14 +987,13 @@ class Context {
984
987
  for (const key in inputs) {
985
988
  const input = inputs[key];
986
989
  const exists = this.layer.get(key);
987
- if (exists)
988
- if (exists !== input)
989
- throw Oops.NewValue(key);
990
- else
991
- continue;
992
- const instance = this.add(input);
993
- this.layer.set(key, input);
994
- init.set(instance, true);
990
+ if (!exists) {
991
+ const instance = this.add(input);
992
+ this.layer.set(key, input);
993
+ init.set(instance, true);
994
+ }
995
+ else if (exists !== input)
996
+ return this.bailout(inputs);
995
997
  }
996
998
  for (const [model] of init) {
997
999
  const { state } = control(model, true);
@@ -1004,6 +1006,12 @@ class Context {
1004
1006
  }
1005
1007
  return init;
1006
1008
  }
1009
+ /** Context must force-reset becasue inputs are no longer safe. */
1010
+ bailout(inputs) {
1011
+ this.pop();
1012
+ this.key = uid();
1013
+ return this.include(inputs);
1014
+ }
1007
1015
  add(input, implicit) {
1008
1016
  let writable = true;
1009
1017
  let T;
package/package.json CHANGED
@@ -27,5 +27,5 @@
27
27
  "preversion": "npm run test && npm run build",
28
28
  "postversion": "git push & npm publish"
29
29
  },
30
- "version": "0.21.2"
30
+ "version": "0.21.7"
31
31
  }