@expressive/mvc 0.48.0 → 0.49.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/dist/index.d.ts CHANGED
@@ -354,6 +354,18 @@ declare function has<T extends Model>(type: Model.Type<T>, one: true): T;
354
354
  declare function has<T extends Model>(type: Model.Type<T>, required: boolean): T | undefined;
355
355
  declare function has<T extends Model>(type: Model.Type<T>, arg?: has.Callback<T>): Set<T>;
356
356
 
357
+ type Effect<T extends {}> = (this: T, argument: T) => ((update: boolean | null) => void) | Promise<void> | null | void;
358
+ /**
359
+ * Create a side-effect which will update whenever values accessed change.
360
+ * Callback is called immediately and if ever values are stale.
361
+ *
362
+ * @param target - Instance of Model to observe.
363
+ * @param callback - Function to invoke when values change.
364
+ * @param requireValues - If `true` will throw if accessing a value which is `undefined`.
365
+ */
366
+ declare function effect<T extends {}>(target: T, callback: Effect<Required<T>>, requireValues: true): () => void;
367
+ declare function effect<T extends {}>(target: T, callback: Effect<T>, requireValues?: boolean): () => void;
368
+
357
369
  declare namespace Context {
358
370
  type Input = Record<string | number, Model | Model.Type<Model>>;
359
371
  }
@@ -392,4 +404,4 @@ declare global {
392
404
  }
393
405
  }
394
406
 
395
- export { Context, Model, Model as default, get, has, ref, set, use };
407
+ export { Context, Model, Model as default, effect, get, has, ref, set, use };
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ __export(src_exports, {
23
23
  Context: () => Context,
24
24
  Model: () => Model,
25
25
  default: () => Model,
26
+ effect: () => effect,
26
27
  get: () => get,
27
28
  has: () => has,
28
29
  ref: () => ref,
@@ -35,6 +36,7 @@ module.exports = __toCommonJS(src_exports);
35
36
  var DISPATCH = /* @__PURE__ */ new Set();
36
37
  var OBSERVER = /* @__PURE__ */ new WeakMap();
37
38
  var LISTENER = /* @__PURE__ */ new WeakMap();
39
+ var REQUIRED = /* @__PURE__ */ new WeakSet();
38
40
  var onReady = () => null;
39
41
  function addListener(subject, callback, select) {
40
42
  let subs = LISTENER.get(subject);
@@ -59,11 +61,13 @@ function watch(from, key, value) {
59
61
  LISTENER.set(value = Object.create(value), nested);
60
62
  OBSERVER.set(value, observer);
61
63
  }
64
+ if (value === void 0 && REQUIRED.has(from))
65
+ throw new Error(`${from}.${key} is required in this context.`);
62
66
  }
63
67
  return value;
64
68
  }
65
69
  var PENDING = /* @__PURE__ */ new WeakMap();
66
- function event(source, key) {
70
+ function emit(source, key) {
67
71
  const subs = LISTENER.get(source);
68
72
  const ready = !subs.has(onReady);
69
73
  if (key === true && ready)
@@ -90,21 +94,21 @@ function event(source, key) {
90
94
  });
91
95
  PENDING.delete(source);
92
96
  }
93
- function queue(event2) {
97
+ function queue(event) {
94
98
  if (!DISPATCH.size)
95
99
  setTimeout(() => {
96
- DISPATCH.forEach((event3) => {
100
+ DISPATCH.forEach((event2) => {
97
101
  try {
98
- event3();
102
+ event2();
99
103
  } catch (err) {
100
104
  console.error(err);
101
105
  }
102
106
  });
103
107
  DISPATCH.clear();
104
108
  }, 0);
105
- DISPATCH.add(event2);
109
+ DISPATCH.add(event);
106
110
  }
107
- function effect(target, callback) {
111
+ function effect(target, callback, requireValues) {
108
112
  const listeners = LISTENER.get(target);
109
113
  let unset;
110
114
  let reset;
@@ -122,6 +126,8 @@ function effect(target, callback) {
122
126
  }
123
127
  return reset;
124
128
  });
129
+ if (requireValues)
130
+ REQUIRED.add(subscriber);
125
131
  try {
126
132
  const out = callback.call(subscriber, subscriber);
127
133
  unset = typeof out == "function" ? out : void 0;
@@ -267,11 +273,11 @@ var Model = class _Model {
267
273
  return arg1.call(self, key, self);
268
274
  });
269
275
  if (arg1 === null)
270
- return event(this, null);
276
+ return emit(this, null);
271
277
  if (typeof arg1 == "object")
272
278
  assign(self, arg1);
273
279
  else if (arg1 == void 0)
274
- event(this, true);
280
+ emit(this, true);
275
281
  else if (1 in arguments)
276
282
  update(self, arg1, arg2, arg3);
277
283
  else
@@ -301,7 +307,7 @@ var Model = class _Model {
301
307
  */
302
308
  static new(...args) {
303
309
  const instance = new this(...args);
304
- event(instance, true);
310
+ emit(instance, true);
305
311
  return instance;
306
312
  }
307
313
  /**
@@ -368,7 +374,7 @@ function update(subject, key, value, silent) {
368
374
  return true;
369
375
  if (value instanceof Model && !PARENT.has(value)) {
370
376
  PARENT.set(value, subject);
371
- event(value, true);
377
+ emit(value, true);
372
378
  }
373
379
  state[key] = value;
374
380
  if (silent !== true)
@@ -380,13 +386,13 @@ function push(subject, key, silent) {
380
386
  PENDING2.set(subject, pending = /* @__PURE__ */ new Set());
381
387
  if (!silent)
382
388
  queue(() => {
383
- event(subject, false);
389
+ emit(subject, false);
384
390
  PENDING2.delete(subject);
385
391
  });
386
392
  }
387
393
  pending.add(key);
388
394
  if (!silent)
389
- event(subject, key);
395
+ emit(subject, key);
390
396
  }
391
397
  var METHODS = new WeakMap([[Model, []]]);
392
398
  function assign(to, values) {
@@ -863,6 +869,7 @@ function has(type, argument) {
863
869
  0 && (module.exports = {
864
870
  Context,
865
871
  Model,
872
+ effect,
866
873
  get,
867
874
  has,
868
875
  ref,
package/dist/index.mjs CHANGED
@@ -2,6 +2,7 @@
2
2
  var DISPATCH = /* @__PURE__ */ new Set();
3
3
  var OBSERVER = /* @__PURE__ */ new WeakMap();
4
4
  var LISTENER = /* @__PURE__ */ new WeakMap();
5
+ var REQUIRED = /* @__PURE__ */ new WeakSet();
5
6
  var onReady = () => null;
6
7
  function addListener(subject, callback, select) {
7
8
  let subs = LISTENER.get(subject);
@@ -26,11 +27,13 @@ function watch(from, key, value) {
26
27
  LISTENER.set(value = Object.create(value), nested);
27
28
  OBSERVER.set(value, observer);
28
29
  }
30
+ if (value === void 0 && REQUIRED.has(from))
31
+ throw new Error(`${from}.${key} is required in this context.`);
29
32
  }
30
33
  return value;
31
34
  }
32
35
  var PENDING = /* @__PURE__ */ new WeakMap();
33
- function event(source, key) {
36
+ function emit(source, key) {
34
37
  const subs = LISTENER.get(source);
35
38
  const ready = !subs.has(onReady);
36
39
  if (key === true && ready)
@@ -57,21 +60,21 @@ function event(source, key) {
57
60
  });
58
61
  PENDING.delete(source);
59
62
  }
60
- function queue(event2) {
63
+ function queue(event) {
61
64
  if (!DISPATCH.size)
62
65
  setTimeout(() => {
63
- DISPATCH.forEach((event3) => {
66
+ DISPATCH.forEach((event2) => {
64
67
  try {
65
- event3();
68
+ event2();
66
69
  } catch (err) {
67
70
  console.error(err);
68
71
  }
69
72
  });
70
73
  DISPATCH.clear();
71
74
  }, 0);
72
- DISPATCH.add(event2);
75
+ DISPATCH.add(event);
73
76
  }
74
- function effect(target, callback) {
77
+ function effect(target, callback, requireValues) {
75
78
  const listeners = LISTENER.get(target);
76
79
  let unset;
77
80
  let reset;
@@ -89,6 +92,8 @@ function effect(target, callback) {
89
92
  }
90
93
  return reset;
91
94
  });
95
+ if (requireValues)
96
+ REQUIRED.add(subscriber);
92
97
  try {
93
98
  const out = callback.call(subscriber, subscriber);
94
99
  unset = typeof out == "function" ? out : void 0;
@@ -234,11 +239,11 @@ var Model = class _Model {
234
239
  return arg1.call(self, key, self);
235
240
  });
236
241
  if (arg1 === null)
237
- return event(this, null);
242
+ return emit(this, null);
238
243
  if (typeof arg1 == "object")
239
244
  assign(self, arg1);
240
245
  else if (arg1 == void 0)
241
- event(this, true);
246
+ emit(this, true);
242
247
  else if (1 in arguments)
243
248
  update(self, arg1, arg2, arg3);
244
249
  else
@@ -268,7 +273,7 @@ var Model = class _Model {
268
273
  */
269
274
  static new(...args) {
270
275
  const instance = new this(...args);
271
- event(instance, true);
276
+ emit(instance, true);
272
277
  return instance;
273
278
  }
274
279
  /**
@@ -335,7 +340,7 @@ function update(subject, key, value, silent) {
335
340
  return true;
336
341
  if (value instanceof Model && !PARENT.has(value)) {
337
342
  PARENT.set(value, subject);
338
- event(value, true);
343
+ emit(value, true);
339
344
  }
340
345
  state[key] = value;
341
346
  if (silent !== true)
@@ -347,13 +352,13 @@ function push(subject, key, silent) {
347
352
  PENDING2.set(subject, pending = /* @__PURE__ */ new Set());
348
353
  if (!silent)
349
354
  queue(() => {
350
- event(subject, false);
355
+ emit(subject, false);
351
356
  PENDING2.delete(subject);
352
357
  });
353
358
  }
354
359
  pending.add(key);
355
360
  if (!silent)
356
- event(subject, key);
361
+ emit(subject, key);
357
362
  }
358
363
  var METHODS = new WeakMap([[Model, []]]);
359
364
  function assign(to, values) {
@@ -830,6 +835,7 @@ export {
830
835
  Context,
831
836
  Model,
832
837
  Model as default,
838
+ effect,
833
839
  get,
834
840
  has,
835
841
  ref,
package/package.json CHANGED
@@ -28,6 +28,6 @@
28
28
  "prebuild": "rm -rf dist",
29
29
  "preversion": "npm run test && npm run build"
30
30
  },
31
- "version": "0.48.0",
32
- "gitHead": "1f5ddf82e800cf53bf867ac5e546ad3186ce8bf5"
31
+ "version": "0.49.0",
32
+ "gitHead": "3a1423ef6d335d0e876904459d360a2e0ebdff7b"
33
33
  }