@chromahq/store 1.0.0 → 1.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.
package/dist/index.cjs.js CHANGED
@@ -96,12 +96,24 @@ function useCentralStore(store, selector) {
96
96
  function useCentralDispatch(store) {
97
97
  return store.setState;
98
98
  }
99
+ function useStoreReady(store) {
100
+ return React.useSyncExternalStore(
101
+ store.onReady,
102
+ store.isReady,
103
+ () => false
104
+ // Server-side fallback
105
+ );
106
+ }
107
+ function useStoreReset(store) {
108
+ return store.reset;
109
+ }
99
110
 
100
111
  class BridgeStore {
101
112
  constructor(bridge, initialState, storeName = "default") {
102
113
  this.listeners = /* @__PURE__ */ new Set();
103
114
  this.currentState = null;
104
115
  this.previousState = null;
116
+ this.initialState = null;
105
117
  this.ready = false;
106
118
  this.readyCallbacks = /* @__PURE__ */ new Set();
107
119
  this.initialize = async () => {
@@ -109,6 +121,9 @@ class BridgeStore {
109
121
  const state = await this.bridge.send(`store:${this.storeName}:getState`);
110
122
  this.previousState = this.currentState;
111
123
  this.currentState = state;
124
+ if (this.initialState === null) {
125
+ this.initialState = state;
126
+ }
112
127
  this.notifyListeners();
113
128
  this.ready = true;
114
129
  this.notifyReady();
@@ -166,6 +181,18 @@ class BridgeStore {
166
181
  this.readyCallbacks.delete(callback);
167
182
  };
168
183
  };
184
+ this.reset = () => {
185
+ if (this.initialState !== null) {
186
+ this.bridge.send(`store:${this.storeName}:reset`).catch((error) => {
187
+ console.error("Failed to reset state via bridge:", error);
188
+ });
189
+ this.previousState = this.currentState;
190
+ this.currentState = { ...this.initialState };
191
+ this.notifyListeners();
192
+ } else {
193
+ console.warn("BridgeStore: Cannot reset, initial state not available");
194
+ }
195
+ };
169
196
  this.notifyReady = () => {
170
197
  this.readyCallbacks.forEach((callback) => callback());
171
198
  this.readyCallbacks.clear();
@@ -173,6 +200,7 @@ class BridgeStore {
173
200
  this.bridge = bridge;
174
201
  this.currentState = initialState || null;
175
202
  this.previousState = initialState || null;
203
+ this.initialState = initialState || null;
176
204
  this.storeName = storeName;
177
205
  this.setupStateSync();
178
206
  this.initialize();
@@ -329,6 +357,7 @@ class StoreBuilder {
329
357
  createServiceWorkerStore() {
330
358
  let isReady = false;
331
359
  const readyCallbacks = /* @__PURE__ */ new Set();
360
+ let initialState = null;
332
361
  const notifyReady = () => {
333
362
  isReady = true;
334
363
  readyCallbacks.forEach((callback) => callback());
@@ -340,6 +369,9 @@ class StoreBuilder {
340
369
  const sliceState = slice(set, get, store2);
341
370
  state = { ...state, ...sliceState };
342
371
  }
372
+ if (initialState === null) {
373
+ initialState = { ...state };
374
+ }
343
375
  return state;
344
376
  };
345
377
  const persistOptions = {
@@ -350,6 +382,13 @@ class StoreBuilder {
350
382
  const store = vanilla.createStore(persistedCreator);
351
383
  const centralStore = Object.assign(store, {
352
384
  isReady: () => isReady,
385
+ reset: () => {
386
+ if (initialState !== null) {
387
+ store.setState(initialState, true);
388
+ } else {
389
+ console.warn("ServiceWorkerStore: Cannot reset, initial state not available");
390
+ }
391
+ },
353
392
  onReady: (callback) => {
354
393
  if (isReady) {
355
394
  callback();
@@ -464,3 +503,5 @@ exports.createStoreHooks = createStoreHooks;
464
503
  exports.init = init;
465
504
  exports.useCentralDispatch = useCentralDispatch;
466
505
  exports.useCentralStore = useCentralStore;
506
+ exports.useStoreReady = useStoreReady;
507
+ exports.useStoreReset = useStoreReset;
package/dist/index.d.ts CHANGED
@@ -24,6 +24,7 @@ type MergeSlices<Slices extends readonly StateCreator<any, [], [], any>[]> = Sli
24
24
  interface CentralStore<T> extends StoreApi<T> {
25
25
  isReady: () => boolean;
26
26
  onReady: (callback: () => void) => () => void;
27
+ reset: () => void;
27
28
  }
28
29
 
29
30
  declare function chromeStoragePersist<S>(options?: PersistOptions & {
@@ -35,6 +36,14 @@ declare function useCentralDispatch<T>(store: CentralStore<T>): {
35
36
  (partial: T | Partial<T> | ((state: T) => T | Partial<T>), replace?: false): void;
36
37
  (state: T | ((state: T) => T), replace: true): void;
37
38
  };
39
+ /**
40
+ * React hook to check if the store is ready (fully loaded from persistence/bridge)
41
+ */
42
+ declare function useStoreReady<T>(store: CentralStore<T>): boolean;
43
+ /**
44
+ * React hook to get the reset function for a store
45
+ */
46
+ declare function useStoreReset<T>(store: CentralStore<T>): () => void;
38
47
 
39
48
  interface Bridge {
40
49
  send: <Req = unknown, Res = unknown>(key: string, payload?: Req) => Promise<Res>;
@@ -53,6 +62,7 @@ declare class BridgeStore<T> implements CentralStore<T> {
53
62
  private listeners;
54
63
  private currentState;
55
64
  private previousState;
65
+ private initialState;
56
66
  private storeName;
57
67
  private ready;
58
68
  private readyCallbacks;
@@ -68,6 +78,7 @@ declare class BridgeStore<T> implements CentralStore<T> {
68
78
  getInitialState: () => T;
69
79
  isReady: () => boolean;
70
80
  onReady: (callback: () => void) => (() => void);
81
+ reset: () => void;
71
82
  private notifyReady;
72
83
  }
73
84
  declare function createBridgeStore<T>(bridge: BridgeWithEvents, initialState?: T, storeName?: string): CentralStore<T>;
@@ -147,5 +158,5 @@ declare function createStore<T = any>(name?: string): StoreBuilder<T>;
147
158
  */
148
159
  declare function init(storeDefinition: StoreDefinition): Promise<any>;
149
160
 
150
- export { BridgeStore, StoreBuilder, chromeStoragePersist, createActionHookForStore, createBridgeStore, createStore, createStoreHooks, init, useCentralDispatch, useCentralStore };
161
+ export { BridgeStore, StoreBuilder, chromeStoragePersist, createActionHookForStore, createBridgeStore, createStore, createStoreHooks, init, useCentralDispatch, useCentralStore, useStoreReady, useStoreReset };
151
162
  export type { Bridge, BridgeWithEvents, BridgeWithHandlers, CentralStore, ExtractSliceState, MergeSlices, PersistOptions, SliceCreator, StoreConfig, StoreDefinition };
package/dist/index.es.js CHANGED
@@ -76,12 +76,24 @@ function useCentralStore(store, selector) {
76
76
  function useCentralDispatch(store) {
77
77
  return store.setState;
78
78
  }
79
+ function useStoreReady(store) {
80
+ return useSyncExternalStore(
81
+ store.onReady,
82
+ store.isReady,
83
+ () => false
84
+ // Server-side fallback
85
+ );
86
+ }
87
+ function useStoreReset(store) {
88
+ return store.reset;
89
+ }
79
90
 
80
91
  class BridgeStore {
81
92
  constructor(bridge, initialState, storeName = "default") {
82
93
  this.listeners = /* @__PURE__ */ new Set();
83
94
  this.currentState = null;
84
95
  this.previousState = null;
96
+ this.initialState = null;
85
97
  this.ready = false;
86
98
  this.readyCallbacks = /* @__PURE__ */ new Set();
87
99
  this.initialize = async () => {
@@ -89,6 +101,9 @@ class BridgeStore {
89
101
  const state = await this.bridge.send(`store:${this.storeName}:getState`);
90
102
  this.previousState = this.currentState;
91
103
  this.currentState = state;
104
+ if (this.initialState === null) {
105
+ this.initialState = state;
106
+ }
92
107
  this.notifyListeners();
93
108
  this.ready = true;
94
109
  this.notifyReady();
@@ -146,6 +161,18 @@ class BridgeStore {
146
161
  this.readyCallbacks.delete(callback);
147
162
  };
148
163
  };
164
+ this.reset = () => {
165
+ if (this.initialState !== null) {
166
+ this.bridge.send(`store:${this.storeName}:reset`).catch((error) => {
167
+ console.error("Failed to reset state via bridge:", error);
168
+ });
169
+ this.previousState = this.currentState;
170
+ this.currentState = { ...this.initialState };
171
+ this.notifyListeners();
172
+ } else {
173
+ console.warn("BridgeStore: Cannot reset, initial state not available");
174
+ }
175
+ };
149
176
  this.notifyReady = () => {
150
177
  this.readyCallbacks.forEach((callback) => callback());
151
178
  this.readyCallbacks.clear();
@@ -153,6 +180,7 @@ class BridgeStore {
153
180
  this.bridge = bridge;
154
181
  this.currentState = initialState || null;
155
182
  this.previousState = initialState || null;
183
+ this.initialState = initialState || null;
156
184
  this.storeName = storeName;
157
185
  this.setupStateSync();
158
186
  this.initialize();
@@ -309,6 +337,7 @@ class StoreBuilder {
309
337
  createServiceWorkerStore() {
310
338
  let isReady = false;
311
339
  const readyCallbacks = /* @__PURE__ */ new Set();
340
+ let initialState = null;
312
341
  const notifyReady = () => {
313
342
  isReady = true;
314
343
  readyCallbacks.forEach((callback) => callback());
@@ -320,6 +349,9 @@ class StoreBuilder {
320
349
  const sliceState = slice(set, get, store2);
321
350
  state = { ...state, ...sliceState };
322
351
  }
352
+ if (initialState === null) {
353
+ initialState = { ...state };
354
+ }
323
355
  return state;
324
356
  };
325
357
  const persistOptions = {
@@ -330,6 +362,13 @@ class StoreBuilder {
330
362
  const store = createStore$1(persistedCreator);
331
363
  const centralStore = Object.assign(store, {
332
364
  isReady: () => isReady,
365
+ reset: () => {
366
+ if (initialState !== null) {
367
+ store.setState(initialState, true);
368
+ } else {
369
+ console.warn("ServiceWorkerStore: Cannot reset, initial state not available");
370
+ }
371
+ },
333
372
  onReady: (callback) => {
334
373
  if (isReady) {
335
374
  callback();
@@ -434,4 +473,4 @@ if (typeof globalThis !== "undefined") {
434
473
  globalThis.initStores = init;
435
474
  }
436
475
 
437
- export { BridgeStore, StoreBuilder, chromeStoragePersist, createActionHookForStore, createBridgeStore, createStore, createStoreHooks, init, useCentralDispatch, useCentralStore };
476
+ export { BridgeStore, StoreBuilder, chromeStoragePersist, createActionHookForStore, createBridgeStore, createStore, createStoreHooks, init, useCentralDispatch, useCentralStore, useStoreReady, useStoreReset };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chromahq/store",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Centralized, persistent store for Chrome extensions using zustand, accessible from service workers and React, with chrome.storage.local persistence.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",