@solid-primitives/deep 0.3.5 → 1.0.0-next.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/README.md +74 -35
- package/dist/store-updates.d.ts +1 -1
- package/dist/store-updates.js +47 -14
- package/dist/track-deep.d.ts +3 -3
- package/dist/track-deep.js +3 -4
- package/dist/track-store.d.ts +3 -3
- package/dist/track-store.js +17 -55
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
# @solid-primitives/deep
|
|
6
6
|
|
|
7
|
-
[](https://bundlephobia.com/package/@solid-primitives/deep)
|
|
8
8
|
[](https://www.npmjs.com/package/@solid-primitives/deep)
|
|
9
9
|
[](https://github.com/solidjs-community/solid-primitives#contribution-process)
|
|
10
|
+
[](https://vitest.dev)
|
|
10
11
|
|
|
11
12
|
Primitives for tracking and observing nested reactive objects in Solid.
|
|
12
13
|
|
|
@@ -14,6 +15,35 @@ Primitives for tracking and observing nested reactive objects in Solid.
|
|
|
14
15
|
- [`trackStore`](#trackstore) - A more performant alternative to `trackDeep` utilizing specific store implementations.
|
|
15
16
|
- [`captureStoreUpdates`](#capturestoreupdates) - A utility function that captures all updates to a store and returns them as an array.
|
|
16
17
|
|
|
18
|
+
## Comparison with Solid's built-in `deep`
|
|
19
|
+
|
|
20
|
+
Solid 2.0 ships a `deep` helper in `solid-js` that tracks all nested properties of a store and returns a **plain snapshot** — a non-reactive copy suitable for serialization:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { deep } from "solid-js";
|
|
24
|
+
|
|
25
|
+
createEffect(
|
|
26
|
+
() => deep(store),
|
|
27
|
+
snapshot => localStorage.setItem("state", JSON.stringify(snapshot)),
|
|
28
|
+
);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This package complements that with three distinct utilities:
|
|
32
|
+
|
|
33
|
+
| | Solid's `deep` | `trackDeep` | `trackStore` | `captureStoreUpdates` |
|
|
34
|
+
| -------------------------------------- | -------------- | ----------- | ------------ | --------------------- |
|
|
35
|
+
| Tracks all nested changes | ✓ | ✓ | ✓ | ✓ |
|
|
36
|
+
| Returns live store proxy | — | ✓ | ✓ | — |
|
|
37
|
+
| Returns plain snapshot | ✓ | — | — | — |
|
|
38
|
+
| Works on plain objects wrapping stores | — | ✓ | — | — |
|
|
39
|
+
| Reports what changed and where | — | — | — | ✓ |
|
|
40
|
+
|
|
41
|
+
**Use Solid's `deep`** when you want to observe all changes and immediately consume a serializable value (e.g. persist to localStorage, send over the wire).
|
|
42
|
+
|
|
43
|
+
**Use `trackDeep` or `trackStore`** when you need the live reactive proxy back — for example, to pass it reactively to another primitive, or when you want to decide what to do with the store rather than serialize it immediately. `trackStore` is preferred for large or frequently updated stores due to its use of memoized structural subscriptions; `trackDeep` additionally accepts plain objects that contain stores.
|
|
44
|
+
|
|
45
|
+
**Use `captureStoreUpdates`** when you need to know _what_ changed and _where_ — it returns an array of `{ path, value }` deltas since the last call. Solid's `deep` has no equivalent for this.
|
|
46
|
+
|
|
17
47
|
## Installation
|
|
18
48
|
|
|
19
49
|
```bash
|
|
@@ -41,20 +71,23 @@ import { trackDeep } from "@solid-primitives/deep";
|
|
|
41
71
|
|
|
42
72
|
const [state, setState] = createStore({ name: "John", age: 42 });
|
|
43
73
|
|
|
44
|
-
createEffect(
|
|
45
|
-
trackDeep(state)
|
|
46
|
-
|
|
47
|
-
|
|
74
|
+
createEffect(
|
|
75
|
+
() => trackDeep(state),
|
|
76
|
+
() => {
|
|
77
|
+
/* execute some logic whenever the state changes */
|
|
78
|
+
},
|
|
79
|
+
);
|
|
48
80
|
```
|
|
49
81
|
|
|
50
82
|
Or since this has a composable design, you can create _derivative_ functions and use them similar to derivative signals.
|
|
51
83
|
|
|
52
84
|
```ts
|
|
53
85
|
const deeplyTrackedStore = () => trackDeep(sign);
|
|
54
|
-
createEffect(
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
|
|
86
|
+
createEffect(
|
|
87
|
+
() => deeplyTrackedStore(),
|
|
88
|
+
// ^ this causes a re-execution of the effect on deep changes of properties
|
|
89
|
+
value => console.log("Store is:", value),
|
|
90
|
+
);
|
|
58
91
|
```
|
|
59
92
|
|
|
60
93
|
`trackDeep` will traverse any "wrappable" object _(objects that solid stores will wrap with proxies)_, even if it's not a solid store.
|
|
@@ -66,15 +99,17 @@ createEffect(() => {
|
|
|
66
99
|
});
|
|
67
100
|
```
|
|
68
101
|
|
|
69
|
-
> **Warning** If you `
|
|
102
|
+
> **Warning** If you `snapshot` a store, it will no longer be tracked by `trackDeep` nor `trackStore`!
|
|
70
103
|
|
|
71
104
|
```ts
|
|
72
|
-
|
|
105
|
+
import { snapshot } from "solid-js";
|
|
73
106
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
107
|
+
const plain = snapshot(state);
|
|
108
|
+
|
|
109
|
+
createEffect(
|
|
110
|
+
() => trackDeep(plain), // This will NOT work — plain objects are not reactive
|
|
111
|
+
() => {},
|
|
112
|
+
);
|
|
78
113
|
```
|
|
79
114
|
|
|
80
115
|
## `trackStore`
|
|
@@ -92,10 +127,12 @@ import { trackStore } from "@solid-primitives/deep";
|
|
|
92
127
|
|
|
93
128
|
const [state, setState] = createStore({ name: "John", age: 42 });
|
|
94
129
|
|
|
95
|
-
createEffect(
|
|
96
|
-
trackStore(state)
|
|
97
|
-
|
|
98
|
-
|
|
130
|
+
createEffect(
|
|
131
|
+
() => trackStore(state),
|
|
132
|
+
() => {
|
|
133
|
+
/* execute some logic whenever the state changes */
|
|
134
|
+
},
|
|
135
|
+
);
|
|
99
136
|
```
|
|
100
137
|
|
|
101
138
|
## `captureStoreUpdates`
|
|
@@ -115,7 +152,9 @@ const getDelta = captureStoreUpdates(state);
|
|
|
115
152
|
|
|
116
153
|
getDelta(); // [{ path: [], value: { todos: [] } }]
|
|
117
154
|
|
|
118
|
-
setState(
|
|
155
|
+
setState(s => {
|
|
156
|
+
s.todos = ["foo"];
|
|
157
|
+
});
|
|
119
158
|
|
|
120
159
|
getDelta(); // [{ path: ["todos"], value: ["foo"] }]
|
|
121
160
|
```
|
|
@@ -127,11 +166,13 @@ const [state, setState] = createStore({ todos: [] });
|
|
|
127
166
|
|
|
128
167
|
const getDelta = captureStoreUpdates(state);
|
|
129
168
|
|
|
130
|
-
createEffect(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
169
|
+
createEffect(
|
|
170
|
+
() => getDelta(),
|
|
171
|
+
delta => {
|
|
172
|
+
/* execute some logic whenever the state changes */
|
|
173
|
+
console.log(delta);
|
|
174
|
+
},
|
|
175
|
+
);
|
|
135
176
|
```
|
|
136
177
|
|
|
137
178
|
The returned function is not a signal - it won't get updated by itself, it has to be called manually, or under a tracking scope to capture new updates.
|
|
@@ -144,18 +185,16 @@ const [state, setState] = createStore({ todos: [] });
|
|
|
144
185
|
const delta = createMemo(captureStoreUpdates(state));
|
|
145
186
|
|
|
146
187
|
// both of these effects will receive the same delta
|
|
147
|
-
createEffect(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
188
|
+
createEffect(
|
|
189
|
+
() => delta(),
|
|
190
|
+
value => console.log(value),
|
|
191
|
+
);
|
|
192
|
+
createEffect(
|
|
193
|
+
() => delta(),
|
|
194
|
+
value => console.log(value),
|
|
195
|
+
);
|
|
153
196
|
```
|
|
154
197
|
|
|
155
|
-
### Demo
|
|
156
|
-
|
|
157
|
-
See a demo of this primitive in action [here](https://primitives.solidjs.community/playground/deep).
|
|
158
|
-
|
|
159
198
|
## Changelog
|
|
160
199
|
|
|
161
200
|
See [CHANGELOG.md](./CHANGELOG.md)
|
package/dist/store-updates.d.ts
CHANGED
package/dist/store-updates.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { createLazyMemo } from "@solid-primitives/memo";
|
|
2
|
-
import { $PROXY, $TRACK,
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { $PROXY, $TRACK, DEV, runWithOwner, untrack, snapshot } from "solid-js";
|
|
3
|
+
import { isServer } from "@solidjs/web";
|
|
4
|
+
// Typed iterator that preserves numeric keys for arrays vs. string keys for objects.
|
|
5
|
+
// Object.entries() returns [string, T][] even for arrays, losing the numeric key type,
|
|
6
|
+
// so arrays are iterated manually.
|
|
5
7
|
function* entries(obj) {
|
|
6
8
|
if (Array.isArray(obj)) {
|
|
7
9
|
for (let i = 0; i < obj.length; i++) {
|
|
@@ -14,18 +16,31 @@ function* entries(obj) {
|
|
|
14
16
|
yield* Object.entries(obj)[Symbol.iterator]();
|
|
15
17
|
}
|
|
16
18
|
}
|
|
19
|
+
// One lazy memo per store node, keyed by node identity. The memo re-runs whenever the node's
|
|
20
|
+
// structure changes ([$TRACK] subscription) and returns the current set of child store nodes.
|
|
21
|
+
// Detached from any owner so it lives as long as the node is reachable, then self-disposes.
|
|
17
22
|
const StoreNodeChildrenCache = new WeakMap();
|
|
23
|
+
// Returns the reactive snapshot of a node's direct store-node children.
|
|
24
|
+
// Uses a lazy memo so the computation is only created once per node, and only runs when read.
|
|
18
25
|
function getStoreNodechildren(node) {
|
|
19
26
|
let signal = StoreNodeChildrenCache.get(node);
|
|
20
27
|
if (!signal) {
|
|
21
|
-
const
|
|
22
|
-
|
|
28
|
+
const isArray = Array.isArray(node);
|
|
29
|
+
// runWithOwner(null) detaches the memo from any current reactive owner so it won't be
|
|
30
|
+
// disposed when a caller's effect re-runs. It self-disposes when it has no subscribers.
|
|
31
|
+
signal = runWithOwner(null, () => createLazyMemo(() => {
|
|
32
|
+
// Subscribe to structural changes (key additions/removals) on this node.
|
|
23
33
|
node[$TRACK];
|
|
34
|
+
// snapshot() inside untrack() gives us the plain key list without subscribing to
|
|
35
|
+
// individual property signals — we only want to know which keys exist, not their values.
|
|
36
|
+
const unwrapped = untrack(() => snapshot(node));
|
|
24
37
|
const children = isArray ? [] : {};
|
|
25
38
|
for (const [key, child] of entries(unwrapped)) {
|
|
26
39
|
let childNode;
|
|
27
40
|
if (child != null &&
|
|
28
41
|
typeof child === "object" &&
|
|
42
|
+
// Prefer the proxy stored on the plain value ($PROXY), falling back to reading the
|
|
43
|
+
// key through the live store proxy (which re-wraps nested objects on access).
|
|
29
44
|
((childNode = child[$PROXY]) ||
|
|
30
45
|
((childNode = untrack(() => node[key])) && $TRACK in childNode))) {
|
|
31
46
|
children[key] = childNode;
|
|
@@ -37,29 +52,42 @@ function getStoreNodechildren(node) {
|
|
|
37
52
|
}
|
|
38
53
|
return signal();
|
|
39
54
|
}
|
|
55
|
+
// Module-level globals, reset at the start of every getDelta() call.
|
|
56
|
+
// Safe because JS is single-threaded — no two calls can interleave.
|
|
40
57
|
let CurrentUpdates;
|
|
41
58
|
let SeenNodes;
|
|
59
|
+
// Builds a fresh cache entry for a node that was added or changed.
|
|
60
|
+
// Recursively pre-populates children so future calls can diff them.
|
|
42
61
|
function newCacheNode(children) {
|
|
43
62
|
const record = { ...children };
|
|
44
63
|
for (const [key, node] of entries(children)) {
|
|
45
64
|
if (SeenNodes.has(node))
|
|
46
|
-
continue;
|
|
65
|
+
continue; // guard against circular references
|
|
47
66
|
SeenNodes.add(node);
|
|
48
67
|
record[key] = newCacheNode(getStoreNodechildren(node));
|
|
49
68
|
}
|
|
50
69
|
return { children, record };
|
|
51
70
|
}
|
|
71
|
+
// Walks the store tree, diffing each node against its cached snapshot.
|
|
72
|
+
// A node is "changed" when its children reference differs from the cached one —
|
|
73
|
+
// getStoreNodechildren() returns a stable reference when nothing has changed,
|
|
74
|
+
// so a strict equality check is sufficient and cheap.
|
|
75
|
+
// When a change is found, the whole subtree is re-cached and reported as a single
|
|
76
|
+
// update at the shallowest changed node (so leaf changes inside an object are reported
|
|
77
|
+
// as one update on the parent object, not one per leaf).
|
|
52
78
|
function compareStoreWithCache(node, parent, key, path) {
|
|
53
79
|
if (SeenNodes.has(node))
|
|
54
|
-
return;
|
|
80
|
+
return; // guard against circular references
|
|
55
81
|
SeenNodes.add(node);
|
|
56
82
|
const cacheNode = parent[key], children = getStoreNodechildren(node);
|
|
57
83
|
if (cacheNode && children === cacheNode.children) {
|
|
84
|
+
// Node itself is unchanged; recurse to check its children.
|
|
58
85
|
for (const [key, child] of entries(children)) {
|
|
59
86
|
compareStoreWithCache(child, cacheNode.record, key, [...path, key]);
|
|
60
87
|
}
|
|
61
88
|
}
|
|
62
89
|
else {
|
|
90
|
+
// Node is new or its structure changed — record it and rebuild its subtree cache.
|
|
63
91
|
parent[key] = newCacheNode(children);
|
|
64
92
|
CurrentUpdates.push({ path, value: node });
|
|
65
93
|
}
|
|
@@ -82,25 +110,30 @@ function compareStoreWithCache(node, parent, key, path) {
|
|
|
82
110
|
*
|
|
83
111
|
* getDelta(); // [{ path: [], value: { todos: [] } }]
|
|
84
112
|
*
|
|
85
|
-
* setState(
|
|
113
|
+
* setState(s => { s.todos = ["foo"]; });
|
|
86
114
|
*
|
|
87
115
|
* getDelta(); // [{ path: ["todos"], value: ["foo"] }]
|
|
88
116
|
* ```
|
|
89
117
|
*/
|
|
90
118
|
export function captureStoreUpdates(store) {
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
if (isServer
|
|
94
|
-
|
|
119
|
+
// On the server $TRACK is not present on store proxies, so we can't diff.
|
|
120
|
+
// Return the whole store on the first call and nothing thereafter.
|
|
121
|
+
if (isServer) {
|
|
122
|
+
let init = true;
|
|
123
|
+
return () => (init ? ((init = false), [{ path: [], value: store }]) : []);
|
|
124
|
+
}
|
|
125
|
+
if (!(typeof store === "object" && store !== null && $TRACK in store)) {
|
|
126
|
+
if (DEV) {
|
|
95
127
|
// eslint-disable-next-line no-console
|
|
96
|
-
console.warn("
|
|
128
|
+
console.warn("captureStoreUpdates expects a store, got", store);
|
|
97
129
|
}
|
|
98
130
|
let init = true;
|
|
99
131
|
return () => (init ? ((init = false), [{ path: [], value: store }]) : []);
|
|
100
132
|
}
|
|
133
|
+
// The root cache entry — "root" is a synthetic key so compareStoreWithCache can write
|
|
134
|
+
// cache[key] uniformly without special-casing the top level.
|
|
101
135
|
const cache = {};
|
|
102
136
|
return () => {
|
|
103
|
-
// set globals before each cycle
|
|
104
137
|
CurrentUpdates = [];
|
|
105
138
|
SeenNodes = new WeakSet();
|
|
106
139
|
compareStoreWithCache(store, cache, "root", []);
|
package/dist/track-deep.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Store } from "solid-js
|
|
1
|
+
import { type Store } from "solid-js";
|
|
2
2
|
/**
|
|
3
3
|
* Tracks all properties of a {@link store} by iterating over them recursively.
|
|
4
4
|
*
|
|
@@ -9,12 +9,12 @@ import { type Store } from "solid-js/store";
|
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```ts
|
|
12
|
-
* createEffect(
|
|
12
|
+
* createEffect(
|
|
13
13
|
* () => trackDeep(store),
|
|
14
14
|
* () => {
|
|
15
15
|
* // this effect will run when any property of store changes
|
|
16
16
|
* }
|
|
17
|
-
* )
|
|
17
|
+
* );
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
declare function trackDeep<T extends Store<object>>(store: T): T;
|
package/dist/track-deep.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { $PROXY } from "solid-js";
|
|
2
|
-
import {} from "solid-js/store";
|
|
3
2
|
/**
|
|
4
3
|
* Tracks all properties of a {@link store} by iterating over them recursively.
|
|
5
4
|
*
|
|
@@ -10,12 +9,12 @@ import {} from "solid-js/store";
|
|
|
10
9
|
*
|
|
11
10
|
* @example
|
|
12
11
|
* ```ts
|
|
13
|
-
* createEffect(
|
|
12
|
+
* createEffect(
|
|
14
13
|
* () => trackDeep(store),
|
|
15
14
|
* () => {
|
|
16
15
|
* // this effect will run when any property of store changes
|
|
17
16
|
* }
|
|
18
|
-
* )
|
|
17
|
+
* );
|
|
19
18
|
* ```
|
|
20
19
|
*/
|
|
21
20
|
function trackDeep(store) {
|
|
@@ -25,7 +24,7 @@ function trackDeep(store) {
|
|
|
25
24
|
function traverse(value, seen) {
|
|
26
25
|
let isArray;
|
|
27
26
|
let proto;
|
|
28
|
-
// check the same conditions as in `isWrappable` from
|
|
27
|
+
// check the same conditions as in `isWrappable` from solid's store implementation
|
|
29
28
|
if (value != null &&
|
|
30
29
|
typeof value === "object" &&
|
|
31
30
|
!seen.has(value) &&
|
package/dist/track-store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Store } from "solid-js
|
|
1
|
+
import { type Store } from "solid-js";
|
|
2
2
|
/**
|
|
3
3
|
* Tracks all nested changes to passed {@link store}.
|
|
4
4
|
*
|
|
@@ -9,12 +9,12 @@ import { type Store } from "solid-js/store";
|
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```ts
|
|
12
|
-
* createEffect(
|
|
12
|
+
* createEffect(
|
|
13
13
|
* () => trackStore(store),
|
|
14
14
|
* () => {
|
|
15
15
|
* // this effect will run when any property of store changes
|
|
16
16
|
* }
|
|
17
|
-
* )
|
|
17
|
+
* );
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
declare function trackStore<T extends object>(store: Store<T>): T;
|
package/dist/track-store.js
CHANGED
|
@@ -1,54 +1,4 @@
|
|
|
1
|
-
import { $
|
|
2
|
-
import { unwrap } from "solid-js/store";
|
|
3
|
-
const EQUALS_FALSE = { equals: false };
|
|
4
|
-
const TrackStoreCache = new WeakMap();
|
|
5
|
-
// for preventing the same object to be visited multiple times in the same trackStore call
|
|
6
|
-
let TrackVersion = 0;
|
|
7
|
-
function getTrackStoreNode(node) {
|
|
8
|
-
let track = TrackStoreCache.get(node);
|
|
9
|
-
if (!track) {
|
|
10
|
-
createRoot(() => {
|
|
11
|
-
const unwrapped = unwrap(node);
|
|
12
|
-
// custom lazy memo to support circular references
|
|
13
|
-
// maybe it won't be needed in solid 2.0
|
|
14
|
-
let is_reading = false;
|
|
15
|
-
let is_stale = true;
|
|
16
|
-
let version = 0;
|
|
17
|
-
const [signal, trigger] = createSignal(undefined, EQUALS_FALSE);
|
|
18
|
-
const memo = createMemo(() => {
|
|
19
|
-
if (is_reading) {
|
|
20
|
-
node[$TRACK]; // shallow track store node
|
|
21
|
-
// track each child node
|
|
22
|
-
for (const [key, child] of Object.entries(unwrapped)) {
|
|
23
|
-
let childNode;
|
|
24
|
-
if (child != null &&
|
|
25
|
-
typeof child === "object" &&
|
|
26
|
-
((childNode = child[$PROXY]) || $TRACK in (childNode = untrack(() => node[key])))) {
|
|
27
|
-
getTrackStoreNode(childNode)?.();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
signal();
|
|
33
|
-
is_stale = true;
|
|
34
|
-
}
|
|
35
|
-
}, undefined, EQUALS_FALSE);
|
|
36
|
-
track = () => {
|
|
37
|
-
is_reading = true;
|
|
38
|
-
if (is_stale) {
|
|
39
|
-
trigger();
|
|
40
|
-
is_stale = false;
|
|
41
|
-
}
|
|
42
|
-
const already_tracked = version === TrackVersion;
|
|
43
|
-
version = TrackVersion;
|
|
44
|
-
already_tracked || memo();
|
|
45
|
-
is_reading = false;
|
|
46
|
-
};
|
|
47
|
-
TrackStoreCache.set(node, track);
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
return track;
|
|
51
|
-
}
|
|
1
|
+
import { $TRACK } from "solid-js";
|
|
52
2
|
/**
|
|
53
3
|
* Tracks all nested changes to passed {@link store}.
|
|
54
4
|
*
|
|
@@ -59,17 +9,29 @@ function getTrackStoreNode(node) {
|
|
|
59
9
|
*
|
|
60
10
|
* @example
|
|
61
11
|
* ```ts
|
|
62
|
-
* createEffect(
|
|
12
|
+
* createEffect(
|
|
63
13
|
* () => trackStore(store),
|
|
64
14
|
* () => {
|
|
65
15
|
* // this effect will run when any property of store changes
|
|
66
16
|
* }
|
|
67
|
-
* )
|
|
17
|
+
* );
|
|
68
18
|
* ```
|
|
69
19
|
*/
|
|
70
20
|
function trackStore(store) {
|
|
71
|
-
|
|
72
|
-
$TRACK in store && getTrackStoreNode(store)?.();
|
|
21
|
+
traverseStore(store, new Set());
|
|
73
22
|
return store;
|
|
74
23
|
}
|
|
24
|
+
function traverseStore(node, seen) {
|
|
25
|
+
if (!($TRACK in node) || seen.has(node))
|
|
26
|
+
return;
|
|
27
|
+
seen.add(node);
|
|
28
|
+
// subscribe to structural changes (additions/removals)
|
|
29
|
+
node[$TRACK];
|
|
30
|
+
// access all values through the proxy to subscribe to getters and collect children
|
|
31
|
+
for (const child of Object.values(node)) {
|
|
32
|
+
if (child != null && typeof child === "object") {
|
|
33
|
+
traverseStore(child, seen);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
75
37
|
export { trackStore };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solid-primitives/deep",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-next.0",
|
|
4
4
|
"description": "Primitives for tracking and observing nested reactive objects in Solid.",
|
|
5
5
|
"author": "Samuel Burbano <me@iosamuel.dev>",
|
|
6
6
|
"contributors": [
|
|
@@ -17,13 +17,14 @@
|
|
|
17
17
|
},
|
|
18
18
|
"primitive": {
|
|
19
19
|
"name": "deep",
|
|
20
|
-
"stage":
|
|
20
|
+
"stage": 3,
|
|
21
21
|
"list": [
|
|
22
22
|
"trackDeep",
|
|
23
23
|
"trackStore",
|
|
24
24
|
"captureStoreUpdates"
|
|
25
25
|
],
|
|
26
|
-
"category": "Reactivity"
|
|
26
|
+
"category": "Reactivity",
|
|
27
|
+
"gzip": 1298
|
|
27
28
|
},
|
|
28
29
|
"keywords": [
|
|
29
30
|
"solid",
|
|
@@ -51,16 +52,17 @@
|
|
|
51
52
|
},
|
|
52
53
|
"typesVersions": {},
|
|
53
54
|
"dependencies": {
|
|
54
|
-
"@solid-primitives/memo": "^
|
|
55
|
+
"@solid-primitives/memo": "^2.0.0-next.0"
|
|
55
56
|
},
|
|
56
57
|
"peerDependencies": {
|
|
57
|
-
"
|
|
58
|
+
"@solidjs/web": "^2.0.0-beta.15",
|
|
59
|
+
"solid-js": "^2.0.0-beta.15"
|
|
58
60
|
},
|
|
59
61
|
"devDependencies": {
|
|
60
|
-
"
|
|
62
|
+
"@solidjs/web": "2.0.0-beta.15",
|
|
63
|
+
"solid-js": "2.0.0-beta.15"
|
|
61
64
|
},
|
|
62
65
|
"scripts": {
|
|
63
|
-
"dev": "node --import=@nothing-but/node-resolve-ts --experimental-transform-types ../../scripts/dev.ts",
|
|
64
66
|
"build": "node --import=@nothing-but/node-resolve-ts --experimental-transform-types ../../scripts/build.ts",
|
|
65
67
|
"vitest": "vitest -c ../../configs/vitest.config.ts",
|
|
66
68
|
"test": "pnpm run vitest",
|