@expressive/mvc 0.51.2 → 0.52.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
@@ -1,4 +1,3 @@
1
- type MaybeAsync<T> = T | Promise<T>;
2
1
  declare namespace Model {
3
2
  /** Any type of Model, using own class constructor as its identifier. */
4
3
  type Type<T extends Model = Model> = (abstract new (...args: any[]) => T) & typeof Model;
@@ -8,7 +7,7 @@ declare namespace Model {
8
7
  * Model constructor callback - is called when Model finishes intializing.
9
8
  * Returned function will call when model is destroyed.
10
9
  */
11
- type Callback<T extends Model = Model> = (this: T, thisArg: T) => MaybeAsync<(() => void) | Assign<T> | void>;
10
+ type Callback<T extends Model = Model> = (this: T, thisArg: T) => Promise<void> | (() => void) | Assign<T> | void;
12
11
  /** Model constructor argument */
13
12
  type Argument<T extends Model = Model> = Assign<T> | Callback<T> | string | void;
14
13
  /** Model constructor arguments */
@@ -86,15 +85,18 @@ interface Model {
86
85
  }
87
86
  declare abstract class Model {
88
87
  constructor(...args: Model.Args);
89
- /** Pull current values from state. Flattens all models and exotic values recursively. */
88
+ /**
89
+ * Pull current values from state. Flattens all models and exotic values recursively.
90
+ *
91
+ * @returns Object with all values from this controller.
92
+ **/
90
93
  get(): Model.State<this>;
91
94
  /**
92
95
  * Run a function which will run automatically when accessed values change.
93
96
  *
94
- * @param effect - Function to run, and again whenever accessed values change.
95
- * If effect returns a function, it will be called when a change occurs (syncronously),
96
- * effect is cancelled, or parent controller is destroyed.
97
- *
97
+ * @param effect Function to run, and again whenever accessed values change.
98
+ * If effect returns a function, it will be called when a change occurs (syncronously),
99
+ * effect is cancelled, or parent controller is destroyed.
98
100
  * @returns Function to cancel listener.
99
101
  */
100
102
  get(effect: Model.Effect<this>): () => void;
@@ -103,6 +105,7 @@ declare abstract class Model {
103
105
  *
104
106
  * @param key - Property to get value of.
105
107
  * @param required - If true, will throw an error if property is not available.
108
+ * @returns Value of property.
106
109
  */
107
110
  get<T extends Model.Event<this>>(key: T, required?: boolean): Model.Value<this, T>;
108
111
  /**
@@ -110,11 +113,13 @@ declare abstract class Model {
110
113
  *
111
114
  * @param key - Property to watch for updates.
112
115
  * @param callback - Function to call when property is updated.
116
+ * @returns Function to cancel listener.
113
117
  */
114
118
  get<T extends Model.Event<this>>(key: T, callback: Model.OnUpdate<this, T>): () => void;
115
119
  /**
116
120
  * Check if model is expired.
117
121
  *
122
+ * @param status - `null` to check if model is expired.
118
123
  * @returns `true` if model is expired, `false` otherwise.
119
124
  */
120
125
  get(status: null): boolean;
@@ -147,6 +152,8 @@ declare abstract class Model {
147
152
  /**
148
153
  * Declare an end to updates. This event is final and will freeze state.
149
154
  * This event can be watched for as well, to run cleanup logic and internally will remove all listeners.
155
+ *
156
+ * @param status - `null` to end updates.
150
157
  */
151
158
  set(status: null): void;
152
159
  /**
@@ -167,6 +174,9 @@ declare abstract class Model {
167
174
  /**
168
175
  * Update mulitple properties at once. Merges argument with current state.
169
176
  * Properties which are not managed by this controller will be ignored.
177
+ *
178
+ * @param assign - Object with properties to update.
179
+ * @returns Promise which resolves an array of keys which were updated.
170
180
  */
171
181
  set(assign: Model.Assign<this>): PromiseLike<Model.Event<this>[]> | undefined;
172
182
  /**
package/dist/index.js CHANGED
@@ -79,19 +79,19 @@ function emit(source, key2) {
79
79
  });
80
80
  PENDING.delete(source);
81
81
  }
82
- function queue(event) {
82
+ function queue(event2) {
83
83
  if (!DISPATCH.size)
84
84
  setTimeout(() => {
85
- DISPATCH.forEach((event2) => {
85
+ DISPATCH.forEach((event3) => {
86
86
  try {
87
- event2();
87
+ event3();
88
88
  } catch (err) {
89
89
  console.error(err);
90
90
  }
91
91
  });
92
92
  DISPATCH.clear();
93
93
  }, 0);
94
- DISPATCH.add(event);
94
+ DISPATCH.add(event2);
95
95
  }
96
96
  function effect(target, callback, requireValues) {
97
97
  const listeners = LISTENER.get(target);
@@ -155,78 +155,27 @@ function effect(target, callback, requireValues) {
155
155
  }
156
156
 
157
157
  // src/model.ts
158
- var NAMES = /* @__PURE__ */ new WeakMap();
158
+ var define = Object.defineProperty;
159
+ var ID = /* @__PURE__ */ new WeakMap();
159
160
  var STATE = /* @__PURE__ */ new WeakMap();
160
161
  var NOTIFY = /* @__PURE__ */ new WeakMap();
161
162
  var PENDING2 = /* @__PURE__ */ new WeakMap();
162
163
  var PARENT = /* @__PURE__ */ new WeakMap();
164
+ var METHODS = /* @__PURE__ */ new WeakMap();
163
165
  var METHOD = /* @__PURE__ */ new WeakMap();
164
166
  var EXPORT;
165
- var define = Object.defineProperty;
166
167
  var Model = class _Model {
167
168
  constructor(...args) {
168
- const state = {};
169
- let Type = this.constructor;
170
- bindMethods(Type);
169
+ ID.set(this, `${this.constructor}-${uid()}`);
170
+ STATE.set(this, {});
171
+ prepare(this);
171
172
  define(this, "is", { value: this });
172
- STATE.set(this, state);
173
- NAMES.set(this, `${Type}-${uid()}`);
174
- for (const arg of args)
175
- if (typeof arg == "string")
176
- NAMES.set(this, arg);
177
- while (true) {
178
- new Set(NOTIFY.get(Type)).forEach((x) => addListener(this, x));
179
- if (Type === _Model)
180
- break;
181
- Type = Object.getPrototypeOf(Type);
182
- }
183
- addListener(this, () => {
184
- let done;
185
- (async () => {
186
- const cleanup = /* @__PURE__ */ new Set();
187
- for (const arg of args) {
188
- let use2 = typeof arg == "function" ? arg.call(this, this) : arg;
189
- if (use2 instanceof Promise)
190
- use2 = await use2.catch((err) => {
191
- console.error(`Async error in constructor for ${this}:`);
192
- console.error(err);
193
- });
194
- if (typeof use2 == "object")
195
- assign(this, use2);
196
- else if (typeof use2 == "function")
197
- cleanup.add(use2);
198
- }
199
- done = cleanup;
200
- })();
201
- for (const key2 in this) {
202
- const desc = Object.getOwnPropertyDescriptor(this, key2);
203
- if ("value" in desc) {
204
- update(this, key2, desc.value, true);
205
- define(this, key2, {
206
- configurable: false,
207
- set: (x) => update(this, key2, x),
208
- get() {
209
- return watch(this, key2, state[key2]);
210
- }
211
- });
212
- }
213
- }
214
- if (!PARENT.has(this))
215
- PARENT.set(this, null);
216
- addListener(this, () => {
217
- if (!done)
218
- throw new Error(`Tried to destroy ${this} but not fully initialized.`);
219
- for (const [_, value] of this)
220
- if (value instanceof _Model && PARENT.get(value) === this)
221
- value.set(null);
222
- done.forEach((x) => x());
223
- Object.freeze(state);
224
- }, null);
225
- return null;
226
- });
173
+ apply(this, [...args, init]);
227
174
  }
228
175
  get(arg1, arg2) {
229
176
  const self = this.is;
177
+ if (arg1 === void 0)
178
+ return values(self);
230
179
  if (typeof arg1 == "function") {
231
180
  let pending = /* @__PURE__ */ new Set();
232
181
  return effect(self, (state) => {
@@ -238,20 +187,6 @@ var Model = class _Model {
238
187
  };
239
188
  });
240
189
  }
241
- if (arg1 === void 0) {
242
- const values = {};
243
- const current = !EXPORT && (EXPORT = /* @__PURE__ */ new Map([[self, values]]));
244
- for (let [key2, value] of self) {
245
- if (EXPORT.has(value))
246
- value = EXPORT.get(value);
247
- else if (value && typeof value.get === "function")
248
- EXPORT.set(value, value = value.get());
249
- values[key2] = value;
250
- }
251
- if (current)
252
- EXPORT = void 0;
253
- return Object.freeze(values);
254
- }
255
190
  if (typeof arg2 == "function") {
256
191
  if (arg1 === null)
257
192
  return addListener(self, arg2.bind(this, this), null);
@@ -282,7 +217,7 @@ var Model = class _Model {
282
217
  else if (1 in arguments)
283
218
  update(self, arg1, arg2, arg3);
284
219
  else
285
- push(self, arg1);
220
+ event(self, arg1);
286
221
  if (PENDING2.has(self))
287
222
  return {
288
223
  then: (res) => new Promise((res2) => {
@@ -339,7 +274,7 @@ var Model = class _Model {
339
274
  };
340
275
  define(Model.prototype, "toString", {
341
276
  value() {
342
- return NAMES.get(this.is);
277
+ return ID.get(this.is);
343
278
  }
344
279
  });
345
280
  define(Model, "toString", {
@@ -347,6 +282,92 @@ define(Model, "toString", {
347
282
  return this.name;
348
283
  }
349
284
  });
285
+ function prepare(model) {
286
+ const chain = [];
287
+ let type = model.constructor;
288
+ let keys2 = /* @__PURE__ */ new Set();
289
+ while (type.name) {
290
+ chain.unshift(type);
291
+ type = Object.getPrototypeOf(type);
292
+ }
293
+ for (const type2 of chain) {
294
+ for (const cb of NOTIFY.get(type2) || [])
295
+ addListener(model, cb);
296
+ if (type2 == Model)
297
+ continue;
298
+ if (METHODS.has(type2)) {
299
+ keys2 = METHODS.get(type2);
300
+ continue;
301
+ }
302
+ METHODS.set(type2, keys2 = new Set(keys2));
303
+ for (const { key: key2, value } of entries(type2.prototype)) {
304
+ let set3 = function(method) {
305
+ const value2 = method.bind(this.is);
306
+ METHOD.set(value2, method);
307
+ define(this.is, key2, { value: value2, writable: true });
308
+ return value2;
309
+ };
310
+ var set2 = set3;
311
+ if (!value || key2 == "constructor")
312
+ continue;
313
+ keys2.add(key2);
314
+ Object.defineProperty(type2.prototype, key2, {
315
+ set: set3,
316
+ get() {
317
+ return this.hasOwnProperty(key2) ? value : set3.call(this, value);
318
+ }
319
+ });
320
+ }
321
+ }
322
+ }
323
+ function apply(model, args) {
324
+ for (const arg of args)
325
+ if (typeof arg == "string")
326
+ ID.set(model, arg);
327
+ addListener(model, () => {
328
+ const done = /* @__PURE__ */ new Set();
329
+ for (const arg of args) {
330
+ const use2 = typeof arg == "function" ? arg.call(model, model) : arg;
331
+ if (use2 instanceof Promise)
332
+ use2.catch((err) => {
333
+ console.error(`Async error in constructor for ${model}:`);
334
+ console.error(err);
335
+ });
336
+ else if (typeof use2 == "object")
337
+ assign(model, use2);
338
+ else if (typeof use2 == "function")
339
+ done.add(use2);
340
+ }
341
+ addListener(model, () => {
342
+ done.forEach((x) => x());
343
+ }, null);
344
+ return null;
345
+ });
346
+ }
347
+ function init(model) {
348
+ const state = STATE.get(model);
349
+ if (!PARENT.has(model))
350
+ PARENT.set(model, null);
351
+ for (const key2 in model) {
352
+ const desc = Object.getOwnPropertyDescriptor(model, key2);
353
+ if ("value" in desc) {
354
+ update(model, key2, desc.value, true);
355
+ define(model, key2, {
356
+ configurable: false,
357
+ set: (x) => update(model, key2, x),
358
+ get() {
359
+ return watch(this, key2, state[key2]);
360
+ }
361
+ });
362
+ }
363
+ }
364
+ return () => {
365
+ for (const [_, value] of model)
366
+ if (value instanceof Model && PARENT.get(value) === model)
367
+ value.set(null);
368
+ Object.freeze(state);
369
+ };
370
+ }
350
371
  function fetch(subject, property, required) {
351
372
  const state = STATE.get(subject);
352
373
  if (property in state || required === false) {
@@ -392,9 +413,9 @@ function update(subject, key2, value, arg) {
392
413
  }
393
414
  state[key2] = value;
394
415
  if (arg !== true)
395
- push(subject, key2);
416
+ event(subject, key2);
396
417
  }
397
- function push(subject, key2, silent) {
418
+ function event(subject, key2, silent) {
398
419
  let pending = PENDING2.get(subject);
399
420
  if (!pending) {
400
421
  PENDING2.set(subject, pending = /* @__PURE__ */ new Set());
@@ -408,43 +429,34 @@ function push(subject, key2, silent) {
408
429
  if (!silent)
409
430
  emit(subject, key2);
410
431
  }
411
- var METHODS = new WeakMap([[Model, []]]);
412
- function assign(to, values) {
432
+ function assign(to, values2) {
413
433
  const methods = METHODS.get(to.constructor);
414
- const applicable = new Set(Object.keys(to).concat(methods));
415
- for (const key2 in values)
416
- if (applicable.has(key2))
417
- to[key2] = values[key2];
434
+ for (const key2 in values2)
435
+ if (key2 in to || methods.has(key2))
436
+ to[key2] = values2[key2];
418
437
  }
419
- function bindMethods(type) {
420
- let keys2 = METHODS.get(type);
421
- if (!keys2) {
422
- METHODS.set(type, keys2 = bindMethods(Object.getPrototypeOf(type)).slice());
423
- const desc = Object.getOwnPropertyDescriptors(type.prototype);
424
- for (const key2 in desc)
425
- if (key2 != "constructor" && "value" in desc[key2]) {
426
- let bind2 = function(method) {
427
- const value2 = method.bind(this.is);
428
- METHOD.set(value2, method);
429
- define(this.is, key2, { value: value2, writable: true });
430
- return value2;
431
- };
432
- var bind = bind2;
433
- let { value } = desc[key2];
434
- keys2.push(key2);
435
- Object.defineProperty(type.prototype, key2, {
436
- set: bind2,
437
- get() {
438
- return this.hasOwnProperty(key2) ? value : bind2.call(this, value);
439
- }
440
- });
441
- }
438
+ function values(model) {
439
+ const values2 = {};
440
+ const current = !EXPORT && (EXPORT = /* @__PURE__ */ new Map([[model, values2]]));
441
+ for (let [key2, value] of model) {
442
+ if (EXPORT.has(value))
443
+ value = EXPORT.get(value);
444
+ else if (value && typeof value.get === "function")
445
+ EXPORT.set(value, value = value.get());
446
+ values2[key2] = value;
442
447
  }
443
- return keys2;
448
+ if (current)
449
+ EXPORT = void 0;
450
+ return Object.freeze(values2);
444
451
  }
445
452
  function uid() {
446
453
  return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
447
454
  }
455
+ function entries(object) {
456
+ return Object.entries(
457
+ Object.getOwnPropertyDescriptors(object)
458
+ ).map(([key2, desc]) => ({ key: key2, ...desc }));
459
+ }
448
460
 
449
461
  // src/context.ts
450
462
  var Register = /* @__PURE__ */ new WeakMap();
@@ -507,7 +519,7 @@ var Context = class _Context {
507
519
  this.layer.clear();
508
520
  }
509
521
  include(inputs, forEach) {
510
- const init = /* @__PURE__ */ new Map();
522
+ const init2 = /* @__PURE__ */ new Map();
511
523
  Object.entries(inputs).forEach(([K, V]) => {
512
524
  if (!(Model.is(V) || V instanceof Model))
513
525
  throw new Error(`Context can only include Model or instance but got ${V}${K && " as " + K}.`);
@@ -518,21 +530,21 @@ var Context = class _Context {
518
530
  if (!exists) {
519
531
  const instance = this.add(input);
520
532
  this.layer.set(key2, input);
521
- init.set(instance, true);
533
+ init2.set(instance, true);
522
534
  } else if (exists !== input) {
523
535
  this.pop();
524
536
  this.id = uid();
525
537
  this.include(inputs);
526
538
  }
527
539
  }
528
- for (const [model, explicit] of init) {
540
+ for (const [model, explicit] of init2) {
529
541
  model.set();
530
542
  if (forEach)
531
543
  forEach(model, explicit);
532
544
  for (const [_key, value] of model)
533
545
  if (PARENT.get(value) === model) {
534
546
  this.add(value, true);
535
- init.set(value, false);
547
+ init2.set(value, false);
536
548
  }
537
549
  }
538
550
  }
@@ -597,38 +609,36 @@ function use(arg1, arg2) {
597
609
  INSTRUCT.set(token, arg1);
598
610
  return token;
599
611
  }
600
- Model.on((_, subject) => {
601
- const state = STATE.get(subject);
602
- const props = Object.getOwnPropertyDescriptors(subject);
603
- for (const key2 in props) {
604
- const { value } = props[key2];
612
+ Model.on((_, model) => {
613
+ const state = STATE.get(model);
614
+ for (const { key: key2, value } of entries(model)) {
605
615
  const instruction = INSTRUCT.get(value);
606
616
  if (!instruction) {
607
617
  if (value instanceof Model && key2 !== "is")
608
- update(subject, key2, value);
618
+ update(model, key2, value);
609
619
  continue;
610
620
  }
611
621
  INSTRUCT.delete(value);
612
- delete subject[key2];
613
- const output = instruction.call(subject, key2, subject, state);
622
+ delete model[key2];
623
+ const output = instruction.call(model, key2, model, state);
614
624
  if (!output)
615
625
  continue;
616
626
  const desc = typeof output == "object" ? output : { get: output };
617
627
  if ("value" in desc)
618
628
  state[key2] = desc.value;
619
- Object.defineProperty(subject, key2, {
629
+ Object.defineProperty(model, key2, {
620
630
  enumerable: desc.enumerable !== false,
621
631
  get() {
622
632
  return watch(
623
633
  this,
624
634
  key2,
625
- typeof desc.get == "function" ? desc.get(this) : fetch(subject, key2, desc.get)
635
+ typeof desc.get == "function" ? desc.get(this) : fetch(model, key2, desc.get)
626
636
  );
627
637
  },
628
638
  set(next) {
629
639
  if (desc.set === false)
630
- throw new Error(`${subject}.${key2} is read-only.`);
631
- update(subject, key2, next, desc.set);
640
+ throw new Error(`${model}.${key2} is read-only.`);
641
+ update(model, key2, next, desc.set);
632
642
  }
633
643
  });
634
644
  }
@@ -676,7 +686,7 @@ function get(arg0, arg1) {
676
686
  return (didUpdate) => {
677
687
  if (didUpdate) {
678
688
  STALE.add(compute2);
679
- push(subject, key2, true);
689
+ event(subject, key2, true);
680
690
  }
681
691
  };
682
692
  });
@@ -768,7 +778,7 @@ function set(value, argument) {
768
778
  return use((key2, subject) => {
769
779
  const output = {};
770
780
  if (typeof value == "function" || value instanceof Promise) {
771
- let init2 = function() {
781
+ let init3 = function() {
772
782
  if (typeof value == "function")
773
783
  try {
774
784
  value = attempt(value.bind(subject, key2));
@@ -792,11 +802,11 @@ function set(value, argument) {
792
802
  if (0 in arguments)
793
803
  return subject[key2];
794
804
  };
795
- var init = init2;
805
+ var init2 = init3;
796
806
  if (argument)
797
- init2();
807
+ init3();
798
808
  else
799
- output.get = init2;
809
+ output.get = init3;
800
810
  } else if (value !== void 0)
801
811
  output.value = value;
802
812
  if (typeof argument == "function") {
package/dist/index.mjs CHANGED
@@ -45,19 +45,19 @@ function emit(source, key2) {
45
45
  });
46
46
  PENDING.delete(source);
47
47
  }
48
- function queue(event) {
48
+ function queue(event2) {
49
49
  if (!DISPATCH.size)
50
50
  setTimeout(() => {
51
- DISPATCH.forEach((event2) => {
51
+ DISPATCH.forEach((event3) => {
52
52
  try {
53
- event2();
53
+ event3();
54
54
  } catch (err) {
55
55
  console.error(err);
56
56
  }
57
57
  });
58
58
  DISPATCH.clear();
59
59
  }, 0);
60
- DISPATCH.add(event);
60
+ DISPATCH.add(event2);
61
61
  }
62
62
  function effect(target, callback, requireValues) {
63
63
  const listeners = LISTENER.get(target);
@@ -121,78 +121,27 @@ function effect(target, callback, requireValues) {
121
121
  }
122
122
 
123
123
  // src/model.ts
124
- var NAMES = /* @__PURE__ */ new WeakMap();
124
+ var define = Object.defineProperty;
125
+ var ID = /* @__PURE__ */ new WeakMap();
125
126
  var STATE = /* @__PURE__ */ new WeakMap();
126
127
  var NOTIFY = /* @__PURE__ */ new WeakMap();
127
128
  var PENDING2 = /* @__PURE__ */ new WeakMap();
128
129
  var PARENT = /* @__PURE__ */ new WeakMap();
130
+ var METHODS = /* @__PURE__ */ new WeakMap();
129
131
  var METHOD = /* @__PURE__ */ new WeakMap();
130
132
  var EXPORT;
131
- var define = Object.defineProperty;
132
133
  var Model = class _Model {
133
134
  constructor(...args) {
134
- const state = {};
135
- let Type = this.constructor;
136
- bindMethods(Type);
135
+ ID.set(this, `${this.constructor}-${uid()}`);
136
+ STATE.set(this, {});
137
+ prepare(this);
137
138
  define(this, "is", { value: this });
138
- STATE.set(this, state);
139
- NAMES.set(this, `${Type}-${uid()}`);
140
- for (const arg of args)
141
- if (typeof arg == "string")
142
- NAMES.set(this, arg);
143
- while (true) {
144
- new Set(NOTIFY.get(Type)).forEach((x) => addListener(this, x));
145
- if (Type === _Model)
146
- break;
147
- Type = Object.getPrototypeOf(Type);
148
- }
149
- addListener(this, () => {
150
- let done;
151
- (async () => {
152
- const cleanup = /* @__PURE__ */ new Set();
153
- for (const arg of args) {
154
- let use2 = typeof arg == "function" ? arg.call(this, this) : arg;
155
- if (use2 instanceof Promise)
156
- use2 = await use2.catch((err) => {
157
- console.error(`Async error in constructor for ${this}:`);
158
- console.error(err);
159
- });
160
- if (typeof use2 == "object")
161
- assign(this, use2);
162
- else if (typeof use2 == "function")
163
- cleanup.add(use2);
164
- }
165
- done = cleanup;
166
- })();
167
- for (const key2 in this) {
168
- const desc = Object.getOwnPropertyDescriptor(this, key2);
169
- if ("value" in desc) {
170
- update(this, key2, desc.value, true);
171
- define(this, key2, {
172
- configurable: false,
173
- set: (x) => update(this, key2, x),
174
- get() {
175
- return watch(this, key2, state[key2]);
176
- }
177
- });
178
- }
179
- }
180
- if (!PARENT.has(this))
181
- PARENT.set(this, null);
182
- addListener(this, () => {
183
- if (!done)
184
- throw new Error(`Tried to destroy ${this} but not fully initialized.`);
185
- for (const [_, value] of this)
186
- if (value instanceof _Model && PARENT.get(value) === this)
187
- value.set(null);
188
- done.forEach((x) => x());
189
- Object.freeze(state);
190
- }, null);
191
- return null;
192
- });
139
+ apply(this, [...args, init]);
193
140
  }
194
141
  get(arg1, arg2) {
195
142
  const self = this.is;
143
+ if (arg1 === void 0)
144
+ return values(self);
196
145
  if (typeof arg1 == "function") {
197
146
  let pending = /* @__PURE__ */ new Set();
198
147
  return effect(self, (state) => {
@@ -204,20 +153,6 @@ var Model = class _Model {
204
153
  };
205
154
  });
206
155
  }
207
- if (arg1 === void 0) {
208
- const values = {};
209
- const current = !EXPORT && (EXPORT = /* @__PURE__ */ new Map([[self, values]]));
210
- for (let [key2, value] of self) {
211
- if (EXPORT.has(value))
212
- value = EXPORT.get(value);
213
- else if (value && typeof value.get === "function")
214
- EXPORT.set(value, value = value.get());
215
- values[key2] = value;
216
- }
217
- if (current)
218
- EXPORT = void 0;
219
- return Object.freeze(values);
220
- }
221
156
  if (typeof arg2 == "function") {
222
157
  if (arg1 === null)
223
158
  return addListener(self, arg2.bind(this, this), null);
@@ -248,7 +183,7 @@ var Model = class _Model {
248
183
  else if (1 in arguments)
249
184
  update(self, arg1, arg2, arg3);
250
185
  else
251
- push(self, arg1);
186
+ event(self, arg1);
252
187
  if (PENDING2.has(self))
253
188
  return {
254
189
  then: (res) => new Promise((res2) => {
@@ -305,7 +240,7 @@ var Model = class _Model {
305
240
  };
306
241
  define(Model.prototype, "toString", {
307
242
  value() {
308
- return NAMES.get(this.is);
243
+ return ID.get(this.is);
309
244
  }
310
245
  });
311
246
  define(Model, "toString", {
@@ -313,6 +248,92 @@ define(Model, "toString", {
313
248
  return this.name;
314
249
  }
315
250
  });
251
+ function prepare(model) {
252
+ const chain = [];
253
+ let type = model.constructor;
254
+ let keys2 = /* @__PURE__ */ new Set();
255
+ while (type.name) {
256
+ chain.unshift(type);
257
+ type = Object.getPrototypeOf(type);
258
+ }
259
+ for (const type2 of chain) {
260
+ for (const cb of NOTIFY.get(type2) || [])
261
+ addListener(model, cb);
262
+ if (type2 == Model)
263
+ continue;
264
+ if (METHODS.has(type2)) {
265
+ keys2 = METHODS.get(type2);
266
+ continue;
267
+ }
268
+ METHODS.set(type2, keys2 = new Set(keys2));
269
+ for (const { key: key2, value } of entries(type2.prototype)) {
270
+ let set3 = function(method) {
271
+ const value2 = method.bind(this.is);
272
+ METHOD.set(value2, method);
273
+ define(this.is, key2, { value: value2, writable: true });
274
+ return value2;
275
+ };
276
+ var set2 = set3;
277
+ if (!value || key2 == "constructor")
278
+ continue;
279
+ keys2.add(key2);
280
+ Object.defineProperty(type2.prototype, key2, {
281
+ set: set3,
282
+ get() {
283
+ return this.hasOwnProperty(key2) ? value : set3.call(this, value);
284
+ }
285
+ });
286
+ }
287
+ }
288
+ }
289
+ function apply(model, args) {
290
+ for (const arg of args)
291
+ if (typeof arg == "string")
292
+ ID.set(model, arg);
293
+ addListener(model, () => {
294
+ const done = /* @__PURE__ */ new Set();
295
+ for (const arg of args) {
296
+ const use2 = typeof arg == "function" ? arg.call(model, model) : arg;
297
+ if (use2 instanceof Promise)
298
+ use2.catch((err) => {
299
+ console.error(`Async error in constructor for ${model}:`);
300
+ console.error(err);
301
+ });
302
+ else if (typeof use2 == "object")
303
+ assign(model, use2);
304
+ else if (typeof use2 == "function")
305
+ done.add(use2);
306
+ }
307
+ addListener(model, () => {
308
+ done.forEach((x) => x());
309
+ }, null);
310
+ return null;
311
+ });
312
+ }
313
+ function init(model) {
314
+ const state = STATE.get(model);
315
+ if (!PARENT.has(model))
316
+ PARENT.set(model, null);
317
+ for (const key2 in model) {
318
+ const desc = Object.getOwnPropertyDescriptor(model, key2);
319
+ if ("value" in desc) {
320
+ update(model, key2, desc.value, true);
321
+ define(model, key2, {
322
+ configurable: false,
323
+ set: (x) => update(model, key2, x),
324
+ get() {
325
+ return watch(this, key2, state[key2]);
326
+ }
327
+ });
328
+ }
329
+ }
330
+ return () => {
331
+ for (const [_, value] of model)
332
+ if (value instanceof Model && PARENT.get(value) === model)
333
+ value.set(null);
334
+ Object.freeze(state);
335
+ };
336
+ }
316
337
  function fetch(subject, property, required) {
317
338
  const state = STATE.get(subject);
318
339
  if (property in state || required === false) {
@@ -358,9 +379,9 @@ function update(subject, key2, value, arg) {
358
379
  }
359
380
  state[key2] = value;
360
381
  if (arg !== true)
361
- push(subject, key2);
382
+ event(subject, key2);
362
383
  }
363
- function push(subject, key2, silent) {
384
+ function event(subject, key2, silent) {
364
385
  let pending = PENDING2.get(subject);
365
386
  if (!pending) {
366
387
  PENDING2.set(subject, pending = /* @__PURE__ */ new Set());
@@ -374,43 +395,34 @@ function push(subject, key2, silent) {
374
395
  if (!silent)
375
396
  emit(subject, key2);
376
397
  }
377
- var METHODS = new WeakMap([[Model, []]]);
378
- function assign(to, values) {
398
+ function assign(to, values2) {
379
399
  const methods = METHODS.get(to.constructor);
380
- const applicable = new Set(Object.keys(to).concat(methods));
381
- for (const key2 in values)
382
- if (applicable.has(key2))
383
- to[key2] = values[key2];
400
+ for (const key2 in values2)
401
+ if (key2 in to || methods.has(key2))
402
+ to[key2] = values2[key2];
384
403
  }
385
- function bindMethods(type) {
386
- let keys2 = METHODS.get(type);
387
- if (!keys2) {
388
- METHODS.set(type, keys2 = bindMethods(Object.getPrototypeOf(type)).slice());
389
- const desc = Object.getOwnPropertyDescriptors(type.prototype);
390
- for (const key2 in desc)
391
- if (key2 != "constructor" && "value" in desc[key2]) {
392
- let bind2 = function(method) {
393
- const value2 = method.bind(this.is);
394
- METHOD.set(value2, method);
395
- define(this.is, key2, { value: value2, writable: true });
396
- return value2;
397
- };
398
- var bind = bind2;
399
- let { value } = desc[key2];
400
- keys2.push(key2);
401
- Object.defineProperty(type.prototype, key2, {
402
- set: bind2,
403
- get() {
404
- return this.hasOwnProperty(key2) ? value : bind2.call(this, value);
405
- }
406
- });
407
- }
404
+ function values(model) {
405
+ const values2 = {};
406
+ const current = !EXPORT && (EXPORT = /* @__PURE__ */ new Map([[model, values2]]));
407
+ for (let [key2, value] of model) {
408
+ if (EXPORT.has(value))
409
+ value = EXPORT.get(value);
410
+ else if (value && typeof value.get === "function")
411
+ EXPORT.set(value, value = value.get());
412
+ values2[key2] = value;
408
413
  }
409
- return keys2;
414
+ if (current)
415
+ EXPORT = void 0;
416
+ return Object.freeze(values2);
410
417
  }
411
418
  function uid() {
412
419
  return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
413
420
  }
421
+ function entries(object) {
422
+ return Object.entries(
423
+ Object.getOwnPropertyDescriptors(object)
424
+ ).map(([key2, desc]) => ({ key: key2, ...desc }));
425
+ }
414
426
 
415
427
  // src/context.ts
416
428
  var Register = /* @__PURE__ */ new WeakMap();
@@ -473,7 +485,7 @@ var Context = class _Context {
473
485
  this.layer.clear();
474
486
  }
475
487
  include(inputs, forEach) {
476
- const init = /* @__PURE__ */ new Map();
488
+ const init2 = /* @__PURE__ */ new Map();
477
489
  Object.entries(inputs).forEach(([K, V]) => {
478
490
  if (!(Model.is(V) || V instanceof Model))
479
491
  throw new Error(`Context can only include Model or instance but got ${V}${K && " as " + K}.`);
@@ -484,21 +496,21 @@ var Context = class _Context {
484
496
  if (!exists) {
485
497
  const instance = this.add(input);
486
498
  this.layer.set(key2, input);
487
- init.set(instance, true);
499
+ init2.set(instance, true);
488
500
  } else if (exists !== input) {
489
501
  this.pop();
490
502
  this.id = uid();
491
503
  this.include(inputs);
492
504
  }
493
505
  }
494
- for (const [model, explicit] of init) {
506
+ for (const [model, explicit] of init2) {
495
507
  model.set();
496
508
  if (forEach)
497
509
  forEach(model, explicit);
498
510
  for (const [_key, value] of model)
499
511
  if (PARENT.get(value) === model) {
500
512
  this.add(value, true);
501
- init.set(value, false);
513
+ init2.set(value, false);
502
514
  }
503
515
  }
504
516
  }
@@ -563,38 +575,36 @@ function use(arg1, arg2) {
563
575
  INSTRUCT.set(token, arg1);
564
576
  return token;
565
577
  }
566
- Model.on((_, subject) => {
567
- const state = STATE.get(subject);
568
- const props = Object.getOwnPropertyDescriptors(subject);
569
- for (const key2 in props) {
570
- const { value } = props[key2];
578
+ Model.on((_, model) => {
579
+ const state = STATE.get(model);
580
+ for (const { key: key2, value } of entries(model)) {
571
581
  const instruction = INSTRUCT.get(value);
572
582
  if (!instruction) {
573
583
  if (value instanceof Model && key2 !== "is")
574
- update(subject, key2, value);
584
+ update(model, key2, value);
575
585
  continue;
576
586
  }
577
587
  INSTRUCT.delete(value);
578
- delete subject[key2];
579
- const output = instruction.call(subject, key2, subject, state);
588
+ delete model[key2];
589
+ const output = instruction.call(model, key2, model, state);
580
590
  if (!output)
581
591
  continue;
582
592
  const desc = typeof output == "object" ? output : { get: output };
583
593
  if ("value" in desc)
584
594
  state[key2] = desc.value;
585
- Object.defineProperty(subject, key2, {
595
+ Object.defineProperty(model, key2, {
586
596
  enumerable: desc.enumerable !== false,
587
597
  get() {
588
598
  return watch(
589
599
  this,
590
600
  key2,
591
- typeof desc.get == "function" ? desc.get(this) : fetch(subject, key2, desc.get)
601
+ typeof desc.get == "function" ? desc.get(this) : fetch(model, key2, desc.get)
592
602
  );
593
603
  },
594
604
  set(next) {
595
605
  if (desc.set === false)
596
- throw new Error(`${subject}.${key2} is read-only.`);
597
- update(subject, key2, next, desc.set);
606
+ throw new Error(`${model}.${key2} is read-only.`);
607
+ update(model, key2, next, desc.set);
598
608
  }
599
609
  });
600
610
  }
@@ -642,7 +652,7 @@ function get(arg0, arg1) {
642
652
  return (didUpdate) => {
643
653
  if (didUpdate) {
644
654
  STALE.add(compute2);
645
- push(subject, key2, true);
655
+ event(subject, key2, true);
646
656
  }
647
657
  };
648
658
  });
@@ -734,7 +744,7 @@ function set(value, argument) {
734
744
  return use((key2, subject) => {
735
745
  const output = {};
736
746
  if (typeof value == "function" || value instanceof Promise) {
737
- let init2 = function() {
747
+ let init3 = function() {
738
748
  if (typeof value == "function")
739
749
  try {
740
750
  value = attempt(value.bind(subject, key2));
@@ -758,11 +768,11 @@ function set(value, argument) {
758
768
  if (0 in arguments)
759
769
  return subject[key2];
760
770
  };
761
- var init = init2;
771
+ var init2 = init3;
762
772
  if (argument)
763
- init2();
773
+ init3();
764
774
  else
765
- output.get = init2;
775
+ output.get = init3;
766
776
  } else if (value !== void 0)
767
777
  output.value = value;
768
778
  if (typeof argument == "function") {
package/package.json CHANGED
@@ -32,6 +32,6 @@
32
32
  "jest": "^27.0.6",
33
33
  "tsup": "^8.0.2"
34
34
  },
35
- "version": "0.51.2",
36
- "gitHead": "fc4ca0a906025eb8a0dbed96887f2613782d567a"
35
+ "version": "0.52.0",
36
+ "gitHead": "b6b92114b8b0c69f1a36eae8c03fec2e068d03c4"
37
37
  }