@expressive/mvc 0.35.0-alpha.0 → 0.35.1
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 +18 -30
- package/dist/index.js +90 -120
- package/dist/index.mjs +90 -119
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
type Async<T = any, Y extends any[] = any> = {
|
|
2
|
-
(...args: Y): Promise<T>;
|
|
3
|
-
active: boolean;
|
|
4
|
-
};
|
|
5
|
-
/**
|
|
6
|
-
* Sets an exotic method with managed ready-state. Property accepts an async function.
|
|
7
|
-
*
|
|
8
|
-
* When a run-method is invoked, its `active` property to true for duration of call.
|
|
9
|
-
* This is emitted as an update to property, both when called and after returns (or throws).
|
|
10
|
-
*
|
|
11
|
-
* **Note:** Subsequent calls will immediately throw if one is still pending.
|
|
12
|
-
*
|
|
13
|
-
* @param action - Action to fire when resulting property is invoked.
|
|
14
|
-
*/
|
|
15
|
-
declare function run<T, Y extends any[]>(action: (...args: Y) => T | Promise<T>): Async<T, Y>;
|
|
16
|
-
|
|
17
1
|
type Predicate = (key: string) => boolean | void;
|
|
18
2
|
declare namespace Model {
|
|
19
3
|
/** Any type of Model, using own class constructor as its identifier. */
|
|
@@ -44,8 +28,8 @@ declare namespace Model {
|
|
|
44
28
|
current: T | null;
|
|
45
29
|
};
|
|
46
30
|
/** A callback function which is subscribed to parent and updates when values change. */
|
|
47
|
-
type Effect<T> = (this: T, argument: T) =>
|
|
48
|
-
type Event = (key: string) =>
|
|
31
|
+
type Effect<T> = (this: T, argument: T) => (() => void) | Promise<void> | null | void;
|
|
32
|
+
type Event = (this: Model, key: string, value: unknown) => (() => void) | void;
|
|
49
33
|
namespace Instruction {
|
|
50
34
|
type Getter<T> = (source: Model) => T;
|
|
51
35
|
type Setter<T> = (value: T, previous: T) => boolean | void | (() => T);
|
|
@@ -74,16 +58,16 @@ declare class Model {
|
|
|
74
58
|
/** Pull current values from state. Flattens all models and exotic values amongst properties. */
|
|
75
59
|
get(): Model.Export<this>;
|
|
76
60
|
/** Run a function which will run automatically when accessed values change. */
|
|
77
|
-
get(effect: Model.Effect<this>):
|
|
61
|
+
get(effect: Model.Effect<this>): () => void;
|
|
78
62
|
get<T extends string>(key: T, required: true): Exclude<Model.ValueOf<this, T>, undefined>;
|
|
79
63
|
get<T extends string>(key: T, required?: boolean): Model.ValueOf<this, T>;
|
|
80
64
|
/**
|
|
81
65
|
* Check if update is in progress.
|
|
82
|
-
* Returns a promise which resolves updated keys. If no update, will resolve `false`.
|
|
66
|
+
* Returns a promise which resolves updated keys. If no update, will resolve to `false`.
|
|
83
67
|
**/
|
|
84
68
|
set(): Promise<Model.Values<this> | false>;
|
|
85
69
|
/**
|
|
86
|
-
* Expect an update to state within a set
|
|
70
|
+
* Expect an update to state within a set time.
|
|
87
71
|
*
|
|
88
72
|
* @param timeout - milliseconds to wait for update
|
|
89
73
|
* @param predicate - optional function to filter for specific updates. If returns true, update is accepted.
|
|
@@ -92,26 +76,29 @@ declare class Model {
|
|
|
92
76
|
*/
|
|
93
77
|
set(timeout: number, predicate?: Predicate): Promise<Model.Values<this>>;
|
|
94
78
|
/**
|
|
95
|
-
* Call a function whenever an update
|
|
79
|
+
* Call a function whenever an update occurs.
|
|
96
80
|
*
|
|
97
|
-
* @param callback
|
|
81
|
+
* @param callback
|
|
98
82
|
* Note: This will be called for every assignment which changes the value.
|
|
99
83
|
* To run logic on final value only, this callback may return a function.
|
|
100
|
-
* Returning the same function for
|
|
101
|
-
* will ensure it is only called once.
|
|
84
|
+
* Returning the same function for a key will ensure it is only called once.
|
|
102
85
|
*
|
|
103
|
-
* @returns a function to remove listener.
|
|
86
|
+
* @returns a function to remove listener. Returns true if listener isn't removed already.
|
|
104
87
|
*/
|
|
105
88
|
set(callback: Model.Event): () => boolean;
|
|
106
89
|
/**
|
|
107
90
|
* Push an update without changing the value of associated property.
|
|
108
91
|
*
|
|
109
92
|
* This is useful where a property value internally has changed, but the object remains the same.
|
|
110
|
-
* For example:
|
|
93
|
+
* For example: An array which has pushed a new value, or a change to nested property.
|
|
94
|
+
*/
|
|
95
|
+
set(key: string): void;
|
|
96
|
+
/**
|
|
97
|
+
* Declare an end to updates. This event will freeze state.
|
|
111
98
|
*/
|
|
112
|
-
set(key:
|
|
99
|
+
set(key: null): void;
|
|
113
100
|
/**
|
|
114
|
-
* Update a property
|
|
101
|
+
* Update a property with value.
|
|
115
102
|
*
|
|
116
103
|
* @param key - property to update
|
|
117
104
|
* @param value - value to update property with (if the same as current, no update will occur)
|
|
@@ -136,6 +123,7 @@ declare class Model {
|
|
|
136
123
|
*/
|
|
137
124
|
static is<T extends Model.Type>(this: T, maybe: any): maybe is T;
|
|
138
125
|
}
|
|
126
|
+
|
|
139
127
|
declare function add<T = any, M extends Model = any>(instruction: Model.Instruction): T;
|
|
140
128
|
|
|
141
129
|
declare namespace get {
|
|
@@ -309,4 +297,4 @@ declare class Context {
|
|
|
309
297
|
pop(): void;
|
|
310
298
|
}
|
|
311
299
|
|
|
312
|
-
export { Context, Model, add, Model as default, get, ref,
|
|
300
|
+
export { Context, Model, add, Model as default, get, ref, set, use };
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,6 @@ __export(src_exports, {
|
|
|
26
26
|
default: () => Model,
|
|
27
27
|
get: () => get,
|
|
28
28
|
ref: () => ref,
|
|
29
|
-
run: () => run,
|
|
30
29
|
set: () => set,
|
|
31
30
|
use: () => use
|
|
32
31
|
});
|
|
@@ -36,14 +35,13 @@ module.exports = __toCommonJS(src_exports);
|
|
|
36
35
|
var DISPATCH = /* @__PURE__ */ new Set();
|
|
37
36
|
var OBSERVER = /* @__PURE__ */ new WeakMap();
|
|
38
37
|
var LISTENER = /* @__PURE__ */ new WeakMap();
|
|
39
|
-
var EXPIRED = /* @__PURE__ */ new WeakSet();
|
|
40
38
|
function onReady() {
|
|
41
39
|
return null;
|
|
42
40
|
}
|
|
43
41
|
function addListener(to, fn) {
|
|
44
42
|
let subs = LISTENER.get(to);
|
|
45
43
|
if (!subs)
|
|
46
|
-
LISTENER.set(to, subs = /* @__PURE__ */ new Map(
|
|
44
|
+
LISTENER.set(to, subs = (/* @__PURE__ */ new Map()).set(onReady, null));
|
|
47
45
|
if (!subs.has(onReady))
|
|
48
46
|
fn(true, to);
|
|
49
47
|
subs.set(fn, null);
|
|
@@ -55,7 +53,7 @@ function watch(from, key, value) {
|
|
|
55
53
|
if (observer) {
|
|
56
54
|
listeners.set(
|
|
57
55
|
observer,
|
|
58
|
-
|
|
56
|
+
(listeners.get(observer) || /* @__PURE__ */ new Set()).add(key)
|
|
59
57
|
);
|
|
60
58
|
const nested = LISTENER.get(value);
|
|
61
59
|
if (nested) {
|
|
@@ -66,7 +64,8 @@ function watch(from, key, value) {
|
|
|
66
64
|
return value;
|
|
67
65
|
}
|
|
68
66
|
function event(source, key) {
|
|
69
|
-
LISTENER.get(source)
|
|
67
|
+
const subs = LISTENER.get(source);
|
|
68
|
+
subs.forEach((select, callback) => {
|
|
70
69
|
let after;
|
|
71
70
|
if (!select || select.has(key)) {
|
|
72
71
|
if (after = callback.call(source, key, source))
|
|
@@ -95,11 +94,12 @@ function effect(target, callback) {
|
|
|
95
94
|
let refresh;
|
|
96
95
|
let unSet;
|
|
97
96
|
function invoke() {
|
|
97
|
+
let expired;
|
|
98
98
|
const local = Object.create(target);
|
|
99
99
|
const update2 = () => {
|
|
100
|
-
if (
|
|
100
|
+
if (expired)
|
|
101
101
|
return null;
|
|
102
|
-
|
|
102
|
+
expired = true;
|
|
103
103
|
if (refresh && unSet) {
|
|
104
104
|
unSet();
|
|
105
105
|
unSet = void 0;
|
|
@@ -141,10 +141,11 @@ var PARENT = /* @__PURE__ */ new WeakMap();
|
|
|
141
141
|
var INSTRUCT = /* @__PURE__ */ new Map();
|
|
142
142
|
var PENDING = /* @__PURE__ */ new WeakMap();
|
|
143
143
|
var STATE = /* @__PURE__ */ new WeakMap();
|
|
144
|
+
var define = Object.defineProperty;
|
|
144
145
|
var Model = class _Model {
|
|
145
146
|
constructor(id) {
|
|
146
147
|
const state = {};
|
|
147
|
-
|
|
148
|
+
define(this, "is", { value: this });
|
|
148
149
|
ID.set(this, `${this.constructor}-${id ? String(id) : uid()}`);
|
|
149
150
|
STATE.set(this, state);
|
|
150
151
|
function onNull(key) {
|
|
@@ -153,23 +154,20 @@ var Model = class _Model {
|
|
|
153
154
|
}
|
|
154
155
|
addListener(this, () => {
|
|
155
156
|
for (const key in this) {
|
|
156
|
-
const
|
|
157
|
-
const instruction = INSTRUCT.get(value);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
state[key] = value;
|
|
171
|
-
if (desc)
|
|
172
|
-
Object.defineProperty(this, key, desc);
|
|
157
|
+
const property = Object.getOwnPropertyDescriptor(this, key);
|
|
158
|
+
const instruction = INSTRUCT.get(property.value);
|
|
159
|
+
if (instruction)
|
|
160
|
+
instruction(this, key, state);
|
|
161
|
+
else {
|
|
162
|
+
state[key] = property.value;
|
|
163
|
+
define(this, key, {
|
|
164
|
+
enumerable: true,
|
|
165
|
+
set: (x) => update(this, key, x),
|
|
166
|
+
get() {
|
|
167
|
+
return watch(this, key, state[key]);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
173
171
|
}
|
|
174
172
|
addListener(this, onNull);
|
|
175
173
|
return null;
|
|
@@ -200,7 +198,7 @@ var Model = class _Model {
|
|
|
200
198
|
if (typeof arg1 == "function")
|
|
201
199
|
return addListener(self, (key) => {
|
|
202
200
|
if (typeof key == "string")
|
|
203
|
-
return arg1(key);
|
|
201
|
+
return arg1.call(this, key, STATE.get(self)[key]);
|
|
204
202
|
});
|
|
205
203
|
if (typeof arg1 == "string" || arg1 === null)
|
|
206
204
|
return 1 in arguments ? update(self, arg1, arg2, arg3) : update(self, arg1);
|
|
@@ -249,53 +247,16 @@ var Model = class _Model {
|
|
|
249
247
|
return typeof maybe == "function" && maybe.prototype instanceof this;
|
|
250
248
|
}
|
|
251
249
|
};
|
|
252
|
-
|
|
250
|
+
define(Model.prototype, "toString", {
|
|
253
251
|
value() {
|
|
254
252
|
return ID.get(this.is);
|
|
255
253
|
}
|
|
256
254
|
});
|
|
257
|
-
|
|
255
|
+
define(Model, "toString", {
|
|
258
256
|
value() {
|
|
259
257
|
return this.name;
|
|
260
258
|
}
|
|
261
259
|
});
|
|
262
|
-
function add(instruction) {
|
|
263
|
-
const placeholder = Symbol("instruction");
|
|
264
|
-
INSTRUCT.set(placeholder, (subject, key, state) => {
|
|
265
|
-
const output = instruction.call(subject, key, subject, state);
|
|
266
|
-
if (!output)
|
|
267
|
-
return;
|
|
268
|
-
const desc = typeof output == "object" ? output : { get: output };
|
|
269
|
-
const { enumerable = true } = desc;
|
|
270
|
-
if ("value" in desc)
|
|
271
|
-
state[key] = desc.value;
|
|
272
|
-
return {
|
|
273
|
-
enumerable,
|
|
274
|
-
set(next) {
|
|
275
|
-
let { set: set2 } = desc;
|
|
276
|
-
if (set2 === false)
|
|
277
|
-
throw new Error(`${subject}.${key} is read-only.`);
|
|
278
|
-
if (typeof set2 == "function") {
|
|
279
|
-
const result = set2.call(subject, next, state[key]);
|
|
280
|
-
if (result === false)
|
|
281
|
-
return;
|
|
282
|
-
if (typeof result == "function")
|
|
283
|
-
next = result();
|
|
284
|
-
set2 = false;
|
|
285
|
-
}
|
|
286
|
-
update(subject, key, next, !!set2);
|
|
287
|
-
},
|
|
288
|
-
get() {
|
|
289
|
-
return watch(
|
|
290
|
-
this,
|
|
291
|
-
key,
|
|
292
|
-
typeof desc.get == "function" ? desc.get(this) : fetch(subject, key, desc.get)
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
});
|
|
297
|
-
return placeholder;
|
|
298
|
-
}
|
|
299
260
|
function fetch(subject, property, required) {
|
|
300
261
|
const state = STATE.get(subject);
|
|
301
262
|
if (property in state || required === false) {
|
|
@@ -340,10 +301,7 @@ function update(subject, key, value, silent) {
|
|
|
340
301
|
PENDING.delete(subject);
|
|
341
302
|
});
|
|
342
303
|
}
|
|
343
|
-
|
|
344
|
-
pending[key] = state[key];
|
|
345
|
-
if (skip)
|
|
346
|
-
return;
|
|
304
|
+
pending[key] = value;
|
|
347
305
|
}
|
|
348
306
|
event(subject, key);
|
|
349
307
|
}
|
|
@@ -351,49 +309,45 @@ function uid() {
|
|
|
351
309
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
352
310
|
}
|
|
353
311
|
|
|
354
|
-
// src/instruction/
|
|
355
|
-
function
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
312
|
+
// src/instruction/add.ts
|
|
313
|
+
function add(instruction) {
|
|
314
|
+
const placeholder = Symbol("instruction");
|
|
315
|
+
INSTRUCT.set(placeholder, (subject, key, state) => {
|
|
316
|
+
INSTRUCT.delete(placeholder);
|
|
317
|
+
delete subject[key];
|
|
318
|
+
const output = instruction.call(subject, key, subject, state);
|
|
319
|
+
if (!output)
|
|
320
|
+
return;
|
|
321
|
+
const desc = typeof output == "object" ? output : { get: output };
|
|
322
|
+
const { enumerable = true } = desc;
|
|
323
|
+
if ("value" in desc)
|
|
324
|
+
state[key] = desc.value;
|
|
325
|
+
Object.defineProperty(subject, key, {
|
|
326
|
+
enumerable,
|
|
327
|
+
set(next) {
|
|
328
|
+
let { set: set2 } = desc;
|
|
329
|
+
if (set2 === false)
|
|
330
|
+
throw new Error(`${subject}.${key} is read-only.`);
|
|
331
|
+
if (typeof set2 == "function") {
|
|
332
|
+
const result = set2.call(subject, next, state[key]);
|
|
333
|
+
if (result === false)
|
|
334
|
+
return;
|
|
335
|
+
if (typeof result == "function")
|
|
336
|
+
next = result();
|
|
337
|
+
set2 = false;
|
|
338
|
+
}
|
|
339
|
+
update(subject, key, next, !!set2);
|
|
340
|
+
},
|
|
341
|
+
get() {
|
|
342
|
+
return watch(
|
|
343
|
+
this,
|
|
344
|
+
key,
|
|
345
|
+
typeof desc.get == "function" ? desc.get(this) : fetch(subject, key, desc.get)
|
|
362
346
|
);
|
|
363
|
-
pending = true;
|
|
364
|
-
subject.set(key);
|
|
365
|
-
try {
|
|
366
|
-
return await attempt(() => task.apply(subject, args));
|
|
367
|
-
} finally {
|
|
368
|
-
pending = false;
|
|
369
|
-
subject.set(key);
|
|
370
347
|
}
|
|
371
|
-
}
|
|
372
|
-
Object.defineProperty(invoke, "active", {
|
|
373
|
-
get: () => pending
|
|
374
348
|
});
|
|
375
|
-
return {
|
|
376
|
-
value: invoke,
|
|
377
|
-
set: false
|
|
378
|
-
};
|
|
379
349
|
});
|
|
380
|
-
|
|
381
|
-
function attempt(fn) {
|
|
382
|
-
function retry(err) {
|
|
383
|
-
if (err instanceof Promise)
|
|
384
|
-
return err.then(compute2);
|
|
385
|
-
else
|
|
386
|
-
throw err;
|
|
387
|
-
}
|
|
388
|
-
function compute2() {
|
|
389
|
-
try {
|
|
390
|
-
const output = fn();
|
|
391
|
-
return output instanceof Promise ? output.catch(retry) : output;
|
|
392
|
-
} catch (err) {
|
|
393
|
-
return retry(err);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
return compute2();
|
|
350
|
+
return placeholder;
|
|
397
351
|
}
|
|
398
352
|
|
|
399
353
|
// src/context.ts
|
|
@@ -529,7 +483,7 @@ function compute(subject, key, source, setter) {
|
|
|
529
483
|
let isAsync;
|
|
530
484
|
let proxy;
|
|
531
485
|
function connect(model) {
|
|
532
|
-
reset = model
|
|
486
|
+
reset = effect(model, (current) => {
|
|
533
487
|
proxy = current;
|
|
534
488
|
if (!reset)
|
|
535
489
|
compute2(true);
|
|
@@ -565,28 +519,28 @@ function compute(subject, key, source, setter) {
|
|
|
565
519
|
}
|
|
566
520
|
|
|
567
521
|
// src/instruction/ref.ts
|
|
568
|
-
var
|
|
522
|
+
var define2 = Object.defineProperty;
|
|
569
523
|
function ref(arg, arg2) {
|
|
570
524
|
return add((key, subject, state) => {
|
|
571
525
|
let value = {};
|
|
572
526
|
if (arg === subject)
|
|
573
527
|
for (const key2 in state)
|
|
574
528
|
if (typeof arg2 == "function")
|
|
575
|
-
|
|
529
|
+
define2(value, key2, {
|
|
576
530
|
configurable: true,
|
|
577
531
|
get() {
|
|
578
532
|
const out = arg2(key2);
|
|
579
|
-
|
|
533
|
+
define2(value, key2, { value: out });
|
|
580
534
|
return out;
|
|
581
535
|
}
|
|
582
536
|
});
|
|
583
537
|
else {
|
|
584
538
|
const ref2 = (value2) => subject.set(key2, value2);
|
|
585
|
-
|
|
539
|
+
define2(ref2, "current", {
|
|
586
540
|
get: () => state[key2],
|
|
587
541
|
set: ref2
|
|
588
542
|
});
|
|
589
|
-
|
|
543
|
+
define2(value, key2, { value: ref2 });
|
|
590
544
|
}
|
|
591
545
|
else if (typeof arg == "object")
|
|
592
546
|
throw new Error("ref instruction does not support object which is not 'this'");
|
|
@@ -603,12 +557,12 @@ function ref(arg, arg2) {
|
|
|
603
557
|
unSet = out;
|
|
604
558
|
}
|
|
605
559
|
};
|
|
606
|
-
value =
|
|
560
|
+
value = define2(set2, "current", {
|
|
607
561
|
get: () => state[key],
|
|
608
562
|
set: set2
|
|
609
563
|
});
|
|
610
564
|
}
|
|
611
|
-
|
|
565
|
+
define2(subject, key, { value });
|
|
612
566
|
});
|
|
613
567
|
}
|
|
614
568
|
|
|
@@ -667,13 +621,27 @@ function set(value, argument) {
|
|
|
667
621
|
return output;
|
|
668
622
|
});
|
|
669
623
|
}
|
|
624
|
+
function attempt(fn) {
|
|
625
|
+
function retry(err) {
|
|
626
|
+
if (err instanceof Promise)
|
|
627
|
+
return err.then(compute2);
|
|
628
|
+
else
|
|
629
|
+
throw err;
|
|
630
|
+
}
|
|
631
|
+
function compute2() {
|
|
632
|
+
try {
|
|
633
|
+
const output = fn();
|
|
634
|
+
return output instanceof Promise ? output.catch(retry) : output;
|
|
635
|
+
} catch (err) {
|
|
636
|
+
return retry(err);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
return compute2();
|
|
640
|
+
}
|
|
670
641
|
|
|
671
642
|
// src/instruction/use.ts
|
|
672
643
|
function use(value, argument) {
|
|
673
644
|
return add((property, subject) => {
|
|
674
|
-
if (typeof value === "function")
|
|
675
|
-
value = new value();
|
|
676
|
-
const output = { set: set2, value };
|
|
677
645
|
function set2(next) {
|
|
678
646
|
if (value instanceof Model && !(next instanceof value.constructor))
|
|
679
647
|
throw new Error(`${subject}.${property} expected Model of type ${value.constructor} but got ${next}.`);
|
|
@@ -698,6 +666,9 @@ function use(value, argument) {
|
|
|
698
666
|
if (typeof argument == "function")
|
|
699
667
|
argument(next);
|
|
700
668
|
}
|
|
669
|
+
if (typeof value === "function")
|
|
670
|
+
value = new value();
|
|
671
|
+
const output = { set: set2, value };
|
|
701
672
|
set2(value);
|
|
702
673
|
return output;
|
|
703
674
|
});
|
|
@@ -709,7 +680,6 @@ function use(value, argument) {
|
|
|
709
680
|
add,
|
|
710
681
|
get,
|
|
711
682
|
ref,
|
|
712
|
-
run,
|
|
713
683
|
set,
|
|
714
684
|
use
|
|
715
685
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
var DISPATCH = /* @__PURE__ */ new Set();
|
|
3
3
|
var OBSERVER = /* @__PURE__ */ new WeakMap();
|
|
4
4
|
var LISTENER = /* @__PURE__ */ new WeakMap();
|
|
5
|
-
var EXPIRED = /* @__PURE__ */ new WeakSet();
|
|
6
5
|
function onReady() {
|
|
7
6
|
return null;
|
|
8
7
|
}
|
|
9
8
|
function addListener(to, fn) {
|
|
10
9
|
let subs = LISTENER.get(to);
|
|
11
10
|
if (!subs)
|
|
12
|
-
LISTENER.set(to, subs = /* @__PURE__ */ new Map(
|
|
11
|
+
LISTENER.set(to, subs = (/* @__PURE__ */ new Map()).set(onReady, null));
|
|
13
12
|
if (!subs.has(onReady))
|
|
14
13
|
fn(true, to);
|
|
15
14
|
subs.set(fn, null);
|
|
@@ -21,7 +20,7 @@ function watch(from, key, value) {
|
|
|
21
20
|
if (observer) {
|
|
22
21
|
listeners.set(
|
|
23
22
|
observer,
|
|
24
|
-
|
|
23
|
+
(listeners.get(observer) || /* @__PURE__ */ new Set()).add(key)
|
|
25
24
|
);
|
|
26
25
|
const nested = LISTENER.get(value);
|
|
27
26
|
if (nested) {
|
|
@@ -32,7 +31,8 @@ function watch(from, key, value) {
|
|
|
32
31
|
return value;
|
|
33
32
|
}
|
|
34
33
|
function event(source, key) {
|
|
35
|
-
LISTENER.get(source)
|
|
34
|
+
const subs = LISTENER.get(source);
|
|
35
|
+
subs.forEach((select, callback) => {
|
|
36
36
|
let after;
|
|
37
37
|
if (!select || select.has(key)) {
|
|
38
38
|
if (after = callback.call(source, key, source))
|
|
@@ -61,11 +61,12 @@ function effect(target, callback) {
|
|
|
61
61
|
let refresh;
|
|
62
62
|
let unSet;
|
|
63
63
|
function invoke() {
|
|
64
|
+
let expired;
|
|
64
65
|
const local = Object.create(target);
|
|
65
66
|
const update2 = () => {
|
|
66
|
-
if (
|
|
67
|
+
if (expired)
|
|
67
68
|
return null;
|
|
68
|
-
|
|
69
|
+
expired = true;
|
|
69
70
|
if (refresh && unSet) {
|
|
70
71
|
unSet();
|
|
71
72
|
unSet = void 0;
|
|
@@ -107,10 +108,11 @@ var PARENT = /* @__PURE__ */ new WeakMap();
|
|
|
107
108
|
var INSTRUCT = /* @__PURE__ */ new Map();
|
|
108
109
|
var PENDING = /* @__PURE__ */ new WeakMap();
|
|
109
110
|
var STATE = /* @__PURE__ */ new WeakMap();
|
|
111
|
+
var define = Object.defineProperty;
|
|
110
112
|
var Model = class _Model {
|
|
111
113
|
constructor(id) {
|
|
112
114
|
const state = {};
|
|
113
|
-
|
|
115
|
+
define(this, "is", { value: this });
|
|
114
116
|
ID.set(this, `${this.constructor}-${id ? String(id) : uid()}`);
|
|
115
117
|
STATE.set(this, state);
|
|
116
118
|
function onNull(key) {
|
|
@@ -119,23 +121,20 @@ var Model = class _Model {
|
|
|
119
121
|
}
|
|
120
122
|
addListener(this, () => {
|
|
121
123
|
for (const key in this) {
|
|
122
|
-
const
|
|
123
|
-
const instruction = INSTRUCT.get(value);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
state[key] = value;
|
|
137
|
-
if (desc)
|
|
138
|
-
Object.defineProperty(this, key, desc);
|
|
124
|
+
const property = Object.getOwnPropertyDescriptor(this, key);
|
|
125
|
+
const instruction = INSTRUCT.get(property.value);
|
|
126
|
+
if (instruction)
|
|
127
|
+
instruction(this, key, state);
|
|
128
|
+
else {
|
|
129
|
+
state[key] = property.value;
|
|
130
|
+
define(this, key, {
|
|
131
|
+
enumerable: true,
|
|
132
|
+
set: (x) => update(this, key, x),
|
|
133
|
+
get() {
|
|
134
|
+
return watch(this, key, state[key]);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
139
138
|
}
|
|
140
139
|
addListener(this, onNull);
|
|
141
140
|
return null;
|
|
@@ -166,7 +165,7 @@ var Model = class _Model {
|
|
|
166
165
|
if (typeof arg1 == "function")
|
|
167
166
|
return addListener(self, (key) => {
|
|
168
167
|
if (typeof key == "string")
|
|
169
|
-
return arg1(key);
|
|
168
|
+
return arg1.call(this, key, STATE.get(self)[key]);
|
|
170
169
|
});
|
|
171
170
|
if (typeof arg1 == "string" || arg1 === null)
|
|
172
171
|
return 1 in arguments ? update(self, arg1, arg2, arg3) : update(self, arg1);
|
|
@@ -215,53 +214,16 @@ var Model = class _Model {
|
|
|
215
214
|
return typeof maybe == "function" && maybe.prototype instanceof this;
|
|
216
215
|
}
|
|
217
216
|
};
|
|
218
|
-
|
|
217
|
+
define(Model.prototype, "toString", {
|
|
219
218
|
value() {
|
|
220
219
|
return ID.get(this.is);
|
|
221
220
|
}
|
|
222
221
|
});
|
|
223
|
-
|
|
222
|
+
define(Model, "toString", {
|
|
224
223
|
value() {
|
|
225
224
|
return this.name;
|
|
226
225
|
}
|
|
227
226
|
});
|
|
228
|
-
function add(instruction) {
|
|
229
|
-
const placeholder = Symbol("instruction");
|
|
230
|
-
INSTRUCT.set(placeholder, (subject, key, state) => {
|
|
231
|
-
const output = instruction.call(subject, key, subject, state);
|
|
232
|
-
if (!output)
|
|
233
|
-
return;
|
|
234
|
-
const desc = typeof output == "object" ? output : { get: output };
|
|
235
|
-
const { enumerable = true } = desc;
|
|
236
|
-
if ("value" in desc)
|
|
237
|
-
state[key] = desc.value;
|
|
238
|
-
return {
|
|
239
|
-
enumerable,
|
|
240
|
-
set(next) {
|
|
241
|
-
let { set: set2 } = desc;
|
|
242
|
-
if (set2 === false)
|
|
243
|
-
throw new Error(`${subject}.${key} is read-only.`);
|
|
244
|
-
if (typeof set2 == "function") {
|
|
245
|
-
const result = set2.call(subject, next, state[key]);
|
|
246
|
-
if (result === false)
|
|
247
|
-
return;
|
|
248
|
-
if (typeof result == "function")
|
|
249
|
-
next = result();
|
|
250
|
-
set2 = false;
|
|
251
|
-
}
|
|
252
|
-
update(subject, key, next, !!set2);
|
|
253
|
-
},
|
|
254
|
-
get() {
|
|
255
|
-
return watch(
|
|
256
|
-
this,
|
|
257
|
-
key,
|
|
258
|
-
typeof desc.get == "function" ? desc.get(this) : fetch(subject, key, desc.get)
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
});
|
|
263
|
-
return placeholder;
|
|
264
|
-
}
|
|
265
227
|
function fetch(subject, property, required) {
|
|
266
228
|
const state = STATE.get(subject);
|
|
267
229
|
if (property in state || required === false) {
|
|
@@ -306,10 +268,7 @@ function update(subject, key, value, silent) {
|
|
|
306
268
|
PENDING.delete(subject);
|
|
307
269
|
});
|
|
308
270
|
}
|
|
309
|
-
|
|
310
|
-
pending[key] = state[key];
|
|
311
|
-
if (skip)
|
|
312
|
-
return;
|
|
271
|
+
pending[key] = value;
|
|
313
272
|
}
|
|
314
273
|
event(subject, key);
|
|
315
274
|
}
|
|
@@ -317,49 +276,45 @@ function uid() {
|
|
|
317
276
|
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
318
277
|
}
|
|
319
278
|
|
|
320
|
-
// src/instruction/
|
|
321
|
-
function
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
279
|
+
// src/instruction/add.ts
|
|
280
|
+
function add(instruction) {
|
|
281
|
+
const placeholder = Symbol("instruction");
|
|
282
|
+
INSTRUCT.set(placeholder, (subject, key, state) => {
|
|
283
|
+
INSTRUCT.delete(placeholder);
|
|
284
|
+
delete subject[key];
|
|
285
|
+
const output = instruction.call(subject, key, subject, state);
|
|
286
|
+
if (!output)
|
|
287
|
+
return;
|
|
288
|
+
const desc = typeof output == "object" ? output : { get: output };
|
|
289
|
+
const { enumerable = true } = desc;
|
|
290
|
+
if ("value" in desc)
|
|
291
|
+
state[key] = desc.value;
|
|
292
|
+
Object.defineProperty(subject, key, {
|
|
293
|
+
enumerable,
|
|
294
|
+
set(next) {
|
|
295
|
+
let { set: set2 } = desc;
|
|
296
|
+
if (set2 === false)
|
|
297
|
+
throw new Error(`${subject}.${key} is read-only.`);
|
|
298
|
+
if (typeof set2 == "function") {
|
|
299
|
+
const result = set2.call(subject, next, state[key]);
|
|
300
|
+
if (result === false)
|
|
301
|
+
return;
|
|
302
|
+
if (typeof result == "function")
|
|
303
|
+
next = result();
|
|
304
|
+
set2 = false;
|
|
305
|
+
}
|
|
306
|
+
update(subject, key, next, !!set2);
|
|
307
|
+
},
|
|
308
|
+
get() {
|
|
309
|
+
return watch(
|
|
310
|
+
this,
|
|
311
|
+
key,
|
|
312
|
+
typeof desc.get == "function" ? desc.get(this) : fetch(subject, key, desc.get)
|
|
328
313
|
);
|
|
329
|
-
pending = true;
|
|
330
|
-
subject.set(key);
|
|
331
|
-
try {
|
|
332
|
-
return await attempt(() => task.apply(subject, args));
|
|
333
|
-
} finally {
|
|
334
|
-
pending = false;
|
|
335
|
-
subject.set(key);
|
|
336
314
|
}
|
|
337
|
-
}
|
|
338
|
-
Object.defineProperty(invoke, "active", {
|
|
339
|
-
get: () => pending
|
|
340
315
|
});
|
|
341
|
-
return {
|
|
342
|
-
value: invoke,
|
|
343
|
-
set: false
|
|
344
|
-
};
|
|
345
316
|
});
|
|
346
|
-
|
|
347
|
-
function attempt(fn) {
|
|
348
|
-
function retry(err) {
|
|
349
|
-
if (err instanceof Promise)
|
|
350
|
-
return err.then(compute2);
|
|
351
|
-
else
|
|
352
|
-
throw err;
|
|
353
|
-
}
|
|
354
|
-
function compute2() {
|
|
355
|
-
try {
|
|
356
|
-
const output = fn();
|
|
357
|
-
return output instanceof Promise ? output.catch(retry) : output;
|
|
358
|
-
} catch (err) {
|
|
359
|
-
return retry(err);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return compute2();
|
|
317
|
+
return placeholder;
|
|
363
318
|
}
|
|
364
319
|
|
|
365
320
|
// src/context.ts
|
|
@@ -495,7 +450,7 @@ function compute(subject, key, source, setter) {
|
|
|
495
450
|
let isAsync;
|
|
496
451
|
let proxy;
|
|
497
452
|
function connect(model) {
|
|
498
|
-
reset = model
|
|
453
|
+
reset = effect(model, (current) => {
|
|
499
454
|
proxy = current;
|
|
500
455
|
if (!reset)
|
|
501
456
|
compute2(true);
|
|
@@ -531,28 +486,28 @@ function compute(subject, key, source, setter) {
|
|
|
531
486
|
}
|
|
532
487
|
|
|
533
488
|
// src/instruction/ref.ts
|
|
534
|
-
var
|
|
489
|
+
var define2 = Object.defineProperty;
|
|
535
490
|
function ref(arg, arg2) {
|
|
536
491
|
return add((key, subject, state) => {
|
|
537
492
|
let value = {};
|
|
538
493
|
if (arg === subject)
|
|
539
494
|
for (const key2 in state)
|
|
540
495
|
if (typeof arg2 == "function")
|
|
541
|
-
|
|
496
|
+
define2(value, key2, {
|
|
542
497
|
configurable: true,
|
|
543
498
|
get() {
|
|
544
499
|
const out = arg2(key2);
|
|
545
|
-
|
|
500
|
+
define2(value, key2, { value: out });
|
|
546
501
|
return out;
|
|
547
502
|
}
|
|
548
503
|
});
|
|
549
504
|
else {
|
|
550
505
|
const ref2 = (value2) => subject.set(key2, value2);
|
|
551
|
-
|
|
506
|
+
define2(ref2, "current", {
|
|
552
507
|
get: () => state[key2],
|
|
553
508
|
set: ref2
|
|
554
509
|
});
|
|
555
|
-
|
|
510
|
+
define2(value, key2, { value: ref2 });
|
|
556
511
|
}
|
|
557
512
|
else if (typeof arg == "object")
|
|
558
513
|
throw new Error("ref instruction does not support object which is not 'this'");
|
|
@@ -569,12 +524,12 @@ function ref(arg, arg2) {
|
|
|
569
524
|
unSet = out;
|
|
570
525
|
}
|
|
571
526
|
};
|
|
572
|
-
value =
|
|
527
|
+
value = define2(set2, "current", {
|
|
573
528
|
get: () => state[key],
|
|
574
529
|
set: set2
|
|
575
530
|
});
|
|
576
531
|
}
|
|
577
|
-
|
|
532
|
+
define2(subject, key, { value });
|
|
578
533
|
});
|
|
579
534
|
}
|
|
580
535
|
|
|
@@ -633,13 +588,27 @@ function set(value, argument) {
|
|
|
633
588
|
return output;
|
|
634
589
|
});
|
|
635
590
|
}
|
|
591
|
+
function attempt(fn) {
|
|
592
|
+
function retry(err) {
|
|
593
|
+
if (err instanceof Promise)
|
|
594
|
+
return err.then(compute2);
|
|
595
|
+
else
|
|
596
|
+
throw err;
|
|
597
|
+
}
|
|
598
|
+
function compute2() {
|
|
599
|
+
try {
|
|
600
|
+
const output = fn();
|
|
601
|
+
return output instanceof Promise ? output.catch(retry) : output;
|
|
602
|
+
} catch (err) {
|
|
603
|
+
return retry(err);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return compute2();
|
|
607
|
+
}
|
|
636
608
|
|
|
637
609
|
// src/instruction/use.ts
|
|
638
610
|
function use(value, argument) {
|
|
639
611
|
return add((property, subject) => {
|
|
640
|
-
if (typeof value === "function")
|
|
641
|
-
value = new value();
|
|
642
|
-
const output = { set: set2, value };
|
|
643
612
|
function set2(next) {
|
|
644
613
|
if (value instanceof Model && !(next instanceof value.constructor))
|
|
645
614
|
throw new Error(`${subject}.${property} expected Model of type ${value.constructor} but got ${next}.`);
|
|
@@ -664,6 +633,9 @@ function use(value, argument) {
|
|
|
664
633
|
if (typeof argument == "function")
|
|
665
634
|
argument(next);
|
|
666
635
|
}
|
|
636
|
+
if (typeof value === "function")
|
|
637
|
+
value = new value();
|
|
638
|
+
const output = { set: set2, value };
|
|
667
639
|
set2(value);
|
|
668
640
|
return output;
|
|
669
641
|
});
|
|
@@ -675,7 +647,6 @@ export {
|
|
|
675
647
|
Model as default,
|
|
676
648
|
get,
|
|
677
649
|
ref,
|
|
678
|
-
run,
|
|
679
650
|
set,
|
|
680
651
|
use
|
|
681
652
|
};
|
package/package.json
CHANGED