@esportsplus/reactivity 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.d.ts +1 -2
- package/build/index.js +1 -2
- package/build/reactive/array.js +1 -1
- package/build/reactive/{promise.d.ts → async.d.ts} +2 -2
- package/build/reactive/{promise.js → async.js} +3 -3
- package/build/reactive/index.d.ts +4 -4
- package/build/reactive/index.js +10 -10
- package/build/reactive/object.js +3 -3
- package/build/system.d.ts +15 -0
- package/build/system.js +345 -0
- package/build/types.d.ts +3 -2
- package/package.json +1 -1
- package/src/index.ts +1 -2
- package/src/reactive/array.ts +1 -1
- package/src/reactive/{promise.ts → async.ts} +3 -3
- package/src/reactive/index.ts +12 -12
- package/src/reactive/object.ts +3 -3
- package/src/{signal.ts → system.ts} +152 -125
- package/src/types.ts +3 -2
- package/build/scheduler.d.ts +0 -4
- package/build/scheduler.js +0 -17
- package/build/signal.d.ts +0 -18
- package/build/signal.js +0 -325
- package/src/scheduler.ts +0 -27
package/build/index.d.ts
CHANGED
package/build/index.js
CHANGED
package/build/reactive/array.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isFunction, isInstanceOf, isNumber, isObject } from '@esportsplus/utilities';
|
|
2
|
-
import { computed, dispose, isComputed, read } from '../
|
|
2
|
+
import { computed, dispose, isComputed, read } from '../system.js';
|
|
3
3
|
import object from './object.js';
|
|
4
4
|
import { Disposable } from './disposable.js';
|
|
5
5
|
class ReactiveArray extends Disposable {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import CustomFunction from '@esportsplus/custom-function';
|
|
2
|
-
declare class
|
|
2
|
+
declare class ReactiveAsyncFunction<A extends unknown[], R extends Promise<unknown>> extends CustomFunction {
|
|
3
3
|
private arguments;
|
|
4
4
|
private okay;
|
|
5
5
|
private response;
|
|
@@ -9,5 +9,5 @@ declare class ReactivePromise<A extends unknown[], R extends Promise<unknown>> e
|
|
|
9
9
|
get input(): A | null;
|
|
10
10
|
get ok(): boolean | null;
|
|
11
11
|
}
|
|
12
|
-
declare const _default: <A extends unknown[], R extends Promise<unknown>>(fn: (...args: A) => R) =>
|
|
12
|
+
declare const _default: <A extends unknown[], R extends Promise<unknown>>(fn: (...args: A) => R) => ReactiveAsyncFunction<A, R>;
|
|
13
13
|
export default _default;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import CustomFunction from '@esportsplus/custom-function';
|
|
2
|
-
import { read, root, signal } from '../
|
|
2
|
+
import { read, root, signal } from '../system.js';
|
|
3
3
|
let { set } = signal;
|
|
4
|
-
class
|
|
4
|
+
class ReactiveAsyncFunction extends CustomFunction {
|
|
5
5
|
arguments;
|
|
6
6
|
okay;
|
|
7
7
|
response;
|
|
@@ -44,5 +44,5 @@ class ReactivePromise extends CustomFunction {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
export default (fn) => {
|
|
47
|
-
return new
|
|
47
|
+
return new ReactiveAsyncFunction(fn);
|
|
48
48
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import array from './array.js';
|
|
2
|
+
import async from './async.js';
|
|
2
3
|
import object from './object.js';
|
|
3
|
-
|
|
4
|
-
type
|
|
5
|
-
type Guard<T> = T extends (...args: unknown[]) => Promise<unknown> ? T : T extends {
|
|
4
|
+
type API<T> = T extends (...args: infer A) => Promise<infer R> ? ReturnType<typeof async<A, Promise<R>>> : T extends Record<PropertyKey, unknown> ? ReturnType<typeof object<T>> : T extends unknown[] ? ReturnType<typeof array<T>> : never;
|
|
5
|
+
type Input<T> = T extends (...args: unknown[]) => Promise<unknown> ? T : T extends {
|
|
6
6
|
dispose: any;
|
|
7
7
|
} | {
|
|
8
8
|
signals: any;
|
|
9
9
|
} ? {
|
|
10
10
|
never: '[ dispose, signals ] are reserved keys';
|
|
11
11
|
} : T extends Record<PropertyKey, unknown> | unknown[] ? T : never;
|
|
12
|
-
declare const _default: <T>(
|
|
12
|
+
declare const _default: <T>(input: Input<T>) => API<T>;
|
|
13
13
|
export default _default;
|
package/build/reactive/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { isArray,
|
|
1
|
+
import { isArray, isAsyncFunction, isObject } from '@esportsplus/utilities';
|
|
2
2
|
import array from './array.js';
|
|
3
|
+
import async from './async.js';
|
|
3
4
|
import object from './object.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return array(data);
|
|
5
|
+
export default (input) => {
|
|
6
|
+
if (isArray(input)) {
|
|
7
|
+
return array(input);
|
|
8
8
|
}
|
|
9
|
-
else if (
|
|
10
|
-
return
|
|
9
|
+
else if (isAsyncFunction(input)) {
|
|
10
|
+
return async(input);
|
|
11
11
|
}
|
|
12
|
-
else if (
|
|
13
|
-
return
|
|
12
|
+
else if (isObject(input)) {
|
|
13
|
+
return object(input);
|
|
14
14
|
}
|
|
15
|
-
throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(
|
|
15
|
+
throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(input)}`);
|
|
16
16
|
};
|
package/build/reactive/object.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { defineProperty, isArray, isAsyncFunction, isFunction, isInstanceOf } from '@esportsplus/utilities';
|
|
2
2
|
import array from './array.js';
|
|
3
|
-
import { computed, dispose, read, signal } from '../
|
|
3
|
+
import { computed, dispose, read, signal } from '../system.js';
|
|
4
4
|
import { Disposable } from './disposable.js';
|
|
5
|
-
import
|
|
5
|
+
import async from './async.js';
|
|
6
6
|
let { set } = signal;
|
|
7
7
|
class ReactiveObject extends Disposable {
|
|
8
8
|
disposable = {};
|
|
@@ -26,7 +26,7 @@ class ReactiveObject extends Disposable {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
else if (isAsyncFunction(value)) {
|
|
29
|
-
let p =
|
|
29
|
+
let p = async(value);
|
|
30
30
|
defineProperty(this, key, {
|
|
31
31
|
enumerable: true,
|
|
32
32
|
get() {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Computed, Signal } from './types.js';
|
|
2
|
+
declare const computed: <T>(fn: Computed<T>["fn"]) => Computed<T>;
|
|
3
|
+
declare const dispose: <T>(computed: Computed<T>) => void;
|
|
4
|
+
declare const effect: <T>(fn: Computed<T>["fn"]) => void;
|
|
5
|
+
declare const isComputed: (value: unknown) => value is Computed<unknown>;
|
|
6
|
+
declare const isSignal: (value: unknown) => value is Signal<unknown>;
|
|
7
|
+
declare const onCleanup: (fn: VoidFunction) => typeof fn;
|
|
8
|
+
declare const read: <T>(node: Signal<T> | Computed<T>) => T;
|
|
9
|
+
declare const root: <T>(fn: () => T) => T;
|
|
10
|
+
declare const signal: {
|
|
11
|
+
<T>(value: T): Signal<T>;
|
|
12
|
+
set<T>(signal: Signal<T>, value: T): void;
|
|
13
|
+
};
|
|
14
|
+
declare const stabilize: () => void;
|
|
15
|
+
export { computed, dispose, effect, isComputed, isSignal, onCleanup, read, root, signal, stabilize };
|
package/build/system.js
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { defineProperty, isArray, isObject } from '@esportsplus/utilities';
|
|
2
|
+
import { REACTIVE, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
|
|
3
|
+
let depth = 0, heap = new Array(2000), index = 0, length = 0, notified = false, observer = null, scheduled = false, scheduler = null, version = 0;
|
|
4
|
+
function cleanup(node) {
|
|
5
|
+
if (!node.cleanup) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
let cleanup = node.cleanup;
|
|
9
|
+
if (isArray(cleanup)) {
|
|
10
|
+
for (let i = 0; i < cleanup.length; i++) {
|
|
11
|
+
cleanup[i]();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
cleanup();
|
|
16
|
+
}
|
|
17
|
+
node.cleanup = null;
|
|
18
|
+
}
|
|
19
|
+
function deleteFromHeap(computed) {
|
|
20
|
+
let state = computed.state;
|
|
21
|
+
if (!(state & STATE_IN_HEAP)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
computed.state = state & ~STATE_IN_HEAP;
|
|
25
|
+
let height = computed.height;
|
|
26
|
+
if (computed.prevHeap === computed) {
|
|
27
|
+
heap[height] = undefined;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
let next = computed.nextHeap, dhh = heap[height], end = next ?? dhh;
|
|
31
|
+
if (computed === dhh) {
|
|
32
|
+
heap[height] = next;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
computed.prevHeap.nextHeap = next;
|
|
36
|
+
}
|
|
37
|
+
end.prevHeap = computed.prevHeap;
|
|
38
|
+
}
|
|
39
|
+
computed.nextHeap = undefined;
|
|
40
|
+
computed.prevHeap = computed;
|
|
41
|
+
}
|
|
42
|
+
function insertIntoHeap(computed) {
|
|
43
|
+
let state = computed.state;
|
|
44
|
+
if (state & STATE_IN_HEAP) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
computed.state = state | STATE_IN_HEAP;
|
|
48
|
+
let height = computed.height, heapAtHeight = heap[height];
|
|
49
|
+
if (heapAtHeight === undefined) {
|
|
50
|
+
heap[height] = computed;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
let tail = heapAtHeight.prevHeap;
|
|
54
|
+
tail.nextHeap = computed;
|
|
55
|
+
computed.prevHeap = tail;
|
|
56
|
+
heapAtHeight.prevHeap = computed;
|
|
57
|
+
}
|
|
58
|
+
if (height > length) {
|
|
59
|
+
length = height;
|
|
60
|
+
if (height >= heap.length) {
|
|
61
|
+
heap.length += 250;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function link(dep, sub) {
|
|
66
|
+
let prevDep = sub.depsTail;
|
|
67
|
+
if (prevDep !== null && prevDep.dep === dep) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
let nextDep = null;
|
|
71
|
+
if (sub.state & STATE_RECOMPUTING) {
|
|
72
|
+
nextDep = prevDep !== null ? prevDep.nextDep : sub.deps;
|
|
73
|
+
if (nextDep !== null && nextDep.dep === dep) {
|
|
74
|
+
nextDep.version = version;
|
|
75
|
+
sub.depsTail = nextDep;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
let prevSub = dep.subsTail;
|
|
80
|
+
if (prevSub !== null &&
|
|
81
|
+
prevSub.version === version &&
|
|
82
|
+
prevSub.sub === sub) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
let newLink = sub.depsTail =
|
|
86
|
+
dep.subsTail = {
|
|
87
|
+
dep,
|
|
88
|
+
sub,
|
|
89
|
+
nextDep,
|
|
90
|
+
prevSub,
|
|
91
|
+
nextSub: null,
|
|
92
|
+
version
|
|
93
|
+
};
|
|
94
|
+
if (prevDep !== null) {
|
|
95
|
+
prevDep.nextDep = newLink;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
sub.deps = newLink;
|
|
99
|
+
}
|
|
100
|
+
if (prevSub !== null) {
|
|
101
|
+
prevSub.nextSub = newLink;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
dep.subs = newLink;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function notify(computed, newState = STATE_DIRTY) {
|
|
108
|
+
let state = computed.state;
|
|
109
|
+
if ((state & (STATE_CHECK | STATE_DIRTY)) >= newState) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
computed.state = state | newState;
|
|
113
|
+
for (let link = computed.subs; link !== null; link = link.nextSub) {
|
|
114
|
+
notify(link.sub, STATE_CHECK);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function recompute(computed, del) {
|
|
118
|
+
if (del) {
|
|
119
|
+
deleteFromHeap(computed);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
computed.nextHeap = undefined;
|
|
123
|
+
computed.prevHeap = computed;
|
|
124
|
+
}
|
|
125
|
+
cleanup(computed);
|
|
126
|
+
let o = observer, ok = true, value;
|
|
127
|
+
observer = computed;
|
|
128
|
+
computed.depsTail = null;
|
|
129
|
+
computed.state = STATE_RECOMPUTING;
|
|
130
|
+
depth++;
|
|
131
|
+
version++;
|
|
132
|
+
try {
|
|
133
|
+
value = computed.fn(onCleanup);
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
ok = false;
|
|
137
|
+
}
|
|
138
|
+
observer = o;
|
|
139
|
+
computed.state = STATE_NONE;
|
|
140
|
+
let depsTail = computed.depsTail, toRemove = depsTail !== null ? depsTail.nextDep : computed.deps;
|
|
141
|
+
if (toRemove !== null) {
|
|
142
|
+
do {
|
|
143
|
+
toRemove = unlink(toRemove);
|
|
144
|
+
} while (toRemove !== null);
|
|
145
|
+
if (depsTail !== null) {
|
|
146
|
+
depsTail.nextDep = null;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
computed.deps = null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (ok && value !== computed.value) {
|
|
153
|
+
computed.value = value;
|
|
154
|
+
for (let c = computed.subs; c !== null; c = c.nextSub) {
|
|
155
|
+
let o = c.sub, state = o.state;
|
|
156
|
+
if (state & STATE_CHECK) {
|
|
157
|
+
o.state = state | STATE_DIRTY;
|
|
158
|
+
}
|
|
159
|
+
insertIntoHeap(o);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!--depth) {
|
|
163
|
+
if (!scheduled && scheduler) {
|
|
164
|
+
scheduled = true;
|
|
165
|
+
scheduler(stabilize);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
throw new Error('@esportsplus/reactivity: stabilize.scheduler has not been set to process updates.');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function unlink(link) {
|
|
173
|
+
let { dep, nextDep, nextSub, prevSub } = link;
|
|
174
|
+
if (nextSub !== null) {
|
|
175
|
+
nextSub.prevSub = prevSub;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
dep.subsTail = prevSub;
|
|
179
|
+
}
|
|
180
|
+
if (prevSub !== null) {
|
|
181
|
+
prevSub.nextSub = nextSub;
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
dep.subs = nextSub;
|
|
185
|
+
if (nextSub === null && 'fn' in dep) {
|
|
186
|
+
dispose(dep);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return nextDep;
|
|
190
|
+
}
|
|
191
|
+
function update(computed) {
|
|
192
|
+
if (computed.state & STATE_CHECK) {
|
|
193
|
+
for (let link = computed.deps; link; link = link.nextDep) {
|
|
194
|
+
let dep = link.dep;
|
|
195
|
+
if ('fn' in dep) {
|
|
196
|
+
update(dep);
|
|
197
|
+
}
|
|
198
|
+
if (computed.state & STATE_DIRTY) {
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (computed.state & STATE_DIRTY) {
|
|
204
|
+
recompute(computed, true);
|
|
205
|
+
}
|
|
206
|
+
computed.state = STATE_NONE;
|
|
207
|
+
}
|
|
208
|
+
const computed = (fn) => {
|
|
209
|
+
let self = {
|
|
210
|
+
[REACTIVE]: true,
|
|
211
|
+
cleanup: null,
|
|
212
|
+
deps: null,
|
|
213
|
+
depsTail: null,
|
|
214
|
+
fn: fn,
|
|
215
|
+
height: 0,
|
|
216
|
+
nextHeap: undefined,
|
|
217
|
+
prevHeap: null,
|
|
218
|
+
state: STATE_NONE,
|
|
219
|
+
subs: null,
|
|
220
|
+
subsTail: null,
|
|
221
|
+
value: undefined,
|
|
222
|
+
};
|
|
223
|
+
self.prevHeap = self;
|
|
224
|
+
if (observer) {
|
|
225
|
+
if (observer.depsTail === null) {
|
|
226
|
+
self.height = observer.height;
|
|
227
|
+
recompute(self, false);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
self.height = observer.height + 1;
|
|
231
|
+
insertIntoHeap(self);
|
|
232
|
+
}
|
|
233
|
+
link(self, observer);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
recompute(self, false);
|
|
237
|
+
}
|
|
238
|
+
return self;
|
|
239
|
+
};
|
|
240
|
+
const dispose = (computed) => {
|
|
241
|
+
deleteFromHeap(computed);
|
|
242
|
+
let dep = computed.deps;
|
|
243
|
+
while (dep !== null) {
|
|
244
|
+
dep = unlink(dep);
|
|
245
|
+
}
|
|
246
|
+
computed.deps = null;
|
|
247
|
+
cleanup(computed);
|
|
248
|
+
};
|
|
249
|
+
const effect = (fn) => {
|
|
250
|
+
computed(fn);
|
|
251
|
+
};
|
|
252
|
+
const isComputed = (value) => {
|
|
253
|
+
return isObject(value) && REACTIVE in value && 'fn' in value;
|
|
254
|
+
};
|
|
255
|
+
const isSignal = (value) => {
|
|
256
|
+
return isObject(value) && REACTIVE in value && 'fn' in value === false;
|
|
257
|
+
};
|
|
258
|
+
const onCleanup = (fn) => {
|
|
259
|
+
if (!observer) {
|
|
260
|
+
return fn;
|
|
261
|
+
}
|
|
262
|
+
let node = observer;
|
|
263
|
+
if (!node.cleanup) {
|
|
264
|
+
node.cleanup = fn;
|
|
265
|
+
}
|
|
266
|
+
else if (isArray(node.cleanup)) {
|
|
267
|
+
node.cleanup.push(fn);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
node.cleanup = [node.cleanup, fn];
|
|
271
|
+
}
|
|
272
|
+
return fn;
|
|
273
|
+
};
|
|
274
|
+
const read = (node) => {
|
|
275
|
+
if (observer) {
|
|
276
|
+
link(node, observer);
|
|
277
|
+
if ('fn' in node) {
|
|
278
|
+
let height = node.height;
|
|
279
|
+
if (height >= observer.height) {
|
|
280
|
+
observer.height = height + 1;
|
|
281
|
+
}
|
|
282
|
+
if (height >= index ||
|
|
283
|
+
node.state & (STATE_DIRTY | STATE_CHECK)) {
|
|
284
|
+
if (!notified) {
|
|
285
|
+
notified = true;
|
|
286
|
+
for (let i = 0; i <= length; i++) {
|
|
287
|
+
for (let computed = heap[i]; computed !== undefined; computed = computed.nextHeap) {
|
|
288
|
+
notify(computed);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
update(node);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return node.value;
|
|
297
|
+
};
|
|
298
|
+
const root = (fn) => {
|
|
299
|
+
let o = observer;
|
|
300
|
+
observer = null;
|
|
301
|
+
let value = fn();
|
|
302
|
+
observer = o;
|
|
303
|
+
return value;
|
|
304
|
+
};
|
|
305
|
+
const signal = (value) => {
|
|
306
|
+
return {
|
|
307
|
+
[REACTIVE]: true,
|
|
308
|
+
subs: null,
|
|
309
|
+
subsTail: null,
|
|
310
|
+
value,
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
signal.set = (signal, value) => {
|
|
314
|
+
if (signal.value === value) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
notified = false;
|
|
318
|
+
signal.value = value;
|
|
319
|
+
for (let link = signal.subs; link !== null; link = link.nextSub) {
|
|
320
|
+
insertIntoHeap(link.sub);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
const stabilize = () => {
|
|
324
|
+
root(() => {
|
|
325
|
+
for (index = 0; index <= length; index++) {
|
|
326
|
+
let computed = heap[index];
|
|
327
|
+
heap[index] = undefined;
|
|
328
|
+
while (computed !== undefined) {
|
|
329
|
+
let next = computed.nextHeap;
|
|
330
|
+
recompute(computed, false);
|
|
331
|
+
computed = next;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
scheduled = false;
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
defineProperty(stabilize, 'scheduler', {
|
|
338
|
+
get() {
|
|
339
|
+
return scheduler;
|
|
340
|
+
},
|
|
341
|
+
set(s) {
|
|
342
|
+
scheduler = s;
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
export { computed, dispose, effect, isComputed, isSignal, onCleanup, read, root, signal, stabilize };
|
package/build/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { REACTIVE, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
|
|
2
|
-
import {
|
|
2
|
+
import { onCleanup } from './system.js';
|
|
3
3
|
import { ReactiveArray } from './reactive/array.js';
|
|
4
4
|
import { ReactiveObject } from './reactive/object.js';
|
|
5
5
|
interface Computed<T> extends Signal<T> {
|
|
@@ -7,7 +7,7 @@ interface Computed<T> extends Signal<T> {
|
|
|
7
7
|
cleanup: VoidFunction | VoidFunction[] | null;
|
|
8
8
|
deps: Link | null;
|
|
9
9
|
depsTail: Link | null;
|
|
10
|
-
fn: (oc?: typeof
|
|
10
|
+
fn: (oc?: typeof onCleanup) => T;
|
|
11
11
|
height: number;
|
|
12
12
|
nextHeap: Computed<unknown> | undefined;
|
|
13
13
|
prevHeap: Computed<unknown>;
|
|
@@ -22,6 +22,7 @@ interface Link {
|
|
|
22
22
|
nextDep: Link | null;
|
|
23
23
|
nextSub: Link | null;
|
|
24
24
|
prevSub: Link | null;
|
|
25
|
+
version: number;
|
|
25
26
|
}
|
|
26
27
|
type Reactive<T> = T extends Record<PropertyKey, unknown> ? ReactiveObject<T> : ReactiveArray<T>;
|
|
27
28
|
type Signal<T> = {
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/reactive/array.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isFunction, isInstanceOf, isNumber, isObject } from '@esportsplus/utilities';
|
|
2
|
-
import { computed, dispose, isComputed, read } from '~/
|
|
2
|
+
import { computed, dispose, isComputed, read } from '~/system';
|
|
3
3
|
import { Computed, Infer } from '~/types';
|
|
4
4
|
import object, { ReactiveObject } from './object';
|
|
5
5
|
import { Disposable } from './disposable';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import CustomFunction from '@esportsplus/custom-function';
|
|
2
|
-
import { read, root, signal } from '~/
|
|
2
|
+
import { read, root, signal } from '~/system';
|
|
3
3
|
import { Signal } from '~/types';
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
let { set } = signal;
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class ReactiveAsyncFunction<A extends unknown[], R extends Promise<unknown>> extends CustomFunction {
|
|
10
10
|
private arguments: Signal<A | null>;
|
|
11
11
|
private okay: Signal<boolean | null>;
|
|
12
12
|
private response: Signal<Awaited<R> | null>;
|
|
@@ -63,5 +63,5 @@ class ReactivePromise<A extends unknown[], R extends Promise<unknown>> extends C
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
export default <A extends unknown[], R extends Promise<unknown>>(fn: (...args: A) => R) => {
|
|
66
|
-
return new
|
|
66
|
+
return new ReactiveAsyncFunction(fn);
|
|
67
67
|
};
|
package/src/reactive/index.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { isArray,
|
|
1
|
+
import { isArray, isAsyncFunction, isObject } from '@esportsplus/utilities';
|
|
2
2
|
import array from './array';
|
|
3
|
+
import async from './async';
|
|
3
4
|
import object from './object';
|
|
4
|
-
import promise from './promise';
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
type API<T> =
|
|
8
8
|
T extends (...args: infer A) => Promise<infer R>
|
|
9
|
-
? ReturnType<typeof
|
|
9
|
+
? ReturnType<typeof async<A, Promise<R>>>
|
|
10
10
|
: T extends Record<PropertyKey, unknown>
|
|
11
11
|
? ReturnType<typeof object<T>>
|
|
12
12
|
: T extends unknown[]
|
|
13
13
|
? ReturnType<typeof array<T>>
|
|
14
14
|
: never;
|
|
15
15
|
|
|
16
|
-
type
|
|
16
|
+
type Input<T> =
|
|
17
17
|
T extends (...args: unknown[]) => Promise<unknown>
|
|
18
18
|
? T
|
|
19
19
|
: T extends { dispose: any } | { signals: any }
|
|
@@ -23,16 +23,16 @@ type Guard<T> =
|
|
|
23
23
|
: never;
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
export default <T>(
|
|
27
|
-
if (isArray(
|
|
28
|
-
return array(
|
|
26
|
+
export default <T>(input: Input<T>): API<T> => {
|
|
27
|
+
if (isArray(input)) {
|
|
28
|
+
return array(input) as API<T>;
|
|
29
29
|
}
|
|
30
|
-
else if (
|
|
31
|
-
return
|
|
30
|
+
else if (isAsyncFunction(input)) {
|
|
31
|
+
return async(input) as API<T>;
|
|
32
32
|
}
|
|
33
|
-
else if (
|
|
34
|
-
return
|
|
33
|
+
else if (isObject(input)) {
|
|
34
|
+
return object(input) as API<T>;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(
|
|
37
|
+
throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(input)}`);
|
|
38
38
|
};
|
package/src/reactive/object.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { defineProperty, isArray, isAsyncFunction, isFunction, isInstanceOf, Prettify } from '@esportsplus/utilities';
|
|
2
2
|
import array, { ReactiveArray } from './array';
|
|
3
|
-
import { computed, dispose, read, signal } from '~/
|
|
3
|
+
import { computed, dispose, read, signal } from '~/system';
|
|
4
4
|
import { Computed, Infer, Signal } from '~/types';
|
|
5
5
|
import { Disposable } from './disposable';
|
|
6
|
-
import
|
|
6
|
+
import async from './async';
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
type API<T extends Record<PropertyKey, unknown>> = Prettify<{ [K in keyof T]: Infer<T[K]> }> & ReactiveObject<T>;
|
|
@@ -45,7 +45,7 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable
|
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
else if (isAsyncFunction(value)) {
|
|
48
|
-
let p =
|
|
48
|
+
let p = async(value);
|
|
49
49
|
|
|
50
50
|
defineProperty(this, key, {
|
|
51
51
|
enumerable: true,
|