@expressive/mvc 0.35.5-alpha.0 → 0.35.6
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 +27 -23
- package/dist/index.js +93 -69
- package/dist/index.mjs +93 -69
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -6,21 +6,21 @@ declare namespace Model {
|
|
|
6
6
|
/** Subset of `keyof T` which are not methods or defined by base Model U. **/
|
|
7
7
|
type Field<T> = Exclude<keyof T, keyof Model>;
|
|
8
8
|
type Key<T> = Field<T> | (string & {}) | number | symbol;
|
|
9
|
-
/** Actual value stored in state. */
|
|
10
|
-
type Actual<R> = R extends Ref<infer T> ? T : R extends Model ? State<R> : R;
|
|
11
9
|
type Value<T extends Model, K extends Key<T>> = K extends keyof T ? T[K] extends Ref<infer V> ? V : T[K] : unknown;
|
|
12
10
|
type OnUpdate<T extends Model, K extends Key<T>> = (this: T, value: Value<T, K>, key: K, thisArg: K) => void;
|
|
11
|
+
/** Export/Import compatible value for a given property in a Model. */
|
|
12
|
+
type Export<R> = R extends Ref<infer T> ? T : R extends Model ? State<R> : R;
|
|
13
13
|
/**
|
|
14
14
|
* Values from current state of given controller.
|
|
15
15
|
* Differs from `Values` as values here will drill
|
|
16
16
|
* into "real" values held by exotics like ref.
|
|
17
17
|
*/
|
|
18
18
|
type State<T> = {
|
|
19
|
-
[P in Field<T>]:
|
|
19
|
+
[P in Field<T>]: Export<T[P]>;
|
|
20
20
|
};
|
|
21
21
|
/** Object comperable to data found in T. */
|
|
22
22
|
type Values<T> = {
|
|
23
|
-
[P in Field<T>]?:
|
|
23
|
+
[P in Field<T>]?: Export<T[P]>;
|
|
24
24
|
};
|
|
25
25
|
/** Exotic value, where actual value is contained within. */
|
|
26
26
|
type Ref<T = any> = {
|
|
@@ -28,7 +28,7 @@ declare namespace Model {
|
|
|
28
28
|
current: T | null;
|
|
29
29
|
};
|
|
30
30
|
/** A callback function which is subscribed to parent and updates when values change. */
|
|
31
|
-
type Effect<T> = (this: T, argument: T) => (() => void) | Promise<void> | null | void;
|
|
31
|
+
type Effect<T> = (this: T, argument: T) => ((update: boolean | null) => void) | Promise<void> | null | void;
|
|
32
32
|
type Event<T extends Model> = (this: T, key: unknown, source: T) => (() => void) | void | null;
|
|
33
33
|
namespace Instruction {
|
|
34
34
|
type Getter<T> = (source: Model) => T;
|
|
@@ -59,18 +59,18 @@ declare class Model {
|
|
|
59
59
|
get(): Model.State<this>;
|
|
60
60
|
/** Run a function which will run automatically when accessed values change. */
|
|
61
61
|
get(effect: Model.Effect<this>): () => void;
|
|
62
|
-
/** Check if model is expired. */
|
|
63
|
-
get(event: null): boolean;
|
|
64
|
-
/** Callback when model is to be destroyed. */
|
|
65
|
-
get(event: null, callback: () => void): () => void;
|
|
66
62
|
get<T extends Model.Key<this>>(key: T, required?: boolean): Model.Value<this, T>;
|
|
67
63
|
get<T extends Model.Key<this>>(key: T, callback: Model.OnUpdate<this, T>): () => void;
|
|
64
|
+
/** Check if model is expired. */
|
|
65
|
+
get(status: null): boolean;
|
|
66
|
+
/** Callback when model is to be destroyed. */
|
|
67
|
+
get(status: null, callback: () => void): () => void;
|
|
68
68
|
/**
|
|
69
69
|
* Get update in progress.
|
|
70
70
|
*
|
|
71
71
|
* @returns Promise which resolves object with updated values. Is `undefined` if there is no update.
|
|
72
72
|
**/
|
|
73
|
-
set():
|
|
73
|
+
set(): PromiseLike<Model.Key<this>[]> | undefined;
|
|
74
74
|
/**
|
|
75
75
|
* Call a function when update occurs.
|
|
76
76
|
*
|
|
@@ -84,15 +84,21 @@ declare class Model {
|
|
|
84
84
|
set(callback: Model.Event<this>): () => boolean;
|
|
85
85
|
/**
|
|
86
86
|
* Declare an end to updates. This event is final and will freeze state.
|
|
87
|
+
* This event can be watched for as well, to run cleanup logic and internally will remove all listeners.
|
|
87
88
|
*/
|
|
88
|
-
set(
|
|
89
|
+
set(status: null): void;
|
|
89
90
|
/**
|
|
90
91
|
* Push an update. This will not change the value of associated property.
|
|
91
92
|
*
|
|
92
93
|
* Useful where a property value internally has changed, but the object is the same.
|
|
93
94
|
* For example: An array has pushed a new value, or a nested property is updated.
|
|
95
|
+
*
|
|
96
|
+
* You can also use this to dispatch arbitrary events as well. Symbols are generally
|
|
97
|
+
* recommended as non-property events, however you can use any string. If doing so,
|
|
98
|
+
* be sure to avoid collisions with property names - an easy way to do this will be to
|
|
99
|
+
* prefix your event with "!" and/or use dash-case. e.g. `set("!event")` or `set("my-event")`.
|
|
94
100
|
*/
|
|
95
|
-
set(key: Model.Key<this>):
|
|
101
|
+
set(key: Model.Key<this>): PromiseLike<Model.Key<this>[]>;
|
|
96
102
|
/**
|
|
97
103
|
* Update a property with value.
|
|
98
104
|
*
|
|
@@ -100,7 +106,7 @@ declare class Model {
|
|
|
100
106
|
* @param value - value to update property with (if the same as current, no update will occur)
|
|
101
107
|
* @param silent - if true, will not notify listeners of an update
|
|
102
108
|
*/
|
|
103
|
-
set<K extends string>(key: K, value?: Model.Value<this, K>, silent?: boolean):
|
|
109
|
+
set<K extends string>(key: K, value?: Model.Value<this, K>, silent?: boolean): PromiseLike<Model.Key<this>[]> | undefined;
|
|
104
110
|
/** Iterate over managed properties in this instance of Model. */
|
|
105
111
|
[Symbol.iterator](): Iterator<[string, unknown]>;
|
|
106
112
|
/**
|
|
@@ -276,21 +282,19 @@ declare function use<T extends Model>(model: T, ready?: (i: T) => void): T;
|
|
|
276
282
|
declare function use<T extends {}, O = use.Object<T>>(data: T, ready?: (object: O) => void): O;
|
|
277
283
|
|
|
278
284
|
declare namespace Context {
|
|
279
|
-
type
|
|
280
|
-
[key: string | number]: Model | Model.New;
|
|
281
|
-
};
|
|
285
|
+
type Input = Model | Model.New<Model> | Record<string | number, Model | Model.New<Model>>;
|
|
282
286
|
}
|
|
283
287
|
declare class Context {
|
|
284
|
-
static
|
|
285
|
-
constructor(inputs?: Context.Inputs);
|
|
288
|
+
static get(from: Model, callback: (context: Context) => void): void;
|
|
286
289
|
key: string;
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
+
protected table: WeakMap<Model.Type<Model>, symbol>;
|
|
291
|
+
protected layer: Map<string | number, Model | Model.Type<Model>>;
|
|
292
|
+
constructor(inputs?: Context.Input);
|
|
293
|
+
protected has(T: Model.Type): keyof this;
|
|
290
294
|
get<T extends Model>(Type: Model.Type<T>): T | undefined;
|
|
291
|
-
include(inputs: Context.
|
|
295
|
+
include(inputs: Context.Input): Map<Model, boolean>;
|
|
292
296
|
protected add<T extends Model>(input: T | Model.New<T>, implicit?: boolean): T;
|
|
293
|
-
push(): this;
|
|
297
|
+
push(inputs?: Context.Input): this;
|
|
294
298
|
pop(): void;
|
|
295
299
|
}
|
|
296
300
|
|
package/dist/index.js
CHANGED
|
@@ -102,7 +102,7 @@ function effect(target, callback) {
|
|
|
102
102
|
return null;
|
|
103
103
|
expired = true;
|
|
104
104
|
if (refresh && unSet) {
|
|
105
|
-
unSet();
|
|
105
|
+
unSet(true);
|
|
106
106
|
unSet = void 0;
|
|
107
107
|
}
|
|
108
108
|
return refresh;
|
|
@@ -129,9 +129,11 @@ function effect(target, callback) {
|
|
|
129
129
|
else if (!refresh)
|
|
130
130
|
return refresh;
|
|
131
131
|
if (key === null && unSet)
|
|
132
|
-
unSet();
|
|
132
|
+
unSet(null);
|
|
133
133
|
});
|
|
134
134
|
return () => {
|
|
135
|
+
if (unSet)
|
|
136
|
+
unSet(false);
|
|
135
137
|
refresh = null;
|
|
136
138
|
};
|
|
137
139
|
}
|
|
@@ -156,16 +158,19 @@ var Model = class _Model {
|
|
|
156
158
|
break;
|
|
157
159
|
Type = Object.getPrototypeOf(Type);
|
|
158
160
|
}
|
|
159
|
-
addListener(this, () => {
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
const remove = addListener(this, (key) => {
|
|
162
|
+
remove();
|
|
163
|
+
if (key !== true)
|
|
164
|
+
event(this, true);
|
|
165
|
+
for (const key2 in this) {
|
|
166
|
+
const desc = Object.getOwnPropertyDescriptor(this, key2);
|
|
162
167
|
if ("value" in desc) {
|
|
163
|
-
state[
|
|
164
|
-
define(this,
|
|
168
|
+
state[key2] = desc.value;
|
|
169
|
+
define(this, key2, {
|
|
165
170
|
enumerable: true,
|
|
166
|
-
set: (x) => update(this,
|
|
171
|
+
set: (x) => update(this, key2, x),
|
|
167
172
|
get() {
|
|
168
|
-
return watch(this,
|
|
173
|
+
return watch(this, key2, state[key2]);
|
|
169
174
|
}
|
|
170
175
|
});
|
|
171
176
|
}
|
|
@@ -176,43 +181,25 @@ var Model = class _Model {
|
|
|
176
181
|
value.set(null);
|
|
177
182
|
Object.freeze(state);
|
|
178
183
|
}, null);
|
|
179
|
-
return null;
|
|
180
184
|
});
|
|
181
185
|
}
|
|
182
186
|
get(arg1, arg2) {
|
|
183
187
|
const self = this.is;
|
|
184
188
|
if (typeof arg1 == "function")
|
|
185
189
|
return effect(self, arg1);
|
|
186
|
-
if (arg1 === void 0)
|
|
187
|
-
|
|
188
|
-
if (value instanceof _Model) {
|
|
189
|
-
if (cache.has(value))
|
|
190
|
-
return cache.get(value);
|
|
191
|
-
const model = value;
|
|
192
|
-
cache.set(value, value = {});
|
|
193
|
-
for (const [key, val] of model)
|
|
194
|
-
value[key] = get3(val);
|
|
195
|
-
}
|
|
196
|
-
return value;
|
|
197
|
-
};
|
|
198
|
-
var get2 = get3;
|
|
199
|
-
const cache = /* @__PURE__ */ new WeakMap();
|
|
200
|
-
return get3(self);
|
|
201
|
-
}
|
|
202
|
-
if (arg1 === null)
|
|
203
|
-
if (typeof arg2 == "function")
|
|
204
|
-
return addListener(self, arg2.bind(this, this), null);
|
|
205
|
-
else
|
|
206
|
-
return Object.isFrozen(STATE.get(self));
|
|
190
|
+
if (arg1 === void 0)
|
|
191
|
+
return extract(self);
|
|
207
192
|
if (typeof arg2 == "function") {
|
|
193
|
+
if (arg1 === null)
|
|
194
|
+
return addListener(self, arg2.bind(this, this), null);
|
|
208
195
|
const state = STATE.get(self);
|
|
209
196
|
if (arg1 in state)
|
|
210
197
|
arg2.call(this, state[arg1], arg1, this);
|
|
211
198
|
return addListener(self, () => {
|
|
212
199
|
arg2.call(this, arg1 in state ? state[arg1] : arg1, arg1, this);
|
|
213
200
|
}, arg1);
|
|
214
|
-
}
|
|
215
|
-
|
|
201
|
+
}
|
|
202
|
+
return arg1 === null ? Object.isFrozen(STATE.get(self)) : fetch(self, arg1, arg2);
|
|
216
203
|
}
|
|
217
204
|
set(arg1, arg2, arg3) {
|
|
218
205
|
const self = this.is;
|
|
@@ -221,18 +208,24 @@ var Model = class _Model {
|
|
|
221
208
|
if (typeof key == "string")
|
|
222
209
|
return arg1.call(self, key, self);
|
|
223
210
|
});
|
|
211
|
+
if (arg1 === null)
|
|
212
|
+
return event(this, null);
|
|
224
213
|
if (arg1 !== void 0)
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
214
|
+
if (1 in arguments)
|
|
215
|
+
update(self, arg1, arg2, arg3);
|
|
216
|
+
else
|
|
217
|
+
push(self, arg1);
|
|
218
|
+
if (PENDING.has(self))
|
|
219
|
+
return {
|
|
220
|
+
then: (res) => new Promise((res2) => {
|
|
221
|
+
const remove = addListener(self, (key) => {
|
|
222
|
+
if (key !== true) {
|
|
223
|
+
remove();
|
|
224
|
+
return res2.bind(null, Array.from(PENDING.get(self)));
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}).then(res)
|
|
228
|
+
};
|
|
236
229
|
}
|
|
237
230
|
/** Iterate over managed properties in this instance of Model. */
|
|
238
231
|
[Symbol.iterator]() {
|
|
@@ -285,14 +278,14 @@ function fetch(subject, property, required) {
|
|
|
285
278
|
return value;
|
|
286
279
|
}
|
|
287
280
|
const error = new Error(`${subject}.${property} is not yet available.`);
|
|
288
|
-
const promise = new Promise((resolve,
|
|
281
|
+
const promise = new Promise((resolve, reject2) => {
|
|
289
282
|
addListener(subject, (key) => {
|
|
290
283
|
if (key === property) {
|
|
291
284
|
resolve(state[key]);
|
|
292
285
|
return null;
|
|
293
286
|
}
|
|
294
287
|
if (key === null)
|
|
295
|
-
|
|
288
|
+
reject2(new Error(`${subject} is destroyed.`));
|
|
296
289
|
});
|
|
297
290
|
});
|
|
298
291
|
throw Object.assign(promise, {
|
|
@@ -304,26 +297,42 @@ function fetch(subject, property, required) {
|
|
|
304
297
|
}
|
|
305
298
|
function update(subject, key, value, silent) {
|
|
306
299
|
const state = STATE.get(subject);
|
|
300
|
+
if (Object.isFrozen(state))
|
|
301
|
+
throw new Error(`Tried to update ${String(key)} but ${subject} is destroyed.`);
|
|
302
|
+
const previous = state[key];
|
|
303
|
+
if (value === previous)
|
|
304
|
+
return true;
|
|
305
|
+
state[key] = value;
|
|
306
|
+
if (silent === true)
|
|
307
|
+
return;
|
|
308
|
+
push(subject, key);
|
|
309
|
+
}
|
|
310
|
+
function push(subject, key) {
|
|
307
311
|
let pending = PENDING.get(subject);
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
return;
|
|
312
|
+
if (!pending) {
|
|
313
|
+
PENDING.set(subject, pending = /* @__PURE__ */ new Set());
|
|
314
|
+
queue(() => {
|
|
315
|
+
event(subject, false);
|
|
316
|
+
PENDING.delete(subject);
|
|
317
|
+
});
|
|
315
318
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
319
|
+
pending.add(key);
|
|
320
|
+
event(subject, key);
|
|
321
|
+
}
|
|
322
|
+
function extract(from) {
|
|
323
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
324
|
+
function get2(value) {
|
|
325
|
+
if (value instanceof Model) {
|
|
326
|
+
if (cache.has(value))
|
|
327
|
+
return cache.get(value);
|
|
328
|
+
const model = value;
|
|
329
|
+
cache.set(value, value = {});
|
|
330
|
+
for (const [key, val] of model)
|
|
331
|
+
value[key] = get2(val);
|
|
323
332
|
}
|
|
324
|
-
|
|
333
|
+
return value;
|
|
325
334
|
}
|
|
326
|
-
|
|
335
|
+
return get2(from);
|
|
327
336
|
}
|
|
328
337
|
function uid() {
|
|
329
338
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
@@ -388,7 +397,7 @@ var Context = class {
|
|
|
388
397
|
if (inputs)
|
|
389
398
|
this.include(inputs);
|
|
390
399
|
}
|
|
391
|
-
static
|
|
400
|
+
static get() {
|
|
392
401
|
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
393
402
|
}
|
|
394
403
|
has(T) {
|
|
@@ -407,6 +416,14 @@ var Context = class {
|
|
|
407
416
|
}
|
|
408
417
|
include(inputs) {
|
|
409
418
|
const init = /* @__PURE__ */ new Map();
|
|
419
|
+
if (typeof inputs == "function" || inputs instanceof Model)
|
|
420
|
+
inputs = { [0]: inputs };
|
|
421
|
+
else if (!inputs)
|
|
422
|
+
reject(inputs);
|
|
423
|
+
Object.entries(inputs).forEach(([K, V]) => {
|
|
424
|
+
if (!(Model.is(V) || V instanceof Model))
|
|
425
|
+
reject(`${V} as ${K}`);
|
|
426
|
+
});
|
|
410
427
|
for (const key in inputs) {
|
|
411
428
|
const input = inputs[key];
|
|
412
429
|
const exists = this.layer.get(key);
|
|
@@ -453,9 +470,11 @@ var Context = class {
|
|
|
453
470
|
} while (T !== Model);
|
|
454
471
|
return I;
|
|
455
472
|
}
|
|
456
|
-
push() {
|
|
473
|
+
push(inputs) {
|
|
457
474
|
const next = Object.create(this);
|
|
458
475
|
next.layer = /* @__PURE__ */ new Map();
|
|
476
|
+
if (inputs)
|
|
477
|
+
next.include(inputs);
|
|
459
478
|
return next;
|
|
460
479
|
}
|
|
461
480
|
pop() {
|
|
@@ -471,6 +490,9 @@ var Context = class {
|
|
|
471
490
|
this.layer.clear();
|
|
472
491
|
}
|
|
473
492
|
};
|
|
493
|
+
function reject(argument) {
|
|
494
|
+
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
495
|
+
}
|
|
474
496
|
|
|
475
497
|
// src/instruction/get.ts
|
|
476
498
|
function get(arg0, arg1) {
|
|
@@ -487,7 +509,7 @@ function get(arg0, arg1) {
|
|
|
487
509
|
if (arg1 === true)
|
|
488
510
|
throw new Error(`${from} may only exist as a child of type ${arg0}.`);
|
|
489
511
|
source = (resolve) => {
|
|
490
|
-
Context.
|
|
512
|
+
Context.get(from, (context) => {
|
|
491
513
|
const model = context.get(arg0);
|
|
492
514
|
if (model)
|
|
493
515
|
resolve(model);
|
|
@@ -519,9 +541,11 @@ function compute(subject, key, source, setter) {
|
|
|
519
541
|
compute2(true);
|
|
520
542
|
else if (STALE.delete(compute2))
|
|
521
543
|
compute2();
|
|
522
|
-
return () => {
|
|
523
|
-
|
|
524
|
-
|
|
544
|
+
return (reason) => {
|
|
545
|
+
if (reason) {
|
|
546
|
+
STALE.add(compute2);
|
|
547
|
+
subject.set(key);
|
|
548
|
+
}
|
|
525
549
|
};
|
|
526
550
|
});
|
|
527
551
|
}
|
|
@@ -576,7 +600,7 @@ function ref(arg, arg2) {
|
|
|
576
600
|
else {
|
|
577
601
|
let unSet;
|
|
578
602
|
const set2 = (value2) => {
|
|
579
|
-
if (subject.set(key, value2) || !arg)
|
|
603
|
+
if (!subject.set(key, value2) || !arg)
|
|
580
604
|
return;
|
|
581
605
|
if (unSet)
|
|
582
606
|
unSet = void unSet(value2);
|
package/dist/index.mjs
CHANGED
|
@@ -69,7 +69,7 @@ function effect(target, callback) {
|
|
|
69
69
|
return null;
|
|
70
70
|
expired = true;
|
|
71
71
|
if (refresh && unSet) {
|
|
72
|
-
unSet();
|
|
72
|
+
unSet(true);
|
|
73
73
|
unSet = void 0;
|
|
74
74
|
}
|
|
75
75
|
return refresh;
|
|
@@ -96,9 +96,11 @@ function effect(target, callback) {
|
|
|
96
96
|
else if (!refresh)
|
|
97
97
|
return refresh;
|
|
98
98
|
if (key === null && unSet)
|
|
99
|
-
unSet();
|
|
99
|
+
unSet(null);
|
|
100
100
|
});
|
|
101
101
|
return () => {
|
|
102
|
+
if (unSet)
|
|
103
|
+
unSet(false);
|
|
102
104
|
refresh = null;
|
|
103
105
|
};
|
|
104
106
|
}
|
|
@@ -123,16 +125,19 @@ var Model = class _Model {
|
|
|
123
125
|
break;
|
|
124
126
|
Type = Object.getPrototypeOf(Type);
|
|
125
127
|
}
|
|
126
|
-
addListener(this, () => {
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
const remove = addListener(this, (key) => {
|
|
129
|
+
remove();
|
|
130
|
+
if (key !== true)
|
|
131
|
+
event(this, true);
|
|
132
|
+
for (const key2 in this) {
|
|
133
|
+
const desc = Object.getOwnPropertyDescriptor(this, key2);
|
|
129
134
|
if ("value" in desc) {
|
|
130
|
-
state[
|
|
131
|
-
define(this,
|
|
135
|
+
state[key2] = desc.value;
|
|
136
|
+
define(this, key2, {
|
|
132
137
|
enumerable: true,
|
|
133
|
-
set: (x) => update(this,
|
|
138
|
+
set: (x) => update(this, key2, x),
|
|
134
139
|
get() {
|
|
135
|
-
return watch(this,
|
|
140
|
+
return watch(this, key2, state[key2]);
|
|
136
141
|
}
|
|
137
142
|
});
|
|
138
143
|
}
|
|
@@ -143,43 +148,25 @@ var Model = class _Model {
|
|
|
143
148
|
value.set(null);
|
|
144
149
|
Object.freeze(state);
|
|
145
150
|
}, null);
|
|
146
|
-
return null;
|
|
147
151
|
});
|
|
148
152
|
}
|
|
149
153
|
get(arg1, arg2) {
|
|
150
154
|
const self = this.is;
|
|
151
155
|
if (typeof arg1 == "function")
|
|
152
156
|
return effect(self, arg1);
|
|
153
|
-
if (arg1 === void 0)
|
|
154
|
-
|
|
155
|
-
if (value instanceof _Model) {
|
|
156
|
-
if (cache.has(value))
|
|
157
|
-
return cache.get(value);
|
|
158
|
-
const model = value;
|
|
159
|
-
cache.set(value, value = {});
|
|
160
|
-
for (const [key, val] of model)
|
|
161
|
-
value[key] = get3(val);
|
|
162
|
-
}
|
|
163
|
-
return value;
|
|
164
|
-
};
|
|
165
|
-
var get2 = get3;
|
|
166
|
-
const cache = /* @__PURE__ */ new WeakMap();
|
|
167
|
-
return get3(self);
|
|
168
|
-
}
|
|
169
|
-
if (arg1 === null)
|
|
170
|
-
if (typeof arg2 == "function")
|
|
171
|
-
return addListener(self, arg2.bind(this, this), null);
|
|
172
|
-
else
|
|
173
|
-
return Object.isFrozen(STATE.get(self));
|
|
157
|
+
if (arg1 === void 0)
|
|
158
|
+
return extract(self);
|
|
174
159
|
if (typeof arg2 == "function") {
|
|
160
|
+
if (arg1 === null)
|
|
161
|
+
return addListener(self, arg2.bind(this, this), null);
|
|
175
162
|
const state = STATE.get(self);
|
|
176
163
|
if (arg1 in state)
|
|
177
164
|
arg2.call(this, state[arg1], arg1, this);
|
|
178
165
|
return addListener(self, () => {
|
|
179
166
|
arg2.call(this, arg1 in state ? state[arg1] : arg1, arg1, this);
|
|
180
167
|
}, arg1);
|
|
181
|
-
}
|
|
182
|
-
|
|
168
|
+
}
|
|
169
|
+
return arg1 === null ? Object.isFrozen(STATE.get(self)) : fetch(self, arg1, arg2);
|
|
183
170
|
}
|
|
184
171
|
set(arg1, arg2, arg3) {
|
|
185
172
|
const self = this.is;
|
|
@@ -188,18 +175,24 @@ var Model = class _Model {
|
|
|
188
175
|
if (typeof key == "string")
|
|
189
176
|
return arg1.call(self, key, self);
|
|
190
177
|
});
|
|
178
|
+
if (arg1 === null)
|
|
179
|
+
return event(this, null);
|
|
191
180
|
if (arg1 !== void 0)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
181
|
+
if (1 in arguments)
|
|
182
|
+
update(self, arg1, arg2, arg3);
|
|
183
|
+
else
|
|
184
|
+
push(self, arg1);
|
|
185
|
+
if (PENDING.has(self))
|
|
186
|
+
return {
|
|
187
|
+
then: (res) => new Promise((res2) => {
|
|
188
|
+
const remove = addListener(self, (key) => {
|
|
189
|
+
if (key !== true) {
|
|
190
|
+
remove();
|
|
191
|
+
return res2.bind(null, Array.from(PENDING.get(self)));
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}).then(res)
|
|
195
|
+
};
|
|
203
196
|
}
|
|
204
197
|
/** Iterate over managed properties in this instance of Model. */
|
|
205
198
|
[Symbol.iterator]() {
|
|
@@ -252,14 +245,14 @@ function fetch(subject, property, required) {
|
|
|
252
245
|
return value;
|
|
253
246
|
}
|
|
254
247
|
const error = new Error(`${subject}.${property} is not yet available.`);
|
|
255
|
-
const promise = new Promise((resolve,
|
|
248
|
+
const promise = new Promise((resolve, reject2) => {
|
|
256
249
|
addListener(subject, (key) => {
|
|
257
250
|
if (key === property) {
|
|
258
251
|
resolve(state[key]);
|
|
259
252
|
return null;
|
|
260
253
|
}
|
|
261
254
|
if (key === null)
|
|
262
|
-
|
|
255
|
+
reject2(new Error(`${subject} is destroyed.`));
|
|
263
256
|
});
|
|
264
257
|
});
|
|
265
258
|
throw Object.assign(promise, {
|
|
@@ -271,26 +264,42 @@ function fetch(subject, property, required) {
|
|
|
271
264
|
}
|
|
272
265
|
function update(subject, key, value, silent) {
|
|
273
266
|
const state = STATE.get(subject);
|
|
267
|
+
if (Object.isFrozen(state))
|
|
268
|
+
throw new Error(`Tried to update ${String(key)} but ${subject} is destroyed.`);
|
|
269
|
+
const previous = state[key];
|
|
270
|
+
if (value === previous)
|
|
271
|
+
return true;
|
|
272
|
+
state[key] = value;
|
|
273
|
+
if (silent === true)
|
|
274
|
+
return;
|
|
275
|
+
push(subject, key);
|
|
276
|
+
}
|
|
277
|
+
function push(subject, key) {
|
|
274
278
|
let pending = PENDING.get(subject);
|
|
275
|
-
if (
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
return;
|
|
279
|
+
if (!pending) {
|
|
280
|
+
PENDING.set(subject, pending = /* @__PURE__ */ new Set());
|
|
281
|
+
queue(() => {
|
|
282
|
+
event(subject, false);
|
|
283
|
+
PENDING.delete(subject);
|
|
284
|
+
});
|
|
282
285
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
286
|
+
pending.add(key);
|
|
287
|
+
event(subject, key);
|
|
288
|
+
}
|
|
289
|
+
function extract(from) {
|
|
290
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
291
|
+
function get2(value) {
|
|
292
|
+
if (value instanceof Model) {
|
|
293
|
+
if (cache.has(value))
|
|
294
|
+
return cache.get(value);
|
|
295
|
+
const model = value;
|
|
296
|
+
cache.set(value, value = {});
|
|
297
|
+
for (const [key, val] of model)
|
|
298
|
+
value[key] = get2(val);
|
|
290
299
|
}
|
|
291
|
-
|
|
300
|
+
return value;
|
|
292
301
|
}
|
|
293
|
-
|
|
302
|
+
return get2(from);
|
|
294
303
|
}
|
|
295
304
|
function uid() {
|
|
296
305
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
@@ -355,7 +364,7 @@ var Context = class {
|
|
|
355
364
|
if (inputs)
|
|
356
365
|
this.include(inputs);
|
|
357
366
|
}
|
|
358
|
-
static
|
|
367
|
+
static get() {
|
|
359
368
|
throw new Error(`Using context requires an adapter. If you are only testing, define \`get.context\` to simulate one.`);
|
|
360
369
|
}
|
|
361
370
|
has(T) {
|
|
@@ -374,6 +383,14 @@ var Context = class {
|
|
|
374
383
|
}
|
|
375
384
|
include(inputs) {
|
|
376
385
|
const init = /* @__PURE__ */ new Map();
|
|
386
|
+
if (typeof inputs == "function" || inputs instanceof Model)
|
|
387
|
+
inputs = { [0]: inputs };
|
|
388
|
+
else if (!inputs)
|
|
389
|
+
reject(inputs);
|
|
390
|
+
Object.entries(inputs).forEach(([K, V]) => {
|
|
391
|
+
if (!(Model.is(V) || V instanceof Model))
|
|
392
|
+
reject(`${V} as ${K}`);
|
|
393
|
+
});
|
|
377
394
|
for (const key in inputs) {
|
|
378
395
|
const input = inputs[key];
|
|
379
396
|
const exists = this.layer.get(key);
|
|
@@ -420,9 +437,11 @@ var Context = class {
|
|
|
420
437
|
} while (T !== Model);
|
|
421
438
|
return I;
|
|
422
439
|
}
|
|
423
|
-
push() {
|
|
440
|
+
push(inputs) {
|
|
424
441
|
const next = Object.create(this);
|
|
425
442
|
next.layer = /* @__PURE__ */ new Map();
|
|
443
|
+
if (inputs)
|
|
444
|
+
next.include(inputs);
|
|
426
445
|
return next;
|
|
427
446
|
}
|
|
428
447
|
pop() {
|
|
@@ -438,6 +457,9 @@ var Context = class {
|
|
|
438
457
|
this.layer.clear();
|
|
439
458
|
}
|
|
440
459
|
};
|
|
460
|
+
function reject(argument) {
|
|
461
|
+
throw new Error(`Context can only include Model or instance but got ${argument}.`);
|
|
462
|
+
}
|
|
441
463
|
|
|
442
464
|
// src/instruction/get.ts
|
|
443
465
|
function get(arg0, arg1) {
|
|
@@ -454,7 +476,7 @@ function get(arg0, arg1) {
|
|
|
454
476
|
if (arg1 === true)
|
|
455
477
|
throw new Error(`${from} may only exist as a child of type ${arg0}.`);
|
|
456
478
|
source = (resolve) => {
|
|
457
|
-
Context.
|
|
479
|
+
Context.get(from, (context) => {
|
|
458
480
|
const model = context.get(arg0);
|
|
459
481
|
if (model)
|
|
460
482
|
resolve(model);
|
|
@@ -486,9 +508,11 @@ function compute(subject, key, source, setter) {
|
|
|
486
508
|
compute2(true);
|
|
487
509
|
else if (STALE.delete(compute2))
|
|
488
510
|
compute2();
|
|
489
|
-
return () => {
|
|
490
|
-
|
|
491
|
-
|
|
511
|
+
return (reason) => {
|
|
512
|
+
if (reason) {
|
|
513
|
+
STALE.add(compute2);
|
|
514
|
+
subject.set(key);
|
|
515
|
+
}
|
|
492
516
|
};
|
|
493
517
|
});
|
|
494
518
|
}
|
|
@@ -543,7 +567,7 @@ function ref(arg, arg2) {
|
|
|
543
567
|
else {
|
|
544
568
|
let unSet;
|
|
545
569
|
const set2 = (value2) => {
|
|
546
|
-
if (subject.set(key, value2) || !arg)
|
|
570
|
+
if (!subject.set(key, value2) || !arg)
|
|
547
571
|
return;
|
|
548
572
|
if (unSet)
|
|
549
573
|
unSet = void unSet(value2);
|
package/package.json
CHANGED