@solidjs/signals 2.0.0-beta.23 → 2.0.0-beta.25
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/dev.js +615 -125
- package/dist/node.cjs +1551 -1092
- package/dist/prod/core/core.js +106 -69
- package/dist/prod/core/effect.js +9 -9
- package/dist/prod/core/error.js +9 -0
- package/dist/prod/core/graph.js +3 -3
- package/dist/prod/core/heap.js +12 -12
- package/dist/prod/core/optimistic.js +6 -4
- package/dist/prod/core/owner.js +10 -10
- package/dist/prod/core/scheduler.js +6 -6
- package/dist/prod/core/verdict.js +2 -2
- package/dist/prod/map.js +53 -29
- package/dist/prod/store/optimistic.js +40 -31
- package/dist/prod/store/projection.js +25 -18
- package/dist/prod/store/reconcile.js +433 -208
- package/dist/prod/store/store.js +250 -116
- package/dist/prod/store/utils.js +34 -22
- package/dist/types/core/core.d.ts +15 -0
- package/dist/types/core/error.d.ts +1 -1
- package/dist/types/store/optimistic.d.ts +1 -1
- package/dist/types/store/reconcile.d.ts +17 -8
- package/dist/types/store/store.d.ts +20 -2
- package/dist/types-cjs/core/core.d.cts +15 -0
- package/dist/types-cjs/core/error.d.cts +1 -1
- package/dist/types-cjs/store/optimistic.d.cts +1 -1
- package/dist/types-cjs/store/reconcile.d.cts +17 -8
- package/dist/types-cjs/store/store.d.cts +20 -2
- package/package.json +1 -1
package/dist/prod/store/utils.js
CHANGED
|
@@ -12,14 +12,14 @@ import "../core/effect.js";
|
|
|
12
12
|
|
|
13
13
|
import { createMemo } from "../signals.js";
|
|
14
14
|
|
|
15
|
-
import { ownEnumerableKeys, $PROXY, isWrappable, $TARGET, trackSelf, witnessAffectsMark, mergedOverlay, STORE_VALUE, storeLookup, STORE_LOOKUP, $DELETED, wrap, getStoreSymbols, getPropertyDescriptor, getStoreKeys, getKeys, $TRACK } from "./store.js";
|
|
15
|
+
import { ownEnumerableKeys, $PROXY, isWrappable, $TARGET, lookupTarget, trackSelf, witnessAffectsMark, mergedOverlay, STORE_VALUE, storeLookup, STORE_LOOKUP, $DELETED, wrap, getStoreSymbols, getPropertyDescriptor, getStoreKeys, getKeys, $TRACK, rawValuesUsed, isRawValue } from "./store.js";
|
|
16
16
|
|
|
17
17
|
function snapshotImpl(e, t, r, n) {
|
|
18
18
|
let o, s, i, c, f, u;
|
|
19
19
|
if (!isWrappable(e)) return e;
|
|
20
20
|
if (r && r.has(e)) return r.get(e);
|
|
21
21
|
if (!r) r = new Map;
|
|
22
|
-
if (o = e[$TARGET] ||
|
|
22
|
+
if (o = e[$TARGET] || lookupTarget(e, n)) {
|
|
23
23
|
if (t) {
|
|
24
24
|
trackSelf(o, $TRACK);
|
|
25
25
|
// A tracked walk reads THROUGH the record without touching the proxy
|
|
@@ -27,6 +27,18 @@ function snapshotImpl(e, t, r, n) {
|
|
|
27
27
|
if (pendingCheckActive) witnessAffectsMark(o);
|
|
28
28
|
}
|
|
29
29
|
i = mergedOverlay(o);
|
|
30
|
+
// A derived store's STORE_VALUE is the inner store's live proxy
|
|
31
|
+
// (store-in-store: createOptimisticStore/createProjection over a store).
|
|
32
|
+
// Without an overlay of its own, the fast path below would map to — and
|
|
33
|
+
// could return — that proxy verbatim. Recurse instead so the
|
|
34
|
+
// inner store's own target branch unwraps it (chains of any depth).
|
|
35
|
+
// With an overlay, a fresh `result` is always built, so the walk over the
|
|
36
|
+
// inner proxy already copies plain values.
|
|
37
|
+
if (!i && o[STORE_VALUE][$TARGET]) {
|
|
38
|
+
f = snapshotImpl(o[STORE_VALUE], t, r, n);
|
|
39
|
+
r.set(e, f);
|
|
40
|
+
return f;
|
|
41
|
+
}
|
|
30
42
|
s = Array.isArray(o[STORE_VALUE]);
|
|
31
43
|
r.set(e, i ? c = s ? [] : Object.create(Object.getPrototypeOf(o[STORE_VALUE])) : o[STORE_VALUE]);
|
|
32
44
|
e = o[STORE_VALUE];
|
|
@@ -37,24 +49,24 @@ function snapshotImpl(e, t, r, n) {
|
|
|
37
49
|
}
|
|
38
50
|
if (s) {
|
|
39
51
|
const s = i?.length ?? e.length;
|
|
40
|
-
for (let
|
|
41
|
-
u = i &&
|
|
52
|
+
for (let a = 0; a < s; a++) {
|
|
53
|
+
u = i && a in i ? i[a] : e[a];
|
|
42
54
|
if (u === $DELETED) continue;
|
|
43
|
-
if (t && isWrappable(u)) wrap(u, o);
|
|
55
|
+
if (t && isWrappable(u) && !(rawValuesUsed && isRawValue(u))) wrap(u, o);
|
|
44
56
|
if ((f = snapshotImpl(u, t, r, n)) !== u || c) {
|
|
45
57
|
if (!c) r.set(e, c = [ ...e ]);
|
|
46
|
-
c[
|
|
58
|
+
c[a] = f;
|
|
47
59
|
}
|
|
48
60
|
}
|
|
49
61
|
// Enumerate array symbols separately to avoid scanning indices twice.
|
|
50
62
|
// Spread copies omit symbols, so assign them after the numeric walk.
|
|
51
|
-
const
|
|
52
|
-
for (let s = 0, l =
|
|
53
|
-
const l =
|
|
54
|
-
const
|
|
55
|
-
if (!
|
|
63
|
+
const a = n ? getStoreSymbols(e, i) : [];
|
|
64
|
+
for (let s = 0, l = a.length; s < l; s++) {
|
|
65
|
+
const l = a[s];
|
|
66
|
+
const p = getPropertyDescriptor(e, i, l);
|
|
67
|
+
if (!p || p.get) continue;
|
|
56
68
|
u = i && l in i ? i[l] : e[l];
|
|
57
|
-
if (t && isWrappable(u)) wrap(u, o);
|
|
69
|
+
if (t && isWrappable(u) && !(rawValuesUsed && isRawValue(u))) wrap(u, o);
|
|
58
70
|
f = snapshotImpl(u, t, r, n);
|
|
59
71
|
if (f !== u || c) {
|
|
60
72
|
if (!c) r.set(e, c = Object.assign([ ...e ], e));
|
|
@@ -71,30 +83,30 @@ function snapshotImpl(e, t, r, n) {
|
|
|
71
83
|
// A lookup means this object belongs to an immutable store backing tree,
|
|
72
84
|
// even if that nested value has not needed its own proxy yet.
|
|
73
85
|
const s = n ? getStoreKeys(e, undefined) : getKeys(e, undefined);
|
|
74
|
-
for (let i = 0,
|
|
75
|
-
const
|
|
76
|
-
const l = Object.getOwnPropertyDescriptor(e,
|
|
86
|
+
for (let i = 0, a = s.length; i < a; i++) {
|
|
87
|
+
const a = s[i];
|
|
88
|
+
const l = Object.getOwnPropertyDescriptor(e, a);
|
|
77
89
|
if (l.get) continue;
|
|
78
90
|
u = l.value;
|
|
79
|
-
if (t && isWrappable(u)) wrap(u, o);
|
|
91
|
+
if (t && isWrappable(u) && !(rawValuesUsed && isRawValue(u))) wrap(u, o);
|
|
80
92
|
if ((f = snapshotImpl(u, t, r, n)) !== u || c) {
|
|
81
93
|
if (!c) {
|
|
82
94
|
c = Object.create(Object.getPrototypeOf(e));
|
|
83
95
|
Object.assign(c, e);
|
|
84
96
|
}
|
|
85
|
-
c[
|
|
97
|
+
c[a] = f;
|
|
86
98
|
}
|
|
87
99
|
}
|
|
88
100
|
} else {
|
|
89
101
|
// An override only exists on a store record, and the target branch above
|
|
90
102
|
// always set `lookup` alongside it — so this branch is always store-keyed.
|
|
91
103
|
const s = getStoreKeys(e, i);
|
|
92
|
-
for (let
|
|
93
|
-
let l = s[
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
104
|
+
for (let a = 0, l = s.length; a < l; a++) {
|
|
105
|
+
let l = s[a];
|
|
106
|
+
const p = getPropertyDescriptor(e, i, l);
|
|
107
|
+
if (p.get) continue;
|
|
96
108
|
u = l in i ? i[l] : e[l];
|
|
97
|
-
if (t && isWrappable(u)) wrap(u, o);
|
|
109
|
+
if (t && isWrappable(u) && !(rawValuesUsed && isRawValue(u))) wrap(u, o);
|
|
98
110
|
if ((f = snapshotImpl(u, t, r, n)) !== e[l] || c) {
|
|
99
111
|
if (!c) {
|
|
100
112
|
c = Object.create(Object.getPrototypeOf(e));
|
|
@@ -72,6 +72,21 @@ export declare function untrack<T>(fn: () => T, strictReadLabel?: string | false
|
|
|
72
72
|
* date so its status flags reflect the current graph.
|
|
73
73
|
*/
|
|
74
74
|
export declare function prepareComputed(comp: Computed<unknown>, refresh: boolean): void;
|
|
75
|
+
/**
|
|
76
|
+
* Sentinel returned by readNodeFast when the plain-signal fast path does not
|
|
77
|
+
* apply and the caller must fall back to the full read().
|
|
78
|
+
*/
|
|
79
|
+
export declare const READ_SLOW: unique symbol;
|
|
80
|
+
/**
|
|
81
|
+
* read()'s plain-signal fast path as a standalone entry for hot callers
|
|
82
|
+
* (store traps). Safe to substitute for read() only because the bail
|
|
83
|
+
* conditions mirror read()'s prelude and fast-path guard exactly: the
|
|
84
|
+
* latestRead and pendingCheck windows run side-effectful hooks before the
|
|
85
|
+
* fast path, `_fn` nodes need prepareComputed, and firewall / override /
|
|
86
|
+
* snapshot / transition / lane / dev-strictRead state all take the full
|
|
87
|
+
* resolution. Anything slow returns READ_SLOW; the caller then calls read().
|
|
88
|
+
*/
|
|
89
|
+
export declare function readNodeFast<T>(el: Signal<T>): T | typeof READ_SLOW;
|
|
75
90
|
export declare function read<T>(el: Signal<T> | Computed<T>): T;
|
|
76
91
|
export declare function setSignal<T>(el: Signal<T> | Computed<T>, v: T | ((prev: T) => T)): T;
|
|
77
92
|
/**
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
export declare class NotReadyError extends Error {
|
|
26
|
-
source: any;
|
|
27
26
|
/**
|
|
28
27
|
* Tags a visibility-only notification on the affects() boundary channel:
|
|
29
28
|
* boundaries update display state from it, but the root queue never
|
|
@@ -31,6 +30,7 @@ export declare class NotReadyError extends Error {
|
|
|
31
30
|
* construction.
|
|
32
31
|
*/
|
|
33
32
|
_markVisual?: boolean;
|
|
33
|
+
source: any;
|
|
34
34
|
constructor(source: any);
|
|
35
35
|
}
|
|
36
36
|
export declare class StatusError extends Error {
|
|
@@ -41,5 +41,5 @@ import { type NoFn, type ProjectionOptions, type Store, type StoreSetter } from
|
|
|
41
41
|
*
|
|
42
42
|
* @returns `[store: Store<T>, setStore: StoreSetter<T>]`
|
|
43
43
|
*/
|
|
44
|
-
export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T
|
|
44
|
+
export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
|
|
45
45
|
export declare function createOptimisticStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Returns a draft-mutating function that smart-merges `value` into a store,
|
|
3
|
-
* preserving
|
|
4
|
-
* new states. Useful when applying server payloads or full-replacement data
|
|
5
|
-
* onto an existing store without losing fine-grained reactivity.
|
|
3
|
+
* preserving fine-grained reactivity: only changed leaves trigger updates.
|
|
6
4
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* With a `key` (default `"id"`), array items whose key matches between old
|
|
6
|
+
* and new states keep their identity (updated in place, moves and removals
|
|
7
|
+
* update the corresponding signals) — the shape for keyed server payloads.
|
|
8
|
+
* Items without the key field fall back to positional matching.
|
|
9
|
+
*
|
|
10
|
+
* With `key: null`, matching is purely positional: index N of the new array
|
|
11
|
+
* merges into index N of the old, and object properties merge recursively —
|
|
12
|
+
* the classic pattern for fixed-shape data that churns in place (dashboards,
|
|
13
|
+
* monitors), where no keyed diff pass is needed or wanted.
|
|
9
14
|
*
|
|
10
15
|
* @param value the next state to merge in
|
|
11
|
-
* @param key property name (string) or extractor function for stable
|
|
16
|
+
* @param key property name (string) or extractor function for stable
|
|
17
|
+
* identity (default `"id"`); pass `null` for positional merging
|
|
12
18
|
*
|
|
13
19
|
* @example
|
|
14
20
|
* ```ts
|
|
@@ -16,8 +22,11 @@
|
|
|
16
22
|
*
|
|
17
23
|
* async function refresh() {
|
|
18
24
|
* const fresh = await api.getTodos();
|
|
19
|
-
* setTodos(reconcile(fresh
|
|
25
|
+
* setTodos(reconcile(fresh)); // diff-merge by `id`
|
|
20
26
|
* }
|
|
27
|
+
*
|
|
28
|
+
* // fixed-shape polling data — positional merge
|
|
29
|
+
* setStats(reconcile(nextStats, null));
|
|
21
30
|
* ```
|
|
22
31
|
*/
|
|
23
|
-
export declare function reconcile<T extends U, U>(value: T, key
|
|
32
|
+
export declare function reconcile<T extends U, U>(value: T, key?: string | ((item: NonNullable<any>) => any) | null): (state: U) => void;
|
|
@@ -31,6 +31,8 @@ export interface StoreOptions {
|
|
|
31
31
|
export interface ProjectionOptions extends StoreOptions {
|
|
32
32
|
/** Key property name or function for reconciliation identity */
|
|
33
33
|
key?: string | ((item: NonNullable<any>) => any);
|
|
34
|
+
/** Single-layer store: root keys reactive, values raw records replaced by reference */
|
|
35
|
+
shallow?: boolean;
|
|
34
36
|
}
|
|
35
37
|
export type NoFn<T> = T extends Function ? never : T;
|
|
36
38
|
type DataNode = Signal<any>;
|
|
@@ -42,7 +44,7 @@ type DataNodes = Record<PropertyKey, DataNode>;
|
|
|
42
44
|
* @internal
|
|
43
45
|
*/
|
|
44
46
|
export declare const $TRACK: unique symbol, $TARGET: unique symbol, $PROXY: unique symbol, $DELETED: unique symbol, $AFFECTS: unique symbol;
|
|
45
|
-
export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d";
|
|
47
|
+
export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d", STORE_SHALLOW = "s";
|
|
46
48
|
export type StoreNode = {
|
|
47
49
|
[$PROXY]: any;
|
|
48
50
|
[STORE_VALUE]: Record<PropertyKey, any>;
|
|
@@ -58,6 +60,7 @@ export type StoreNode = {
|
|
|
58
60
|
[STORE_OPTIMISTIC]?: boolean;
|
|
59
61
|
[STORE_SNAPSHOT_PROPS]?: Record<PropertyKey, any>;
|
|
60
62
|
[STORE_PARENT]?: StoreNode;
|
|
63
|
+
[STORE_SHALLOW]?: boolean;
|
|
61
64
|
[STORE_DESC]?: boolean;
|
|
62
65
|
};
|
|
63
66
|
export declare namespace SolidStore {
|
|
@@ -68,7 +71,20 @@ export type NotWrappable = string | number | bigint | symbol | boolean | Functio
|
|
|
68
71
|
export declare function createStoreProxy<T extends object>(value: T, traps?: ProxyHandler<StoreNode>, extend?: (target: StoreNode) => void): any;
|
|
69
72
|
export declare const storeLookup: WeakMap<WeakKey, any>;
|
|
70
73
|
export declare const symbolKeyedRecords: WeakSet<object>;
|
|
74
|
+
export declare function lookupTarget(value: any, lookup?: WeakMap<any, any>): StoreNode | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Marks a value as raw: no store will ever wrap it — every store presents it
|
|
77
|
+
* as-is, tracked by reference at whatever slot holds it and updated by
|
|
78
|
+
* replacement. Useful for class instances and external objects (editors,
|
|
79
|
+
* scene graphs, Maps) and for record-shaped data updated wholesale. Sticky
|
|
80
|
+
* for the value's lifetime.
|
|
81
|
+
*/
|
|
82
|
+
export declare let rawValuesUsed: boolean;
|
|
83
|
+
export declare function isRawValue(value: any): boolean;
|
|
84
|
+
export declare function markRaw<T>(value: T): T;
|
|
85
|
+
export declare function markRawIngest(container: any): void;
|
|
71
86
|
export declare function wrap<T extends Record<PropertyKey, any>>(value: T, target?: StoreNode): T;
|
|
87
|
+
export declare function wrapShallow<T extends Record<PropertyKey, any>>(value: T): T;
|
|
72
88
|
export declare function isWrappable<T>(obj: T | NotWrappable): obj is T;
|
|
73
89
|
export declare function setWriteOverride(value: boolean): void;
|
|
74
90
|
export declare function ownEnumerableKeys(o: object): (string | symbol)[];
|
|
@@ -176,6 +192,8 @@ export declare function storeSetter<T extends object>(store: Store<T>, fn: (draf
|
|
|
176
192
|
*
|
|
177
193
|
* @returns `[store: Store<T>, setStore: StoreSetter<T>]`
|
|
178
194
|
*/
|
|
179
|
-
export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T
|
|
195
|
+
export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions & {
|
|
196
|
+
shallow?: boolean;
|
|
197
|
+
}): StoreReturn<T>;
|
|
180
198
|
export declare function createStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): ProjectionStoreReturn<T>;
|
|
181
199
|
export {};
|
|
@@ -72,6 +72,21 @@ export declare function untrack<T>(fn: () => T, strictReadLabel?: string | false
|
|
|
72
72
|
* date so its status flags reflect the current graph.
|
|
73
73
|
*/
|
|
74
74
|
export declare function prepareComputed(comp: Computed<unknown>, refresh: boolean): void;
|
|
75
|
+
/**
|
|
76
|
+
* Sentinel returned by readNodeFast when the plain-signal fast path does not
|
|
77
|
+
* apply and the caller must fall back to the full read().
|
|
78
|
+
*/
|
|
79
|
+
export declare const READ_SLOW: unique symbol;
|
|
80
|
+
/**
|
|
81
|
+
* read()'s plain-signal fast path as a standalone entry for hot callers
|
|
82
|
+
* (store traps). Safe to substitute for read() only because the bail
|
|
83
|
+
* conditions mirror read()'s prelude and fast-path guard exactly: the
|
|
84
|
+
* latestRead and pendingCheck windows run side-effectful hooks before the
|
|
85
|
+
* fast path, `_fn` nodes need prepareComputed, and firewall / override /
|
|
86
|
+
* snapshot / transition / lane / dev-strictRead state all take the full
|
|
87
|
+
* resolution. Anything slow returns READ_SLOW; the caller then calls read().
|
|
88
|
+
*/
|
|
89
|
+
export declare function readNodeFast<T>(el: Signal<T>): T | typeof READ_SLOW;
|
|
75
90
|
export declare function read<T>(el: Signal<T> | Computed<T>): T;
|
|
76
91
|
export declare function setSignal<T>(el: Signal<T> | Computed<T>, v: T | ((prev: T) => T)): T;
|
|
77
92
|
/**
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
export declare class NotReadyError extends Error {
|
|
26
|
-
source: any;
|
|
27
26
|
/**
|
|
28
27
|
* Tags a visibility-only notification on the affects() boundary channel:
|
|
29
28
|
* boundaries update display state from it, but the root queue never
|
|
@@ -31,6 +30,7 @@ export declare class NotReadyError extends Error {
|
|
|
31
30
|
* construction.
|
|
32
31
|
*/
|
|
33
32
|
_markVisual?: boolean;
|
|
33
|
+
source: any;
|
|
34
34
|
constructor(source: any);
|
|
35
35
|
}
|
|
36
36
|
export declare class StatusError extends Error {
|
|
@@ -41,5 +41,5 @@ import { type NoFn, type ProjectionOptions, type Store, type StoreSetter } from
|
|
|
41
41
|
*
|
|
42
42
|
* @returns `[store: Store<T>, setStore: StoreSetter<T>]`
|
|
43
43
|
*/
|
|
44
|
-
export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T
|
|
44
|
+
export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
|
|
45
45
|
export declare function createOptimisticStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Returns a draft-mutating function that smart-merges `value` into a store,
|
|
3
|
-
* preserving
|
|
4
|
-
* new states. Useful when applying server payloads or full-replacement data
|
|
5
|
-
* onto an existing store without losing fine-grained reactivity.
|
|
3
|
+
* preserving fine-grained reactivity: only changed leaves trigger updates.
|
|
6
4
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* With a `key` (default `"id"`), array items whose key matches between old
|
|
6
|
+
* and new states keep their identity (updated in place, moves and removals
|
|
7
|
+
* update the corresponding signals) — the shape for keyed server payloads.
|
|
8
|
+
* Items without the key field fall back to positional matching.
|
|
9
|
+
*
|
|
10
|
+
* With `key: null`, matching is purely positional: index N of the new array
|
|
11
|
+
* merges into index N of the old, and object properties merge recursively —
|
|
12
|
+
* the classic pattern for fixed-shape data that churns in place (dashboards,
|
|
13
|
+
* monitors), where no keyed diff pass is needed or wanted.
|
|
9
14
|
*
|
|
10
15
|
* @param value the next state to merge in
|
|
11
|
-
* @param key property name (string) or extractor function for stable
|
|
16
|
+
* @param key property name (string) or extractor function for stable
|
|
17
|
+
* identity (default `"id"`); pass `null` for positional merging
|
|
12
18
|
*
|
|
13
19
|
* @example
|
|
14
20
|
* ```ts
|
|
@@ -16,8 +22,11 @@
|
|
|
16
22
|
*
|
|
17
23
|
* async function refresh() {
|
|
18
24
|
* const fresh = await api.getTodos();
|
|
19
|
-
* setTodos(reconcile(fresh
|
|
25
|
+
* setTodos(reconcile(fresh)); // diff-merge by `id`
|
|
20
26
|
* }
|
|
27
|
+
*
|
|
28
|
+
* // fixed-shape polling data — positional merge
|
|
29
|
+
* setStats(reconcile(nextStats, null));
|
|
21
30
|
* ```
|
|
22
31
|
*/
|
|
23
|
-
export declare function reconcile<T extends U, U>(value: T, key
|
|
32
|
+
export declare function reconcile<T extends U, U>(value: T, key?: string | ((item: NonNullable<any>) => any) | null): (state: U) => void;
|
|
@@ -31,6 +31,8 @@ export interface StoreOptions {
|
|
|
31
31
|
export interface ProjectionOptions extends StoreOptions {
|
|
32
32
|
/** Key property name or function for reconciliation identity */
|
|
33
33
|
key?: string | ((item: NonNullable<any>) => any);
|
|
34
|
+
/** Single-layer store: root keys reactive, values raw records replaced by reference */
|
|
35
|
+
shallow?: boolean;
|
|
34
36
|
}
|
|
35
37
|
export type NoFn<T> = T extends Function ? never : T;
|
|
36
38
|
type DataNode = Signal<any>;
|
|
@@ -42,7 +44,7 @@ type DataNodes = Record<PropertyKey, DataNode>;
|
|
|
42
44
|
* @internal
|
|
43
45
|
*/
|
|
44
46
|
export declare const $TRACK: unique symbol, $TARGET: unique symbol, $PROXY: unique symbol, $DELETED: unique symbol, $AFFECTS: unique symbol;
|
|
45
|
-
export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d";
|
|
47
|
+
export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d", STORE_SHALLOW = "s";
|
|
46
48
|
export type StoreNode = {
|
|
47
49
|
[$PROXY]: any;
|
|
48
50
|
[STORE_VALUE]: Record<PropertyKey, any>;
|
|
@@ -58,6 +60,7 @@ export type StoreNode = {
|
|
|
58
60
|
[STORE_OPTIMISTIC]?: boolean;
|
|
59
61
|
[STORE_SNAPSHOT_PROPS]?: Record<PropertyKey, any>;
|
|
60
62
|
[STORE_PARENT]?: StoreNode;
|
|
63
|
+
[STORE_SHALLOW]?: boolean;
|
|
61
64
|
[STORE_DESC]?: boolean;
|
|
62
65
|
};
|
|
63
66
|
export declare namespace SolidStore {
|
|
@@ -68,7 +71,20 @@ export type NotWrappable = string | number | bigint | symbol | boolean | Functio
|
|
|
68
71
|
export declare function createStoreProxy<T extends object>(value: T, traps?: ProxyHandler<StoreNode>, extend?: (target: StoreNode) => void): any;
|
|
69
72
|
export declare const storeLookup: WeakMap<WeakKey, any>;
|
|
70
73
|
export declare const symbolKeyedRecords: WeakSet<object>;
|
|
74
|
+
export declare function lookupTarget(value: any, lookup?: WeakMap<any, any>): StoreNode | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Marks a value as raw: no store will ever wrap it — every store presents it
|
|
77
|
+
* as-is, tracked by reference at whatever slot holds it and updated by
|
|
78
|
+
* replacement. Useful for class instances and external objects (editors,
|
|
79
|
+
* scene graphs, Maps) and for record-shaped data updated wholesale. Sticky
|
|
80
|
+
* for the value's lifetime.
|
|
81
|
+
*/
|
|
82
|
+
export declare let rawValuesUsed: boolean;
|
|
83
|
+
export declare function isRawValue(value: any): boolean;
|
|
84
|
+
export declare function markRaw<T>(value: T): T;
|
|
85
|
+
export declare function markRawIngest(container: any): void;
|
|
71
86
|
export declare function wrap<T extends Record<PropertyKey, any>>(value: T, target?: StoreNode): T;
|
|
87
|
+
export declare function wrapShallow<T extends Record<PropertyKey, any>>(value: T): T;
|
|
72
88
|
export declare function isWrappable<T>(obj: T | NotWrappable): obj is T;
|
|
73
89
|
export declare function setWriteOverride(value: boolean): void;
|
|
74
90
|
export declare function ownEnumerableKeys(o: object): (string | symbol)[];
|
|
@@ -176,6 +192,8 @@ export declare function storeSetter<T extends object>(store: Store<T>, fn: (draf
|
|
|
176
192
|
*
|
|
177
193
|
* @returns `[store: Store<T>, setStore: StoreSetter<T>]`
|
|
178
194
|
*/
|
|
179
|
-
export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T
|
|
195
|
+
export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions & {
|
|
196
|
+
shallow?: boolean;
|
|
197
|
+
}): StoreReturn<T>;
|
|
180
198
|
export declare function createStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): ProjectionStoreReturn<T>;
|
|
181
199
|
export {};
|
package/package.json
CHANGED