@expressive/mvc 0.21.1 → 0.21.3

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 HasHook = (type: typeof Model, relativeTo: Model, callback: (got: Model | undefined) => 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;
@@ -93,7 +114,7 @@ declare class Control<T extends Model = any> {
93
114
  declare function control<T extends Model>(subject: T, ready: Control.OnReady<T>): Callback;
94
115
  declare function control<T extends Model>(subject: T, ready?: boolean): Control<T>;
95
116
  declare function watch<T extends Model>(on: T, cb: Observer): T;
96
- declare function apply<T = any>(instruction: Control.Instruction<any>): T;
117
+ declare function apply<T = any>(instruction: Control.Instruction<T>): T;
97
118
 
98
119
  declare const STATE = "__state";
99
120
  declare const UPDATE = "__update";
@@ -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 input;
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
 
@@ -953,13 +953,12 @@ function use(input, argument) {
953
953
  }
954
954
 
955
955
  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.`
956
+ MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
958
957
  });
959
958
  class Context {
960
959
  constructor() {
961
960
  this.table = new WeakMap();
962
- this.input = new Map();
961
+ this.layer = new Map();
963
962
  }
964
963
  has(T) {
965
964
  let key = this.table.get(T);
@@ -979,15 +978,14 @@ class Context {
979
978
  const init = new Map();
980
979
  for (const key in inputs) {
981
980
  const input = inputs[key];
982
- const exists = this.input.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.input.set(key, input);
990
- init.set(instance, true);
981
+ const exists = this.layer.get(key);
982
+ if (!exists) {
983
+ const instance = this.add(input);
984
+ this.layer.set(key, input);
985
+ init.set(instance, true);
986
+ }
987
+ else if (exists !== input)
988
+ return this.bailout(inputs);
991
989
  }
992
990
  for (const [model] of init) {
993
991
  const { state } = control(model, true);
@@ -1000,6 +998,12 @@ class Context {
1000
998
  }
1001
999
  return init;
1002
1000
  }
1001
+ /** Context must force-reset becasue inputs are no longer safe. */
1002
+ bailout(inputs) {
1003
+ this.pop();
1004
+ this.key = uid();
1005
+ return this.include(inputs);
1006
+ }
1003
1007
  add(input, implicit) {
1004
1008
  let writable = true;
1005
1009
  let T;
@@ -1028,7 +1032,7 @@ class Context {
1028
1032
  }
1029
1033
  push() {
1030
1034
  const next = create(this);
1031
- next.input = new Map();
1035
+ next.layer = new Map();
1032
1036
  return next;
1033
1037
  }
1034
1038
  pop() {
@@ -1041,7 +1045,7 @@ class Context {
1041
1045
  }
1042
1046
  for (const model of items)
1043
1047
  model.null();
1044
- this.input.clear();
1048
+ this.layer.clear();
1045
1049
  }
1046
1050
  }
1047
1051
 
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
 
@@ -957,13 +957,12 @@ function use(input, argument) {
957
957
  }
958
958
 
959
959
  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.`
960
+ MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
962
961
  });
963
962
  class Context {
964
963
  constructor() {
965
964
  this.table = new WeakMap();
966
- this.input = new Map();
965
+ this.layer = new Map();
967
966
  }
968
967
  has(T) {
969
968
  let key = this.table.get(T);
@@ -983,15 +982,14 @@ class Context {
983
982
  const init = new Map();
984
983
  for (const key in inputs) {
985
984
  const input = inputs[key];
986
- const exists = this.input.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.input.set(key, input);
994
- init.set(instance, true);
985
+ const exists = this.layer.get(key);
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);
995
993
  }
996
994
  for (const [model] of init) {
997
995
  const { state } = control(model, true);
@@ -1004,6 +1002,12 @@ class Context {
1004
1002
  }
1005
1003
  return init;
1006
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
+ }
1007
1011
  add(input, implicit) {
1008
1012
  let writable = true;
1009
1013
  let T;
@@ -1032,7 +1036,7 @@ class Context {
1032
1036
  }
1033
1037
  push() {
1034
1038
  const next = create(this);
1035
- next.input = new Map();
1039
+ next.layer = new Map();
1036
1040
  return next;
1037
1041
  }
1038
1042
  pop() {
@@ -1045,7 +1049,7 @@ class Context {
1045
1049
  }
1046
1050
  for (const model of items)
1047
1051
  model.null();
1048
- this.input.clear();
1052
+ this.layer.clear();
1049
1053
  }
1050
1054
  }
1051
1055
 
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.1"
30
+ "version": "0.21.3"
31
31
  }