@chromahq/store 1.0.2 → 1.0.4
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 +64 -11
- package/dist/index.d.ts +23 -2
- package/dist/index.es.js +64 -11
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -109,15 +109,31 @@ function useStoreReset(store) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
class BridgeStore {
|
|
112
|
-
constructor(bridge, initialState, storeName = "default") {
|
|
112
|
+
constructor(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
|
|
113
113
|
this.listeners = /* @__PURE__ */ new Set();
|
|
114
114
|
this.currentState = null;
|
|
115
115
|
this.previousState = null;
|
|
116
116
|
this.initialState = null;
|
|
117
117
|
this.ready = false;
|
|
118
118
|
this.readyCallbacks = /* @__PURE__ */ new Set();
|
|
119
|
+
this.initializationAttempts = 0;
|
|
120
|
+
this.maxInitializationAttempts = 10;
|
|
119
121
|
this.initialize = async () => {
|
|
122
|
+
this.initializationAttempts++;
|
|
120
123
|
try {
|
|
124
|
+
if (this.initializationAttempts > this.maxInitializationAttempts) {
|
|
125
|
+
console.error(
|
|
126
|
+
`BridgeStore[${this.storeName}]: Max initialization attempts (${this.maxInitializationAttempts}) reached, giving up`
|
|
127
|
+
);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (!this.bridge.isConnected) {
|
|
131
|
+
console.warn(
|
|
132
|
+
`BridgeStore[${this.storeName}]: Bridge not connected (attempt ${this.initializationAttempts}), retrying in 1s...`
|
|
133
|
+
);
|
|
134
|
+
setTimeout(() => this.initialize(), 500);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
121
137
|
const state = await this.bridge.send(`store:${this.storeName}:getState`);
|
|
122
138
|
this.previousState = this.currentState;
|
|
123
139
|
this.currentState = state;
|
|
@@ -128,7 +144,19 @@ class BridgeStore {
|
|
|
128
144
|
this.ready = true;
|
|
129
145
|
this.notifyReady();
|
|
130
146
|
} catch (error) {
|
|
131
|
-
console.
|
|
147
|
+
console.error(
|
|
148
|
+
`BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
|
|
149
|
+
error
|
|
150
|
+
);
|
|
151
|
+
if (this.bridge.isConnected && this.initializationAttempts < this.maxInitializationAttempts) {
|
|
152
|
+
const delay = Math.min(2e3 * this.initializationAttempts, 1e4);
|
|
153
|
+
console.warn(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
|
|
154
|
+
setTimeout(() => this.initialize(), delay);
|
|
155
|
+
} else {
|
|
156
|
+
console.error(
|
|
157
|
+
`BridgeStore[${this.storeName}]: Bridge disconnected or max attempts reached, cannot retry`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
132
160
|
}
|
|
133
161
|
};
|
|
134
162
|
this.notifyListeners = () => {
|
|
@@ -197,11 +225,36 @@ class BridgeStore {
|
|
|
197
225
|
this.readyCallbacks.forEach((callback) => callback());
|
|
198
226
|
this.readyCallbacks.clear();
|
|
199
227
|
};
|
|
228
|
+
/**
|
|
229
|
+
* Force re-initialization of the store (useful for debugging)
|
|
230
|
+
*/
|
|
231
|
+
this.forceInitialize = async () => {
|
|
232
|
+
console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
|
|
233
|
+
this.ready = false;
|
|
234
|
+
this.initializationAttempts = 0;
|
|
235
|
+
await this.initialize();
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Get debug information about the store state
|
|
239
|
+
*/
|
|
240
|
+
this.getDebugInfo = () => {
|
|
241
|
+
return {
|
|
242
|
+
storeName: this.storeName,
|
|
243
|
+
ready: this.ready,
|
|
244
|
+
bridgeConnected: this.bridge.isConnected,
|
|
245
|
+
hasCurrentState: this.currentState !== null,
|
|
246
|
+
hasInitialState: this.initialState !== null,
|
|
247
|
+
readyCallbacksCount: this.readyCallbacks.size,
|
|
248
|
+
initializationAttempts: this.initializationAttempts,
|
|
249
|
+
maxInitializationAttempts: this.maxInitializationAttempts
|
|
250
|
+
};
|
|
251
|
+
};
|
|
200
252
|
this.bridge = bridge;
|
|
201
253
|
this.currentState = initialState || null;
|
|
202
254
|
this.previousState = initialState || null;
|
|
203
255
|
this.initialState = initialState || null;
|
|
204
256
|
this.storeName = storeName;
|
|
257
|
+
this.readyCallbacks = readyCallbacks;
|
|
205
258
|
this.setupStateSync();
|
|
206
259
|
this.initialize();
|
|
207
260
|
}
|
|
@@ -240,8 +293,8 @@ class BridgeStore {
|
|
|
240
293
|
}
|
|
241
294
|
}
|
|
242
295
|
}
|
|
243
|
-
function createBridgeStore(bridge, initialState, storeName = "default") {
|
|
244
|
-
return new BridgeStore(bridge, initialState, storeName);
|
|
296
|
+
function createBridgeStore(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
|
|
297
|
+
return new BridgeStore(bridge, initialState, storeName, readyCallbacks);
|
|
245
298
|
}
|
|
246
299
|
|
|
247
300
|
function createActionHookForStore(store, actionsFactory) {
|
|
@@ -317,8 +370,10 @@ function createStoreHooks() {
|
|
|
317
370
|
};
|
|
318
371
|
}
|
|
319
372
|
|
|
373
|
+
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
320
374
|
class StoreBuilder {
|
|
321
375
|
constructor(name = "default") {
|
|
376
|
+
this.onReadyCallbacks = /* @__PURE__ */ new Set();
|
|
322
377
|
this.config = {
|
|
323
378
|
name,
|
|
324
379
|
slices: []
|
|
@@ -331,6 +386,10 @@ class StoreBuilder {
|
|
|
331
386
|
this.config.slices = [...this.config.slices, ...slices];
|
|
332
387
|
return this;
|
|
333
388
|
}
|
|
389
|
+
onReady(callback) {
|
|
390
|
+
this.onReadyCallbacks.add(callback);
|
|
391
|
+
return this;
|
|
392
|
+
}
|
|
334
393
|
/**
|
|
335
394
|
* Attach a bridge for cross-context communication
|
|
336
395
|
*/
|
|
@@ -350,13 +409,12 @@ class StoreBuilder {
|
|
|
350
409
|
async createBaseStore() {
|
|
351
410
|
const bridge = this.config.bridge;
|
|
352
411
|
if (bridge) {
|
|
353
|
-
return createBridgeStore(bridge, void 0, this.config.name);
|
|
412
|
+
return createBridgeStore(bridge, void 0, this.config.name, this.onReadyCallbacks);
|
|
354
413
|
}
|
|
355
414
|
return this.createServiceWorkerStore();
|
|
356
415
|
}
|
|
357
416
|
createServiceWorkerStore() {
|
|
358
417
|
let isReady = false;
|
|
359
|
-
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
360
418
|
let initialState = null;
|
|
361
419
|
const notifyReady = () => {
|
|
362
420
|
isReady = true;
|
|
@@ -487,11 +545,6 @@ async function init(storeDefinition) {
|
|
|
487
545
|
throw error;
|
|
488
546
|
}
|
|
489
547
|
}
|
|
490
|
-
if (typeof globalThis !== "undefined") {
|
|
491
|
-
globalThis.__CHROMA__ = globalThis.__CHROMA__ || {};
|
|
492
|
-
globalThis.__CHROMA__.initStores = init;
|
|
493
|
-
globalThis.initStores = init;
|
|
494
|
-
}
|
|
495
548
|
|
|
496
549
|
exports.BridgeStore = BridgeStore;
|
|
497
550
|
exports.StoreBuilder = StoreBuilder;
|
package/dist/index.d.ts
CHANGED
|
@@ -66,7 +66,9 @@ declare class BridgeStore<T> implements CentralStore<T> {
|
|
|
66
66
|
private storeName;
|
|
67
67
|
private ready;
|
|
68
68
|
private readyCallbacks;
|
|
69
|
-
|
|
69
|
+
private initializationAttempts;
|
|
70
|
+
private readonly maxInitializationAttempts;
|
|
71
|
+
constructor(bridge: BridgeWithEvents, initialState?: T, storeName?: string, readyCallbacks?: Set<() => void>);
|
|
70
72
|
initialize: () => Promise<void>;
|
|
71
73
|
private setupStateSync;
|
|
72
74
|
private notifyListeners;
|
|
@@ -80,8 +82,25 @@ declare class BridgeStore<T> implements CentralStore<T> {
|
|
|
80
82
|
onReady: (callback: () => void) => (() => void);
|
|
81
83
|
reset: () => void;
|
|
82
84
|
private notifyReady;
|
|
85
|
+
/**
|
|
86
|
+
* Force re-initialization of the store (useful for debugging)
|
|
87
|
+
*/
|
|
88
|
+
forceInitialize: () => Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Get debug information about the store state
|
|
91
|
+
*/
|
|
92
|
+
getDebugInfo: () => {
|
|
93
|
+
storeName: string;
|
|
94
|
+
ready: boolean;
|
|
95
|
+
bridgeConnected: boolean;
|
|
96
|
+
hasCurrentState: boolean;
|
|
97
|
+
hasInitialState: boolean;
|
|
98
|
+
readyCallbacksCount: number;
|
|
99
|
+
initializationAttempts: number;
|
|
100
|
+
maxInitializationAttempts: number;
|
|
101
|
+
};
|
|
83
102
|
}
|
|
84
|
-
declare function createBridgeStore<T>(bridge: BridgeWithEvents, initialState?: T, storeName?: string): CentralStore<T>;
|
|
103
|
+
declare function createBridgeStore<T>(bridge: BridgeWithEvents, initialState?: T, storeName?: string, readyCallbacks?: Set<() => void>): CentralStore<T>;
|
|
85
104
|
|
|
86
105
|
/**
|
|
87
106
|
* Generic action hook factory for any store instance.
|
|
@@ -132,11 +151,13 @@ declare function createStoreHooks<T extends Record<string, any>>(): {
|
|
|
132
151
|
*/
|
|
133
152
|
declare class StoreBuilder<T = any> {
|
|
134
153
|
private config;
|
|
154
|
+
private onReadyCallbacks;
|
|
135
155
|
constructor(name?: string);
|
|
136
156
|
/**
|
|
137
157
|
* Add state slices to the store
|
|
138
158
|
*/
|
|
139
159
|
withSlices(...slices: StateCreator$1<any, [], [], any>[]): this;
|
|
160
|
+
onReady(callback: () => void): this;
|
|
140
161
|
/**
|
|
141
162
|
* Attach a bridge for cross-context communication
|
|
142
163
|
*/
|
package/dist/index.es.js
CHANGED
|
@@ -89,15 +89,31 @@ function useStoreReset(store) {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
class BridgeStore {
|
|
92
|
-
constructor(bridge, initialState, storeName = "default") {
|
|
92
|
+
constructor(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
|
|
93
93
|
this.listeners = /* @__PURE__ */ new Set();
|
|
94
94
|
this.currentState = null;
|
|
95
95
|
this.previousState = null;
|
|
96
96
|
this.initialState = null;
|
|
97
97
|
this.ready = false;
|
|
98
98
|
this.readyCallbacks = /* @__PURE__ */ new Set();
|
|
99
|
+
this.initializationAttempts = 0;
|
|
100
|
+
this.maxInitializationAttempts = 10;
|
|
99
101
|
this.initialize = async () => {
|
|
102
|
+
this.initializationAttempts++;
|
|
100
103
|
try {
|
|
104
|
+
if (this.initializationAttempts > this.maxInitializationAttempts) {
|
|
105
|
+
console.error(
|
|
106
|
+
`BridgeStore[${this.storeName}]: Max initialization attempts (${this.maxInitializationAttempts}) reached, giving up`
|
|
107
|
+
);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (!this.bridge.isConnected) {
|
|
111
|
+
console.warn(
|
|
112
|
+
`BridgeStore[${this.storeName}]: Bridge not connected (attempt ${this.initializationAttempts}), retrying in 1s...`
|
|
113
|
+
);
|
|
114
|
+
setTimeout(() => this.initialize(), 500);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
101
117
|
const state = await this.bridge.send(`store:${this.storeName}:getState`);
|
|
102
118
|
this.previousState = this.currentState;
|
|
103
119
|
this.currentState = state;
|
|
@@ -108,7 +124,19 @@ class BridgeStore {
|
|
|
108
124
|
this.ready = true;
|
|
109
125
|
this.notifyReady();
|
|
110
126
|
} catch (error) {
|
|
111
|
-
console.
|
|
127
|
+
console.error(
|
|
128
|
+
`BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
|
|
129
|
+
error
|
|
130
|
+
);
|
|
131
|
+
if (this.bridge.isConnected && this.initializationAttempts < this.maxInitializationAttempts) {
|
|
132
|
+
const delay = Math.min(2e3 * this.initializationAttempts, 1e4);
|
|
133
|
+
console.warn(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
|
|
134
|
+
setTimeout(() => this.initialize(), delay);
|
|
135
|
+
} else {
|
|
136
|
+
console.error(
|
|
137
|
+
`BridgeStore[${this.storeName}]: Bridge disconnected or max attempts reached, cannot retry`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
112
140
|
}
|
|
113
141
|
};
|
|
114
142
|
this.notifyListeners = () => {
|
|
@@ -177,11 +205,36 @@ class BridgeStore {
|
|
|
177
205
|
this.readyCallbacks.forEach((callback) => callback());
|
|
178
206
|
this.readyCallbacks.clear();
|
|
179
207
|
};
|
|
208
|
+
/**
|
|
209
|
+
* Force re-initialization of the store (useful for debugging)
|
|
210
|
+
*/
|
|
211
|
+
this.forceInitialize = async () => {
|
|
212
|
+
console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
|
|
213
|
+
this.ready = false;
|
|
214
|
+
this.initializationAttempts = 0;
|
|
215
|
+
await this.initialize();
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Get debug information about the store state
|
|
219
|
+
*/
|
|
220
|
+
this.getDebugInfo = () => {
|
|
221
|
+
return {
|
|
222
|
+
storeName: this.storeName,
|
|
223
|
+
ready: this.ready,
|
|
224
|
+
bridgeConnected: this.bridge.isConnected,
|
|
225
|
+
hasCurrentState: this.currentState !== null,
|
|
226
|
+
hasInitialState: this.initialState !== null,
|
|
227
|
+
readyCallbacksCount: this.readyCallbacks.size,
|
|
228
|
+
initializationAttempts: this.initializationAttempts,
|
|
229
|
+
maxInitializationAttempts: this.maxInitializationAttempts
|
|
230
|
+
};
|
|
231
|
+
};
|
|
180
232
|
this.bridge = bridge;
|
|
181
233
|
this.currentState = initialState || null;
|
|
182
234
|
this.previousState = initialState || null;
|
|
183
235
|
this.initialState = initialState || null;
|
|
184
236
|
this.storeName = storeName;
|
|
237
|
+
this.readyCallbacks = readyCallbacks;
|
|
185
238
|
this.setupStateSync();
|
|
186
239
|
this.initialize();
|
|
187
240
|
}
|
|
@@ -220,8 +273,8 @@ class BridgeStore {
|
|
|
220
273
|
}
|
|
221
274
|
}
|
|
222
275
|
}
|
|
223
|
-
function createBridgeStore(bridge, initialState, storeName = "default") {
|
|
224
|
-
return new BridgeStore(bridge, initialState, storeName);
|
|
276
|
+
function createBridgeStore(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
|
|
277
|
+
return new BridgeStore(bridge, initialState, storeName, readyCallbacks);
|
|
225
278
|
}
|
|
226
279
|
|
|
227
280
|
function createActionHookForStore(store, actionsFactory) {
|
|
@@ -297,8 +350,10 @@ function createStoreHooks() {
|
|
|
297
350
|
};
|
|
298
351
|
}
|
|
299
352
|
|
|
353
|
+
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
300
354
|
class StoreBuilder {
|
|
301
355
|
constructor(name = "default") {
|
|
356
|
+
this.onReadyCallbacks = /* @__PURE__ */ new Set();
|
|
302
357
|
this.config = {
|
|
303
358
|
name,
|
|
304
359
|
slices: []
|
|
@@ -311,6 +366,10 @@ class StoreBuilder {
|
|
|
311
366
|
this.config.slices = [...this.config.slices, ...slices];
|
|
312
367
|
return this;
|
|
313
368
|
}
|
|
369
|
+
onReady(callback) {
|
|
370
|
+
this.onReadyCallbacks.add(callback);
|
|
371
|
+
return this;
|
|
372
|
+
}
|
|
314
373
|
/**
|
|
315
374
|
* Attach a bridge for cross-context communication
|
|
316
375
|
*/
|
|
@@ -330,13 +389,12 @@ class StoreBuilder {
|
|
|
330
389
|
async createBaseStore() {
|
|
331
390
|
const bridge = this.config.bridge;
|
|
332
391
|
if (bridge) {
|
|
333
|
-
return createBridgeStore(bridge, void 0, this.config.name);
|
|
392
|
+
return createBridgeStore(bridge, void 0, this.config.name, this.onReadyCallbacks);
|
|
334
393
|
}
|
|
335
394
|
return this.createServiceWorkerStore();
|
|
336
395
|
}
|
|
337
396
|
createServiceWorkerStore() {
|
|
338
397
|
let isReady = false;
|
|
339
|
-
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
340
398
|
let initialState = null;
|
|
341
399
|
const notifyReady = () => {
|
|
342
400
|
isReady = true;
|
|
@@ -467,10 +525,5 @@ async function init(storeDefinition) {
|
|
|
467
525
|
throw error;
|
|
468
526
|
}
|
|
469
527
|
}
|
|
470
|
-
if (typeof globalThis !== "undefined") {
|
|
471
|
-
globalThis.__CHROMA__ = globalThis.__CHROMA__ || {};
|
|
472
|
-
globalThis.__CHROMA__.initStores = init;
|
|
473
|
-
globalThis.initStores = init;
|
|
474
|
-
}
|
|
475
528
|
|
|
476
529
|
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.4",
|
|
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",
|