@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 +41 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.es.js +40 -1
- package/package.json +1 -1
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.
|
|
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",
|