@expressive/mvc 0.71.0 → 0.73.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.js CHANGED
@@ -1,1012 +1,872 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key2 of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key2) && key2 !== except)
14
- __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- Context: () => Context,
24
- METHOD: () => METHOD,
25
- Model: () => Model,
26
- Observable: () => Observable,
27
- addListener: () => addListener,
28
- createEffect: () => createEffect,
29
- default: () => Model,
30
- event: () => event,
31
- get: () => get,
32
- has: () => has,
33
- ref: () => ref,
34
- set: () => set,
35
- use: () => use
36
- });
37
- module.exports = __toCommonJS(index_exports);
1
+ Object.defineProperty(exports, '__esModule', { value: true });
38
2
 
39
- // src/control.ts
40
- var Observable = Symbol("observe");
41
- var onReady = () => null;
42
- var LISTENERS = /* @__PURE__ */ new WeakMap();
43
- var PENDING = /* @__PURE__ */ new WeakMap();
44
- var PENDING_KEYS = /* @__PURE__ */ new WeakMap();
45
- var DISPATCH = /* @__PURE__ */ new Set();
3
+ //#region src/observable.ts
4
+ const Observable = Symbol("observe");
5
+ /** Placeholder event determines if state is initialized or not. */
6
+ const onReady = () => null;
7
+ const LISTENERS = /* @__PURE__ */ new WeakMap();
8
+ /** Events pending for a given object. */
9
+ const PENDING = /* @__PURE__ */ new WeakMap();
10
+ /** Update register. */
11
+ const PENDING_KEYS = /* @__PURE__ */ new WeakMap();
12
+ /** Central event dispatch. Bunches all updates to occur at same time. */
13
+ const DISPATCH = /* @__PURE__ */ new Set();
46
14
  function addListener(subject, callback, select) {
47
- let listeners = LISTENERS.get(subject);
48
- if (!listeners)
49
- LISTENERS.set(subject, listeners = /* @__PURE__ */ new Map([[onReady, void 0]]));
50
- if (select !== void 0 && !(select instanceof Set))
51
- select = /* @__PURE__ */ new Set([select]);
52
- if (!listeners.has(onReady) && !select)
53
- callback.call(subject, true, subject);
54
- listeners.set(callback, select);
55
- return () => listeners.delete(callback);
15
+ let listeners = LISTENERS.get(subject);
16
+ if (!listeners) LISTENERS.set(subject, listeners = new Map([[onReady, void 0]]));
17
+ if (select !== void 0 && !(select instanceof Set)) select = new Set([select]);
18
+ if (!listeners.has(onReady) && !select) callback.call(subject, true, subject);
19
+ listeners.set(callback, select);
20
+ return () => listeners.delete(callback);
56
21
  }
57
- function emit(model, key2) {
58
- const listeners = LISTENERS.get(model);
59
- const notReady = listeners.has(onReady);
60
- if (key2 === true && !notReady)
61
- return;
62
- let pending = PENDING.get(model);
63
- if (pending) {
64
- pending.add(key2);
65
- return;
66
- }
67
- PENDING.set(model, pending = new Set(notReady ? [true, key2] : [key2]));
68
- for (const key3 of pending)
69
- for (const [callback, filter] of listeners)
70
- if (!filter || filter.has(key3)) {
71
- const after = callback.call(model, key3, model);
72
- if (after)
73
- enqueue(after);
74
- else if (after === null)
75
- listeners.delete(callback);
76
- }
77
- if (key2 === null)
78
- listeners.clear();
79
- PENDING.delete(model);
22
+ function emit(state, key) {
23
+ const listeners = LISTENERS.get(state);
24
+ const notReady = listeners.has(onReady);
25
+ if (key === true && !notReady) return;
26
+ let pending = PENDING.get(state);
27
+ if (pending) {
28
+ pending.add(key);
29
+ return;
30
+ }
31
+ PENDING.set(state, pending = new Set(notReady ? [true, key] : [key]));
32
+ for (const key of pending) for (const [callback, filter] of listeners) if (!filter || filter.has(key)) {
33
+ const after = callback.call(state, key, state);
34
+ if (after) enqueue(after);
35
+ else if (after === null) listeners.delete(callback);
36
+ }
37
+ if (key === null) listeners.clear();
38
+ PENDING.delete(state);
80
39
  }
81
- function event(subject, key2, silent) {
82
- if (key2 === null)
83
- return emit(subject, key2);
84
- if (!key2)
85
- return emit(subject, true);
86
- let pending = PENDING_KEYS.get(subject);
87
- if (!pending) {
88
- PENDING_KEYS.set(subject, pending = /* @__PURE__ */ new Set());
89
- if (!silent)
90
- enqueue(() => {
91
- emit(subject, false);
92
- PENDING_KEYS.delete(subject);
93
- });
94
- }
95
- pending.add(key2);
96
- if (!silent)
97
- emit(subject, key2);
40
+ function event(subject, key, silent) {
41
+ if (key === null) return emit(subject, key);
42
+ if (!key) return emit(subject, true);
43
+ let pending = PENDING_KEYS.get(subject);
44
+ if (!pending) {
45
+ PENDING_KEYS.set(subject, pending = /* @__PURE__ */ new Set());
46
+ if (!silent) enqueue(() => {
47
+ emit(subject, false);
48
+ PENDING_KEYS.delete(subject);
49
+ });
50
+ }
51
+ pending.add(key);
52
+ if (!silent) emit(subject, key);
98
53
  }
99
54
  function enqueue(eventHandler) {
100
- if (!DISPATCH.size)
101
- setTimeout(() => {
102
- DISPATCH.forEach((event2) => {
103
- try {
104
- event2();
105
- } catch (err) {
106
- console.error(err);
107
- }
108
- });
109
- DISPATCH.clear();
110
- }, 0);
111
- DISPATCH.add(eventHandler);
55
+ if (!DISPATCH.size) setTimeout(() => {
56
+ DISPATCH.forEach((event) => {
57
+ try {
58
+ event();
59
+ } catch (err) {
60
+ console.error(err);
61
+ }
62
+ });
63
+ DISPATCH.clear();
64
+ }, 0);
65
+ DISPATCH.add(eventHandler);
112
66
  }
113
- function createEffect(target, callback, argument) {
114
- let unset;
115
- let reset;
116
- function invoke() {
117
- let ignore = true;
118
- function onUpdate() {
119
- if (ignore || reset === null)
120
- return;
121
- ignore = true;
122
- if (reset && unset) {
123
- unset(true);
124
- unset = void 0;
125
- }
126
- enqueue(invoke);
127
- return { then: enqueue };
128
- }
129
- try {
130
- const exit = enter(argument === false);
131
- const output = callback(target[Observable](onUpdate, argument === true));
132
- const flush = exit();
133
- ignore = false;
134
- reset = output === null ? null : invoke;
135
- unset = (key2) => {
136
- if (typeof output == "function")
137
- output(key2);
138
- flush();
139
- };
140
- } catch (err) {
141
- if (err instanceof Promise) {
142
- reset = void 0;
143
- err.then(invoke);
144
- } else
145
- throw err;
146
- }
147
- }
148
- function cleanup() {
149
- if (unset)
150
- unset(false);
151
- reset = null;
152
- }
153
- ;
154
- if (EffectContext && argument !== false)
155
- EffectContext.add(cleanup);
156
- addListener(target, (key2) => {
157
- if (key2 === true)
158
- invoke();
159
- else if (!reset)
160
- return reset;
161
- if (key2 === null && unset)
162
- unset(null);
163
- });
164
- return cleanup;
67
+ function watch(target, callback, argument) {
68
+ let unset;
69
+ let reset;
70
+ function invoke() {
71
+ let ignore = true;
72
+ function onUpdate() {
73
+ if (ignore || reset === null) return;
74
+ ignore = true;
75
+ if (reset && unset) {
76
+ unset(true);
77
+ unset = void 0;
78
+ }
79
+ enqueue(invoke);
80
+ return { then: enqueue };
81
+ }
82
+ try {
83
+ const exit = argument === false ? void 0 : scope();
84
+ const output = callback(target[Observable](onUpdate, argument === true));
85
+ const flush = exit ? exit() : () => {};
86
+ ignore = false;
87
+ reset = output === null ? null : invoke;
88
+ unset = (key) => {
89
+ if (typeof output == "function") output(key);
90
+ flush();
91
+ };
92
+ } catch (err) {
93
+ if (err instanceof Promise) {
94
+ reset = void 0;
95
+ err.then(invoke);
96
+ } else throw err;
97
+ }
98
+ }
99
+ function cleanup() {
100
+ if (unset) unset(false);
101
+ reset = null;
102
+ }
103
+ if (EffectContext && argument !== false) EffectContext.add(cleanup);
104
+ addListener(target, (key) => {
105
+ if (key === true) invoke();
106
+ else if (!reset) return reset;
107
+ if (key === null && unset) unset(null);
108
+ });
109
+ return cleanup;
165
110
  }
166
- var EffectContext;
167
- function enter(ignore) {
168
- if (ignore)
169
- return () => () => {
170
- };
171
- const last = EffectContext;
172
- const context = EffectContext = /* @__PURE__ */ new Set();
173
- return () => {
174
- EffectContext = last;
175
- return () => context.forEach((fn) => fn());
176
- };
111
+ let EffectContext;
112
+ function scope() {
113
+ const last = EffectContext;
114
+ const context = EffectContext = /* @__PURE__ */ new Set();
115
+ return () => {
116
+ EffectContext = last;
117
+ return () => context.forEach((fn) => fn());
118
+ };
177
119
  }
178
120
 
179
- // src/model.ts
180
- var define = Object.defineProperty;
181
- var ID = /* @__PURE__ */ new WeakMap();
182
- var STATE = /* @__PURE__ */ new WeakMap();
183
- var NOTIFY = /* @__PURE__ */ new WeakMap();
184
- var PARENT = /* @__PURE__ */ new WeakMap();
185
- var METHODS = /* @__PURE__ */ new WeakMap();
186
- var METHOD = /* @__PURE__ */ new WeakMap();
187
- var Model = class {
188
- constructor(...args) {
189
- prepare(this);
190
- define(this, "is", { value: this });
191
- init(this, args);
192
- }
193
- [Observable](callback, required) {
194
- const watch2 = /* @__PURE__ */ new Set();
195
- const proxy = Object.create(this);
196
- addListener(this, (key2) => {
197
- if (watch2.has(key2))
198
- callback();
199
- });
200
- OBSERVER.set(proxy, (key2, value) => {
201
- if (value === void 0 && required)
202
- throw new Error(`${this}.${key2} is required in this context.`);
203
- watch2.add(key2);
204
- if (value instanceof Object && Observable in value)
205
- return value[Observable](callback, required) || value;
206
- return value;
207
- });
208
- return proxy;
209
- }
210
- get(arg1, arg2) {
211
- const self = this.is;
212
- if (typeof arg1 == "function") {
213
- const effect = METHOD.get(arg1) || arg1;
214
- let pending = /* @__PURE__ */ new Set();
215
- return createEffect(self, (proxy) => {
216
- const cb = effect.call(proxy, proxy, pending);
217
- return cb === null ? null : (update2) => {
218
- pending = PENDING_KEYS.get(self);
219
- if (typeof cb == "function")
220
- cb(update2);
221
- };
222
- });
223
- }
224
- return arg1 === void 0 ? snapshot(self) : typeof arg2 == "function" ? addListener(self, arg2, arg1) : arg1 === null ? Object.isFrozen(STATE.get(self)) : fetch(self, arg1, arg2);
225
- }
226
- set(arg1, arg2, arg3) {
227
- const self = this.is;
228
- if (typeof arg1 == "function")
229
- return addListener(self, (key2) => {
230
- if (arg2 === key2 || arg2 === void 0 && typeof key2 == "string")
231
- return arg1.call(self, key2, self);
232
- });
233
- if (arg1 && typeof arg1 == "object")
234
- assign(self, arg1, arg2 === true);
235
- else if (!arg2)
236
- event(self, arg1);
237
- else if (arg3)
238
- manage(self, arg1, arg2);
239
- else
240
- update(self, arg1, arg2);
241
- const pending = PENDING_KEYS.get(this);
242
- if (pending)
243
- return {
244
- then: (res) => new Promise((res2) => {
245
- const remove = addListener(this, (key2) => {
246
- if (key2 !== true) {
247
- remove();
248
- return res2.bind(null, Array.from(pending));
249
- }
250
- });
251
- }).then(res)
252
- };
253
- }
254
- /**
255
- * Iterate over managed properties in this instance of Model.
256
- * Yeilds the key and current value for each property.
257
- */
258
- [Symbol.iterator]() {
259
- return Object.entries(STATE.get(this.is))[Symbol.iterator]();
260
- }
261
- /**
262
- * Create and activate a new instance of this model.
263
- *
264
- * **Important** - Unlike `new this(...)` - this method also activates state.
265
- *
266
- * @param args - arguments sent to constructor
267
- */
268
- static new(...args) {
269
- const instance = new this(...args);
270
- event(instance);
271
- return instance;
272
- }
273
- /**
274
- * Static equivalent of `x instanceof this`.
275
- * Determines if provided class is a subtype of this one.
276
- * If so, language server will make available all static
277
- * methods and properties of this class.
278
- */
279
- static is(maybe) {
280
- return maybe === this || typeof maybe == "function" && maybe.prototype instanceof this;
281
- }
282
- /**
283
- * Register a callback to run when any instance of this Model is updated.
284
- */
285
- static on(listener) {
286
- let notify = NOTIFY.get(this);
287
- if (!notify)
288
- NOTIFY.set(this, notify = /* @__PURE__ */ new Set());
289
- notify.add(listener);
290
- return () => notify.delete(listener);
291
- }
121
+ //#endregion
122
+ //#region src/state.ts
123
+ const define = Object.defineProperty;
124
+ /** Register for all active states via string identifiers (usually unique). */
125
+ const ID = /* @__PURE__ */ new WeakMap();
126
+ /** Internal state assigned to states. */
127
+ const STATE = /* @__PURE__ */ new WeakMap();
128
+ /** External listeners for any given State. */
129
+ const NOTIFY = /* @__PURE__ */ new WeakMap();
130
+ /** Parent-child relationships. */
131
+ const PARENT = /* @__PURE__ */ new WeakMap();
132
+ /** List of methods defined by a given type. */
133
+ const METHODS = /* @__PURE__ */ new WeakMap();
134
+ /** Reference bound instance methods to real ones. */
135
+ const METHOD = /* @__PURE__ */ new WeakMap();
136
+ /** Currently accumulating export. Stores real values of placeholder properties such as ref() or child states. */
137
+ let EXPORT;
138
+ var State = class {
139
+ constructor(...args) {
140
+ prepare(this);
141
+ define(this, "is", { value: this });
142
+ init$1(this, ...args, (x) => x.new && x.new());
143
+ }
144
+ [Observable](callback, required) {
145
+ const watch = /* @__PURE__ */ new Set();
146
+ const proxy = Object.create(this);
147
+ addListener(this, (key) => {
148
+ if (watch.has(key)) callback();
149
+ });
150
+ OBSERVER.set(proxy, (key, value) => {
151
+ if (value === void 0 && required) throw new Error(`${this}.${key} is required in this context.`);
152
+ watch.add(key);
153
+ if (value instanceof Object && Observable in value) return value[Observable](callback, required) || value;
154
+ return value;
155
+ });
156
+ return proxy;
157
+ }
158
+ get(arg1, arg2) {
159
+ const self = this.is;
160
+ if (arg1 === void 0) return values(self);
161
+ if (typeof arg1 == "function") return effect(self, arg1);
162
+ if (typeof arg2 == "function") return addListener(self, arg2, arg1);
163
+ if (arg1 === null) return Object.isFrozen(STATE.get(self));
164
+ return access(self, arg1, arg2);
165
+ }
166
+ set(arg1, arg2, arg3) {
167
+ const self = this.is;
168
+ if (typeof arg1 == "function") return addListener(self, (key) => {
169
+ if (arg2 === key || arg2 === void 0 && typeof key == "string") return arg1.call(self, key, self);
170
+ });
171
+ if (arg1 && typeof arg1 == "object") assign(self, arg1, arg2 === true);
172
+ else if (!arg2) event(self, arg1);
173
+ else if (arg3) manage(self, arg1, arg2);
174
+ else update(self, arg1, arg2);
175
+ const pending = PENDING_KEYS.get(this);
176
+ if (pending) return { then: (resolve) => new Promise((res) => {
177
+ const remove = addListener(this, (key) => {
178
+ if (key !== true) {
179
+ remove();
180
+ return () => res(Array.from(pending));
181
+ }
182
+ });
183
+ }).then(resolve) };
184
+ }
185
+ /**
186
+ * Iterate over managed properties in this instance of State.
187
+ * Yeilds the key and current value for each property.
188
+ */
189
+ [Symbol.iterator]() {
190
+ return Object.entries(STATE.get(this.is))[Symbol.iterator]();
191
+ }
192
+ /**
193
+ * Create and activate a new instance of this state.
194
+ *
195
+ * **Important** - Unlike `new this(...)` - this method also activates state.
196
+ *
197
+ * @param args - arguments sent to constructor
198
+ */
199
+ static new(...args) {
200
+ const instance = new this(...args);
201
+ event(instance);
202
+ return instance;
203
+ }
204
+ /**
205
+ * Static equivalent of `x instanceof this`.
206
+ * Determines if provided class is a subtype of this one.
207
+ * If so, language server will make available all static
208
+ * methods and properties of this class.
209
+ */
210
+ static is(maybe) {
211
+ return maybe === this || typeof maybe == "function" && maybe.prototype instanceof this;
212
+ }
213
+ /**
214
+ * Register a callback to run when any instance of this State is updated.
215
+ */
216
+ static on(listener) {
217
+ let notify = NOTIFY.get(this);
218
+ if (!notify) NOTIFY.set(this, notify = /* @__PURE__ */ new Set());
219
+ notify.add(listener);
220
+ return () => notify.delete(listener);
221
+ }
292
222
  };
293
- define(Model.prototype, "toString", {
294
- value() {
295
- return ID.get(this.is);
296
- }
297
- });
298
- define(Model, "toString", {
299
- value() {
300
- return this.name;
301
- }
302
- });
223
+ define(State.prototype, "toString", { value() {
224
+ return ID.get(this.is);
225
+ } });
226
+ define(State, "toString", { value() {
227
+ return this.name;
228
+ } });
303
229
  function assign(subject, data, silent) {
304
- const methods = METHODS.get(subject.constructor);
305
- for (const key2 in data) {
306
- const bind = methods.get(key2);
307
- if (bind)
308
- bind.call(subject, data[key2]);
309
- else if (key2 in subject && key2 !== "is") {
310
- const desc = Object.getOwnPropertyDescriptor(subject, key2);
311
- const set2 = desc && desc.set;
312
- if (set2)
313
- set2.call(subject, data[key2], silent);
314
- else
315
- subject[key2] = data[key2];
316
- }
317
- }
230
+ const methods = METHODS.get(subject.constructor);
231
+ for (const key in data) {
232
+ const bind = methods.get(key);
233
+ if (bind) bind.call(subject, data[key]);
234
+ else if (key in subject && key !== "is") {
235
+ const desc = Object.getOwnPropertyDescriptor(subject, key);
236
+ const set = desc && desc.set;
237
+ if (set) set.call(subject, data[key], silent);
238
+ else subject[key] = data[key];
239
+ }
240
+ }
318
241
  }
319
- function prepare(model) {
320
- let T = model.constructor;
321
- if (T === Model)
322
- throw new Error("Cannot create base Model.");
323
- const chain = [];
324
- let keys2 = /* @__PURE__ */ new Map();
325
- ID.set(model, `${T}-${uid()}`);
326
- while (T.name) {
327
- for (const cb of NOTIFY.get(T) || [])
328
- addListener(model, cb);
329
- if (T === Model) break;
330
- else chain.unshift(T);
331
- T = Object.getPrototypeOf(T);
332
- }
333
- for (const type of chain) {
334
- if (METHODS.has(type)) {
335
- keys2 = METHODS.get(type);
336
- continue;
337
- }
338
- METHODS.set(type, keys2 = new Map(keys2));
339
- for (const [key2, { value }] of Object.entries(
340
- Object.getOwnPropertyDescriptors(type.prototype)
341
- )) {
342
- let bind2 = function(original) {
343
- const { is } = this;
344
- if (is.hasOwnProperty(key2) && !original)
345
- return value;
346
- const fn = original || value;
347
- const bound = fn.bind(is);
348
- METHOD.set(bound, fn);
349
- define(is, key2, { value: bound, writable: true });
350
- return bound;
351
- };
352
- var bind = bind2;
353
- if (!value || key2 == "constructor")
354
- continue;
355
- keys2.set(key2, bind2);
356
- define(type.prototype, key2, { get: bind2, set: bind2 });
357
- }
358
- }
242
+ /** Apply instructions and inherited event listeners. Ensure class metadata is ready. */
243
+ function prepare(state) {
244
+ let T = state.constructor;
245
+ if (T === State) throw new Error("Cannot create base State.");
246
+ const chain = [];
247
+ let keys = /* @__PURE__ */ new Map();
248
+ ID.set(state, `${T}-${uid()}`);
249
+ while (T.name) {
250
+ for (const cb of NOTIFY.get(T) || []) addListener(state, cb);
251
+ if (T === State) break;
252
+ else chain.unshift(T);
253
+ T = Object.getPrototypeOf(T);
254
+ }
255
+ for (const type of chain) {
256
+ if (METHODS.has(type)) {
257
+ keys = METHODS.get(type);
258
+ continue;
259
+ }
260
+ METHODS.set(type, keys = new Map(keys));
261
+ for (const [key, { value }] of Object.entries(Object.getOwnPropertyDescriptors(type.prototype))) {
262
+ if (!value || key == "constructor") continue;
263
+ function bind(original) {
264
+ const { is } = this;
265
+ if (is.hasOwnProperty(key) && !original) return value;
266
+ const fn = original || value;
267
+ const bound = fn.bind(is);
268
+ METHOD.set(bound, fn);
269
+ define(is, key, {
270
+ value: bound,
271
+ writable: true
272
+ });
273
+ return bound;
274
+ }
275
+ keys.set(key, bind);
276
+ define(type.prototype, key, {
277
+ get: bind,
278
+ set: bind
279
+ });
280
+ }
281
+ }
359
282
  }
360
- function init(model, args) {
361
- const state = {};
362
- STATE.set(model, state);
363
- args = args.flat().filter((arg) => {
364
- if (typeof arg != "string")
365
- return true;
366
- ID.set(model, arg);
367
- });
368
- addListener(model, () => {
369
- if (!PARENT.has(model))
370
- PARENT.set(model, null);
371
- for (const key2 in model) {
372
- const desc = Object.getOwnPropertyDescriptor(model, key2);
373
- if ("value" in desc)
374
- manage(model, key2, desc.value, true);
375
- }
376
- for (const arg of args) {
377
- const use2 = typeof arg == "function" ? arg.call(model, model) : arg;
378
- if (use2 instanceof Promise)
379
- use2.catch((err) => {
380
- console.error(`Async error in constructor for ${model}:`);
381
- console.error(err);
382
- });
383
- else if (typeof use2 == "function")
384
- addListener(model, use2, null);
385
- else if (typeof use2 == "object")
386
- assign(model, use2, true);
387
- }
388
- addListener(model, () => {
389
- for (const [_, value] of model)
390
- if (value instanceof Model && PARENT.get(value) === model)
391
- value.set(null);
392
- Object.freeze(state);
393
- }, null);
394
- return null;
395
- });
283
+ /**
284
+ * Apply state arguemnts, run callbacks and observe properties.
285
+ * Accumulate and handle cleanup events.
286
+ **/
287
+ function init$1(self, ...args) {
288
+ const state = {};
289
+ STATE.set(self, state);
290
+ args = args.flat().filter((arg) => {
291
+ if (typeof arg == "string") ID.set(self, arg);
292
+ else return true;
293
+ });
294
+ addListener(self, () => {
295
+ if (!PARENT.has(self)) PARENT.set(self, null);
296
+ for (const key in self) {
297
+ const desc = Object.getOwnPropertyDescriptor(self, key);
298
+ if ("value" in desc) manage(self, key, desc.value, true);
299
+ }
300
+ for (const arg of args) {
301
+ const use = typeof arg == "function" ? arg.call(self, self) : arg;
302
+ if (use instanceof Promise) use.catch((err) => {
303
+ console.error(`Async error in constructor for ${self}:`);
304
+ console.error(err);
305
+ });
306
+ else if (Array.isArray(use)) args.push(...use);
307
+ else if (typeof use == "function") addListener(self, use, null);
308
+ else if (typeof use == "object") assign(self, use, true);
309
+ }
310
+ addListener(self, () => {
311
+ for (const [_, value] of self) if (value instanceof State && PARENT.get(value) === self) value.set(null);
312
+ Object.freeze(state);
313
+ }, null);
314
+ return null;
315
+ });
396
316
  }
397
- function manage(target, key2, value, silent) {
398
- const state = STATE.get(target);
399
- function get2() {
400
- return watch(this, key2, state[key2]);
401
- }
402
- function set2(value2, silent2) {
403
- update(target, key2, value2, silent2);
404
- if (value2 instanceof Model && !PARENT.has(value2)) {
405
- PARENT.set(value2, target);
406
- event(value2);
407
- }
408
- }
409
- define(target, key2, { set: set2, get: get2 });
410
- set2(value, silent);
317
+ function manage(target, key, value, silent) {
318
+ const state = STATE.get(target);
319
+ function get() {
320
+ return follow(this, key, state[key]);
321
+ }
322
+ function set(value, silent) {
323
+ update(target, key, value, silent);
324
+ if (value instanceof State && !PARENT.has(value)) {
325
+ PARENT.set(value, target);
326
+ event(value);
327
+ }
328
+ }
329
+ define(target, key, {
330
+ set,
331
+ get
332
+ });
333
+ set(value, silent);
411
334
  }
412
- var OBSERVER = /* @__PURE__ */ new WeakMap();
413
- function watch(from, key2, value) {
414
- const access = OBSERVER.get(from);
415
- return access ? access(key2, value) : value;
335
+ function effect(target, fn) {
336
+ const effect = METHOD.get(fn) || fn;
337
+ let pending = /* @__PURE__ */ new Set();
338
+ return watch(target, (proxy) => {
339
+ const cb = effect.call(proxy, proxy, pending);
340
+ if (cb === null) return cb;
341
+ return (update) => {
342
+ pending = PENDING_KEYS.get(target);
343
+ if (typeof cb == "function") cb(update);
344
+ };
345
+ });
416
346
  }
417
- function fetch(subject, property, required) {
418
- const state = STATE.get(subject);
419
- if (property in state || required === false) {
420
- const value = state[property];
421
- if (value !== void 0 || !required)
422
- return value;
423
- }
424
- if (METHODS.get(subject.constructor).has(property))
425
- return METHOD.get(subject[property]);
426
- const error = new Error(`${subject}.${property} is not yet available.`);
427
- const promise = new Promise((resolve, reject) => {
428
- addListener(subject, (key2) => {
429
- if (key2 === property) {
430
- resolve(state[key2]);
431
- return null;
432
- }
433
- if (key2 === null)
434
- reject(new Error(`${subject} is destroyed.`));
435
- });
436
- });
437
- throw Object.assign(promise, {
438
- toString: () => String(error),
439
- name: "Suspense",
440
- message: error.message,
441
- stack: error.stack
442
- });
347
+ function values(target) {
348
+ const values = {};
349
+ let isNotRecursive;
350
+ if (!EXPORT) {
351
+ isNotRecursive = true;
352
+ EXPORT = new Map([[target, values]]);
353
+ }
354
+ for (let [key, value] of target) {
355
+ if (EXPORT.has(value)) value = EXPORT.get(value);
356
+ else if (value && typeof value == "object" && "get" in value && typeof value.get === "function") EXPORT.set(value, value = value.get());
357
+ values[key] = value;
358
+ }
359
+ if (isNotRecursive) EXPORT = void 0;
360
+ return Object.freeze(values);
443
361
  }
444
- var EXPORT;
445
- function snapshot(model) {
446
- const values = {};
447
- let isNotRecursive;
448
- if (!EXPORT) {
449
- isNotRecursive = true;
450
- EXPORT = /* @__PURE__ */ new Map([[model, values]]);
451
- }
452
- for (let [key2, value] of model) {
453
- if (EXPORT.has(value))
454
- value = EXPORT.get(value);
455
- else if (value && typeof value == "object" && "get" in value && typeof value.get === "function")
456
- EXPORT.set(value, value = value.get());
457
- values[key2] = value;
458
- }
459
- if (isNotRecursive)
460
- EXPORT = void 0;
461
- return Object.freeze(values);
362
+ const OBSERVER = /* @__PURE__ */ new WeakMap();
363
+ function follow(from, key, value) {
364
+ const observe = OBSERVER.get(from);
365
+ return observe ? observe(key, value) : value;
462
366
  }
463
- function update(subject, key2, value, arg) {
464
- const state = STATE.get(subject);
465
- if (Object.isFrozen(state))
466
- throw new Error(`Tried to update ${subject}.${String(key2)} but model is destroyed.`);
467
- const previous = state[key2];
468
- if (typeof arg == "function") {
469
- const out = arg.call(subject, value, previous);
470
- if (out === false)
471
- return false;
472
- if (typeof out == "function")
473
- value = out();
474
- }
475
- if (value === previous && key2 in state)
476
- return;
477
- state[key2] = value;
478
- if (arg !== true)
479
- event(subject, key2);
480
- return true;
367
+ function access(subject, property, required) {
368
+ const state = STATE.get(subject);
369
+ if (property in state || required === false) {
370
+ const value = state[property];
371
+ if (value !== void 0 || !required) return value;
372
+ }
373
+ if (METHODS.get(subject.constructor).has(property)) return METHOD.get(subject[property]);
374
+ const error = /* @__PURE__ */ new Error(`${subject}.${property} is not yet available.`);
375
+ const promise = new Promise((resolve, reject) => {
376
+ addListener(subject, (key) => {
377
+ if (key === property) {
378
+ resolve(state[key]);
379
+ return null;
380
+ }
381
+ if (key === null) reject(/* @__PURE__ */ new Error(`${subject} is destroyed.`));
382
+ });
383
+ });
384
+ throw Object.assign(promise, {
385
+ toString: () => String(error),
386
+ name: "Suspense",
387
+ message: error.message,
388
+ stack: error.stack
389
+ });
481
390
  }
482
- function uid() {
483
- return (0.278 + Math.random() * 0.722).toString(36).substring(2, 8).toUpperCase();
391
+ function update(subject, key, value, arg) {
392
+ const state = STATE.get(subject);
393
+ if (Object.isFrozen(state)) throw new Error(`Tried to update ${subject}.${String(key)} but state is destroyed.`);
394
+ const previous = state[key];
395
+ if (typeof arg == "function") {
396
+ const out = arg.call(subject, value, previous);
397
+ if (out === false) return false;
398
+ if (typeof out == "function") value = out();
399
+ }
400
+ if (value === previous && key in state) return;
401
+ state[key] = value;
402
+ if (arg !== true) event(subject, key);
403
+ return true;
484
404
  }
485
-
486
- // src/context.ts
487
- var LOOKUP = /* @__PURE__ */ new WeakMap();
488
- var KEYS = /* @__PURE__ */ new Map();
489
- function key(T, upstream) {
490
- let K = KEYS.get(T);
491
- if (!K)
492
- KEYS.set(T, K = Symbol(
493
- typeof T == "symbol" ? "get " + T.description : String(T)
494
- ));
495
- return upstream ? key(K) : K;
496
- }
497
- function keys(from, upstream) {
498
- const keys2 = /* @__PURE__ */ new Set();
499
- do {
500
- keys2.add(key(from, upstream));
501
- } while ((from = Object.getPrototypeOf(from)) !== Model);
502
- return keys2;
405
+ /** Random alphanumberic of length 6; always starts with a letter. */
406
+ function uid() {
407
+ return (.278 + Math.random() * .722).toString(36).substring(2, 8).toUpperCase();
503
408
  }
504
- var Context = class _Context {
505
- constructor(inputs) {
506
- this.layer = /* @__PURE__ */ new Map();
507
- this.cleanup = /* @__PURE__ */ new Set();
508
- if (inputs)
509
- this.include(inputs);
510
- }
511
- static get({ is }, callback) {
512
- const waiting = LOOKUP.get(is);
513
- if (waiting instanceof _Context) {
514
- if (callback)
515
- callback(waiting);
516
- return waiting;
517
- }
518
- if (callback)
519
- if (waiting)
520
- waiting.push(callback);
521
- else
522
- LOOKUP.set(is, [callback]);
523
- }
524
- /** Run callback when a specified type is registered to a **child** context. */
525
- has(Type, callback) {
526
- Object.defineProperty(this, key(Type, true), { value: callback, configurable: true });
527
- }
528
- get(Type, require2) {
529
- const result = this[key(Type)];
530
- if (result === null)
531
- throw new Error(`Did find ${Type} in context, but multiple were defined.`);
532
- if (result)
533
- return result;
534
- if (require2)
535
- throw new Error(`Could not find ${Type} in context.`);
536
- }
537
- push(inputs) {
538
- const next = Object.create(this);
539
- this.cleanup = /* @__PURE__ */ new Set([() => next.pop(), ...this.cleanup]);
540
- next.layer = /* @__PURE__ */ new Map();
541
- next.cleanup = /* @__PURE__ */ new Set();
542
- if (inputs)
543
- next.include(inputs);
544
- return next;
545
- }
546
- pop() {
547
- for (const key2 of Object.getOwnPropertySymbols(this))
548
- delete this[key2];
549
- this.cleanup.forEach((cb) => cb());
550
- this.cleanup.clear();
551
- this.layer.clear();
552
- }
553
- include(inputs, forEach) {
554
- const init3 = /* @__PURE__ */ new Map();
555
- if (typeof inputs == "function" || inputs instanceof Model)
556
- inputs = { [forEach ? 0 : this.layer.size]: inputs };
557
- for (const [K, V] of Object.entries(inputs)) {
558
- if (Model.is(V) || V instanceof Model) {
559
- const exists = this.layer.get(K);
560
- if (!exists) {
561
- const instance = this.add(V);
562
- this.layer.set(K, V);
563
- init3.set(instance, true);
564
- } else if (exists !== V) {
565
- this.pop();
566
- this.id = uid();
567
- this.include(inputs);
568
- }
569
- continue;
570
- }
571
- throw new Error(
572
- `Context may only include instance or class \`extends Model\` but got ${K == "0" || K == String(V) ? V : `${V} (as '${K}')`}.`
573
- );
574
- }
575
- for (const [model, explicit] of init3) {
576
- model.set();
577
- if (explicit && forEach)
578
- forEach(model);
579
- for (const [_key, value] of model)
580
- if (PARENT.get(value) === model) {
581
- this.add(value, true);
582
- init3.set(value, false);
583
- }
584
- }
585
- }
586
- add(input, implicit) {
587
- const cleanup = /* @__PURE__ */ new Set();
588
- let T;
589
- let I;
590
- if (typeof input == "function") {
591
- T = input;
592
- I = new input();
593
- } else {
594
- T = input.constructor;
595
- I = input;
596
- }
597
- keys(T, true).forEach((K) => {
598
- const expects = this[K];
599
- if (!expects)
600
- return;
601
- addListener(I, (event2) => {
602
- if (event2 === true) {
603
- const callback = expects(I);
604
- if (callback)
605
- cleanup.add(callback);
606
- }
607
- return null;
608
- });
609
- });
610
- keys(T).forEach((K) => {
611
- const value = this.hasOwnProperty(K) ? null : I;
612
- if (value || this[K] !== I && !implicit)
613
- Object.defineProperty(this, K, {
614
- configurable: true,
615
- value
616
- });
617
- });
618
- this.cleanup.add(() => {
619
- cleanup.forEach((cb) => cb());
620
- if (I !== input)
621
- event(I, null);
622
- });
623
- const waiting = LOOKUP.get(I);
624
- if (waiting instanceof Array)
625
- waiting.forEach((cb) => cb(this));
626
- LOOKUP.set(I, this);
627
- return I;
628
- }
629
- };
630
409
 
631
- // src/instruction/use.ts
632
- var INSTRUCTION = /* @__PURE__ */ new Map();
410
+ //#endregion
411
+ //#region src/instruction/use.ts
412
+ const INSTRUCTION = /* @__PURE__ */ new Map();
633
413
  function use(arg1, arg2) {
634
- if (Model.is(arg1))
635
- arg1 = childInstruction(arg1, arg2);
636
- const token = Symbol("instruction-" + uid());
637
- INSTRUCTION.set(token, arg1);
638
- return token;
414
+ if (State.is(arg1)) arg1 = childInstruction(arg1, arg2);
415
+ const token = Symbol("instruction-" + uid());
416
+ INSTRUCTION.set(token, arg1);
417
+ return token;
639
418
  }
640
419
  function childInstruction(type, arg2) {
641
- return (key2, subject) => {
642
- function set2(next) {
643
- if (next ? !(next instanceof type) : arg2 !== false)
644
- throw new Error(`${subject}.${key2} expected Model of type ${type} but got ${next && next.constructor}.`);
645
- update(subject, key2, next);
646
- if (next && typeof arg2 == "function")
647
- arg2(next);
648
- return false;
649
- }
650
- const value = new type();
651
- set2(value);
652
- PARENT.set(value, subject);
653
- value.set();
654
- return { set: set2 };
655
- };
420
+ return (key, subject) => {
421
+ function set(next) {
422
+ if (next ? !(next instanceof type) : arg2 !== false) throw new Error(`${subject}.${key} expected State of type ${type} but got ${next && next.constructor}.`);
423
+ update(subject, key, next);
424
+ if (next && typeof arg2 == "function") arg2(next);
425
+ return false;
426
+ }
427
+ const value = new type();
428
+ set(value);
429
+ PARENT.set(value, subject);
430
+ value.set();
431
+ return { set };
432
+ };
656
433
  }
657
- function init2() {
658
- const state = STATE.get(this);
659
- for (const key2 in this) {
660
- const { value } = Object.getOwnPropertyDescriptor(this, key2);
661
- const instruction = INSTRUCTION.get(value);
662
- if (!instruction)
663
- continue;
664
- INSTRUCTION.delete(value);
665
- delete this[key2];
666
- const output = instruction.call(this, key2, this, state);
667
- if (!output)
668
- continue;
669
- const desc = typeof output == "object" ? output : { get: output };
670
- if ("value" in desc)
671
- state[key2] = desc.value;
672
- const model = this;
673
- Object.defineProperty(model, key2, {
674
- enumerable: desc.enumerable !== false,
675
- get() {
676
- return watch(
677
- this,
678
- key2,
679
- typeof desc.get == "function" ? desc.get(this) : fetch(model, key2, desc.get)
680
- );
681
- },
682
- set(next) {
683
- if (desc.set === false)
684
- throw new Error(`${model}.${key2} is read-only.`);
685
- update(model, key2, next, desc.set);
686
- }
687
- });
688
- }
689
- return null;
434
+ function init() {
435
+ const state = STATE.get(this);
436
+ for (const key in this) {
437
+ const { value } = Object.getOwnPropertyDescriptor(this, key);
438
+ const instruction = INSTRUCTION.get(value);
439
+ if (!instruction) continue;
440
+ INSTRUCTION.delete(value);
441
+ delete this[key];
442
+ const output = instruction.call(this, key, this, state);
443
+ if (!output) continue;
444
+ const desc = typeof output == "object" ? output : { get: output };
445
+ if ("value" in desc) state[key] = desc.value;
446
+ const self = this;
447
+ Object.defineProperty(self, key, {
448
+ enumerable: desc.enumerable !== false,
449
+ get() {
450
+ return follow(this, key, typeof desc.get == "function" ? desc.get(this) : access(self, key, desc.get));
451
+ },
452
+ set(next) {
453
+ if (desc.set === false) throw new Error(`${self}.${key} is read-only.`);
454
+ update(self, key, next, desc.set);
455
+ }
456
+ });
457
+ }
458
+ return null;
690
459
  }
691
- Model.on(init2);
460
+ State.on(init);
692
461
 
693
- // src/instruction/get.ts
694
- var STALE = /* @__PURE__ */ new WeakSet();
695
- function get(arg0, arg1) {
696
- return use((key2, subject, state) => {
697
- if (typeof arg0 == "symbol")
698
- throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${subject}.${key2}. This is not allowed.`);
699
- if (Model.is(arg0)) {
700
- let assign3 = function(value) {
701
- if (typeof arg1 == "function")
702
- value.get((x) => arg1(x, key2));
703
- update(subject, key2, value);
704
- };
705
- var assign2 = assign3;
706
- const hasParent = PARENT.get(subject);
707
- if (!hasParent && arg1 === true)
708
- throw new Error(`${subject} may only exist as a child of type ${arg0}.`);
709
- else if (hasParent) {
710
- if (hasParent instanceof arg0) {
711
- assign3(hasParent);
712
- return {};
713
- } else if (arg1 === true)
714
- throw new Error(`New ${subject} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
715
- }
716
- Context.get(subject, (context) => {
717
- const model = context.get(arg0);
718
- if (model)
719
- assign3(model);
720
- else if (arg1 !== false)
721
- throw new Error(`Required ${arg0} not found in context for ${subject}.`);
722
- });
723
- return {
724
- get: arg1 !== false,
725
- enumerable: false
726
- };
727
- }
728
- let from = subject;
729
- if (arg0 instanceof Model) {
730
- from = arg0;
731
- } else {
732
- const fn = METHOD.get(arg0) || arg0;
733
- arg1 = (p, k) => fn.call(p, k, p);
734
- }
735
- const source = (resolve) => resolve(from);
736
- const getter = arg1;
737
- let reset;
738
- let isAsync;
739
- let proxy;
740
- function connect(model) {
741
- reset = createEffect(model, (current) => {
742
- proxy = current;
743
- if (!(key2 in state) || STALE.delete(compute))
744
- compute(!reset);
745
- return (didUpdate) => {
746
- if (didUpdate) {
747
- STALE.add(compute);
748
- event(subject, key2, true);
749
- }
750
- };
751
- }, false);
752
- }
753
- function compute(initial) {
754
- let next;
755
- try {
756
- next = getter.call(proxy, proxy, key2);
757
- } catch (err) {
758
- console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key2}.`);
759
- if (initial)
760
- throw err;
761
- console.error(err);
762
- }
763
- update(subject, key2, next, !isAsync);
764
- }
765
- return () => {
766
- if (!proxy) {
767
- source(connect);
768
- isAsync = true;
769
- }
770
- if (STALE.delete(compute))
771
- compute();
772
- return fetch(subject, key2, !proxy);
773
- };
774
- });
462
+ //#endregion
463
+ //#region src/context.ts
464
+ const LOOKUP = /* @__PURE__ */ new WeakMap();
465
+ const KEYS = /* @__PURE__ */ new Map();
466
+ function key(T, upstream) {
467
+ let K = KEYS.get(T);
468
+ if (!K) {
469
+ K = Symbol(typeof T == "symbol" ? "get " + T.description : String(T));
470
+ KEYS.set(T, K);
471
+ }
472
+ return upstream ? key(K) : K;
775
473
  }
474
+ function keys(from, upstream) {
475
+ const keys = /* @__PURE__ */ new Set();
476
+ do {
477
+ keys.add(key(from, upstream));
478
+ from = Object.getPrototypeOf(from);
479
+ } while (from !== State);
480
+ return keys;
481
+ }
482
+ var Context = class Context {
483
+ static get({ is }, callback) {
484
+ const context = LOOKUP.get(is);
485
+ if (context instanceof Context) {
486
+ if (callback) callback(context);
487
+ return context;
488
+ }
489
+ if (callback) if (context) context.push(callback);
490
+ else LOOKUP.set(is, [callback]);
491
+ }
492
+ constructor(inputs) {
493
+ this.id = uid();
494
+ this.inputs = {};
495
+ this.cleanup = /* @__PURE__ */ new Set();
496
+ if (inputs) this.use(inputs);
497
+ }
498
+ get(Type, arg2) {
499
+ if (typeof arg2 == "function") {
500
+ const k = key(Type, true);
501
+ Object.defineProperty(this, k, {
502
+ value: arg2,
503
+ configurable: true
504
+ });
505
+ return () => {
506
+ delete this[k];
507
+ };
508
+ }
509
+ const result = this[key(Type)];
510
+ if (result === null) throw new Error(`Did find ${Type} in context, but multiple were defined.`);
511
+ if (result) return result;
512
+ if (arg2) throw new Error(`Could not find ${Type} in context.`);
513
+ }
514
+ /**
515
+ * Adds a State to this context.
516
+ */
517
+ add(input, implicit) {
518
+ const cleanup = /* @__PURE__ */ new Set();
519
+ let T;
520
+ let I;
521
+ if (typeof input == "function") {
522
+ T = input;
523
+ I = new input();
524
+ } else {
525
+ T = input.constructor;
526
+ I = input;
527
+ }
528
+ keys(T, true).forEach((K) => {
529
+ const expects = this[K];
530
+ if (expects) addListener(I, (event) => {
531
+ if (event === true) {
532
+ const cb = expects(I);
533
+ if (cb) cleanup.add(cb);
534
+ }
535
+ return null;
536
+ });
537
+ });
538
+ keys(T).forEach((K) => {
539
+ const value = this.hasOwnProperty(K) ? null : I;
540
+ if (value || this[K] !== I && !implicit) Object.defineProperty(this, K, {
541
+ configurable: true,
542
+ value
543
+ });
544
+ });
545
+ this.cleanup.add(() => {
546
+ cleanup.forEach((cb) => cb());
547
+ if (I !== input) event(I, null);
548
+ });
549
+ const waiting = LOOKUP.get(I);
550
+ if (waiting instanceof Array) waiting.forEach((cb) => cb(this));
551
+ LOOKUP.set(I, this);
552
+ return I;
553
+ }
554
+ /**
555
+ * Register one or more States to this context.
556
+ *
557
+ * Context will add or remove States as needed to keep with provided input.
558
+ *
559
+ * @param inputs State, State class, or map of States / State classes to register.
560
+ * @param forEach Optional callback to run for each State registered.
561
+ */
562
+ use(inputs, forEach) {
563
+ const init = /* @__PURE__ */ new Map();
564
+ if (typeof inputs == "function" || inputs instanceof State) inputs = { [0]: inputs };
565
+ for (const [K, V] of Object.entries(inputs)) {
566
+ if (!(State.is(V) || V instanceof State)) throw new Error(`Context may only include instance or class \`extends State\` but got ${K == "0" || K == String(V) ? V : `${V} (as '${K}')`}.`);
567
+ const exists = this.inputs[K];
568
+ if (!exists) init.set(this.add(V), true);
569
+ else if (exists !== V) {
570
+ this.pop();
571
+ this.use(inputs);
572
+ this.id = uid();
573
+ return;
574
+ }
575
+ }
576
+ for (const [state, explicit] of init) {
577
+ state.set();
578
+ if (explicit && forEach) forEach(state);
579
+ for (const [_key, value] of state) if (PARENT.get(value) === state) {
580
+ this.add(value, true);
581
+ init.set(value, false);
582
+ }
583
+ }
584
+ this.inputs = inputs;
585
+ }
586
+ /**
587
+ * Create a child context, optionally registering one or more States to it.
588
+ *
589
+ * @param inputs State, State class, or map of States / State classes to register.
590
+ */
591
+ push(inputs) {
592
+ const next = Object.create(this);
593
+ this.cleanup = new Set([() => next.pop(), ...this.cleanup]);
594
+ next.inputs = {};
595
+ next.cleanup = /* @__PURE__ */ new Set();
596
+ if (inputs) next.use(inputs);
597
+ return next;
598
+ }
599
+ /**
600
+ * Remove all States from this context.
601
+ *
602
+ * Will also run any cleanup callbacks registered when States were added.
603
+ */
604
+ pop() {
605
+ for (const key of Object.getOwnPropertySymbols(this)) delete this[key];
606
+ this.cleanup.forEach((cb) => cb());
607
+ this.cleanup.clear();
608
+ this.inputs = {};
609
+ }
610
+ };
611
+ Object.defineProperty(Context.prototype, "toString", { value() {
612
+ return `Context-${this.id}`;
613
+ } });
776
614
 
777
- // src/instruction/ref.ts
778
- var { defineProperty, defineProperties } = Object;
779
- function ref(arg, arg2) {
780
- return use((key2, subject, state) => {
781
- let value = {};
782
- const method = (key3, from) => (callback) => callback ? addListener(subject, () => callback(from[key3]), key3) : from[key3];
783
- if (arg === subject)
784
- addListener(subject, () => {
785
- for (const key3 in subject)
786
- if (typeof arg2 == "function")
787
- defineProperty(value, key3, {
788
- configurable: true,
789
- get() {
790
- const out = arg2(key3);
791
- defineProperty(value, key3, { value: out });
792
- return out;
793
- }
794
- });
795
- else {
796
- const get2 = method(key3, subject);
797
- const set2 = (x) => subject[key3] = x;
798
- defineProperties(set2, {
799
- current: { get: get2, set: set2 },
800
- get: { value: get2 },
801
- is: { value: subject },
802
- key: { value: key3 }
803
- });
804
- defineProperty(value, key3, { value: set2 });
805
- }
806
- return null;
807
- }, true);
808
- else if (typeof arg == "object")
809
- throw new Error("ref instruction does not support object which is not 'this'");
810
- else {
811
- let unset;
812
- const get2 = method(key2, state);
813
- const set2 = (value2) => {
814
- if (!update(subject, key2, value2) || !arg)
815
- return;
816
- if (unset)
817
- unset = void unset(value2);
818
- if (value2 === null && arg2 !== false)
819
- return;
820
- const exit = enter();
821
- const out = arg.call(subject, value2);
822
- const flush = exit();
823
- unset = (key3) => {
824
- if (typeof out == "function")
825
- out(key3);
826
- flush();
827
- };
828
- };
829
- state[key2] = null;
830
- value = defineProperties({ get: get2, key: key2, is: subject }, {
831
- current: { get: get2, set: set2 }
832
- });
833
- }
834
- defineProperty(subject, key2, { value });
835
- });
615
+ //#endregion
616
+ //#region src/instruction/get.ts
617
+ function get(Type, arg1, arg2) {
618
+ const isDownstream = arg1 === true;
619
+ const isOptional = arg1 === false;
620
+ return use((key, subject) => {
621
+ if (isDownstream) {
622
+ const callback = typeof arg2 === "function" ? arg2 : void 0;
623
+ const applied = /* @__PURE__ */ new Set();
624
+ const reset = () => {
625
+ update(subject, key, Object.freeze(Array.from(applied)));
626
+ };
627
+ Context.get(subject, (context) => {
628
+ context.get(Type, (state) => {
629
+ let remove;
630
+ let flush;
631
+ if (applied.has(state)) return;
632
+ if (callback) {
633
+ const exit = scope();
634
+ try {
635
+ const done = callback(state, subject);
636
+ if (done === false) return false;
637
+ if (typeof done == "function") remove = done;
638
+ } finally {
639
+ flush = exit();
640
+ }
641
+ }
642
+ applied.add(state);
643
+ reset();
644
+ const done = () => {
645
+ if (flush) flush();
646
+ ignore();
647
+ applied.delete(state);
648
+ reset();
649
+ if (typeof remove == "function") remove();
650
+ remove = void 0;
651
+ };
652
+ const ignore = state.set(done, null);
653
+ return done;
654
+ });
655
+ });
656
+ return {
657
+ value: [],
658
+ enumerable: false
659
+ };
660
+ }
661
+ const hasParent = PARENT.get(subject);
662
+ function assign(value) {
663
+ if (typeof arg1 === "function") {
664
+ const result = arg1(value, subject);
665
+ if (typeof result === "function") subject.set(result, null);
666
+ }
667
+ update(subject, key, value);
668
+ }
669
+ if (hasParent && hasParent instanceof Type) {
670
+ assign(hasParent);
671
+ return {};
672
+ }
673
+ Context.get(subject, (context) => {
674
+ const self = context.get(Type);
675
+ if (self) assign(self);
676
+ else if (!isOptional) throw new Error(`Required ${Type} not found in context for ${subject}.`);
677
+ });
678
+ return {
679
+ get: !isOptional,
680
+ enumerable: false
681
+ };
682
+ });
836
683
  }
837
684
 
838
- // src/instruction/set.ts
685
+ //#endregion
686
+ //#region src/instruction/set.ts
687
+ const STALE = /* @__PURE__ */ new WeakSet();
839
688
  function set(value, argument) {
840
- return use((key2, subject) => {
841
- const property = {};
842
- if (typeof value == "function" || isThenable(value)) {
843
- let init4 = function() {
844
- if (typeof value == "function")
845
- try {
846
- value = attempt(value.bind(subject, key2));
847
- } catch (err) {
848
- console.warn(`Generating initial value for ${subject}.${key2} failed.`);
849
- throw err;
850
- }
851
- property.get = argument !== false;
852
- const set2 = (value2) => subject[key2] = value2;
853
- if (isThenable(value))
854
- value.then(set2, (error) => {
855
- event(subject, key2);
856
- property.get = () => {
857
- throw error;
858
- };
859
- });
860
- else
861
- set2(value);
862
- if (argument)
863
- return null;
864
- return subject[key2];
865
- };
866
- var init3 = init4;
867
- if (argument)
868
- addListener(subject, init4, true);
869
- else
870
- property.get = init4;
871
- } else if (value !== void 0)
872
- property.value = value;
873
- if (typeof argument == "function") {
874
- let unset;
875
- property.set = function(value2, previous) {
876
- const exit = enter();
877
- const returns = argument.call(this, value2, previous);
878
- const flush = exit();
879
- if (returns === false)
880
- return false;
881
- if (typeof unset == "function")
882
- unset(value2);
883
- unset = (next) => {
884
- if (typeof returns == "function")
885
- returns(next);
886
- flush();
887
- };
888
- };
889
- } else
890
- property.set = (value2) => {
891
- property.get = void 0;
892
- update(subject, key2, value2);
893
- };
894
- return property;
895
- });
689
+ return use((key, subject, state) => {
690
+ if (typeof value == "symbol") throw new Error(`Attempted to use an instruction result (probably use or get) as computed source for ${subject}.${key}. This is not allowed.`);
691
+ const property = {};
692
+ if (value instanceof State || value === true) {
693
+ let from = subject;
694
+ let getter;
695
+ if (value instanceof State) {
696
+ from = value;
697
+ getter = argument;
698
+ } else {
699
+ const fn = METHOD.get(argument) || argument;
700
+ getter = ((p, k) => fn.call(p, k, p));
701
+ }
702
+ const source = (resolve) => resolve(from);
703
+ let reset;
704
+ let isAsync;
705
+ let proxy;
706
+ function connect(self) {
707
+ reset = watch(self, (current) => {
708
+ proxy = current;
709
+ if (!(key in state) || STALE.delete(compute)) compute(!reset);
710
+ return (didUpdate) => {
711
+ if (didUpdate) {
712
+ STALE.add(compute);
713
+ event(subject, key, true);
714
+ }
715
+ };
716
+ }, false);
717
+ }
718
+ function compute(initial) {
719
+ let next;
720
+ try {
721
+ next = getter.call(proxy, proxy, key);
722
+ } catch (err) {
723
+ console.warn(`An exception was thrown while ${initial ? "initializing" : "refreshing"} ${subject}.${key}.`);
724
+ if (initial) throw err;
725
+ console.error(err);
726
+ }
727
+ update(subject, key, next, !isAsync);
728
+ }
729
+ return () => {
730
+ if (!proxy) {
731
+ source(connect);
732
+ isAsync = true;
733
+ }
734
+ if (STALE.delete(compute)) compute();
735
+ return access(subject, key, !proxy);
736
+ };
737
+ }
738
+ if (typeof value == "function" || value instanceof Promise) {
739
+ function init() {
740
+ if (typeof value == "function") try {
741
+ value = attempt(value.bind(subject, key));
742
+ } catch (err) {
743
+ console.warn(`Generating initial value for ${subject}.${key} failed.`);
744
+ throw err;
745
+ }
746
+ property.get = argument !== false;
747
+ const set = (value) => subject[key] = value;
748
+ if (value instanceof Promise) value.then(set, (error) => {
749
+ event(subject, key);
750
+ property.get = () => {
751
+ throw error;
752
+ };
753
+ });
754
+ else set(value);
755
+ if (argument) return null;
756
+ return subject[key];
757
+ }
758
+ if (argument) addListener(subject, init, true);
759
+ else property.get = init;
760
+ } else if (value !== void 0) property.value = value;
761
+ if (typeof argument == "function") {
762
+ let unset;
763
+ property.set = function(value, previous) {
764
+ const exit = scope();
765
+ const returns = argument.call(this, value, previous);
766
+ const flush = exit();
767
+ if (returns === false) return false;
768
+ if (typeof unset == "function") unset(value);
769
+ unset = (next) => {
770
+ if (typeof returns == "function") returns(next);
771
+ flush();
772
+ };
773
+ };
774
+ } else property.set = (value) => {
775
+ property.get = void 0;
776
+ update(subject, key, value);
777
+ };
778
+ return property;
779
+ });
896
780
  }
897
781
  function attempt(fn) {
898
- function retry(err) {
899
- if (err instanceof Promise)
900
- return err.then(compute);
901
- else
902
- throw err;
903
- }
904
- function compute() {
905
- try {
906
- const output = fn();
907
- return output instanceof Promise ? output.catch(retry) : output;
908
- } catch (err) {
909
- return retry(err);
910
- }
911
- }
912
- return compute();
913
- }
914
- function isThenable(value) {
915
- return value && typeof value == "object" && typeof value.then == "function";
782
+ function retry(err) {
783
+ if (err instanceof Promise) return err.then(compute);
784
+ else throw err;
785
+ }
786
+ function compute() {
787
+ try {
788
+ const output = fn();
789
+ return output instanceof Promise ? output.catch(retry) : output;
790
+ } catch (err) {
791
+ return retry(err);
792
+ }
793
+ }
794
+ return compute();
916
795
  }
917
796
 
918
- // src/instruction/has.ts
919
- var APPLY = /* @__PURE__ */ new WeakMap();
920
- function has(arg1, arg2) {
921
- return use((key2, subject) => {
922
- const applied = /* @__PURE__ */ new Set();
923
- const reset = () => {
924
- update(subject, key2, Object.freeze(Array.from(applied)));
925
- };
926
- if (Model.is(arg1))
927
- Context.get(subject, (ctx) => {
928
- ctx.has(arg1, (model) => {
929
- let remove;
930
- let disconnect;
931
- let flush;
932
- if (applied.has(model))
933
- return;
934
- const exit = enter();
935
- try {
936
- const notify = APPLY.get(model);
937
- if (notify) {
938
- const after = notify(subject);
939
- if (after === false)
940
- return;
941
- if (typeof after == "function")
942
- disconnect = after;
943
- }
944
- if (typeof arg2 == "function") {
945
- const done2 = arg2(model, subject);
946
- if (done2 === false)
947
- return false;
948
- if (typeof done2 == "function")
949
- remove = done2;
950
- }
951
- } finally {
952
- flush = exit();
953
- }
954
- applied.add(model);
955
- reset();
956
- const done = () => {
957
- flush();
958
- ignore();
959
- applied.delete(model);
960
- reset();
961
- if (disconnect)
962
- disconnect();
963
- if (typeof remove == "function")
964
- remove();
965
- remove = void 0;
966
- };
967
- const ignore = model.set(done, null);
968
- return done;
969
- });
970
- });
971
- else {
972
- if (APPLY.has(subject))
973
- throw new Error(`'has' callback can only be used once per model.`);
974
- APPLY.set(subject, (recipient) => {
975
- let remove;
976
- if (arg1) {
977
- remove = arg1(recipient, subject);
978
- if (remove === false)
979
- return false;
980
- }
981
- applied.add(recipient);
982
- reset();
983
- return () => {
984
- applied.delete(recipient);
985
- reset();
986
- if (typeof remove == "function")
987
- remove();
988
- };
989
- });
990
- }
991
- return {
992
- value: [],
993
- enumerable: false
994
- };
995
- });
797
+ //#endregion
798
+ //#region src/instruction/ref.ts
799
+ const { defineProperty, defineProperties } = Object;
800
+ function ref(arg, arg2) {
801
+ return use((key, subject, state) => {
802
+ let value = {};
803
+ const method = (key, from) => (callback) => callback ? addListener(subject, () => callback(from[key]), key) : from[key];
804
+ if (arg === subject) addListener(subject, () => {
805
+ for (const key in subject) if (typeof arg2 == "function") defineProperty(value, key, {
806
+ configurable: true,
807
+ get() {
808
+ const out = arg2(key);
809
+ defineProperty(value, key, { value: out });
810
+ return out;
811
+ }
812
+ });
813
+ else {
814
+ const get = method(key, subject);
815
+ const set = (x) => subject[key] = x;
816
+ defineProperties(set, {
817
+ current: {
818
+ get,
819
+ set
820
+ },
821
+ get: { value: get },
822
+ is: { value: subject },
823
+ key: { value: key }
824
+ });
825
+ defineProperty(value, key, { value: set });
826
+ }
827
+ return null;
828
+ }, true);
829
+ else if (typeof arg == "object") throw new Error("ref instruction does not support object which is not 'this'");
830
+ else {
831
+ let unset;
832
+ const get = method(key, state);
833
+ const set = (value) => {
834
+ if (!update(subject, key, value) || !arg) return;
835
+ if (unset) unset = void unset(value);
836
+ if (value === null && arg2 !== false) return;
837
+ const exit = scope();
838
+ const out = arg.call(subject, value);
839
+ const flush = exit();
840
+ unset = (key) => {
841
+ if (typeof out == "function") out(key);
842
+ flush();
843
+ };
844
+ };
845
+ state[key] = null;
846
+ value = defineProperty({
847
+ get,
848
+ key,
849
+ is: subject
850
+ }, "current", {
851
+ get,
852
+ set
853
+ });
854
+ }
855
+ defineProperty(subject, key, { value });
856
+ });
996
857
  }
997
- // Annotate the CommonJS export names for ESM import in node:
998
- 0 && (module.exports = {
999
- Context,
1000
- METHOD,
1001
- Model,
1002
- Observable,
1003
- addListener,
1004
- createEffect,
1005
- event,
1006
- get,
1007
- has,
1008
- ref,
1009
- set,
1010
- use
1011
- });
858
+
859
+ //#endregion
860
+ exports.Context = Context;
861
+ exports.METHOD = METHOD;
862
+ exports.Observable = Observable;
863
+ exports.State = State;
864
+ exports.addListener = addListener;
865
+ exports.default = State;
866
+ exports.event = event;
867
+ exports.get = get;
868
+ exports.ref = ref;
869
+ exports.set = set;
870
+ exports.use = use;
871
+ exports.watch = watch;
1012
872
  //# sourceMappingURL=index.js.map