@planet-matrix/mobius-model 0.1.4 → 0.3.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/CHANGELOG.md +46 -0
- package/README.md +21 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +12 -6
- package/dist/reactor/index.d.ts +3 -0
- package/dist/reactor/index.d.ts.map +1 -0
- package/dist/reactor/reactor-core/flags.d.ts.map +1 -0
- package/dist/reactor/reactor-core/index.d.ts.map +1 -0
- package/dist/reactor/reactor-core/primitive.d.ts +276 -0
- package/dist/reactor/reactor-core/primitive.d.ts.map +1 -0
- package/dist/{signal/signal-core → reactor/reactor-core}/reactive-system.d.ts +102 -22
- package/dist/reactor/reactor-core/reactive-system.d.ts.map +1 -0
- package/dist/reactor/reactor-operators/branch.d.ts +19 -0
- package/dist/reactor/reactor-operators/branch.d.ts.map +1 -0
- package/dist/reactor/reactor-operators/convert.d.ts +30 -0
- package/dist/reactor/reactor-operators/convert.d.ts.map +1 -0
- package/dist/reactor/reactor-operators/create.d.ts +26 -0
- package/dist/reactor/reactor-operators/create.d.ts.map +1 -0
- package/dist/reactor/reactor-operators/filter.d.ts +269 -0
- package/dist/reactor/reactor-operators/filter.d.ts.map +1 -0
- package/dist/reactor/reactor-operators/index.d.ts +8 -0
- package/dist/reactor/reactor-operators/index.d.ts.map +1 -0
- package/dist/reactor/reactor-operators/join.d.ts +48 -0
- package/dist/reactor/reactor-operators/join.d.ts.map +1 -0
- package/dist/reactor/reactor-operators/map.d.ts +165 -0
- package/dist/reactor/reactor-operators/map.d.ts.map +1 -0
- package/dist/reactor/reactor-operators/utility.d.ts +48 -0
- package/dist/reactor/reactor-operators/utility.d.ts.map +1 -0
- package/package.json +9 -9
- package/src/index.ts +1 -1
- package/src/reactor/README.md +18 -0
- package/src/reactor/index.ts +2 -0
- package/src/reactor/reactor-core/primitive.ts +1046 -0
- package/src/{signal/signal-core → reactor/reactor-core}/reactive-system.ts +392 -93
- package/src/reactor/reactor-operators/branch.ts +66 -0
- package/src/reactor/reactor-operators/convert.ts +70 -0
- package/src/reactor/reactor-operators/create.ts +66 -0
- package/src/reactor/reactor-operators/filter.ts +988 -0
- package/src/reactor/reactor-operators/index.ts +7 -0
- package/src/reactor/reactor-operators/join.ts +174 -0
- package/src/reactor/reactor-operators/map.ts +599 -0
- package/src/reactor/reactor-operators/utility.ts +102 -0
- package/tests/unit/{signal/computed.spec.ts → reactor/alien-signals-computed.spec.ts} +15 -10
- package/tests/unit/reactor/alien-signals-effect-scope.spec.ts +86 -0
- package/tests/unit/reactor/alien-signals-effect.spec.ts +395 -0
- package/tests/unit/reactor/alien-signals-topology.spec.ts +361 -0
- package/tests/unit/reactor/alien-signals-trigger.spec.ts +75 -0
- package/tests/unit/reactor/alien-signals-untrack.spec.ts +91 -0
- package/tests/unit/reactor/preact-signal.spec.ts +73 -0
- package/tests/unit/reactor/reactor-core.spec.ts +219 -0
- package/tests/unit/reactor/reactor-operators-branch.spec.ts +33 -0
- package/tests/unit/reactor/reactor-operators-convert.spec.ts +31 -0
- package/tests/unit/reactor/reactor-operators-create.spec.ts +47 -0
- package/tests/unit/reactor/reactor-operators-filter.spec.ts +604 -0
- package/tests/unit/reactor/reactor-operators-join.spec.ts +94 -0
- package/tests/unit/reactor/reactor-operators-map.spec.ts +327 -0
- package/tests/unit/reactor/reactor-operators-utility.spec.ts +55 -0
- package/dist/signal/index.d.ts +0 -3
- package/dist/signal/index.d.ts.map +0 -1
- package/dist/signal/signal-core/flags.d.ts.map +0 -1
- package/dist/signal/signal-core/index.d.ts.map +0 -1
- package/dist/signal/signal-core/primitive.d.ts +0 -67
- package/dist/signal/signal-core/primitive.d.ts.map +0 -1
- package/dist/signal/signal-core/reactive-system.d.ts.map +0 -1
- package/dist/signal/signal-operators/index.d.ts +0 -4
- package/dist/signal/signal-operators/index.d.ts.map +0 -1
- package/src/signal/index.ts +0 -2
- package/src/signal/signal-core/README.md +0 -4
- package/src/signal/signal-core/primitive.ts +0 -275
- package/src/signal/signal-operators/index.ts +0 -19
- package/tests/unit/signal/effect.spec.ts +0 -108
- /package/dist/{signal/signal-core → reactor/reactor-core}/flags.d.ts +0 -0
- /package/dist/{signal/signal-core → reactor/reactor-core}/index.d.ts +0 -0
- /package/src/{signal/signal-core → reactor/reactor-core}/flags.ts +0 -0
- /package/src/{signal/signal-core → reactor/reactor-core}/index.ts +0 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { computed, derived, effect, reactiveSystem, signal } from '#Source/reactor/index.ts';
|
|
4
|
+
|
|
5
|
+
test("should derived update activily or passively", () => {
|
|
6
|
+
const a = signal(() => 1);
|
|
7
|
+
const b = derived(() => {
|
|
8
|
+
return a.get() + 1;
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
expect(b.get()).toBe(2);
|
|
12
|
+
|
|
13
|
+
a.set(2);
|
|
14
|
+
expect(b.get()).toBe(3);
|
|
15
|
+
|
|
16
|
+
b.set(2);
|
|
17
|
+
expect(b.get()).toBe(2);
|
|
18
|
+
|
|
19
|
+
a.set(3);
|
|
20
|
+
expect(b.get()).toBe(4);
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test("should use isEqual from options", () => {
|
|
24
|
+
const a = signal(() => [] as number[], {
|
|
25
|
+
isEqual: (oldValue, newValue) => {
|
|
26
|
+
return oldValue.length === newValue.length;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
let effectRunTimes = 0;
|
|
30
|
+
effect(() => {
|
|
31
|
+
effectRunTimes = effectRunTimes + 1;
|
|
32
|
+
a.get();
|
|
33
|
+
})
|
|
34
|
+
expect(effectRunTimes).toBe(1);
|
|
35
|
+
|
|
36
|
+
a.set([1]);
|
|
37
|
+
expect(effectRunTimes).toBe(2);
|
|
38
|
+
|
|
39
|
+
a.set([2]);
|
|
40
|
+
expect(effectRunTimes).toBe(2);
|
|
41
|
+
|
|
42
|
+
a.set([3, 4]);
|
|
43
|
+
expect(effectRunTimes).toBe(3);
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test("should trigger callbacks", () => {
|
|
47
|
+
const logs: string[] = [];
|
|
48
|
+
const a = signal(() => 1, {
|
|
49
|
+
name: "a",
|
|
50
|
+
onDepChanged: () => logs.push("a dep changed"),
|
|
51
|
+
onSubChanged: () => logs.push("a sub changed"),
|
|
52
|
+
onHasDep: (dep) => logs.push(`a has first dep ${dep.getName()}`),
|
|
53
|
+
onNoDep: (dep) => logs.push(`a no dep ${dep.getName()}`),
|
|
54
|
+
onHasSub: (sub) => logs.push(`a has first sub ${sub.getName()}`),
|
|
55
|
+
onNoSub: (sub) => logs.push(`a no sub ${sub.getName()}`),
|
|
56
|
+
});
|
|
57
|
+
const b = signal(() => 2, {
|
|
58
|
+
name: "b",
|
|
59
|
+
onDepChanged: () => logs.push("b dep changed"),
|
|
60
|
+
onSubChanged: () => logs.push("b sub changed"),
|
|
61
|
+
onHasDep: (dep) => logs.push(`b has first dep ${dep.getName()}`),
|
|
62
|
+
onNoDep: (dep) => logs.push(`b no dep ${dep.getName()}`),
|
|
63
|
+
onHasSub: (sub) => logs.push(`b has first sub ${sub.getName()}`),
|
|
64
|
+
onNoSub: (sub) => logs.push(`b no sub ${sub.getName()}`),
|
|
65
|
+
});
|
|
66
|
+
const c = computed(() => a.get() + b.get(), {
|
|
67
|
+
name: "c",
|
|
68
|
+
onDepChanged: () => logs.push("c dep changed"),
|
|
69
|
+
onSubChanged: () => logs.push("c sub changed"),
|
|
70
|
+
onHasDep: (dep) => logs.push(`c has first dep ${dep.getName()}`),
|
|
71
|
+
onNoDep: (dep) => logs.push(`c no dep ${dep.getName()}`),
|
|
72
|
+
onHasSub: (sub) => logs.push(`c has first sub ${sub.getName()}`),
|
|
73
|
+
onNoSub: (sub) => logs.push(`c no sub ${sub.getName()}`),
|
|
74
|
+
});
|
|
75
|
+
const e = effect(() => {
|
|
76
|
+
c.get();
|
|
77
|
+
}, {
|
|
78
|
+
name: "e",
|
|
79
|
+
onDepChanged: () => logs.push("e dep changed"),
|
|
80
|
+
onSubChanged: () => logs.push("e sub changed"),
|
|
81
|
+
onHasDep: (dep) => logs.push(`e has first dep ${dep.getName()}`),
|
|
82
|
+
onNoDep: (dep) => logs.push(`e no dep ${dep.getName()}`),
|
|
83
|
+
onHasSub: (sub) => logs.push(`e has first sub ${sub.getName()}`),
|
|
84
|
+
onNoSub: (sub) => logs.push(`e no sub ${sub.getName()}`),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
expect(logs).toEqual([
|
|
88
|
+
"c sub changed",
|
|
89
|
+
"c has first sub e",
|
|
90
|
+
"e dep changed",
|
|
91
|
+
"e has first dep c",
|
|
92
|
+
"a sub changed",
|
|
93
|
+
"a has first sub c",
|
|
94
|
+
"c dep changed",
|
|
95
|
+
"c has first dep a",
|
|
96
|
+
"b sub changed",
|
|
97
|
+
"b has first sub c",
|
|
98
|
+
"c dep changed",
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
logs.length = 0;
|
|
102
|
+
a.set(3);
|
|
103
|
+
expect(logs).toEqual([
|
|
104
|
+
"c dep changed",
|
|
105
|
+
"c dep changed",
|
|
106
|
+
"e dep changed",
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
logs.length = 0;
|
|
110
|
+
e.dispose();
|
|
111
|
+
expect(logs).toEqual([
|
|
112
|
+
"c sub changed",
|
|
113
|
+
"c no sub e",
|
|
114
|
+
"a sub changed",
|
|
115
|
+
"a no sub c",
|
|
116
|
+
"c dep changed",
|
|
117
|
+
"b sub changed",
|
|
118
|
+
"b no sub c",
|
|
119
|
+
"c dep changed",
|
|
120
|
+
"c no dep b",
|
|
121
|
+
"e dep changed",
|
|
122
|
+
"e no dep c",
|
|
123
|
+
]);
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test("should trigger onDispose callback", () => {
|
|
127
|
+
const logs: string[] = [];
|
|
128
|
+
const a = signal(() => 1, {
|
|
129
|
+
name: "a",
|
|
130
|
+
onDispose: () => logs.push("a disposed"),
|
|
131
|
+
});
|
|
132
|
+
const b = derived(() => a.get() + 1, {
|
|
133
|
+
name: "b",
|
|
134
|
+
onDispose: () => logs.push("b disposed"),
|
|
135
|
+
});
|
|
136
|
+
const c = computed(() => b.get() + 1, {
|
|
137
|
+
name: "c",
|
|
138
|
+
onDispose: () => logs.push("c disposed"),
|
|
139
|
+
});
|
|
140
|
+
const e = effect(() => {
|
|
141
|
+
c.get();
|
|
142
|
+
}, {
|
|
143
|
+
name: "e",
|
|
144
|
+
onDispose: () => logs.push("e disposed"),
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
e.dispose();
|
|
148
|
+
expect(logs).toEqual([
|
|
149
|
+
"a disposed",
|
|
150
|
+
"b disposed",
|
|
151
|
+
"c disposed",
|
|
152
|
+
"e disposed",
|
|
153
|
+
]);
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test("should not track when getWithoutTrack", () => {
|
|
157
|
+
const a = signal(() => 0);
|
|
158
|
+
const b = signal(() => 1);
|
|
159
|
+
const c = computed(() => {
|
|
160
|
+
return a.get() + b.get();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
let effectRunTimes = 0;
|
|
164
|
+
effect(() => {
|
|
165
|
+
effectRunTimes = effectRunTimes + 1;
|
|
166
|
+
a.get();
|
|
167
|
+
c.getWithoutTrack();
|
|
168
|
+
});
|
|
169
|
+
expect(effectRunTimes).toBe(1);
|
|
170
|
+
|
|
171
|
+
a.set(2);
|
|
172
|
+
expect(effectRunTimes).toBe(2);
|
|
173
|
+
|
|
174
|
+
b.set(3);
|
|
175
|
+
expect(effectRunTimes).toBe(2);
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
test("should cleanup on stop and re-track on update", () => {
|
|
179
|
+
let cleanupRunTimes = 0;
|
|
180
|
+
const a = signal(() => 0);
|
|
181
|
+
const e = effect((context) => {
|
|
182
|
+
const { setCleanup } = context;
|
|
183
|
+
a.get();
|
|
184
|
+
setCleanup((): void => {
|
|
185
|
+
cleanupRunTimes = cleanupRunTimes + 1;
|
|
186
|
+
})
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
expect(cleanupRunTimes).toBe(0);
|
|
190
|
+
|
|
191
|
+
a.set(1);
|
|
192
|
+
expect(cleanupRunTimes).toBe(1);
|
|
193
|
+
|
|
194
|
+
a.set(2);
|
|
195
|
+
expect(cleanupRunTimes).toBe(2);
|
|
196
|
+
|
|
197
|
+
e.dispose();
|
|
198
|
+
expect(cleanupRunTimes).toBe(3);
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
test("should not track when withoutTracking", () => {
|
|
202
|
+
const a = signal(() => 0);
|
|
203
|
+
const b = signal(() => 1);
|
|
204
|
+
let effectRunTimes = 0;
|
|
205
|
+
effect(() => {
|
|
206
|
+
effectRunTimes = effectRunTimes + 1;
|
|
207
|
+
a.get();
|
|
208
|
+
reactiveSystem.withoutTracking(() => {
|
|
209
|
+
b.get();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
expect(effectRunTimes).toBe(1);
|
|
213
|
+
|
|
214
|
+
a.set(2);
|
|
215
|
+
expect(effectRunTimes).toBe(2);
|
|
216
|
+
|
|
217
|
+
b.set(3);
|
|
218
|
+
expect(effectRunTimes).toBe(2);
|
|
219
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
clone, partition, signal,
|
|
5
|
+
} from '#Source/reactor/index.ts';
|
|
6
|
+
|
|
7
|
+
test("clone operator should work correctly", () => {
|
|
8
|
+
const source = signal(() => 1);
|
|
9
|
+
const cloned = clone({ target: source });
|
|
10
|
+
expect(cloned.get()).toBe(1);
|
|
11
|
+
|
|
12
|
+
source.set(2);
|
|
13
|
+
expect(cloned.get()).toBe(2);
|
|
14
|
+
|
|
15
|
+
source.set(3);
|
|
16
|
+
expect(cloned.get()).toBe(3);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("partition operator should work correctly", () => {
|
|
20
|
+
const source = signal(() => 1);
|
|
21
|
+
const [even, odd] = partition({ target: source, predicate: (value) => value % 2 === 0 });
|
|
22
|
+
|
|
23
|
+
expect(even.get()).toBe(undefined);
|
|
24
|
+
expect(odd.get()).toBe(1);
|
|
25
|
+
|
|
26
|
+
source.set(2);
|
|
27
|
+
expect(even.get()).toBe(2);
|
|
28
|
+
expect(odd.get()).toBe(1);
|
|
29
|
+
|
|
30
|
+
source.set(3);
|
|
31
|
+
expect(even.get()).toBe(2);
|
|
32
|
+
expect(odd.get()).toBe(3);
|
|
33
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { fromPromiseAsync, fromPromiseSync, signal, toPromise } from '#Source/reactor/index.ts';
|
|
4
|
+
|
|
5
|
+
test("fromPromiseAsync operator should work correctly", async () => {
|
|
6
|
+
const a = await fromPromiseAsync({ target: Promise.resolve(42) });
|
|
7
|
+
expect(a.get()).toBe(42);
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test("fromPromiseSync operator should work correctly", async () => {
|
|
11
|
+
const a = fromPromiseSync({ target: Promise.resolve(42) });
|
|
12
|
+
const aPromise = toPromise({ target: a });
|
|
13
|
+
const value = await aPromise;
|
|
14
|
+
expect(value).toBe(42);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("toPromise operator should work correctly", async () => {
|
|
18
|
+
const a = signal(() => 0);
|
|
19
|
+
|
|
20
|
+
const aPromise = toPromise({ target: a });
|
|
21
|
+
a.set(1);
|
|
22
|
+
const value1 = await aPromise;
|
|
23
|
+
expect(value1).toBe(1);
|
|
24
|
+
|
|
25
|
+
const aPromise2 = toPromise({ target: a });
|
|
26
|
+
a.set(2);
|
|
27
|
+
const value2 = await aPromise2;
|
|
28
|
+
expect(value2).toBe(2);
|
|
29
|
+
a.set(3);
|
|
30
|
+
expect(value2).toBe(2);
|
|
31
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { interval, timer } from '#Source/reactor/index.ts';
|
|
4
|
+
|
|
5
|
+
test("timer operator should work correctly", async () => {
|
|
6
|
+
const tmr = timer({ delay: 100, interval: 50 });
|
|
7
|
+
|
|
8
|
+
expect(tmr.get()).toBe(0);
|
|
9
|
+
|
|
10
|
+
await new Promise((resolve) => {
|
|
11
|
+
setTimeout(resolve, 120);
|
|
12
|
+
});
|
|
13
|
+
expect(tmr.get()).toBe(1);
|
|
14
|
+
|
|
15
|
+
await new Promise((resolve) => {
|
|
16
|
+
setTimeout(resolve, 60);
|
|
17
|
+
});
|
|
18
|
+
expect(tmr.get()).toBe(2);
|
|
19
|
+
|
|
20
|
+
tmr.dispose();
|
|
21
|
+
await new Promise((resolve) => {
|
|
22
|
+
setTimeout(resolve, 100);
|
|
23
|
+
});
|
|
24
|
+
expect(tmr.get()).toBe(2);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("interval operator should work correctly", async () => {
|
|
28
|
+
const intv = interval({ interval: 50 });
|
|
29
|
+
|
|
30
|
+
expect(intv.get()).toBe(0);
|
|
31
|
+
|
|
32
|
+
await new Promise((resolve) => {
|
|
33
|
+
setTimeout(resolve, 120);
|
|
34
|
+
});
|
|
35
|
+
expect(intv.get()).toBe(2);
|
|
36
|
+
|
|
37
|
+
await new Promise((resolve) => {
|
|
38
|
+
setTimeout(resolve, 60);
|
|
39
|
+
});
|
|
40
|
+
expect(intv.get()).toBe(3);
|
|
41
|
+
|
|
42
|
+
intv.dispose();
|
|
43
|
+
await new Promise((resolve) => {
|
|
44
|
+
setTimeout(resolve, 100);
|
|
45
|
+
});
|
|
46
|
+
expect(intv.get()).toBe(3);
|
|
47
|
+
});
|