@buoy-gg/zustand 3.0.1 → 3.0.2

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.
Files changed (64) hide show
  1. package/lib/commonjs/index.js +98 -1
  2. package/lib/commonjs/preset.js +102 -1
  3. package/lib/commonjs/zustand/components/ZustandActionButton.js +116 -1
  4. package/lib/commonjs/zustand/components/ZustandDetailViewToggle.js +134 -1
  5. package/lib/commonjs/zustand/components/ZustandEventFilterView.js +291 -1
  6. package/lib/commonjs/zustand/components/ZustandIcon.js +35 -1
  7. package/lib/commonjs/zustand/components/ZustandModal.js +603 -1
  8. package/lib/commonjs/zustand/components/ZustandStateChangeItem.js +165 -1
  9. package/lib/commonjs/zustand/components/ZustandStateDetailContent.js +352 -1
  10. package/lib/commonjs/zustand/components/ZustandStateInfoView.js +508 -1
  11. package/lib/commonjs/zustand/components/ZustandStoreBrowser.js +323 -1
  12. package/lib/commonjs/zustand/components/index.js +73 -1
  13. package/lib/commonjs/zustand/hooks/index.js +12 -1
  14. package/lib/commonjs/zustand/hooks/useZustandStateChanges.js +92 -1
  15. package/lib/commonjs/zustand/index.js +99 -1
  16. package/lib/commonjs/zustand/sync/zustandSyncAdapter.js +48 -0
  17. package/lib/commonjs/zustand/utils/buoyZustandMiddleware.js +220 -1
  18. package/lib/commonjs/zustand/utils/index.js +31 -1
  19. package/lib/commonjs/zustand/utils/zustandStateStore.js +457 -1
  20. package/lib/module/index.js +85 -1
  21. package/lib/module/preset.js +98 -1
  22. package/lib/module/zustand/components/ZustandActionButton.js +112 -1
  23. package/lib/module/zustand/components/ZustandDetailViewToggle.js +129 -1
  24. package/lib/module/zustand/components/ZustandEventFilterView.js +287 -1
  25. package/lib/module/zustand/components/ZustandIcon.js +32 -1
  26. package/lib/module/zustand/components/ZustandModal.js +599 -1
  27. package/lib/module/zustand/components/ZustandStateChangeItem.js +161 -1
  28. package/lib/module/zustand/components/ZustandStateDetailContent.js +348 -1
  29. package/lib/module/zustand/components/ZustandStateInfoView.js +503 -1
  30. package/lib/module/zustand/components/ZustandStoreBrowser.js +319 -1
  31. package/lib/module/zustand/components/index.js +10 -1
  32. package/lib/module/zustand/hooks/index.js +3 -1
  33. package/lib/module/zustand/hooks/useZustandStateChanges.js +88 -1
  34. package/lib/module/zustand/index.js +12 -1
  35. package/lib/module/zustand/sync/zustandSyncAdapter.js +44 -0
  36. package/lib/module/zustand/utils/buoyZustandMiddleware.js +214 -1
  37. package/lib/module/zustand/utils/index.js +4 -1
  38. package/lib/module/zustand/utils/zustandStateStore.js +453 -1
  39. package/lib/typescript/index.d.ts +2 -1
  40. package/lib/typescript/index.d.ts.map +1 -0
  41. package/lib/typescript/preset.d.ts.map +1 -0
  42. package/lib/typescript/zustand/components/ZustandActionButton.d.ts.map +1 -0
  43. package/lib/typescript/zustand/components/ZustandDetailViewToggle.d.ts.map +1 -0
  44. package/lib/typescript/zustand/components/ZustandEventFilterView.d.ts.map +1 -0
  45. package/lib/typescript/zustand/components/ZustandIcon.d.ts.map +1 -0
  46. package/lib/typescript/zustand/components/ZustandModal.d.ts.map +1 -0
  47. package/lib/typescript/zustand/components/ZustandStateChangeItem.d.ts.map +1 -0
  48. package/lib/typescript/zustand/components/ZustandStateDetailContent.d.ts.map +1 -0
  49. package/lib/typescript/zustand/components/ZustandStateInfoView.d.ts.map +1 -0
  50. package/lib/typescript/zustand/components/ZustandStoreBrowser.d.ts +8 -1
  51. package/lib/typescript/zustand/components/ZustandStoreBrowser.d.ts.map +1 -0
  52. package/lib/typescript/zustand/components/index.d.ts.map +1 -0
  53. package/lib/typescript/zustand/hooks/index.d.ts.map +1 -0
  54. package/lib/typescript/zustand/hooks/useZustandStateChanges.d.ts.map +1 -0
  55. package/lib/typescript/zustand/index.d.ts.map +1 -0
  56. package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts +26 -0
  57. package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts.map +1 -0
  58. package/lib/typescript/zustand/types/index.d.ts +12 -0
  59. package/lib/typescript/zustand/types/index.d.ts.map +1 -0
  60. package/lib/typescript/zustand/utils/buoyZustandMiddleware.d.ts.map +1 -0
  61. package/lib/typescript/zustand/utils/index.d.ts.map +1 -0
  62. package/lib/typescript/zustand/utils/zustandStateStore.d.ts +35 -1
  63. package/lib/typescript/zustand/utils/zustandStateStore.d.ts.map +1 -0
  64. package/package.json +3 -3
@@ -1 +1,220 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.buoyDevTools=buoyDevTools,exports.isStoreInstrumented=isStoreInstrumented,exports.watchStores=watchStores;var _zustandStateStore=require("./zustandStateStore");const WATCHED_SYMBOL=Symbol.for("@@buoy-zustand/watched");function detectPersist(t){const e=t.persist;if(e&&"function"==typeof e.getOptions){const t=e.getOptions();return{isPersisted:!0,persistName:t?.name}}return{isPersisted:!1}}function watchStores(t){const e=[];for(const[s,r]of Object.entries(t)){const t=r;if(t[WATCHED_SYMBOL])continue;t[WATCHED_SYMBOL]=!0;const{isPersisted:n,persistName:a}=detectPersist(r);_zustandStateStore.zustandStateStore.registerStore(s,{getState:r.getState,getInitialState:r.getInitialState,setState:r.setState,subscribe:r.subscribe},{isPersisted:n,persistName:a});const o=r.subscribe((t,e)=>{try{_zustandStateStore.zustandStateStore.addStateChange({storeName:s,partial:void 0,replace:!1,prevState:e,nextState:t,duration:void 0,isPersisted:n})}catch{}});e.push(()=>{o(),delete r[WATCHED_SYMBOL],_zustandStateStore.zustandStateStore.unregisterStore(s)})}return()=>{e.forEach(t=>t())}}let unnamedCounter=0;function buoyDevTools(t,e){return(s,r,n)=>{const a=e?.name??"store-"+ ++unnamedCounter,o=!1!==e?.enabled,i=t((t,e)=>{if(!o)return s(t,e);const n=performance.now(),i=r();s(t,e);const S=r(),u=performance.now()-n,d="function"==typeof t?"(updater fn)":t;_zustandStateStore.zustandStateStore.addStateChange({storeName:a,partial:d,replace:e??!1,prevState:i,nextState:S,duration:u,isPersisted:!1})},r,n);return setTimeout(()=>{if(n[WATCHED_SYMBOL])return;n[WATCHED_SYMBOL]=!0;const{isPersisted:t,persistName:e}=detectPersist(n);_zustandStateStore.zustandStateStore.registerStore(a,{getState:r,getInitialState:n.getInitialState,setState:s,subscribe:n.subscribe},{isPersisted:t,persistName:e})},0),i}}function isStoreInstrumented(t){return!0===t[WATCHED_SYMBOL]}
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.buoyDevTools = buoyDevTools;
7
+ exports.isStoreInstrumented = isStoreInstrumented;
8
+ exports.watchStores = watchStores;
9
+ var _zustandStateStore = require("./zustandStateStore");
10
+ /**
11
+ * Buoy Zustand DevTools — Store instrumentation
12
+ *
13
+ * Two approaches, from easiest to most detailed:
14
+ *
15
+ * 1. watchStores() — RECOMMENDED. One line, zero store modifications.
16
+ * Uses store.subscribe() externally. Never touches setState.
17
+ * Safe to add/remove — cannot break your stores even if our code has bugs.
18
+ *
19
+ * 2. buoyDevTools() — Opt-in middleware for advanced use.
20
+ * Wraps setState to capture the partial argument and timing.
21
+ * Requires modifying each store's create() call.
22
+ */
23
+
24
+ /** Symbol to mark stores that have been watched/instrumented */
25
+ const WATCHED_SYMBOL = Symbol.for("@@buoy-zustand/watched");
26
+
27
+ /**
28
+ * Detect if a store is using the persist middleware by checking for persist API
29
+ */
30
+ function detectPersist(store) {
31
+ const persist = store.persist;
32
+ if (persist && typeof persist.getOptions === "function") {
33
+ const options = persist.getOptions();
34
+ return {
35
+ isPersisted: true,
36
+ persistName: options?.name
37
+ };
38
+ }
39
+ return {
40
+ isPersisted: false
41
+ };
42
+ }
43
+
44
+ // =============================================================================
45
+ // watchStores — Primary, non-intrusive approach
46
+ // =============================================================================
47
+
48
+ /** Minimal store shape — what Zustand's create() returns */
49
+
50
+ /**
51
+ * Watch multiple Zustand stores for state changes.
52
+ *
53
+ * This is the recommended, non-intrusive approach. It uses each store's
54
+ * `.subscribe()` method to observe changes from the outside — it never
55
+ * modifies `setState` or any store internals.
56
+ *
57
+ * **Safe by design:** Even if our listener code has a bug, it cannot break
58
+ * your stores. All listener code is wrapped in try/catch.
59
+ *
60
+ * @example
61
+ * ```tsx
62
+ * // In your _layout.tsx or App.tsx — ONE line:
63
+ * import { watchStores } from '@buoy-gg/zustand';
64
+ * import { useCounterStore } from './stores/counter';
65
+ * import { useAuthStore } from './stores/auth';
66
+ * import { useCartStore } from './stores/cart';
67
+ *
68
+ * watchStores({
69
+ * counterStore: useCounterStore,
70
+ * authStore: useAuthStore,
71
+ * cartStore: useCartStore,
72
+ * });
73
+ * ```
74
+ *
75
+ * @param stores - Object mapping store names to Zustand store hooks
76
+ * @returns Cleanup function that removes all subscriptions
77
+ */
78
+ function watchStores(stores) {
79
+ const cleanups = [];
80
+ for (const [name, store] of Object.entries(stores)) {
81
+ // Skip if already watched
82
+ const storeAny = store;
83
+ if (storeAny[WATCHED_SYMBOL]) continue;
84
+ storeAny[WATCHED_SYMBOL] = true;
85
+ const {
86
+ isPersisted,
87
+ persistName
88
+ } = detectPersist(store);
89
+
90
+ // Register the store for overview
91
+ _zustandStateStore.zustandStateStore.registerStore(name, {
92
+ getState: store.getState,
93
+ getInitialState: store.getInitialState,
94
+ setState: store.setState,
95
+ subscribe: store.subscribe
96
+ }, {
97
+ isPersisted,
98
+ persistName
99
+ });
100
+
101
+ // Subscribe to state changes — completely external, never touches setState
102
+ const unsubscribe = store.subscribe((state, prevState) => {
103
+ try {
104
+ _zustandStateStore.zustandStateStore.addStateChange({
105
+ storeName: name,
106
+ partial: undefined,
107
+ // Not available in subscribe-only mode
108
+ replace: false,
109
+ prevState,
110
+ nextState: state,
111
+ duration: undefined,
112
+ // Not available in subscribe-only mode
113
+ isPersisted
114
+ });
115
+ } catch {
116
+ // Silently catch — our bug must never propagate into the store
117
+ }
118
+ });
119
+ cleanups.push(() => {
120
+ unsubscribe();
121
+ delete store[WATCHED_SYMBOL];
122
+ _zustandStateStore.zustandStateStore.unregisterStore(name);
123
+ });
124
+ }
125
+ return () => {
126
+ cleanups.forEach(fn => fn());
127
+ };
128
+ }
129
+
130
+ // =============================================================================
131
+ // buoyDevTools — Opt-in middleware (advanced, more detail)
132
+ // =============================================================================
133
+
134
+ /** Auto-incrementing store name counter for unnamed stores */
135
+ let unnamedCounter = 0;
136
+
137
+ /**
138
+ * Zustand middleware that instruments a store for Buoy DevTools.
139
+ *
140
+ * This is the advanced approach — it wraps setState to capture:
141
+ * - The partial argument passed to setState
142
+ * - Precise timing of each setState call
143
+ *
144
+ * Use this when you want maximum detail. For most cases, `watchStores()`
145
+ * is simpler and safer.
146
+ *
147
+ * @example
148
+ * ```tsx
149
+ * import { create } from 'zustand';
150
+ * import { buoyDevTools } from '@buoy-gg/zustand';
151
+ *
152
+ * const useCounterStore = create(
153
+ * buoyDevTools(
154
+ * (set) => ({
155
+ * count: 0,
156
+ * increment: () => set((s) => ({ count: s.count + 1 })),
157
+ * }),
158
+ * { name: 'counterStore' }
159
+ * )
160
+ * );
161
+ * ```
162
+ */
163
+ function buoyDevTools(config, options) {
164
+ return (set, get, api) => {
165
+ const storeName = options?.name ?? `store-${++unnamedCounter}`;
166
+ const enabled = options?.enabled !== false;
167
+ const instrumentedSet = (partial, replace) => {
168
+ if (!enabled) {
169
+ return set(partial, replace);
170
+ }
171
+ const startTime = performance.now();
172
+ const prevState = get();
173
+ set(partial, replace);
174
+ const nextState = get();
175
+ const duration = performance.now() - startTime;
176
+ const resolvedPartial = typeof partial === "function" ? "(updater fn)" : partial;
177
+ _zustandStateStore.zustandStateStore.addStateChange({
178
+ storeName,
179
+ partial: resolvedPartial,
180
+ replace: replace ?? false,
181
+ prevState,
182
+ nextState,
183
+ duration,
184
+ isPersisted: false
185
+ });
186
+ };
187
+ const result = config(instrumentedSet, get, api);
188
+
189
+ // Register the store after creation
190
+ setTimeout(() => {
191
+ if (api[WATCHED_SYMBOL]) return;
192
+ api[WATCHED_SYMBOL] = true;
193
+ const {
194
+ isPersisted,
195
+ persistName
196
+ } = detectPersist(api);
197
+ _zustandStateStore.zustandStateStore.registerStore(storeName, {
198
+ getState: get,
199
+ getInitialState: api.getInitialState,
200
+ setState: set,
201
+ subscribe: api.subscribe
202
+ }, {
203
+ isPersisted,
204
+ persistName
205
+ });
206
+ }, 0);
207
+ return result;
208
+ };
209
+ }
210
+
211
+ // =============================================================================
212
+ // Utility
213
+ // =============================================================================
214
+
215
+ /**
216
+ * Check if a store is being watched/instrumented
217
+ */
218
+ function isStoreInstrumented(store) {
219
+ return store[WATCHED_SYMBOL] === true;
220
+ }
@@ -1 +1,31 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"buoyDevTools",{enumerable:!0,get:function(){return _buoyZustandMiddleware.buoyDevTools}}),Object.defineProperty(exports,"isStoreInstrumented",{enumerable:!0,get:function(){return _buoyZustandMiddleware.isStoreInstrumented}}),Object.defineProperty(exports,"watchStores",{enumerable:!0,get:function(){return _buoyZustandMiddleware.watchStores}}),Object.defineProperty(exports,"zustandStateStore",{enumerable:!0,get:function(){return _zustandStateStore.zustandStateStore}});var _zustandStateStore=require("./zustandStateStore"),_buoyZustandMiddleware=require("./buoyZustandMiddleware");
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "buoyDevTools", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _buoyZustandMiddleware.buoyDevTools;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "isStoreInstrumented", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _buoyZustandMiddleware.isStoreInstrumented;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "watchStores", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _buoyZustandMiddleware.watchStores;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "zustandStateStore", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _zustandStateStore.zustandStateStore;
28
+ }
29
+ });
30
+ var _zustandStateStore = require("./zustandStateStore");
31
+ var _buoyZustandMiddleware = require("./buoyZustandMiddleware");