@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 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.warn("Failed to initialize bridge store:", error);
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.warn("Failed to initialize bridge store:", error);
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.1",
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",