@buoy-gg/zustand 7.0.18 → 7.0.19

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.
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.zustandSyncAdapter = exports.STATE_ON_DEVICE = exports.PAYLOAD_ON_DEVICE = void 0;
7
7
  var _zustandStateStore = require("../utils/zustandStateStore");
8
+ var _sharedUi = require("@buoy-gg/shared-ui");
8
9
  /**
9
10
  * Sentinel used in WIRE-FORM snapshots in place of raw prevState/nextState.
10
11
  * Same hazard as redux: up to 200 changes × 2 full trees on every snapshot
@@ -22,64 +23,35 @@ const PAYLOAD_ON_DEVICE = exports.PAYLOAD_ON_DEVICE = Object.freeze({
22
23
  });
23
24
  const MAX_CHANGE_DETAIL_BYTES = 8 * 1024 * 1024;
24
25
  const MAX_WIRE_PAYLOAD_BYTES = 16 * 1024;
25
- function jsonLongerThan(value, limit) {
26
- let bytes = 0;
27
- const stack = [value];
28
- const seen = new Set();
29
- while (stack.length > 0) {
30
- if (bytes > limit) return true;
31
- const v = stack.pop();
32
- if (v === null || v === undefined) bytes += 4;else if (typeof v === "string") bytes += v.length + 2;else if (typeof v === "number") bytes += 8;else if (typeof v === "boolean") bytes += 5;else if (typeof v === "object") {
33
- if (seen.has(v)) continue;
34
- seen.add(v);
35
- if (Array.isArray(v)) {
36
- bytes += 2 + v.length;
37
- for (let i = 0; i < v.length; i++) stack.push(v[i]);
38
- } else {
39
- bytes += 2;
40
- for (const k in v) {
41
- bytes += k.length + 4;
42
- stack.push(v[k]);
43
- }
44
- }
45
- } else bytes += 4;
46
- }
47
- return bytes > limit;
48
- }
49
26
  /** Top-level keys of an object state, for the compact (no-values) view. */
50
27
  function topLevelKeys(state) {
51
28
  return state && typeof state === "object" && !Array.isArray(state) ? Object.keys(state) : undefined;
52
29
  }
30
+
31
+ /**
32
+ * Per-change wire cache. The store prepends and never mutates a recorded
33
+ * change, so keying on identity is correct and self-invalidating — without it
34
+ * every `partial` in the list is re-measured on all ~5 snapshots per second.
35
+ */
36
+ const changeCache = new WeakMap();
53
37
  function toWireChange(change) {
54
- return {
38
+ const cached = changeCache.get(change);
39
+ if (cached) return cached;
40
+ const wire = {
55
41
  ...change,
56
42
  prevState: STATE_ON_DEVICE,
57
43
  nextState: STATE_ON_DEVICE,
58
44
  partial: toWirePartial(change.partial)
59
45
  };
46
+ changeCache.set(change, wire);
47
+ return wire;
60
48
  }
61
49
  function toWirePartial(value) {
62
50
  if (value === undefined) return value;
63
- try {
64
- JSON.stringify(value);
65
- } catch {
66
- return PAYLOAD_ON_DEVICE;
67
- }
68
- if (jsonLongerThan(value, MAX_WIRE_PAYLOAD_BYTES)) {
69
- return PAYLOAD_ON_DEVICE;
70
- }
71
- return value;
51
+ return (0, _sharedUi.isOverWireBudget)(value, MAX_WIRE_PAYLOAD_BYTES) ? PAYLOAD_ON_DEVICE : value;
72
52
  }
73
53
  function toWireState(value) {
74
- try {
75
- JSON.stringify(value);
76
- } catch {
77
- return STATE_ON_DEVICE;
78
- }
79
- if (jsonLongerThan(value, MAX_WIRE_PAYLOAD_BYTES)) {
80
- return STATE_ON_DEVICE;
81
- }
82
- return value;
54
+ return (0, _sharedUi.isOverWireBudget)(value, MAX_WIRE_PAYLOAD_BYTES) ? STATE_ON_DEVICE : value;
83
55
  }
84
56
 
85
57
  /**
@@ -143,14 +115,7 @@ const zustandSyncAdapter = exports.zustandSyncAdapter = {
143
115
  __buoyTruncated: true,
144
116
  note: `Exceeds the ${MAX_CHANGE_DETAIL_BYTES / (1024 * 1024)}MB detail limit — inspect it on-device.`
145
117
  };
146
- const cap = value => {
147
- try {
148
- JSON.stringify(value);
149
- } catch {
150
- return cappedNote;
151
- }
152
- return jsonLongerThan(value, MAX_CHANGE_DETAIL_BYTES) ? cappedNote : value;
153
- };
118
+ const cap = value => (0, _sharedUi.isOverWireBudget)(value, MAX_CHANGE_DETAIL_BYTES) ? cappedNote : value;
154
119
  return {
155
120
  found: true,
156
121
  id,
@@ -186,19 +151,17 @@ const zustandSyncAdapter = exports.zustandSyncAdapter = {
186
151
  __buoyTruncated: true,
187
152
  note: `Exceeds the ${MAX_CHANGE_DETAIL_BYTES / (1024 * 1024)}MB detail limit — inspect it on-device.`
188
153
  };
189
- try {
190
- JSON.stringify(currentState);
191
- } catch {
154
+ if (!(0, _sharedUi.isOverWireBudget)(currentState, MAX_CHANGE_DETAIL_BYTES)) {
192
155
  return {
193
156
  found: true,
194
157
  storeName,
195
- currentState: STATE_ON_DEVICE
158
+ currentState
196
159
  };
197
160
  }
198
161
  return {
199
162
  found: true,
200
163
  storeName,
201
- currentState: jsonLongerThan(currentState, MAX_CHANGE_DETAIL_BYTES) ? cappedNote : currentState
164
+ currentState: (0, _sharedUi.isJsonSerializable)(currentState) ? cappedNote : STATE_ON_DEVICE
202
165
  };
203
166
  },
204
167
  /**
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
 
3
3
  import { zustandStateStore } from "../utils/zustandStateStore";
4
+ import { isJsonSerializable, isOverWireBudget } from "@buoy-gg/shared-ui";
5
+
4
6
  /**
5
7
  * Sentinel used in WIRE-FORM snapshots in place of raw prevState/nextState.
6
8
  * Same hazard as redux: up to 200 changes × 2 full trees on every snapshot
@@ -18,64 +20,35 @@ export const PAYLOAD_ON_DEVICE = Object.freeze({
18
20
  });
19
21
  const MAX_CHANGE_DETAIL_BYTES = 8 * 1024 * 1024;
20
22
  const MAX_WIRE_PAYLOAD_BYTES = 16 * 1024;
21
- function jsonLongerThan(value, limit) {
22
- let bytes = 0;
23
- const stack = [value];
24
- const seen = new Set();
25
- while (stack.length > 0) {
26
- if (bytes > limit) return true;
27
- const v = stack.pop();
28
- if (v === null || v === undefined) bytes += 4;else if (typeof v === "string") bytes += v.length + 2;else if (typeof v === "number") bytes += 8;else if (typeof v === "boolean") bytes += 5;else if (typeof v === "object") {
29
- if (seen.has(v)) continue;
30
- seen.add(v);
31
- if (Array.isArray(v)) {
32
- bytes += 2 + v.length;
33
- for (let i = 0; i < v.length; i++) stack.push(v[i]);
34
- } else {
35
- bytes += 2;
36
- for (const k in v) {
37
- bytes += k.length + 4;
38
- stack.push(v[k]);
39
- }
40
- }
41
- } else bytes += 4;
42
- }
43
- return bytes > limit;
44
- }
45
23
  /** Top-level keys of an object state, for the compact (no-values) view. */
46
24
  function topLevelKeys(state) {
47
25
  return state && typeof state === "object" && !Array.isArray(state) ? Object.keys(state) : undefined;
48
26
  }
27
+
28
+ /**
29
+ * Per-change wire cache. The store prepends and never mutates a recorded
30
+ * change, so keying on identity is correct and self-invalidating — without it
31
+ * every `partial` in the list is re-measured on all ~5 snapshots per second.
32
+ */
33
+ const changeCache = new WeakMap();
49
34
  function toWireChange(change) {
50
- return {
35
+ const cached = changeCache.get(change);
36
+ if (cached) return cached;
37
+ const wire = {
51
38
  ...change,
52
39
  prevState: STATE_ON_DEVICE,
53
40
  nextState: STATE_ON_DEVICE,
54
41
  partial: toWirePartial(change.partial)
55
42
  };
43
+ changeCache.set(change, wire);
44
+ return wire;
56
45
  }
57
46
  function toWirePartial(value) {
58
47
  if (value === undefined) return value;
59
- try {
60
- JSON.stringify(value);
61
- } catch {
62
- return PAYLOAD_ON_DEVICE;
63
- }
64
- if (jsonLongerThan(value, MAX_WIRE_PAYLOAD_BYTES)) {
65
- return PAYLOAD_ON_DEVICE;
66
- }
67
- return value;
48
+ return isOverWireBudget(value, MAX_WIRE_PAYLOAD_BYTES) ? PAYLOAD_ON_DEVICE : value;
68
49
  }
69
50
  function toWireState(value) {
70
- try {
71
- JSON.stringify(value);
72
- } catch {
73
- return STATE_ON_DEVICE;
74
- }
75
- if (jsonLongerThan(value, MAX_WIRE_PAYLOAD_BYTES)) {
76
- return STATE_ON_DEVICE;
77
- }
78
- return value;
51
+ return isOverWireBudget(value, MAX_WIRE_PAYLOAD_BYTES) ? STATE_ON_DEVICE : value;
79
52
  }
80
53
 
81
54
  /**
@@ -139,14 +112,7 @@ export const zustandSyncAdapter = {
139
112
  __buoyTruncated: true,
140
113
  note: `Exceeds the ${MAX_CHANGE_DETAIL_BYTES / (1024 * 1024)}MB detail limit — inspect it on-device.`
141
114
  };
142
- const cap = value => {
143
- try {
144
- JSON.stringify(value);
145
- } catch {
146
- return cappedNote;
147
- }
148
- return jsonLongerThan(value, MAX_CHANGE_DETAIL_BYTES) ? cappedNote : value;
149
- };
115
+ const cap = value => isOverWireBudget(value, MAX_CHANGE_DETAIL_BYTES) ? cappedNote : value;
150
116
  return {
151
117
  found: true,
152
118
  id,
@@ -182,19 +148,17 @@ export const zustandSyncAdapter = {
182
148
  __buoyTruncated: true,
183
149
  note: `Exceeds the ${MAX_CHANGE_DETAIL_BYTES / (1024 * 1024)}MB detail limit — inspect it on-device.`
184
150
  };
185
- try {
186
- JSON.stringify(currentState);
187
- } catch {
151
+ if (!isOverWireBudget(currentState, MAX_CHANGE_DETAIL_BYTES)) {
188
152
  return {
189
153
  found: true,
190
154
  storeName,
191
- currentState: STATE_ON_DEVICE
155
+ currentState
192
156
  };
193
157
  }
194
158
  return {
195
159
  found: true,
196
160
  storeName,
197
- currentState: jsonLongerThan(currentState, MAX_CHANGE_DETAIL_BYTES) ? cappedNote : currentState
161
+ currentState: isJsonSerializable(currentState) ? cappedNote : STATE_ON_DEVICE
198
162
  };
199
163
  },
200
164
  /**
@@ -52,7 +52,7 @@ export declare const zustandSyncAdapter: {
52
52
  * The per-snapshot stream stays tree-free; this is the explicit,
53
53
  * size-guarded channel for the detail pane.
54
54
  */
55
- getChangeDetail: (params: unknown) => {
55
+ getChangeDetail: (params?: unknown) => {
56
56
  found: false;
57
57
  reason: string;
58
58
  id?: undefined;
@@ -71,7 +71,7 @@ export declare const zustandSyncAdapter: {
71
71
  * On-demand current state for one store. Wire-form snapshots replace
72
72
  * oversized / unserializable `currentState` with STATE_ON_DEVICE.
73
73
  */
74
- getStoreState: (params: unknown) => {
74
+ getStoreState: (params?: unknown) => {
75
75
  found: false;
76
76
  reason: string;
77
77
  storeName?: undefined;
@@ -88,7 +88,7 @@ export declare const zustandSyncAdapter: {
88
88
  * on the device unless `includeValues` is set (compact view returns just the
89
89
  * top-level `keys` so the shape is visible cheaply).
90
90
  */
91
- listStores: (params: unknown) => {
91
+ listStores: (params?: unknown) => {
92
92
  stores: ({
93
93
  currentState: unknown;
94
94
  name: string;
@@ -106,7 +106,7 @@ export declare const zustandSyncAdapter: {
106
106
  returned: number;
107
107
  includedValues: boolean;
108
108
  };
109
- setState: (params: unknown) => {
109
+ setState: (params?: unknown) => {
110
110
  ok: boolean;
111
111
  error: string;
112
112
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"zustandSyncAdapter.d.ts","sourceRoot":"","sources":["../../../../src/zustand/sync/zustandSyncAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;EAG1B,CAAC;AAEH,sFAAsF;AACtF,eAAO,MAAM,iBAAiB;;;EAG5B,CAAC;AAwFH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;0BASP,MAAM,IAAI;;;QAY9B;;;;WAIG;kCACuB,OAAO;;;;;;;;;;;;;;;QA2BjC;;;WAGG;gCACqB,OAAO;;;;;;;;;;;QAiC/B;;;;;WAKG;6BACkB,OAAO;;;;;;;;;;;;;;;;;;2BAsBT,OAAO;;;;;;;;CAS7B,CAAC"}
1
+ {"version":3,"file":"zustandSyncAdapter.d.ts","sourceRoot":"","sources":["../../../../src/zustand/sync/zustandSyncAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAGnD;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;EAG1B,CAAC;AAEH,sFAAsF;AACtF,eAAO,MAAM,iBAAiB;;;EAG5B,CAAC;AA2DH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;0BASP,MAAM,IAAI;;;QAY9B;;;;WAIG;mCACwB,OAAO;;;;;;;;;;;;;;;QAmBlC;;;WAGG;iCACsB,OAAO;;;;;;;;;;;QA2BhC;;;;;WAKG;8BACmB,OAAO;;;;;;;;;;;;;;;;;;4BAsBT,OAAO;;;;;;;;CAS9B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/zustand",
3
- "version": "7.0.18",
3
+ "version": "7.0.19",
4
4
  "description": "Zustand devtools inside your React Native app — state diffs, jump-to-state & one-tap store reset, no middleware. Part of Buoy devtools.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -29,8 +29,8 @@
29
29
  "**/snapshotProvider.ts"
30
30
  ],
31
31
  "dependencies": {
32
- "@buoy-gg/shared-ui": "^7.0.18",
33
- "@buoy-gg/license": "^7.0.18"
32
+ "@buoy-gg/shared-ui": "^7.0.19",
33
+ "@buoy-gg/license": "^7.0.19"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": "*",
@@ -59,7 +59,12 @@
59
59
  "sourceMaps": false
60
60
  }
61
61
  ],
62
- "typescript"
62
+ [
63
+ "typescript",
64
+ {
65
+ "project": "tsconfig.build.json"
66
+ }
67
+ ]
63
68
  ]
64
69
  },
65
70
  "repository": {