@ng-org/alien-deepsignals 0.1.2-alpha.11 → 0.1.2-alpha.12
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/core.d.ts +5 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +11 -11
- package/dist/deepSignal.d.ts +1 -1
- package/dist/deepSignal.d.ts.map +1 -1
- package/dist/deepSignal.js +16 -27
- package/dist/hooks/react/index.js +2 -8
- package/dist/hooks/react/useDeepSignal.d.ts +2 -2
- package/dist/hooks/react/useDeepSignal.d.ts.map +1 -1
- package/dist/hooks/react/useDeepSignal.js +11 -13
- package/dist/hooks/svelte/index.js +2 -8
- package/dist/hooks/svelte/useDeepSignal.svelte.d.ts +1 -1
- package/dist/hooks/svelte/useDeepSignal.svelte.d.ts.map +1 -1
- package/dist/hooks/svelte/useDeepSignal.svelte.js +6 -9
- package/dist/hooks/svelte4/index.js +2 -8
- package/dist/hooks/svelte4/useDeepSignal.svelte.d.ts +1 -1
- package/dist/hooks/svelte4/useDeepSignal.svelte.d.ts.map +1 -1
- package/dist/hooks/svelte4/useDeepSignal.svelte.js +14 -17
- package/dist/hooks/vue/index.d.ts +1 -1
- package/dist/hooks/vue/index.d.ts.map +1 -1
- package/dist/hooks/vue/index.js +2 -8
- package/dist/hooks/vue/useDeepSignal.d.ts +1 -1
- package/dist/hooks/vue/useDeepSignal.d.ts.map +1 -1
- package/dist/hooks/vue/useDeepSignal.js +6 -9
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -27
- package/dist/iteratorHelpers.js +2 -6
- package/dist/test/frontend/astro-app/src/components/ReactPanel.d.ts.map +1 -1
- package/dist/test/frontend/astro-app/src/components/ReactPanel.jsx +13 -51
- package/dist/test/frontend/playwright/crossFrameworkHooks.spec.js +24 -26
- package/dist/test/frontend/utils/mockData.js +16 -21
- package/dist/test/frontend/utils/paths.js +2 -6
- package/dist/test/frontend/utils/renderMetrics.js +5 -12
- package/dist/test/frontend/utils/state.d.ts +1 -1
- package/dist/test/frontend/utils/state.js +13 -17
- package/dist/test/lib/deepSignalOptions.test.js +66 -68
- package/dist/test/lib/index.test.js +373 -375
- package/dist/test/lib/misc.test.js +98 -100
- package/dist/test/lib/watch.test.js +355 -357
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -2
- package/dist/watch.d.ts +1 -1
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +6 -9
- package/package.json +2 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// Copyright (c) 2025 Laurin Weger, Par le Peuple, NextGraph.org developers
|
|
3
2
|
// All rights reserved.
|
|
4
3
|
// Licensed under the Apache License, Version 2.0
|
|
@@ -8,66 +7,65 @@
|
|
|
8
7
|
// notice may not be copied, modified, or distributed except
|
|
9
8
|
// according to those terms.
|
|
10
9
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
(
|
|
16
|
-
|
|
17
|
-
const st = (0, deepSignal_1.deepSignal)({ a: { b: { c: 1 } } });
|
|
10
|
+
import { describe, it, expect, vi } from "vitest";
|
|
11
|
+
import { deepSignal, getDeepSignalRootId } from "../../deepSignal.js";
|
|
12
|
+
import { watch } from "../../watch.js";
|
|
13
|
+
describe("watch advanced", () => {
|
|
14
|
+
it("basic patch watcher fires on deep mutations", async () => {
|
|
15
|
+
const st = deepSignal({ a: { b: { c: 1 } } });
|
|
18
16
|
let batches = 0;
|
|
19
|
-
|
|
17
|
+
watch(st, ({ patches }) => {
|
|
20
18
|
if (patches.length)
|
|
21
19
|
batches++;
|
|
22
20
|
});
|
|
23
21
|
st.a.b.c = 2;
|
|
24
22
|
st.a.b = { c: 3 };
|
|
25
23
|
await Promise.resolve();
|
|
26
|
-
|
|
24
|
+
expect(batches).toBeGreaterThan(0);
|
|
27
25
|
});
|
|
28
|
-
|
|
29
|
-
const st =
|
|
26
|
+
it("watch once option still stops after first batch", async () => {
|
|
27
|
+
const st = deepSignal({ a: 1 });
|
|
30
28
|
let count = 0;
|
|
31
|
-
|
|
29
|
+
watch(st, () => {
|
|
32
30
|
count++;
|
|
33
31
|
}, { once: true, immediate: true });
|
|
34
32
|
st.a = 2;
|
|
35
33
|
st.a = 3;
|
|
36
34
|
await Promise.resolve();
|
|
37
|
-
|
|
35
|
+
expect(count).toBe(1);
|
|
38
36
|
});
|
|
39
37
|
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const a =
|
|
43
|
-
const b =
|
|
44
|
-
|
|
38
|
+
describe("patches & root ids", () => {
|
|
39
|
+
it("root ids are unique", () => {
|
|
40
|
+
const a = deepSignal({});
|
|
41
|
+
const b = deepSignal({});
|
|
42
|
+
expect(getDeepSignalRootId(a)).not.toBe(getDeepSignalRootId(b));
|
|
45
43
|
});
|
|
46
44
|
// legacy watchPatches API removed; patch mode only valid for deepSignal roots
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
it("watch throws on non-deepSignal input", () => {
|
|
46
|
+
expect(() => watch({}, () => { })).toThrow();
|
|
49
47
|
});
|
|
50
|
-
|
|
48
|
+
it("Map unsupported does not emit patches", async () => {
|
|
51
49
|
const m = new Map();
|
|
52
|
-
const st =
|
|
50
|
+
const st = deepSignal({ m });
|
|
53
51
|
const patches = [];
|
|
54
|
-
const { stopListening: stop } =
|
|
52
|
+
const { stopListening: stop } = watch(st, ({ patches: batch }) => patches.push(batch));
|
|
55
53
|
m.set("a", 1);
|
|
56
54
|
await Promise.resolve();
|
|
57
55
|
await Promise.resolve();
|
|
58
|
-
|
|
56
|
+
expect(patches.length).toBe(0);
|
|
59
57
|
stop();
|
|
60
58
|
});
|
|
61
59
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const st =
|
|
60
|
+
describe("Set iteration variants", () => {
|
|
61
|
+
it("entries() iteration proxies nested mutation", async () => {
|
|
62
|
+
const st = deepSignal({ s: new Set() }, {
|
|
65
63
|
syntheticIdPropertyName: "id",
|
|
66
64
|
propGenerator: ({ object }) => ({ syntheticId: object.id }),
|
|
67
65
|
});
|
|
68
66
|
st.s.add({ id: "eEnt", inner: { v: 1 } });
|
|
69
67
|
const paths = [];
|
|
70
|
-
const { stopListening: stop } =
|
|
68
|
+
const { stopListening: stop } = watch(st, ({ patches }) => paths.push(...patches.map((pp) => pp.path.join("."))));
|
|
71
69
|
for (const [val] of st.s.entries()) {
|
|
72
70
|
val.inner.v;
|
|
73
71
|
} // ensure proxy
|
|
@@ -76,16 +74,16 @@ const watch_1 = require("../../watch");
|
|
|
76
74
|
}
|
|
77
75
|
await Promise.resolve();
|
|
78
76
|
await Promise.resolve();
|
|
79
|
-
|
|
77
|
+
expect(paths.some((p) => p.endsWith("eEnt.inner.v"))).toBe(true);
|
|
80
78
|
stop();
|
|
81
79
|
});
|
|
82
|
-
|
|
83
|
-
const st =
|
|
80
|
+
it("forEach iteration proxies nested mutation", async () => {
|
|
81
|
+
const st = deepSignal({ s: new Set() }, {
|
|
84
82
|
syntheticIdPropertyName: "id",
|
|
85
83
|
propGenerator: ({ object }) => ({ syntheticId: object.id }),
|
|
86
84
|
});
|
|
87
85
|
st.s.add({ id: "fe1", data: { n: 1 } });
|
|
88
|
-
const { stopListening: stop } =
|
|
86
|
+
const { stopListening: stop } = watch(st, () => { });
|
|
89
87
|
st.s.forEach((e) => e.data.n); // access
|
|
90
88
|
st.s.forEach((e) => {
|
|
91
89
|
e.data.n = 2;
|
|
@@ -94,13 +92,13 @@ const watch_1 = require("../../watch");
|
|
|
94
92
|
await Promise.resolve();
|
|
95
93
|
stop();
|
|
96
94
|
});
|
|
97
|
-
|
|
98
|
-
const st =
|
|
95
|
+
it("keys() iteration returns proxies", async () => {
|
|
96
|
+
const st = deepSignal({ s: new Set() }, {
|
|
99
97
|
syntheticIdPropertyName: "id",
|
|
100
98
|
propGenerator: ({ object }) => ({ syntheticId: object.id }),
|
|
101
99
|
});
|
|
102
100
|
st.s.add({ id: "k1", foo: { x: 1 } });
|
|
103
|
-
const { stopListening: stop } =
|
|
101
|
+
const { stopListening: stop } = watch(st, () => { });
|
|
104
102
|
for (const e of st.s.keys()) {
|
|
105
103
|
e.foo.x = 2;
|
|
106
104
|
}
|
|
@@ -108,41 +106,41 @@ const watch_1 = require("../../watch");
|
|
|
108
106
|
await Promise.resolve();
|
|
109
107
|
stop();
|
|
110
108
|
});
|
|
111
|
-
|
|
112
|
-
const st =
|
|
109
|
+
it("iterator helpers exist on Set iterators and the root Set", () => {
|
|
110
|
+
const st = deepSignal({ s: new Set([1, 2, 3]) });
|
|
113
111
|
const viaIterator = st.s
|
|
114
112
|
.values()
|
|
115
113
|
.map((value) => value * 2)
|
|
116
114
|
.filter((value) => value > 2)
|
|
117
115
|
.toArray();
|
|
118
|
-
|
|
116
|
+
expect(viaIterator).to.deep.equal([4, 6]);
|
|
119
117
|
const viaRoot = st.s
|
|
120
118
|
.map((value) => value + 1)
|
|
121
119
|
.take(2)
|
|
122
120
|
.toArray();
|
|
123
|
-
|
|
121
|
+
expect(viaRoot).to.deep.equal([2, 3]);
|
|
124
122
|
});
|
|
125
|
-
|
|
126
|
-
const st =
|
|
123
|
+
it("set iterator helpers return proxied objects", async () => {
|
|
124
|
+
const st = deepSignal({ s: new Set() }, {
|
|
127
125
|
syntheticIdPropertyName: "id",
|
|
128
126
|
propGenerator: ({ object }) => ({ syntheticId: object.id }),
|
|
129
127
|
});
|
|
130
128
|
st.s.add({ id: "obj1", nested: { value: 1 } });
|
|
131
129
|
const [entry] = st.s.map((value) => value).toArray();
|
|
132
130
|
const paths = [];
|
|
133
|
-
const { stopListening: stop } =
|
|
131
|
+
const { stopListening: stop } = watch(st, ({ patches }) => paths.push(...patches.map((pp) => pp.path.join("."))));
|
|
134
132
|
entry.nested.value = 5;
|
|
135
133
|
await Promise.resolve();
|
|
136
134
|
await Promise.resolve();
|
|
137
|
-
|
|
135
|
+
expect(paths.some((p) => p.endsWith("obj1.nested.value"))).to.equal(true);
|
|
138
136
|
stop();
|
|
139
137
|
});
|
|
140
138
|
});
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const onGet =
|
|
144
|
-
const onSet =
|
|
145
|
-
const ds =
|
|
139
|
+
describe("external subscribers", () => {
|
|
140
|
+
it("onGet / onSet are called for basic types", () => {
|
|
141
|
+
const onGet = vi.fn(() => { });
|
|
142
|
+
const onSet = vi.fn(() => { });
|
|
143
|
+
const ds = deepSignal({
|
|
146
144
|
s1: "str",
|
|
147
145
|
o1: {
|
|
148
146
|
i1: 1,
|
|
@@ -152,92 +150,92 @@ const watch_1 = require("../../watch");
|
|
|
152
150
|
let setCount = 0;
|
|
153
151
|
let getCount = 0;
|
|
154
152
|
ds.o1;
|
|
155
|
-
|
|
156
|
-
|
|
153
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 1));
|
|
154
|
+
expect(onSet).toHaveBeenCalledTimes(setCount);
|
|
157
155
|
ds.o1.b1;
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
157
|
+
expect(onSet).toHaveBeenCalledTimes(setCount);
|
|
160
158
|
ds.s1 = "new string";
|
|
161
|
-
|
|
159
|
+
expect(onGet).toHaveBeenCalledTimes(getCount);
|
|
162
160
|
// We didn't track s1 yet so set won't be called.
|
|
163
|
-
|
|
161
|
+
expect(onSet).toHaveBeenCalledTimes(setCount);
|
|
164
162
|
ds.s1;
|
|
165
163
|
ds.s1 = "new string2";
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 1));
|
|
165
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 1));
|
|
168
166
|
ds.o1 = { b1: true, i1: 2 };
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
expect(onGet).toHaveBeenCalledTimes(getCount);
|
|
168
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 1));
|
|
171
169
|
});
|
|
172
|
-
|
|
173
|
-
const onGet =
|
|
170
|
+
it("onGet / onSet are called for sets", () => {
|
|
171
|
+
const onGet = vi.fn(() => {
|
|
174
172
|
// No op
|
|
175
173
|
let a;
|
|
176
174
|
});
|
|
177
|
-
const onSet =
|
|
175
|
+
const onSet = vi.fn(() => {
|
|
178
176
|
// no op
|
|
179
177
|
let a;
|
|
180
178
|
});
|
|
181
|
-
const createSubscriber =
|
|
182
|
-
const ds =
|
|
179
|
+
const createSubscriber = vi.fn(() => ({ onGet, onSet }));
|
|
180
|
+
const ds = deepSignal({
|
|
183
181
|
set1: new Set([{ s1: "s1 in set" }]),
|
|
184
182
|
set2: new Set([1, 2, 3]),
|
|
185
183
|
}, { subscriberFactories: new Set([createSubscriber]) });
|
|
186
184
|
let setCount = 0;
|
|
187
185
|
let getCount = 0;
|
|
188
186
|
ds.set1.first().s1;
|
|
189
|
-
|
|
190
|
-
|
|
187
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 3));
|
|
188
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
191
189
|
ds.set1.first().s1 = "s1 new value";
|
|
192
|
-
|
|
193
|
-
|
|
190
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
191
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 1));
|
|
194
192
|
ds.set1.add({ s1: "s1.2 in set" });
|
|
195
|
-
|
|
196
|
-
|
|
193
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
194
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 1));
|
|
197
195
|
ds.set2.size; // Track.
|
|
198
196
|
ds.set2.delete(2);
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 4));
|
|
198
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 1));
|
|
201
199
|
ds.set2.delete(2);
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 1));
|
|
201
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
204
202
|
ds.set2.add(4);
|
|
205
|
-
|
|
206
|
-
|
|
203
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
204
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 1));
|
|
207
205
|
ds.set2.add(4);
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
206
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 1));
|
|
207
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
208
|
+
expect(ds.set2.has(4)).toBe(true);
|
|
209
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
210
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
213
211
|
const isDisjoint = ds.set2.isDisjointFrom(new Set([8]));
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
212
|
+
expect(isDisjoint).toBe(true);
|
|
213
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
214
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
215
|
+
expect(ds.set1.size).toBe(2);
|
|
216
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
217
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
218
|
+
expect(ds.set1.getById("")).toBe(undefined);
|
|
219
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 1));
|
|
220
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
223
221
|
ds.set2.clear();
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
223
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 1));
|
|
226
224
|
ds.set2.clear();
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 1));
|
|
226
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
229
227
|
let counter = 0;
|
|
230
228
|
for (const _item of ds.set1) {
|
|
231
229
|
counter += 1;
|
|
232
230
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
expect(counter).toBe(2);
|
|
232
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 2));
|
|
233
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
236
234
|
let concatenated = ds.set1.reduce((previous, current) => {
|
|
237
235
|
return `${previous}_${current.s1}`;
|
|
238
236
|
}, "");
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
237
|
+
expect(concatenated).toBe("_s1 new value_s1.2 in set");
|
|
238
|
+
expect(onGet).toHaveBeenCalledTimes((getCount += 4));
|
|
239
|
+
expect(onSet).toHaveBeenCalledTimes((setCount += 0));
|
|
242
240
|
});
|
|
243
241
|
});
|