@chromahq/store 1.0.1 → 1.0.3
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 +68 -7
- package/dist/index.d.ts +20 -0
- package/dist/index.es.js +68 -7
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -116,8 +116,27 @@ class BridgeStore {
|
|
|
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
|
+
}
|
|
137
|
+
console.debug(
|
|
138
|
+
`BridgeStore[${this.storeName}]: Initializing with bridge (attempt ${this.initializationAttempts})...`
|
|
139
|
+
);
|
|
121
140
|
const state = await this.bridge.send(`store:${this.storeName}:getState`);
|
|
122
141
|
this.previousState = this.currentState;
|
|
123
142
|
this.currentState = state;
|
|
@@ -127,8 +146,23 @@ class BridgeStore {
|
|
|
127
146
|
this.notifyListeners();
|
|
128
147
|
this.ready = true;
|
|
129
148
|
this.notifyReady();
|
|
149
|
+
console.debug(
|
|
150
|
+
`BridgeStore[${this.storeName}]: Successfully initialized and ready after ${this.initializationAttempts} attempts`
|
|
151
|
+
);
|
|
130
152
|
} catch (error) {
|
|
131
|
-
console.
|
|
153
|
+
console.error(
|
|
154
|
+
`BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
|
|
155
|
+
error
|
|
156
|
+
);
|
|
157
|
+
if (this.bridge.isConnected && this.initializationAttempts < this.maxInitializationAttempts) {
|
|
158
|
+
const delay = Math.min(2e3 * this.initializationAttempts, 1e4);
|
|
159
|
+
console.warn(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
|
|
160
|
+
setTimeout(() => this.initialize(), delay);
|
|
161
|
+
} else {
|
|
162
|
+
console.error(
|
|
163
|
+
`BridgeStore[${this.storeName}]: Bridge disconnected or max attempts reached, cannot retry`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
132
166
|
}
|
|
133
167
|
};
|
|
134
168
|
this.notifyListeners = () => {
|
|
@@ -197,11 +231,39 @@ class BridgeStore {
|
|
|
197
231
|
this.readyCallbacks.forEach((callback) => callback());
|
|
198
232
|
this.readyCallbacks.clear();
|
|
199
233
|
};
|
|
234
|
+
/**
|
|
235
|
+
* Force re-initialization of the store (useful for debugging)
|
|
236
|
+
*/
|
|
237
|
+
this.forceInitialize = async () => {
|
|
238
|
+
console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
|
|
239
|
+
this.ready = false;
|
|
240
|
+
this.initializationAttempts = 0;
|
|
241
|
+
await this.initialize();
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* Get debug information about the store state
|
|
245
|
+
*/
|
|
246
|
+
this.getDebugInfo = () => {
|
|
247
|
+
return {
|
|
248
|
+
storeName: this.storeName,
|
|
249
|
+
ready: this.ready,
|
|
250
|
+
bridgeConnected: this.bridge.isConnected,
|
|
251
|
+
hasCurrentState: this.currentState !== null,
|
|
252
|
+
hasInitialState: this.initialState !== null,
|
|
253
|
+
readyCallbacksCount: this.readyCallbacks.size,
|
|
254
|
+
initializationAttempts: this.initializationAttempts,
|
|
255
|
+
maxInitializationAttempts: this.maxInitializationAttempts
|
|
256
|
+
};
|
|
257
|
+
};
|
|
200
258
|
this.bridge = bridge;
|
|
201
259
|
this.currentState = initialState || null;
|
|
202
260
|
this.previousState = initialState || null;
|
|
203
261
|
this.initialState = initialState || null;
|
|
204
262
|
this.storeName = storeName;
|
|
263
|
+
console.debug(
|
|
264
|
+
`BridgeStore[${this.storeName}]: Creating with bridge connected:`,
|
|
265
|
+
bridge.isConnected
|
|
266
|
+
);
|
|
205
267
|
this.setupStateSync();
|
|
206
268
|
this.initialize();
|
|
207
269
|
}
|
|
@@ -317,6 +379,7 @@ function createStoreHooks() {
|
|
|
317
379
|
};
|
|
318
380
|
}
|
|
319
381
|
|
|
382
|
+
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
320
383
|
class StoreBuilder {
|
|
321
384
|
constructor(name = "default") {
|
|
322
385
|
this.config = {
|
|
@@ -331,6 +394,10 @@ class StoreBuilder {
|
|
|
331
394
|
this.config.slices = [...this.config.slices, ...slices];
|
|
332
395
|
return this;
|
|
333
396
|
}
|
|
397
|
+
onReady(callback) {
|
|
398
|
+
readyCallbacks.add(callback);
|
|
399
|
+
return this;
|
|
400
|
+
}
|
|
334
401
|
/**
|
|
335
402
|
* Attach a bridge for cross-context communication
|
|
336
403
|
*/
|
|
@@ -356,7 +423,6 @@ class StoreBuilder {
|
|
|
356
423
|
}
|
|
357
424
|
createServiceWorkerStore() {
|
|
358
425
|
let isReady = false;
|
|
359
|
-
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
360
426
|
let initialState = null;
|
|
361
427
|
const notifyReady = () => {
|
|
362
428
|
isReady = true;
|
|
@@ -487,11 +553,6 @@ async function init(storeDefinition) {
|
|
|
487
553
|
throw error;
|
|
488
554
|
}
|
|
489
555
|
}
|
|
490
|
-
if (typeof globalThis !== "undefined") {
|
|
491
|
-
globalThis.__CHROMA__ = globalThis.__CHROMA__ || {};
|
|
492
|
-
globalThis.__CHROMA__.initStores = init;
|
|
493
|
-
globalThis.initStores = init;
|
|
494
|
-
}
|
|
495
556
|
|
|
496
557
|
exports.BridgeStore = BridgeStore;
|
|
497
558
|
exports.StoreBuilder = StoreBuilder;
|
package/dist/index.d.ts
CHANGED
|
@@ -66,6 +66,8 @@ declare class BridgeStore<T> implements CentralStore<T> {
|
|
|
66
66
|
private storeName;
|
|
67
67
|
private ready;
|
|
68
68
|
private readyCallbacks;
|
|
69
|
+
private initializationAttempts;
|
|
70
|
+
private readonly maxInitializationAttempts;
|
|
69
71
|
constructor(bridge: BridgeWithEvents, initialState?: T, storeName?: string);
|
|
70
72
|
initialize: () => Promise<void>;
|
|
71
73
|
private setupStateSync;
|
|
@@ -80,6 +82,23 @@ 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
103
|
declare function createBridgeStore<T>(bridge: BridgeWithEvents, initialState?: T, storeName?: string): CentralStore<T>;
|
|
85
104
|
|
|
@@ -137,6 +156,7 @@ declare class StoreBuilder<T = any> {
|
|
|
137
156
|
* Add state slices to the store
|
|
138
157
|
*/
|
|
139
158
|
withSlices(...slices: StateCreator$1<any, [], [], any>[]): this;
|
|
159
|
+
onReady(callback: () => void): this;
|
|
140
160
|
/**
|
|
141
161
|
* Attach a bridge for cross-context communication
|
|
142
162
|
*/
|
package/dist/index.es.js
CHANGED
|
@@ -96,8 +96,27 @@ class BridgeStore {
|
|
|
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
|
+
}
|
|
117
|
+
console.debug(
|
|
118
|
+
`BridgeStore[${this.storeName}]: Initializing with bridge (attempt ${this.initializationAttempts})...`
|
|
119
|
+
);
|
|
101
120
|
const state = await this.bridge.send(`store:${this.storeName}:getState`);
|
|
102
121
|
this.previousState = this.currentState;
|
|
103
122
|
this.currentState = state;
|
|
@@ -107,8 +126,23 @@ class BridgeStore {
|
|
|
107
126
|
this.notifyListeners();
|
|
108
127
|
this.ready = true;
|
|
109
128
|
this.notifyReady();
|
|
129
|
+
console.debug(
|
|
130
|
+
`BridgeStore[${this.storeName}]: Successfully initialized and ready after ${this.initializationAttempts} attempts`
|
|
131
|
+
);
|
|
110
132
|
} catch (error) {
|
|
111
|
-
console.
|
|
133
|
+
console.error(
|
|
134
|
+
`BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
|
|
135
|
+
error
|
|
136
|
+
);
|
|
137
|
+
if (this.bridge.isConnected && this.initializationAttempts < this.maxInitializationAttempts) {
|
|
138
|
+
const delay = Math.min(2e3 * this.initializationAttempts, 1e4);
|
|
139
|
+
console.warn(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
|
|
140
|
+
setTimeout(() => this.initialize(), delay);
|
|
141
|
+
} else {
|
|
142
|
+
console.error(
|
|
143
|
+
`BridgeStore[${this.storeName}]: Bridge disconnected or max attempts reached, cannot retry`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
112
146
|
}
|
|
113
147
|
};
|
|
114
148
|
this.notifyListeners = () => {
|
|
@@ -177,11 +211,39 @@ class BridgeStore {
|
|
|
177
211
|
this.readyCallbacks.forEach((callback) => callback());
|
|
178
212
|
this.readyCallbacks.clear();
|
|
179
213
|
};
|
|
214
|
+
/**
|
|
215
|
+
* Force re-initialization of the store (useful for debugging)
|
|
216
|
+
*/
|
|
217
|
+
this.forceInitialize = async () => {
|
|
218
|
+
console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
|
|
219
|
+
this.ready = false;
|
|
220
|
+
this.initializationAttempts = 0;
|
|
221
|
+
await this.initialize();
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Get debug information about the store state
|
|
225
|
+
*/
|
|
226
|
+
this.getDebugInfo = () => {
|
|
227
|
+
return {
|
|
228
|
+
storeName: this.storeName,
|
|
229
|
+
ready: this.ready,
|
|
230
|
+
bridgeConnected: this.bridge.isConnected,
|
|
231
|
+
hasCurrentState: this.currentState !== null,
|
|
232
|
+
hasInitialState: this.initialState !== null,
|
|
233
|
+
readyCallbacksCount: this.readyCallbacks.size,
|
|
234
|
+
initializationAttempts: this.initializationAttempts,
|
|
235
|
+
maxInitializationAttempts: this.maxInitializationAttempts
|
|
236
|
+
};
|
|
237
|
+
};
|
|
180
238
|
this.bridge = bridge;
|
|
181
239
|
this.currentState = initialState || null;
|
|
182
240
|
this.previousState = initialState || null;
|
|
183
241
|
this.initialState = initialState || null;
|
|
184
242
|
this.storeName = storeName;
|
|
243
|
+
console.debug(
|
|
244
|
+
`BridgeStore[${this.storeName}]: Creating with bridge connected:`,
|
|
245
|
+
bridge.isConnected
|
|
246
|
+
);
|
|
185
247
|
this.setupStateSync();
|
|
186
248
|
this.initialize();
|
|
187
249
|
}
|
|
@@ -297,6 +359,7 @@ function createStoreHooks() {
|
|
|
297
359
|
};
|
|
298
360
|
}
|
|
299
361
|
|
|
362
|
+
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
300
363
|
class StoreBuilder {
|
|
301
364
|
constructor(name = "default") {
|
|
302
365
|
this.config = {
|
|
@@ -311,6 +374,10 @@ class StoreBuilder {
|
|
|
311
374
|
this.config.slices = [...this.config.slices, ...slices];
|
|
312
375
|
return this;
|
|
313
376
|
}
|
|
377
|
+
onReady(callback) {
|
|
378
|
+
readyCallbacks.add(callback);
|
|
379
|
+
return this;
|
|
380
|
+
}
|
|
314
381
|
/**
|
|
315
382
|
* Attach a bridge for cross-context communication
|
|
316
383
|
*/
|
|
@@ -336,7 +403,6 @@ class StoreBuilder {
|
|
|
336
403
|
}
|
|
337
404
|
createServiceWorkerStore() {
|
|
338
405
|
let isReady = false;
|
|
339
|
-
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
340
406
|
let initialState = null;
|
|
341
407
|
const notifyReady = () => {
|
|
342
408
|
isReady = true;
|
|
@@ -467,10 +533,5 @@ async function init(storeDefinition) {
|
|
|
467
533
|
throw error;
|
|
468
534
|
}
|
|
469
535
|
}
|
|
470
|
-
if (typeof globalThis !== "undefined") {
|
|
471
|
-
globalThis.__CHROMA__ = globalThis.__CHROMA__ || {};
|
|
472
|
-
globalThis.__CHROMA__.initStores = init;
|
|
473
|
-
globalThis.initStores = init;
|
|
474
|
-
}
|
|
475
536
|
|
|
476
537
|
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.3",
|
|
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",
|