@expressive/mvc 0.52.1 → 0.52.2-alpha.74
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 +57 -36
- package/dist/index.js +118 -97
- package/dist/index.mjs +115 -96
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -133,29 +133,17 @@ declare abstract class Model {
|
|
|
133
133
|
/**
|
|
134
134
|
* Get update in progress.
|
|
135
135
|
*
|
|
136
|
-
* @returns Promise which resolves object with updated values
|
|
136
|
+
* @returns Promise which resolves object with updated values, `undefined` if there no update is pending.
|
|
137
137
|
**/
|
|
138
138
|
set(): PromiseLike<Model.Event<this>[]> | undefined;
|
|
139
139
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* Given function is called for every assignment (which changes value) or explicit `set`.
|
|
143
|
-
*
|
|
144
|
-
* To run logic on final value only, callback may return a function. Using the same
|
|
145
|
-
* function for one or more events will ensure it is called only when events are settled.
|
|
146
|
-
*
|
|
147
|
-
* @param callback - Function to call when update occurs.
|
|
148
|
-
* @returns Function to remove listener. Will return `true` if removed, `false` if inactive already.
|
|
149
|
-
*
|
|
150
|
-
*/
|
|
151
|
-
set(callback: Model.OnEvent<this>): () => boolean;
|
|
152
|
-
/**
|
|
153
|
-
* Declare an end to updates. This event is final and will freeze state.
|
|
154
|
-
* This event can be watched for as well, to run cleanup logic and internally will remove all listeners.
|
|
140
|
+
* Update mulitple properties at once. Merges argument with current state.
|
|
141
|
+
* Properties which are not managed by this model will be ignored.
|
|
155
142
|
*
|
|
156
|
-
* @param
|
|
143
|
+
* @param assign - Object with properties to update.
|
|
144
|
+
* @returns Promise resolving an array of keys updated, `undefined` (immediately) if a noop.
|
|
157
145
|
*/
|
|
158
|
-
set(
|
|
146
|
+
set(assign: Model.Assign<this>): PromiseLike<Model.Event<this>[]> | undefined;
|
|
159
147
|
/**
|
|
160
148
|
* Push an update. This will not change the value of associated property.
|
|
161
149
|
*
|
|
@@ -171,14 +159,6 @@ declare abstract class Model {
|
|
|
171
159
|
* @returns Promise resolves an array of keys updated.
|
|
172
160
|
*/
|
|
173
161
|
set(key: Model.Event<this>): PromiseLike<Model.Event<this>[]>;
|
|
174
|
-
/**
|
|
175
|
-
* Update mulitple properties at once. Merges argument with current state.
|
|
176
|
-
* Properties which are not managed by this model will be ignored.
|
|
177
|
-
*
|
|
178
|
-
* @param assign - Object with properties to update.
|
|
179
|
-
* @returns Promise resolving an array of keys updated, `undefined` (immediately) if a noop.
|
|
180
|
-
*/
|
|
181
|
-
set(assign: Model.Assign<this>): PromiseLike<Model.Event<this>[]> | undefined;
|
|
182
162
|
/**
|
|
183
163
|
* Update a property with value.
|
|
184
164
|
*
|
|
@@ -188,6 +168,26 @@ declare abstract class Model {
|
|
|
188
168
|
* @returns Promise resolving an array of keys updated, `undefined` (immediately) if a noop.
|
|
189
169
|
*/
|
|
190
170
|
set<K extends string>(key: K, value: Model.Value<this, K>, silent?: boolean): PromiseLike<Model.Event<this>[]> | undefined;
|
|
171
|
+
/**
|
|
172
|
+
* Call a function when update occurs.
|
|
173
|
+
*
|
|
174
|
+
* Given function is called for every assignment (which changes value) or explicit `set`.
|
|
175
|
+
*
|
|
176
|
+
* To run logic on final value only, callback may return a function. Using the same
|
|
177
|
+
* function for one or more events will ensure it is called only when events are settled.
|
|
178
|
+
*
|
|
179
|
+
* @param callback - Function to call when update occurs.
|
|
180
|
+
* @returns Function to remove listener. Will return `true` if removed, `false` if inactive already.
|
|
181
|
+
*
|
|
182
|
+
*/
|
|
183
|
+
set(callback: Model.OnEvent<this>): () => boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Declare an end to updates. This event is final and will freeze state.
|
|
186
|
+
* This event can be watched for as well, to run cleanup logic and internally will remove all listeners.
|
|
187
|
+
*
|
|
188
|
+
* @param status - `null` to end updates.
|
|
189
|
+
*/
|
|
190
|
+
set(status: null): void;
|
|
191
191
|
/**
|
|
192
192
|
* Iterate over managed properties in this instance of Model.
|
|
193
193
|
* Yeilds the key and underlying value for each property.
|
|
@@ -326,10 +326,10 @@ declare namespace set {
|
|
|
326
326
|
type Factory<T, S = any> = (this: S, key: string) => Promise<T> | T;
|
|
327
327
|
}
|
|
328
328
|
/**
|
|
329
|
-
* Set property
|
|
329
|
+
* Set property as `undefined` but required.
|
|
330
330
|
*
|
|
331
331
|
* Property cannot be accessed until it is defined. If accessed while undefined, a hybrid
|
|
332
|
-
* `Promise`/`Error` (
|
|
332
|
+
* `Promise`/`Error` (aka: [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html)) will be thrown.
|
|
333
333
|
*/
|
|
334
334
|
declare function set<T = any>(): T;
|
|
335
335
|
/**
|
|
@@ -367,6 +367,21 @@ declare namespace has {
|
|
|
367
367
|
declare function has<T extends Model>(type: Model.Type<T>, callback?: has.Callback<T>): readonly T[];
|
|
368
368
|
declare function has(callback?: has.Callback): readonly Model[];
|
|
369
369
|
|
|
370
|
+
/**
|
|
371
|
+
* Update callback function.
|
|
372
|
+
*
|
|
373
|
+
* @param key -
|
|
374
|
+
* - `string` - property which has updated.
|
|
375
|
+
* - `false` - a normal update has completed.
|
|
376
|
+
* - `true` - initial event; instance is ready.
|
|
377
|
+
* - `null` - terminal event; instance is expired.
|
|
378
|
+
* @param source - Instance of Model for which update has occured.
|
|
379
|
+
*/
|
|
380
|
+
type OnUpdate<T = any> = (this: T, key: unknown, source: T) => (() => void) | null | void;
|
|
381
|
+
type OnAccess<T, R = unknown> = (from: T, key: string | number, value: R) => unknown;
|
|
382
|
+
type Event = number | string | null | boolean | symbol;
|
|
383
|
+
declare function addListener(subject: {}, callback: OnUpdate, select?: Event): () => boolean;
|
|
384
|
+
declare function createProxy<T extends {}>(from: T, observer: OnAccess<T>): any;
|
|
370
385
|
type Effect<T extends {}> = (this: T, argument: T) => ((update: boolean | null) => void) | Promise<void> | null | void;
|
|
371
386
|
/**
|
|
372
387
|
* Create a side-effect which will update whenever values accessed change.
|
|
@@ -376,11 +391,15 @@ type Effect<T extends {}> = (this: T, argument: T) => ((update: boolean | null)
|
|
|
376
391
|
* @param callback - Function to invoke when values change.
|
|
377
392
|
* @param requireValues - If `true` will throw if accessing a value which is `undefined`.
|
|
378
393
|
*/
|
|
379
|
-
declare function
|
|
380
|
-
declare function
|
|
394
|
+
declare function createEffect<T extends {}>(target: T, callback: Effect<Required<T>>, requireValues: true): () => void;
|
|
395
|
+
declare function createEffect<T extends {}>(target: T, callback: Effect<T>, requireValues?: boolean): () => void;
|
|
381
396
|
|
|
382
397
|
declare namespace Context {
|
|
383
|
-
type
|
|
398
|
+
type Multiple<T extends Model> = {
|
|
399
|
+
[key: string | number]: Model.Init<T> | T;
|
|
400
|
+
};
|
|
401
|
+
type Accept<T extends Model = Model> = T | Model.Init<T> | Multiple<T>;
|
|
402
|
+
type ForEach = (added: Model, explicit: boolean) => void;
|
|
384
403
|
type Expect = (model: Model) => (() => void) | void;
|
|
385
404
|
}
|
|
386
405
|
interface Context {
|
|
@@ -392,13 +411,15 @@ declare class Context {
|
|
|
392
411
|
id: string;
|
|
393
412
|
protected layer: Map<string | number, Model | Model.Type<Model>>;
|
|
394
413
|
protected cleanup: Set<() => void>;
|
|
395
|
-
constructor(inputs?: Context.
|
|
414
|
+
constructor(inputs?: Context.Accept);
|
|
415
|
+
/** Run callback when a specified type is registered to a **child** context. */
|
|
416
|
+
has<T extends Model>(Type: Model.Type<T>, callback: (model: T) => void): void;
|
|
417
|
+
/** Find specified type registered to a parent context. Returns undefined if none are found. */
|
|
396
418
|
get<T extends Model>(Type: Model.Type<T>): T | undefined;
|
|
397
|
-
|
|
398
|
-
push(inputs?: Context.Input): this;
|
|
419
|
+
push(inputs?: Context.Accept): this;
|
|
399
420
|
pop(): void;
|
|
400
|
-
include(inputs: Context.
|
|
421
|
+
include<T extends Model>(inputs: Context.Accept<T>, forEach?: Context.ForEach | Model.Assign<T>): void;
|
|
401
422
|
protected add<T extends Model>(input: T | Model.Init<T>, implicit?: boolean): T;
|
|
402
423
|
}
|
|
403
424
|
|
|
404
|
-
export { Context, Model, Model as default,
|
|
425
|
+
export { Context, Model, addListener, createEffect, createProxy, Model as default, get, has, ref, set, use };
|
package/dist/index.js
CHANGED
|
@@ -22,8 +22,10 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
Context: () => Context,
|
|
24
24
|
Model: () => Model,
|
|
25
|
+
addListener: () => addListener,
|
|
26
|
+
createEffect: () => createEffect,
|
|
27
|
+
createProxy: () => createProxy,
|
|
25
28
|
default: () => Model,
|
|
26
|
-
effect: () => effect,
|
|
27
29
|
get: () => get,
|
|
28
30
|
has: () => has,
|
|
29
31
|
ref: () => ref,
|
|
@@ -35,25 +37,30 @@ module.exports = __toCommonJS(src_exports);
|
|
|
35
37
|
// src/control.ts
|
|
36
38
|
var DISPATCH = /* @__PURE__ */ new Set();
|
|
37
39
|
var OBSERVER = /* @__PURE__ */ new WeakMap();
|
|
38
|
-
var
|
|
40
|
+
var LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
41
|
+
var PENDING = /* @__PURE__ */ new WeakMap();
|
|
39
42
|
var onReady = () => null;
|
|
40
43
|
function addListener(subject, callback, select) {
|
|
41
|
-
let subs =
|
|
44
|
+
let subs = LISTENERS.get(subject);
|
|
42
45
|
if (!subs)
|
|
43
|
-
|
|
44
|
-
const filter = select
|
|
46
|
+
LISTENERS.set(subject, subs = /* @__PURE__ */ new Map([[onReady, void 0]]));
|
|
47
|
+
const filter = select === void 0 ? void 0 : /* @__PURE__ */ new Set([select]);
|
|
45
48
|
if (!subs.has(onReady) && !filter)
|
|
46
49
|
callback(true, subject);
|
|
47
50
|
subs.set(callback, filter);
|
|
48
51
|
return () => subs.delete(callback);
|
|
49
52
|
}
|
|
53
|
+
function createProxy(from, observer) {
|
|
54
|
+
const proxy = Object.create(from);
|
|
55
|
+
OBSERVER.set(proxy, observer);
|
|
56
|
+
return proxy;
|
|
57
|
+
}
|
|
50
58
|
function watch(from, key2, value) {
|
|
51
59
|
const access = OBSERVER.get(from);
|
|
52
60
|
return access ? access(from, key2, value) : value;
|
|
53
61
|
}
|
|
54
|
-
var PENDING = /* @__PURE__ */ new WeakMap();
|
|
55
62
|
function emit(source, key2) {
|
|
56
|
-
const subs =
|
|
63
|
+
const subs = LISTENERS.get(source);
|
|
57
64
|
const ready = !subs.has(onReady);
|
|
58
65
|
if (key2 === true && ready)
|
|
59
66
|
return;
|
|
@@ -79,27 +86,28 @@ function emit(source, key2) {
|
|
|
79
86
|
});
|
|
80
87
|
PENDING.delete(source);
|
|
81
88
|
}
|
|
82
|
-
function queue(
|
|
89
|
+
function queue(eventHandler) {
|
|
83
90
|
if (!DISPATCH.size)
|
|
84
91
|
setTimeout(() => {
|
|
85
|
-
DISPATCH.forEach((
|
|
92
|
+
DISPATCH.forEach((event2) => {
|
|
86
93
|
try {
|
|
87
|
-
|
|
94
|
+
event2();
|
|
88
95
|
} catch (err) {
|
|
89
96
|
console.error(err);
|
|
90
97
|
}
|
|
91
98
|
});
|
|
92
99
|
DISPATCH.clear();
|
|
93
100
|
}, 0);
|
|
94
|
-
DISPATCH.add(
|
|
101
|
+
DISPATCH.add(eventHandler);
|
|
95
102
|
}
|
|
96
|
-
function
|
|
97
|
-
const listeners =
|
|
103
|
+
function createEffect(target, callback, requireValues) {
|
|
104
|
+
const listeners = LISTENERS.get(target);
|
|
98
105
|
let unset;
|
|
99
106
|
let reset;
|
|
100
107
|
function invoke() {
|
|
101
108
|
let stale;
|
|
102
|
-
const subscriber =
|
|
109
|
+
const subscriber = createProxy(target, access);
|
|
110
|
+
LISTENERS.set(subscriber, listeners);
|
|
103
111
|
function onUpdate() {
|
|
104
112
|
if (stale)
|
|
105
113
|
return null;
|
|
@@ -113,20 +121,19 @@ function effect(target, callback, requireValues) {
|
|
|
113
121
|
function access(from, key2, value) {
|
|
114
122
|
if (value === void 0 && requireValues)
|
|
115
123
|
throw new Error(`${from}.${key2} is required in this context.`);
|
|
116
|
-
const listeners2 =
|
|
124
|
+
const listeners2 = LISTENERS.get(from);
|
|
117
125
|
let listener = listeners2.get(onUpdate);
|
|
118
126
|
if (!listener)
|
|
119
127
|
listeners2.set(onUpdate, listener = /* @__PURE__ */ new Set());
|
|
120
128
|
listener.add(key2);
|
|
121
|
-
const nested =
|
|
122
|
-
if (nested)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
const nested = LISTENERS.get(value);
|
|
130
|
+
if (nested)
|
|
131
|
+
LISTENERS.set(
|
|
132
|
+
value = createProxy(value, access),
|
|
133
|
+
nested
|
|
134
|
+
);
|
|
126
135
|
return value;
|
|
127
136
|
}
|
|
128
|
-
LISTENER.set(subscriber, listeners);
|
|
129
|
-
OBSERVER.set(subscriber, access);
|
|
130
137
|
try {
|
|
131
138
|
const out = callback.call(subscriber, subscriber);
|
|
132
139
|
unset = typeof out == "function" ? out : void 0;
|
|
@@ -163,27 +170,24 @@ var PENDING2 = /* @__PURE__ */ new WeakMap();
|
|
|
163
170
|
var PARENT = /* @__PURE__ */ new WeakMap();
|
|
164
171
|
var METHODS = /* @__PURE__ */ new WeakMap();
|
|
165
172
|
var METHOD = /* @__PURE__ */ new WeakMap();
|
|
166
|
-
var
|
|
167
|
-
var Model = class _Model {
|
|
173
|
+
var Model = class {
|
|
168
174
|
constructor(...args) {
|
|
169
|
-
define(this, "is", { value: this });
|
|
170
|
-
ID.set(this, `${this.constructor}-${uid()}`);
|
|
171
|
-
STATE.set(this, {});
|
|
172
175
|
prepare(this);
|
|
176
|
+
define(this, "is", { value: this });
|
|
173
177
|
init(this, args);
|
|
174
178
|
}
|
|
175
179
|
get(arg1, arg2) {
|
|
176
180
|
const self = this.is;
|
|
177
181
|
if (arg1 === void 0)
|
|
178
|
-
return
|
|
182
|
+
return snapshot(self);
|
|
179
183
|
if (typeof arg1 == "function") {
|
|
180
184
|
let pending = /* @__PURE__ */ new Set();
|
|
181
|
-
return
|
|
185
|
+
return createEffect(self, (state) => {
|
|
182
186
|
const cb = arg1.call(state, state, pending);
|
|
183
187
|
return cb === null ? cb : (update2) => {
|
|
184
188
|
pending = PENDING2.get(self);
|
|
185
189
|
if (typeof cb == "function")
|
|
186
|
-
|
|
190
|
+
cb(update2);
|
|
187
191
|
};
|
|
188
192
|
});
|
|
189
193
|
}
|
|
@@ -245,7 +249,6 @@ var Model = class _Model {
|
|
|
245
249
|
* @param args - arguments sent to constructor
|
|
246
250
|
*/
|
|
247
251
|
static new(...args) {
|
|
248
|
-
_Model.is(this);
|
|
249
252
|
const instance = new this(...args);
|
|
250
253
|
emit(instance, true);
|
|
251
254
|
return instance;
|
|
@@ -257,9 +260,7 @@ var Model = class _Model {
|
|
|
257
260
|
* methods and properties of this class.
|
|
258
261
|
*/
|
|
259
262
|
static is(maybe) {
|
|
260
|
-
|
|
261
|
-
throw new Error("Model is abstract and not a valid type.");
|
|
262
|
-
return typeof maybe == "function" && maybe.prototype instanceof this;
|
|
263
|
+
return maybe === this || typeof maybe == "function" && maybe.prototype instanceof this;
|
|
263
264
|
}
|
|
264
265
|
/**
|
|
265
266
|
* Register a callback to run when any instance of this Model is updated.
|
|
@@ -283,48 +284,50 @@ define(Model, "toString", {
|
|
|
283
284
|
}
|
|
284
285
|
});
|
|
285
286
|
function prepare(model) {
|
|
287
|
+
let T = model.constructor;
|
|
288
|
+
if (T === Model)
|
|
289
|
+
throw new Error("Cannot create base Model.");
|
|
286
290
|
const chain = [];
|
|
287
|
-
let type = model.constructor;
|
|
288
291
|
let keys2 = /* @__PURE__ */ new Set();
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
for (const type2 of chain) {
|
|
294
|
-
for (const cb of NOTIFY.get(type2) || [])
|
|
292
|
+
ID.set(model, `${T}-${uid()}`);
|
|
293
|
+
while (T.name) {
|
|
294
|
+
for (const cb of NOTIFY.get(T) || [])
|
|
295
295
|
addListener(model, cb);
|
|
296
|
-
if (
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
296
|
+
if (T === Model)
|
|
297
|
+
break;
|
|
298
|
+
else
|
|
299
|
+
chain.unshift(T);
|
|
300
|
+
T = Object.getPrototypeOf(T);
|
|
301
|
+
}
|
|
302
|
+
for (const type of chain) {
|
|
303
|
+
if (METHODS.has(type)) {
|
|
304
|
+
keys2 = METHODS.get(type);
|
|
300
305
|
continue;
|
|
301
306
|
}
|
|
302
|
-
METHODS.set(
|
|
307
|
+
METHODS.set(type, keys2 = new Set(keys2));
|
|
303
308
|
for (const [key2, { value }] of Object.entries(
|
|
304
|
-
Object.getOwnPropertyDescriptors(
|
|
309
|
+
Object.getOwnPropertyDescriptors(type.prototype)
|
|
305
310
|
)) {
|
|
306
|
-
let
|
|
311
|
+
let get3 = function() {
|
|
312
|
+
return this.hasOwnProperty(key2) ? value : set3.call(this, value);
|
|
313
|
+
}, set3 = function(method) {
|
|
307
314
|
const value2 = method.bind(this.is);
|
|
308
315
|
METHOD.set(value2, method);
|
|
309
316
|
define(this.is, key2, { value: value2, writable: true });
|
|
310
317
|
return value2;
|
|
311
318
|
};
|
|
312
|
-
var set2 = set3;
|
|
319
|
+
var get2 = get3, set2 = set3;
|
|
313
320
|
if (!value || key2 == "constructor")
|
|
314
321
|
continue;
|
|
315
322
|
keys2.add(key2);
|
|
316
|
-
|
|
317
|
-
set: set3,
|
|
318
|
-
get() {
|
|
319
|
-
return this.hasOwnProperty(key2) ? value : set3.call(this, value);
|
|
320
|
-
}
|
|
321
|
-
});
|
|
323
|
+
define(type.prototype, key2, { get: get3, set: set3 });
|
|
322
324
|
}
|
|
323
325
|
}
|
|
324
326
|
}
|
|
325
327
|
function init(model, args) {
|
|
326
|
-
const
|
|
327
|
-
const
|
|
328
|
+
const state = {};
|
|
329
|
+
const clean = /* @__PURE__ */ new Set();
|
|
330
|
+
STATE.set(model, state);
|
|
328
331
|
args = args.flat().filter((arg) => {
|
|
329
332
|
if (typeof arg != "string")
|
|
330
333
|
return true;
|
|
@@ -340,10 +343,10 @@ function init(model, args) {
|
|
|
340
343
|
console.error(`Async error in constructor for ${model}:`);
|
|
341
344
|
console.error(err);
|
|
342
345
|
});
|
|
343
|
-
else if (typeof use2 == "function")
|
|
344
|
-
done.add(use2);
|
|
345
346
|
else if (typeof use2 == "object")
|
|
346
347
|
assign(model, use2);
|
|
348
|
+
else if (typeof use2 == "function")
|
|
349
|
+
clean.add(use2);
|
|
347
350
|
});
|
|
348
351
|
for (const key2 in model) {
|
|
349
352
|
const desc = Object.getOwnPropertyDescriptor(model, key2);
|
|
@@ -361,7 +364,7 @@ function init(model, args) {
|
|
|
361
364
|
return null;
|
|
362
365
|
});
|
|
363
366
|
addListener(model, () => {
|
|
364
|
-
|
|
367
|
+
clean.forEach((x) => x());
|
|
365
368
|
for (const [_, value] of model)
|
|
366
369
|
if (value instanceof Model && PARENT.get(value) === model)
|
|
367
370
|
value.set(null);
|
|
@@ -393,19 +396,24 @@ function fetch(subject, property, required) {
|
|
|
393
396
|
stack: error.stack
|
|
394
397
|
});
|
|
395
398
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const
|
|
399
|
+
var EXPORT;
|
|
400
|
+
function snapshot(model) {
|
|
401
|
+
const values = {};
|
|
402
|
+
let isNotRecursive;
|
|
403
|
+
if (!EXPORT) {
|
|
404
|
+
isNotRecursive = true;
|
|
405
|
+
EXPORT = /* @__PURE__ */ new Map([[model, values]]);
|
|
406
|
+
}
|
|
399
407
|
for (let [key2, value] of model) {
|
|
400
408
|
if (EXPORT.has(value))
|
|
401
409
|
value = EXPORT.get(value);
|
|
402
|
-
else if (value && typeof value.get === "function")
|
|
410
|
+
else if (value && typeof value == "object" && "get" in value && typeof value.get === "function")
|
|
403
411
|
EXPORT.set(value, value = value.get());
|
|
404
|
-
|
|
412
|
+
values[key2] = value;
|
|
405
413
|
}
|
|
406
|
-
if (
|
|
414
|
+
if (isNotRecursive)
|
|
407
415
|
EXPORT = void 0;
|
|
408
|
-
return Object.freeze(
|
|
416
|
+
return Object.freeze(values);
|
|
409
417
|
}
|
|
410
418
|
function update(subject, key2, value, arg) {
|
|
411
419
|
const state = STATE.get(subject);
|
|
@@ -443,23 +451,23 @@ function event(subject, key2, silent) {
|
|
|
443
451
|
if (!silent)
|
|
444
452
|
emit(subject, key2);
|
|
445
453
|
}
|
|
446
|
-
function assign(to,
|
|
454
|
+
function assign(to, values) {
|
|
447
455
|
const methods = METHODS.get(to.constructor);
|
|
448
|
-
for (const key2 in
|
|
456
|
+
for (const key2 in values)
|
|
449
457
|
if (key2 in to || methods.has(key2))
|
|
450
|
-
to[key2] =
|
|
458
|
+
to[key2] = values[key2];
|
|
451
459
|
}
|
|
452
460
|
function uid() {
|
|
453
461
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
454
462
|
}
|
|
455
463
|
|
|
456
464
|
// src/context.ts
|
|
457
|
-
var
|
|
458
|
-
var
|
|
465
|
+
var LOOKUP = /* @__PURE__ */ new WeakMap();
|
|
466
|
+
var KEYS = /* @__PURE__ */ new Map();
|
|
459
467
|
function key(T, upstream) {
|
|
460
|
-
let K =
|
|
468
|
+
let K = KEYS.get(T);
|
|
461
469
|
if (!K)
|
|
462
|
-
|
|
470
|
+
KEYS.set(T, K = Symbol(
|
|
463
471
|
typeof T == "symbol" ? "get " + T.description : String(T)
|
|
464
472
|
));
|
|
465
473
|
return upstream ? key(K) : K;
|
|
@@ -479,7 +487,7 @@ var Context = class _Context {
|
|
|
479
487
|
this.include(inputs);
|
|
480
488
|
}
|
|
481
489
|
static get(from, callback) {
|
|
482
|
-
const waiting =
|
|
490
|
+
const waiting = LOOKUP.get(from);
|
|
483
491
|
if (waiting instanceof _Context) {
|
|
484
492
|
if (callback)
|
|
485
493
|
callback(waiting);
|
|
@@ -489,11 +497,14 @@ var Context = class _Context {
|
|
|
489
497
|
if (waiting)
|
|
490
498
|
waiting.push(callback);
|
|
491
499
|
else
|
|
492
|
-
|
|
500
|
+
LOOKUP.set(from, [callback]);
|
|
493
501
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
502
|
+
/** Run callback when a specified type is registered to a **child** context. */
|
|
503
|
+
has(Type, callback) {
|
|
504
|
+
define(this, key(Type, true), { value: callback });
|
|
505
|
+
}
|
|
506
|
+
/** Find specified type registered to a parent context. Returns undefined if none are found. */
|
|
507
|
+
get(Type) {
|
|
497
508
|
const result = this[key(Type)];
|
|
498
509
|
if (result === null)
|
|
499
510
|
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
@@ -515,9 +526,16 @@ var Context = class _Context {
|
|
|
515
526
|
}
|
|
516
527
|
include(inputs, forEach) {
|
|
517
528
|
const init2 = /* @__PURE__ */ new Map();
|
|
529
|
+
if (typeof inputs == "function" || inputs instanceof Model)
|
|
530
|
+
inputs = { 0: inputs };
|
|
518
531
|
Object.entries(inputs).forEach(([K, V]) => {
|
|
519
|
-
if (
|
|
520
|
-
|
|
532
|
+
if (Model.is(V) || V instanceof Model)
|
|
533
|
+
return;
|
|
534
|
+
if (K && K != V)
|
|
535
|
+
V = `${V} (as '${K}')`;
|
|
536
|
+
throw new Error(
|
|
537
|
+
`Context may only include instance or class \`extends Model\` but got ${V}.`
|
|
538
|
+
);
|
|
521
539
|
});
|
|
522
540
|
for (const key2 in inputs) {
|
|
523
541
|
const input = inputs[key2];
|
|
@@ -533,9 +551,11 @@ var Context = class _Context {
|
|
|
533
551
|
}
|
|
534
552
|
}
|
|
535
553
|
for (const [model, explicit] of init2) {
|
|
536
|
-
model
|
|
537
|
-
if (forEach)
|
|
554
|
+
emit(model, true);
|
|
555
|
+
if (typeof forEach == "function")
|
|
538
556
|
forEach(model, explicit);
|
|
557
|
+
else if (forEach && explicit)
|
|
558
|
+
assign(model, forEach);
|
|
539
559
|
for (const [_key, value] of model)
|
|
540
560
|
if (PARENT.get(value) === model) {
|
|
541
561
|
this.add(value, true);
|
|
@@ -566,15 +586,15 @@ var Context = class _Context {
|
|
|
566
586
|
keys(T).forEach((K) => {
|
|
567
587
|
const value = this.hasOwnProperty(K) ? null : I;
|
|
568
588
|
if (value || this[K] !== I && !implicit)
|
|
569
|
-
|
|
589
|
+
define(this, K, {
|
|
570
590
|
configurable: true,
|
|
571
591
|
value
|
|
572
592
|
});
|
|
573
593
|
});
|
|
574
|
-
const waiting =
|
|
594
|
+
const waiting = LOOKUP.get(I);
|
|
575
595
|
if (waiting instanceof Array)
|
|
576
596
|
waiting.forEach((cb) => cb(this));
|
|
577
|
-
|
|
597
|
+
LOOKUP.set(I, this);
|
|
578
598
|
return I;
|
|
579
599
|
}
|
|
580
600
|
};
|
|
@@ -622,7 +642,7 @@ Model.on((_, model) => {
|
|
|
622
642
|
const desc = typeof output == "object" ? output : { get: output };
|
|
623
643
|
if ("value" in desc)
|
|
624
644
|
state[key2] = desc.value;
|
|
625
|
-
|
|
645
|
+
define(model, key2, {
|
|
626
646
|
enumerable: desc.enumerable !== false,
|
|
627
647
|
get() {
|
|
628
648
|
return watch(
|
|
@@ -675,7 +695,7 @@ function get(arg0, arg1) {
|
|
|
675
695
|
}
|
|
676
696
|
if (typeof arg1 == "function") {
|
|
677
697
|
let connect2 = function(model) {
|
|
678
|
-
reset =
|
|
698
|
+
reset = createEffect(model, (current) => {
|
|
679
699
|
proxy = current;
|
|
680
700
|
if (!(key2 in state) || STALE.delete(compute2))
|
|
681
701
|
compute2(!reset);
|
|
@@ -719,7 +739,6 @@ function get(arg0, arg1) {
|
|
|
719
739
|
}
|
|
720
740
|
|
|
721
741
|
// src/instruction/ref.ts
|
|
722
|
-
var define2 = Object.defineProperty;
|
|
723
742
|
function ref(arg, arg2) {
|
|
724
743
|
return use((key2, subject, state) => {
|
|
725
744
|
let value = {};
|
|
@@ -727,20 +746,20 @@ function ref(arg, arg2) {
|
|
|
727
746
|
subject.get(() => {
|
|
728
747
|
for (const key3 in state)
|
|
729
748
|
if (typeof arg2 == "function")
|
|
730
|
-
|
|
749
|
+
define(value, key3, {
|
|
731
750
|
configurable: true,
|
|
732
751
|
get() {
|
|
733
752
|
const out = arg2(key3);
|
|
734
|
-
|
|
753
|
+
define(value, key3, { value: out });
|
|
735
754
|
return out;
|
|
736
755
|
}
|
|
737
756
|
});
|
|
738
757
|
else {
|
|
739
758
|
const get2 = () => state[key3];
|
|
740
759
|
const set2 = (value2) => subject.set(key3, value2);
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
760
|
+
define(set2, "current", { get: get2, set: set2 });
|
|
761
|
+
define(set2, "get", { value: get2 });
|
|
762
|
+
define(value, key3, { value: set2 });
|
|
744
763
|
}
|
|
745
764
|
});
|
|
746
765
|
else if (typeof arg == "object")
|
|
@@ -765,7 +784,7 @@ function ref(arg, arg2) {
|
|
|
765
784
|
get: { value: get2 }
|
|
766
785
|
});
|
|
767
786
|
}
|
|
768
|
-
|
|
787
|
+
define(subject, key2, { value });
|
|
769
788
|
});
|
|
770
789
|
}
|
|
771
790
|
|
|
@@ -852,7 +871,7 @@ function has(arg1, arg2) {
|
|
|
852
871
|
};
|
|
853
872
|
if (Model.is(arg1))
|
|
854
873
|
Context.get(subject, (context) => {
|
|
855
|
-
context.
|
|
874
|
+
context.has(arg1, (got) => {
|
|
856
875
|
let remove;
|
|
857
876
|
let disconnect;
|
|
858
877
|
if (applied.has(got))
|
|
@@ -916,7 +935,9 @@ function has(arg1, arg2) {
|
|
|
916
935
|
0 && (module.exports = {
|
|
917
936
|
Context,
|
|
918
937
|
Model,
|
|
919
|
-
|
|
938
|
+
addListener,
|
|
939
|
+
createEffect,
|
|
940
|
+
createProxy,
|
|
920
941
|
get,
|
|
921
942
|
has,
|
|
922
943
|
ref,
|
package/dist/index.mjs
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
// src/control.ts
|
|
2
2
|
var DISPATCH = /* @__PURE__ */ new Set();
|
|
3
3
|
var OBSERVER = /* @__PURE__ */ new WeakMap();
|
|
4
|
-
var
|
|
4
|
+
var LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
var PENDING = /* @__PURE__ */ new WeakMap();
|
|
5
6
|
var onReady = () => null;
|
|
6
7
|
function addListener(subject, callback, select) {
|
|
7
|
-
let subs =
|
|
8
|
+
let subs = LISTENERS.get(subject);
|
|
8
9
|
if (!subs)
|
|
9
|
-
|
|
10
|
-
const filter = select
|
|
10
|
+
LISTENERS.set(subject, subs = /* @__PURE__ */ new Map([[onReady, void 0]]));
|
|
11
|
+
const filter = select === void 0 ? void 0 : /* @__PURE__ */ new Set([select]);
|
|
11
12
|
if (!subs.has(onReady) && !filter)
|
|
12
13
|
callback(true, subject);
|
|
13
14
|
subs.set(callback, filter);
|
|
14
15
|
return () => subs.delete(callback);
|
|
15
16
|
}
|
|
17
|
+
function createProxy(from, observer) {
|
|
18
|
+
const proxy = Object.create(from);
|
|
19
|
+
OBSERVER.set(proxy, observer);
|
|
20
|
+
return proxy;
|
|
21
|
+
}
|
|
16
22
|
function watch(from, key2, value) {
|
|
17
23
|
const access = OBSERVER.get(from);
|
|
18
24
|
return access ? access(from, key2, value) : value;
|
|
19
25
|
}
|
|
20
|
-
var PENDING = /* @__PURE__ */ new WeakMap();
|
|
21
26
|
function emit(source, key2) {
|
|
22
|
-
const subs =
|
|
27
|
+
const subs = LISTENERS.get(source);
|
|
23
28
|
const ready = !subs.has(onReady);
|
|
24
29
|
if (key2 === true && ready)
|
|
25
30
|
return;
|
|
@@ -45,27 +50,28 @@ function emit(source, key2) {
|
|
|
45
50
|
});
|
|
46
51
|
PENDING.delete(source);
|
|
47
52
|
}
|
|
48
|
-
function queue(
|
|
53
|
+
function queue(eventHandler) {
|
|
49
54
|
if (!DISPATCH.size)
|
|
50
55
|
setTimeout(() => {
|
|
51
|
-
DISPATCH.forEach((
|
|
56
|
+
DISPATCH.forEach((event2) => {
|
|
52
57
|
try {
|
|
53
|
-
|
|
58
|
+
event2();
|
|
54
59
|
} catch (err) {
|
|
55
60
|
console.error(err);
|
|
56
61
|
}
|
|
57
62
|
});
|
|
58
63
|
DISPATCH.clear();
|
|
59
64
|
}, 0);
|
|
60
|
-
DISPATCH.add(
|
|
65
|
+
DISPATCH.add(eventHandler);
|
|
61
66
|
}
|
|
62
|
-
function
|
|
63
|
-
const listeners =
|
|
67
|
+
function createEffect(target, callback, requireValues) {
|
|
68
|
+
const listeners = LISTENERS.get(target);
|
|
64
69
|
let unset;
|
|
65
70
|
let reset;
|
|
66
71
|
function invoke() {
|
|
67
72
|
let stale;
|
|
68
|
-
const subscriber =
|
|
73
|
+
const subscriber = createProxy(target, access);
|
|
74
|
+
LISTENERS.set(subscriber, listeners);
|
|
69
75
|
function onUpdate() {
|
|
70
76
|
if (stale)
|
|
71
77
|
return null;
|
|
@@ -79,20 +85,19 @@ function effect(target, callback, requireValues) {
|
|
|
79
85
|
function access(from, key2, value) {
|
|
80
86
|
if (value === void 0 && requireValues)
|
|
81
87
|
throw new Error(`${from}.${key2} is required in this context.`);
|
|
82
|
-
const listeners2 =
|
|
88
|
+
const listeners2 = LISTENERS.get(from);
|
|
83
89
|
let listener = listeners2.get(onUpdate);
|
|
84
90
|
if (!listener)
|
|
85
91
|
listeners2.set(onUpdate, listener = /* @__PURE__ */ new Set());
|
|
86
92
|
listener.add(key2);
|
|
87
|
-
const nested =
|
|
88
|
-
if (nested)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
const nested = LISTENERS.get(value);
|
|
94
|
+
if (nested)
|
|
95
|
+
LISTENERS.set(
|
|
96
|
+
value = createProxy(value, access),
|
|
97
|
+
nested
|
|
98
|
+
);
|
|
92
99
|
return value;
|
|
93
100
|
}
|
|
94
|
-
LISTENER.set(subscriber, listeners);
|
|
95
|
-
OBSERVER.set(subscriber, access);
|
|
96
101
|
try {
|
|
97
102
|
const out = callback.call(subscriber, subscriber);
|
|
98
103
|
unset = typeof out == "function" ? out : void 0;
|
|
@@ -129,27 +134,24 @@ var PENDING2 = /* @__PURE__ */ new WeakMap();
|
|
|
129
134
|
var PARENT = /* @__PURE__ */ new WeakMap();
|
|
130
135
|
var METHODS = /* @__PURE__ */ new WeakMap();
|
|
131
136
|
var METHOD = /* @__PURE__ */ new WeakMap();
|
|
132
|
-
var
|
|
133
|
-
var Model = class _Model {
|
|
137
|
+
var Model = class {
|
|
134
138
|
constructor(...args) {
|
|
135
|
-
define(this, "is", { value: this });
|
|
136
|
-
ID.set(this, `${this.constructor}-${uid()}`);
|
|
137
|
-
STATE.set(this, {});
|
|
138
139
|
prepare(this);
|
|
140
|
+
define(this, "is", { value: this });
|
|
139
141
|
init(this, args);
|
|
140
142
|
}
|
|
141
143
|
get(arg1, arg2) {
|
|
142
144
|
const self = this.is;
|
|
143
145
|
if (arg1 === void 0)
|
|
144
|
-
return
|
|
146
|
+
return snapshot(self);
|
|
145
147
|
if (typeof arg1 == "function") {
|
|
146
148
|
let pending = /* @__PURE__ */ new Set();
|
|
147
|
-
return
|
|
149
|
+
return createEffect(self, (state) => {
|
|
148
150
|
const cb = arg1.call(state, state, pending);
|
|
149
151
|
return cb === null ? cb : (update2) => {
|
|
150
152
|
pending = PENDING2.get(self);
|
|
151
153
|
if (typeof cb == "function")
|
|
152
|
-
|
|
154
|
+
cb(update2);
|
|
153
155
|
};
|
|
154
156
|
});
|
|
155
157
|
}
|
|
@@ -211,7 +213,6 @@ var Model = class _Model {
|
|
|
211
213
|
* @param args - arguments sent to constructor
|
|
212
214
|
*/
|
|
213
215
|
static new(...args) {
|
|
214
|
-
_Model.is(this);
|
|
215
216
|
const instance = new this(...args);
|
|
216
217
|
emit(instance, true);
|
|
217
218
|
return instance;
|
|
@@ -223,9 +224,7 @@ var Model = class _Model {
|
|
|
223
224
|
* methods and properties of this class.
|
|
224
225
|
*/
|
|
225
226
|
static is(maybe) {
|
|
226
|
-
|
|
227
|
-
throw new Error("Model is abstract and not a valid type.");
|
|
228
|
-
return typeof maybe == "function" && maybe.prototype instanceof this;
|
|
227
|
+
return maybe === this || typeof maybe == "function" && maybe.prototype instanceof this;
|
|
229
228
|
}
|
|
230
229
|
/**
|
|
231
230
|
* Register a callback to run when any instance of this Model is updated.
|
|
@@ -249,48 +248,50 @@ define(Model, "toString", {
|
|
|
249
248
|
}
|
|
250
249
|
});
|
|
251
250
|
function prepare(model) {
|
|
251
|
+
let T = model.constructor;
|
|
252
|
+
if (T === Model)
|
|
253
|
+
throw new Error("Cannot create base Model.");
|
|
252
254
|
const chain = [];
|
|
253
|
-
let type = model.constructor;
|
|
254
255
|
let keys2 = /* @__PURE__ */ new Set();
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
for (const type2 of chain) {
|
|
260
|
-
for (const cb of NOTIFY.get(type2) || [])
|
|
256
|
+
ID.set(model, `${T}-${uid()}`);
|
|
257
|
+
while (T.name) {
|
|
258
|
+
for (const cb of NOTIFY.get(T) || [])
|
|
261
259
|
addListener(model, cb);
|
|
262
|
-
if (
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
260
|
+
if (T === Model)
|
|
261
|
+
break;
|
|
262
|
+
else
|
|
263
|
+
chain.unshift(T);
|
|
264
|
+
T = Object.getPrototypeOf(T);
|
|
265
|
+
}
|
|
266
|
+
for (const type of chain) {
|
|
267
|
+
if (METHODS.has(type)) {
|
|
268
|
+
keys2 = METHODS.get(type);
|
|
266
269
|
continue;
|
|
267
270
|
}
|
|
268
|
-
METHODS.set(
|
|
271
|
+
METHODS.set(type, keys2 = new Set(keys2));
|
|
269
272
|
for (const [key2, { value }] of Object.entries(
|
|
270
|
-
Object.getOwnPropertyDescriptors(
|
|
273
|
+
Object.getOwnPropertyDescriptors(type.prototype)
|
|
271
274
|
)) {
|
|
272
|
-
let
|
|
275
|
+
let get3 = function() {
|
|
276
|
+
return this.hasOwnProperty(key2) ? value : set3.call(this, value);
|
|
277
|
+
}, set3 = function(method) {
|
|
273
278
|
const value2 = method.bind(this.is);
|
|
274
279
|
METHOD.set(value2, method);
|
|
275
280
|
define(this.is, key2, { value: value2, writable: true });
|
|
276
281
|
return value2;
|
|
277
282
|
};
|
|
278
|
-
var set2 = set3;
|
|
283
|
+
var get2 = get3, set2 = set3;
|
|
279
284
|
if (!value || key2 == "constructor")
|
|
280
285
|
continue;
|
|
281
286
|
keys2.add(key2);
|
|
282
|
-
|
|
283
|
-
set: set3,
|
|
284
|
-
get() {
|
|
285
|
-
return this.hasOwnProperty(key2) ? value : set3.call(this, value);
|
|
286
|
-
}
|
|
287
|
-
});
|
|
287
|
+
define(type.prototype, key2, { get: get3, set: set3 });
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
function init(model, args) {
|
|
292
|
-
const
|
|
293
|
-
const
|
|
292
|
+
const state = {};
|
|
293
|
+
const clean = /* @__PURE__ */ new Set();
|
|
294
|
+
STATE.set(model, state);
|
|
294
295
|
args = args.flat().filter((arg) => {
|
|
295
296
|
if (typeof arg != "string")
|
|
296
297
|
return true;
|
|
@@ -306,10 +307,10 @@ function init(model, args) {
|
|
|
306
307
|
console.error(`Async error in constructor for ${model}:`);
|
|
307
308
|
console.error(err);
|
|
308
309
|
});
|
|
309
|
-
else if (typeof use2 == "function")
|
|
310
|
-
done.add(use2);
|
|
311
310
|
else if (typeof use2 == "object")
|
|
312
311
|
assign(model, use2);
|
|
312
|
+
else if (typeof use2 == "function")
|
|
313
|
+
clean.add(use2);
|
|
313
314
|
});
|
|
314
315
|
for (const key2 in model) {
|
|
315
316
|
const desc = Object.getOwnPropertyDescriptor(model, key2);
|
|
@@ -327,7 +328,7 @@ function init(model, args) {
|
|
|
327
328
|
return null;
|
|
328
329
|
});
|
|
329
330
|
addListener(model, () => {
|
|
330
|
-
|
|
331
|
+
clean.forEach((x) => x());
|
|
331
332
|
for (const [_, value] of model)
|
|
332
333
|
if (value instanceof Model && PARENT.get(value) === model)
|
|
333
334
|
value.set(null);
|
|
@@ -359,19 +360,24 @@ function fetch(subject, property, required) {
|
|
|
359
360
|
stack: error.stack
|
|
360
361
|
});
|
|
361
362
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const
|
|
363
|
+
var EXPORT;
|
|
364
|
+
function snapshot(model) {
|
|
365
|
+
const values = {};
|
|
366
|
+
let isNotRecursive;
|
|
367
|
+
if (!EXPORT) {
|
|
368
|
+
isNotRecursive = true;
|
|
369
|
+
EXPORT = /* @__PURE__ */ new Map([[model, values]]);
|
|
370
|
+
}
|
|
365
371
|
for (let [key2, value] of model) {
|
|
366
372
|
if (EXPORT.has(value))
|
|
367
373
|
value = EXPORT.get(value);
|
|
368
|
-
else if (value && typeof value.get === "function")
|
|
374
|
+
else if (value && typeof value == "object" && "get" in value && typeof value.get === "function")
|
|
369
375
|
EXPORT.set(value, value = value.get());
|
|
370
|
-
|
|
376
|
+
values[key2] = value;
|
|
371
377
|
}
|
|
372
|
-
if (
|
|
378
|
+
if (isNotRecursive)
|
|
373
379
|
EXPORT = void 0;
|
|
374
|
-
return Object.freeze(
|
|
380
|
+
return Object.freeze(values);
|
|
375
381
|
}
|
|
376
382
|
function update(subject, key2, value, arg) {
|
|
377
383
|
const state = STATE.get(subject);
|
|
@@ -409,23 +415,23 @@ function event(subject, key2, silent) {
|
|
|
409
415
|
if (!silent)
|
|
410
416
|
emit(subject, key2);
|
|
411
417
|
}
|
|
412
|
-
function assign(to,
|
|
418
|
+
function assign(to, values) {
|
|
413
419
|
const methods = METHODS.get(to.constructor);
|
|
414
|
-
for (const key2 in
|
|
420
|
+
for (const key2 in values)
|
|
415
421
|
if (key2 in to || methods.has(key2))
|
|
416
|
-
to[key2] =
|
|
422
|
+
to[key2] = values[key2];
|
|
417
423
|
}
|
|
418
424
|
function uid() {
|
|
419
425
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
420
426
|
}
|
|
421
427
|
|
|
422
428
|
// src/context.ts
|
|
423
|
-
var
|
|
424
|
-
var
|
|
429
|
+
var LOOKUP = /* @__PURE__ */ new WeakMap();
|
|
430
|
+
var KEYS = /* @__PURE__ */ new Map();
|
|
425
431
|
function key(T, upstream) {
|
|
426
|
-
let K =
|
|
432
|
+
let K = KEYS.get(T);
|
|
427
433
|
if (!K)
|
|
428
|
-
|
|
434
|
+
KEYS.set(T, K = Symbol(
|
|
429
435
|
typeof T == "symbol" ? "get " + T.description : String(T)
|
|
430
436
|
));
|
|
431
437
|
return upstream ? key(K) : K;
|
|
@@ -445,7 +451,7 @@ var Context = class _Context {
|
|
|
445
451
|
this.include(inputs);
|
|
446
452
|
}
|
|
447
453
|
static get(from, callback) {
|
|
448
|
-
const waiting =
|
|
454
|
+
const waiting = LOOKUP.get(from);
|
|
449
455
|
if (waiting instanceof _Context) {
|
|
450
456
|
if (callback)
|
|
451
457
|
callback(waiting);
|
|
@@ -455,11 +461,14 @@ var Context = class _Context {
|
|
|
455
461
|
if (waiting)
|
|
456
462
|
waiting.push(callback);
|
|
457
463
|
else
|
|
458
|
-
|
|
464
|
+
LOOKUP.set(from, [callback]);
|
|
459
465
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
466
|
+
/** Run callback when a specified type is registered to a **child** context. */
|
|
467
|
+
has(Type, callback) {
|
|
468
|
+
define(this, key(Type, true), { value: callback });
|
|
469
|
+
}
|
|
470
|
+
/** Find specified type registered to a parent context. Returns undefined if none are found. */
|
|
471
|
+
get(Type) {
|
|
463
472
|
const result = this[key(Type)];
|
|
464
473
|
if (result === null)
|
|
465
474
|
throw new Error(`Did find ${Type} in context, but multiple were defined.`);
|
|
@@ -481,9 +490,16 @@ var Context = class _Context {
|
|
|
481
490
|
}
|
|
482
491
|
include(inputs, forEach) {
|
|
483
492
|
const init2 = /* @__PURE__ */ new Map();
|
|
493
|
+
if (typeof inputs == "function" || inputs instanceof Model)
|
|
494
|
+
inputs = { 0: inputs };
|
|
484
495
|
Object.entries(inputs).forEach(([K, V]) => {
|
|
485
|
-
if (
|
|
486
|
-
|
|
496
|
+
if (Model.is(V) || V instanceof Model)
|
|
497
|
+
return;
|
|
498
|
+
if (K && K != V)
|
|
499
|
+
V = `${V} (as '${K}')`;
|
|
500
|
+
throw new Error(
|
|
501
|
+
`Context may only include instance or class \`extends Model\` but got ${V}.`
|
|
502
|
+
);
|
|
487
503
|
});
|
|
488
504
|
for (const key2 in inputs) {
|
|
489
505
|
const input = inputs[key2];
|
|
@@ -499,9 +515,11 @@ var Context = class _Context {
|
|
|
499
515
|
}
|
|
500
516
|
}
|
|
501
517
|
for (const [model, explicit] of init2) {
|
|
502
|
-
model
|
|
503
|
-
if (forEach)
|
|
518
|
+
emit(model, true);
|
|
519
|
+
if (typeof forEach == "function")
|
|
504
520
|
forEach(model, explicit);
|
|
521
|
+
else if (forEach && explicit)
|
|
522
|
+
assign(model, forEach);
|
|
505
523
|
for (const [_key, value] of model)
|
|
506
524
|
if (PARENT.get(value) === model) {
|
|
507
525
|
this.add(value, true);
|
|
@@ -532,15 +550,15 @@ var Context = class _Context {
|
|
|
532
550
|
keys(T).forEach((K) => {
|
|
533
551
|
const value = this.hasOwnProperty(K) ? null : I;
|
|
534
552
|
if (value || this[K] !== I && !implicit)
|
|
535
|
-
|
|
553
|
+
define(this, K, {
|
|
536
554
|
configurable: true,
|
|
537
555
|
value
|
|
538
556
|
});
|
|
539
557
|
});
|
|
540
|
-
const waiting =
|
|
558
|
+
const waiting = LOOKUP.get(I);
|
|
541
559
|
if (waiting instanceof Array)
|
|
542
560
|
waiting.forEach((cb) => cb(this));
|
|
543
|
-
|
|
561
|
+
LOOKUP.set(I, this);
|
|
544
562
|
return I;
|
|
545
563
|
}
|
|
546
564
|
};
|
|
@@ -588,7 +606,7 @@ Model.on((_, model) => {
|
|
|
588
606
|
const desc = typeof output == "object" ? output : { get: output };
|
|
589
607
|
if ("value" in desc)
|
|
590
608
|
state[key2] = desc.value;
|
|
591
|
-
|
|
609
|
+
define(model, key2, {
|
|
592
610
|
enumerable: desc.enumerable !== false,
|
|
593
611
|
get() {
|
|
594
612
|
return watch(
|
|
@@ -641,7 +659,7 @@ function get(arg0, arg1) {
|
|
|
641
659
|
}
|
|
642
660
|
if (typeof arg1 == "function") {
|
|
643
661
|
let connect2 = function(model) {
|
|
644
|
-
reset =
|
|
662
|
+
reset = createEffect(model, (current) => {
|
|
645
663
|
proxy = current;
|
|
646
664
|
if (!(key2 in state) || STALE.delete(compute2))
|
|
647
665
|
compute2(!reset);
|
|
@@ -685,7 +703,6 @@ function get(arg0, arg1) {
|
|
|
685
703
|
}
|
|
686
704
|
|
|
687
705
|
// src/instruction/ref.ts
|
|
688
|
-
var define2 = Object.defineProperty;
|
|
689
706
|
function ref(arg, arg2) {
|
|
690
707
|
return use((key2, subject, state) => {
|
|
691
708
|
let value = {};
|
|
@@ -693,20 +710,20 @@ function ref(arg, arg2) {
|
|
|
693
710
|
subject.get(() => {
|
|
694
711
|
for (const key3 in state)
|
|
695
712
|
if (typeof arg2 == "function")
|
|
696
|
-
|
|
713
|
+
define(value, key3, {
|
|
697
714
|
configurable: true,
|
|
698
715
|
get() {
|
|
699
716
|
const out = arg2(key3);
|
|
700
|
-
|
|
717
|
+
define(value, key3, { value: out });
|
|
701
718
|
return out;
|
|
702
719
|
}
|
|
703
720
|
});
|
|
704
721
|
else {
|
|
705
722
|
const get2 = () => state[key3];
|
|
706
723
|
const set2 = (value2) => subject.set(key3, value2);
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
724
|
+
define(set2, "current", { get: get2, set: set2 });
|
|
725
|
+
define(set2, "get", { value: get2 });
|
|
726
|
+
define(value, key3, { value: set2 });
|
|
710
727
|
}
|
|
711
728
|
});
|
|
712
729
|
else if (typeof arg == "object")
|
|
@@ -731,7 +748,7 @@ function ref(arg, arg2) {
|
|
|
731
748
|
get: { value: get2 }
|
|
732
749
|
});
|
|
733
750
|
}
|
|
734
|
-
|
|
751
|
+
define(subject, key2, { value });
|
|
735
752
|
});
|
|
736
753
|
}
|
|
737
754
|
|
|
@@ -818,7 +835,7 @@ function has(arg1, arg2) {
|
|
|
818
835
|
};
|
|
819
836
|
if (Model.is(arg1))
|
|
820
837
|
Context.get(subject, (context) => {
|
|
821
|
-
context.
|
|
838
|
+
context.has(arg1, (got) => {
|
|
822
839
|
let remove;
|
|
823
840
|
let disconnect;
|
|
824
841
|
if (applied.has(got))
|
|
@@ -881,8 +898,10 @@ function has(arg1, arg2) {
|
|
|
881
898
|
export {
|
|
882
899
|
Context,
|
|
883
900
|
Model,
|
|
901
|
+
addListener,
|
|
902
|
+
createEffect,
|
|
903
|
+
createProxy,
|
|
884
904
|
Model as default,
|
|
885
|
-
effect,
|
|
886
905
|
get,
|
|
887
906
|
has,
|
|
888
907
|
ref,
|
package/package.json
CHANGED