@chromahq/store 1.0.18 → 1.0.20

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
@@ -108,6 +108,7 @@ function useStoreReset(store) {
108
108
  return store.reset;
109
109
  }
110
110
 
111
+ const STORE_ENABLE_LOGS = typeof globalThis !== "undefined" && globalThis.__CHROMA_ENABLE_LOGS__ === false ? false : true;
111
112
  class BridgeStore {
112
113
  constructor(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
113
114
  this.listeners = /* @__PURE__ */ new Set();
@@ -132,17 +133,21 @@ class BridgeStore {
132
133
  this.isInitializing = true;
133
134
  try {
134
135
  if (this.initializationAttempts > this.maxInitializationAttempts) {
135
- console.error(
136
- `BridgeStore[${this.storeName}]: Max initialization attempts (${this.maxInitializationAttempts}) reached, giving up`
137
- );
136
+ if (STORE_ENABLE_LOGS) {
137
+ console.error(
138
+ `BridgeStore[${this.storeName}]: Max initialization attempts (${this.maxInitializationAttempts}) reached, giving up`
139
+ );
140
+ }
138
141
  this.isInitializing = false;
139
142
  return;
140
143
  }
141
144
  if (!this.bridge.isConnected) {
142
145
  if (this.initializationAttempts === 1 || this.initializationAttempts % 3 === 0) {
143
- console.log(
144
- `BridgeStore[${this.storeName}]: Waiting for bridge connection (attempt ${this.initializationAttempts}/${this.maxInitializationAttempts})...`
145
- );
146
+ if (STORE_ENABLE_LOGS) {
147
+ console.log(
148
+ `BridgeStore[${this.storeName}]: Waiting for bridge connection (attempt ${this.initializationAttempts}/${this.maxInitializationAttempts})...`
149
+ );
150
+ }
146
151
  }
147
152
  const delay = Math.min(500 * Math.pow(2, this.initializationAttempts - 1), 5e3);
148
153
  this.isInitializing = false;
@@ -158,20 +163,28 @@ class BridgeStore {
158
163
  this.notifyListeners();
159
164
  this.ready = true;
160
165
  this.isInitializing = false;
161
- console.log(`BridgeStore[${this.storeName}]: Initialized successfully`);
166
+ if (STORE_ENABLE_LOGS) {
167
+ console.log(`BridgeStore[${this.storeName}]: Initialized successfully`);
168
+ }
162
169
  this.notifyReady();
163
170
  } catch (error) {
164
171
  this.isInitializing = false;
165
- console.error(
166
- `BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
167
- error
168
- );
172
+ if (STORE_ENABLE_LOGS) {
173
+ console.error(
174
+ `BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
175
+ error
176
+ );
177
+ }
169
178
  if (this.initializationAttempts < this.maxInitializationAttempts) {
170
179
  const delay = Math.min(1e3 * Math.pow(2, this.initializationAttempts - 1), 1e4);
171
- console.log(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
180
+ if (STORE_ENABLE_LOGS) {
181
+ console.log(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
182
+ }
172
183
  this.initializationTimer = setTimeout(() => this.initialize(), delay);
173
184
  } else {
174
- console.error(`BridgeStore[${this.storeName}]: Max attempts reached, cannot retry`);
185
+ if (STORE_ENABLE_LOGS) {
186
+ console.error(`BridgeStore[${this.storeName}]: Max attempts reached, cannot retry`);
187
+ }
175
188
  }
176
189
  }
177
190
  };
@@ -179,7 +192,9 @@ class BridgeStore {
179
192
  this.pendingStateSync = false;
180
193
  this.notifyListeners = () => {
181
194
  if (!this.listeners) {
182
- console.warn("BridgeStore: listeners not initialized");
195
+ if (STORE_ENABLE_LOGS) {
196
+ console.warn("BridgeStore: listeners not initialized");
197
+ }
183
198
  return;
184
199
  }
185
200
  if (this.currentState && this.previousState) {
@@ -191,7 +206,9 @@ class BridgeStore {
191
206
  };
192
207
  this.subscribe = (listener) => {
193
208
  if (!this.listeners) {
194
- console.error("BridgeStore: Cannot subscribe, listeners not initialized");
209
+ if (STORE_ENABLE_LOGS) {
210
+ console.error("BridgeStore: Cannot subscribe, listeners not initialized");
211
+ }
195
212
  return () => {
196
213
  };
197
214
  }
@@ -235,9 +252,11 @@ class BridgeStore {
235
252
  this.reset = () => {
236
253
  if (this.initialState !== null) {
237
254
  if (!this.bridge.isConnected) {
238
- console.warn(
239
- `BridgeStore[${this.storeName}]: Bridge disconnected, reset applied locally only`
240
- );
255
+ if (STORE_ENABLE_LOGS) {
256
+ console.warn(
257
+ `BridgeStore[${this.storeName}]: Bridge disconnected, reset applied locally only`
258
+ );
259
+ }
241
260
  this.previousState = this.currentState;
242
261
  this.currentState = { ...this.initialState };
243
262
  this.notifyListeners();
@@ -248,16 +267,22 @@ class BridgeStore {
248
267
  this.currentState = { ...this.initialState };
249
268
  this.notifyListeners();
250
269
  this.bridge.send(`store:${this.storeName}:reset`).catch((error) => {
251
- console.error(`BridgeStore[${this.storeName}]: Failed to reset state via bridge:`, error);
270
+ if (STORE_ENABLE_LOGS) {
271
+ console.error(`BridgeStore[${this.storeName}]: Failed to reset state via bridge:`, error);
272
+ }
252
273
  if (stateBeforeReset !== null) {
253
- console.warn(`BridgeStore[${this.storeName}]: Rolling back reset due to bridge error`);
274
+ if (STORE_ENABLE_LOGS) {
275
+ console.warn(`BridgeStore[${this.storeName}]: Rolling back reset due to bridge error`);
276
+ }
254
277
  this.previousState = this.currentState;
255
278
  this.currentState = stateBeforeReset;
256
279
  this.notifyListeners();
257
280
  }
258
281
  });
259
282
  } else {
260
- console.warn(`BridgeStore[${this.storeName}]: Cannot reset, initial state not available`);
283
+ if (STORE_ENABLE_LOGS) {
284
+ console.warn(`BridgeStore[${this.storeName}]: Cannot reset, initial state not available`);
285
+ }
261
286
  }
262
287
  };
263
288
  this.notifyReady = () => {
@@ -268,7 +293,9 @@ class BridgeStore {
268
293
  * Force re-initialization of the store (useful for debugging or after reconnection)
269
294
  */
270
295
  this.forceInitialize = async () => {
271
- console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
296
+ if (STORE_ENABLE_LOGS) {
297
+ console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
298
+ }
272
299
  if (this.initializationTimer) {
273
300
  clearTimeout(this.initializationTimer);
274
301
  this.initializationTimer = null;
@@ -301,8 +328,19 @@ class BridgeStore {
301
328
  this.storeName = storeName;
302
329
  this.readyCallbacks = readyCallbacks;
303
330
  this.setupStateSync();
331
+ this.setupReconnectListener();
304
332
  this.initialize();
305
333
  }
334
+ setupReconnectListener() {
335
+ if (this.bridge.on) {
336
+ this.bridge.on("bridge:connected", () => {
337
+ if (STORE_ENABLE_LOGS) {
338
+ console.log(`BridgeStore[${this.storeName}]: Bridge reconnected, re-initializing...`);
339
+ }
340
+ this.forceInitialize();
341
+ });
342
+ }
343
+ }
306
344
  setupStateSync() {
307
345
  if (this.bridge.on) {
308
346
  this.bridge.on(`store:${this.storeName}:stateChanged`, () => {
@@ -318,42 +356,59 @@ class BridgeStore {
318
356
  this.notifyListeners();
319
357
  }
320
358
  }).catch((error) => {
321
- console.error(`BridgeStore[${this.storeName}]: Failed to sync state:`, error);
359
+ if (STORE_ENABLE_LOGS) {
360
+ console.error(`BridgeStore[${this.storeName}]: Failed to sync state:`, error);
361
+ }
322
362
  }).finally(() => {
323
363
  this.pendingStateSync = false;
324
364
  });
325
365
  });
326
366
  } else {
327
- console.warn(`BridgeStore[${this.storeName}]: Bridge does not support event listening`);
367
+ if (STORE_ENABLE_LOGS) {
368
+ console.warn(`BridgeStore[${this.storeName}]: Bridge does not support event listening`);
369
+ }
328
370
  }
329
371
  }
330
372
  setState(partial, replace) {
331
373
  let actualUpdate;
332
374
  if (typeof partial === "function") {
333
375
  if (this.currentState === null) {
334
- console.warn("BridgeStore: Cannot execute function update, state not initialized");
376
+ if (STORE_ENABLE_LOGS) {
377
+ console.warn("BridgeStore: Cannot execute function update, state not initialized");
378
+ }
335
379
  return;
336
380
  }
337
- actualUpdate = partial(this.currentState);
381
+ if (globalThis.__CHROMA_ENABLE_LOGS__ !== false) {
382
+ console.warn("BridgeStore: Cannot execute function update, state not initialized");
383
+ }
338
384
  } else {
339
385
  actualUpdate = partial;
340
386
  }
341
387
  if (!this.bridge.isConnected) {
342
- console.warn(
343
- `BridgeStore[${this.storeName}]: Bridge disconnected, state update queued locally only`
344
- );
345
- this.applyOptimisticUpdate(actualUpdate, replace);
346
- return;
388
+ if (STORE_ENABLE_LOGS) {
389
+ console.warn(
390
+ `BridgeStore[${this.storeName}]: Bridge disconnected, state update queued locally only`
391
+ );
392
+ }
393
+ if (globalThis.__CHROMA_ENABLE_LOGS__ !== false) {
394
+ console.warn(
395
+ `BridgeStore[${this.storeName}]: Bridge disconnected, state update queued locally only`
396
+ );
397
+ }
347
398
  }
348
399
  const stateBeforeUpdate = this.currentState ? { ...this.currentState } : null;
349
400
  this.applyOptimisticUpdate(actualUpdate, replace);
350
401
  const payload = { partial: actualUpdate, replace };
351
402
  this.bridge.send(`store:${this.storeName}:setState`, payload).catch((error) => {
352
- console.error(`BridgeStore[${this.storeName}]: Failed to update state via bridge:`, error);
403
+ if (STORE_ENABLE_LOGS) {
404
+ console.error(`BridgeStore[${this.storeName}]: Failed to update state via bridge:`, error);
405
+ }
353
406
  if (stateBeforeUpdate !== null) {
354
- console.warn(
355
- `BridgeStore[${this.storeName}]: Rolling back optimistic update due to bridge error`
356
- );
407
+ if (STORE_ENABLE_LOGS) {
408
+ console.warn(
409
+ `BridgeStore[${this.storeName}]: Rolling back optimistic update due to bridge error`
410
+ );
411
+ }
357
412
  this.previousState = this.currentState;
358
413
  this.currentState = stateBeforeUpdate;
359
414
  this.notifyListeners();
package/dist/index.d.ts CHANGED
@@ -73,6 +73,7 @@ declare class BridgeStore<T> implements CentralStore<T> {
73
73
  private initializationTimer;
74
74
  private isInitializing;
75
75
  constructor(bridge: BridgeWithEvents, initialState?: T, storeName?: string, readyCallbacks?: Set<() => void>);
76
+ private setupReconnectListener;
76
77
  initialize: () => Promise<void>;
77
78
  private stateSyncSequence;
78
79
  private pendingStateSync;
package/dist/index.es.js CHANGED
@@ -88,6 +88,7 @@ function useStoreReset(store) {
88
88
  return store.reset;
89
89
  }
90
90
 
91
+ const STORE_ENABLE_LOGS = typeof globalThis !== "undefined" && globalThis.__CHROMA_ENABLE_LOGS__ === false ? false : true;
91
92
  class BridgeStore {
92
93
  constructor(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
93
94
  this.listeners = /* @__PURE__ */ new Set();
@@ -112,17 +113,21 @@ class BridgeStore {
112
113
  this.isInitializing = true;
113
114
  try {
114
115
  if (this.initializationAttempts > this.maxInitializationAttempts) {
115
- console.error(
116
- `BridgeStore[${this.storeName}]: Max initialization attempts (${this.maxInitializationAttempts}) reached, giving up`
117
- );
116
+ if (STORE_ENABLE_LOGS) {
117
+ console.error(
118
+ `BridgeStore[${this.storeName}]: Max initialization attempts (${this.maxInitializationAttempts}) reached, giving up`
119
+ );
120
+ }
118
121
  this.isInitializing = false;
119
122
  return;
120
123
  }
121
124
  if (!this.bridge.isConnected) {
122
125
  if (this.initializationAttempts === 1 || this.initializationAttempts % 3 === 0) {
123
- console.log(
124
- `BridgeStore[${this.storeName}]: Waiting for bridge connection (attempt ${this.initializationAttempts}/${this.maxInitializationAttempts})...`
125
- );
126
+ if (STORE_ENABLE_LOGS) {
127
+ console.log(
128
+ `BridgeStore[${this.storeName}]: Waiting for bridge connection (attempt ${this.initializationAttempts}/${this.maxInitializationAttempts})...`
129
+ );
130
+ }
126
131
  }
127
132
  const delay = Math.min(500 * Math.pow(2, this.initializationAttempts - 1), 5e3);
128
133
  this.isInitializing = false;
@@ -138,20 +143,28 @@ class BridgeStore {
138
143
  this.notifyListeners();
139
144
  this.ready = true;
140
145
  this.isInitializing = false;
141
- console.log(`BridgeStore[${this.storeName}]: Initialized successfully`);
146
+ if (STORE_ENABLE_LOGS) {
147
+ console.log(`BridgeStore[${this.storeName}]: Initialized successfully`);
148
+ }
142
149
  this.notifyReady();
143
150
  } catch (error) {
144
151
  this.isInitializing = false;
145
- console.error(
146
- `BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
147
- error
148
- );
152
+ if (STORE_ENABLE_LOGS) {
153
+ console.error(
154
+ `BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
155
+ error
156
+ );
157
+ }
149
158
  if (this.initializationAttempts < this.maxInitializationAttempts) {
150
159
  const delay = Math.min(1e3 * Math.pow(2, this.initializationAttempts - 1), 1e4);
151
- console.log(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
160
+ if (STORE_ENABLE_LOGS) {
161
+ console.log(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
162
+ }
152
163
  this.initializationTimer = setTimeout(() => this.initialize(), delay);
153
164
  } else {
154
- console.error(`BridgeStore[${this.storeName}]: Max attempts reached, cannot retry`);
165
+ if (STORE_ENABLE_LOGS) {
166
+ console.error(`BridgeStore[${this.storeName}]: Max attempts reached, cannot retry`);
167
+ }
155
168
  }
156
169
  }
157
170
  };
@@ -159,7 +172,9 @@ class BridgeStore {
159
172
  this.pendingStateSync = false;
160
173
  this.notifyListeners = () => {
161
174
  if (!this.listeners) {
162
- console.warn("BridgeStore: listeners not initialized");
175
+ if (STORE_ENABLE_LOGS) {
176
+ console.warn("BridgeStore: listeners not initialized");
177
+ }
163
178
  return;
164
179
  }
165
180
  if (this.currentState && this.previousState) {
@@ -171,7 +186,9 @@ class BridgeStore {
171
186
  };
172
187
  this.subscribe = (listener) => {
173
188
  if (!this.listeners) {
174
- console.error("BridgeStore: Cannot subscribe, listeners not initialized");
189
+ if (STORE_ENABLE_LOGS) {
190
+ console.error("BridgeStore: Cannot subscribe, listeners not initialized");
191
+ }
175
192
  return () => {
176
193
  };
177
194
  }
@@ -215,9 +232,11 @@ class BridgeStore {
215
232
  this.reset = () => {
216
233
  if (this.initialState !== null) {
217
234
  if (!this.bridge.isConnected) {
218
- console.warn(
219
- `BridgeStore[${this.storeName}]: Bridge disconnected, reset applied locally only`
220
- );
235
+ if (STORE_ENABLE_LOGS) {
236
+ console.warn(
237
+ `BridgeStore[${this.storeName}]: Bridge disconnected, reset applied locally only`
238
+ );
239
+ }
221
240
  this.previousState = this.currentState;
222
241
  this.currentState = { ...this.initialState };
223
242
  this.notifyListeners();
@@ -228,16 +247,22 @@ class BridgeStore {
228
247
  this.currentState = { ...this.initialState };
229
248
  this.notifyListeners();
230
249
  this.bridge.send(`store:${this.storeName}:reset`).catch((error) => {
231
- console.error(`BridgeStore[${this.storeName}]: Failed to reset state via bridge:`, error);
250
+ if (STORE_ENABLE_LOGS) {
251
+ console.error(`BridgeStore[${this.storeName}]: Failed to reset state via bridge:`, error);
252
+ }
232
253
  if (stateBeforeReset !== null) {
233
- console.warn(`BridgeStore[${this.storeName}]: Rolling back reset due to bridge error`);
254
+ if (STORE_ENABLE_LOGS) {
255
+ console.warn(`BridgeStore[${this.storeName}]: Rolling back reset due to bridge error`);
256
+ }
234
257
  this.previousState = this.currentState;
235
258
  this.currentState = stateBeforeReset;
236
259
  this.notifyListeners();
237
260
  }
238
261
  });
239
262
  } else {
240
- console.warn(`BridgeStore[${this.storeName}]: Cannot reset, initial state not available`);
263
+ if (STORE_ENABLE_LOGS) {
264
+ console.warn(`BridgeStore[${this.storeName}]: Cannot reset, initial state not available`);
265
+ }
241
266
  }
242
267
  };
243
268
  this.notifyReady = () => {
@@ -248,7 +273,9 @@ class BridgeStore {
248
273
  * Force re-initialization of the store (useful for debugging or after reconnection)
249
274
  */
250
275
  this.forceInitialize = async () => {
251
- console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
276
+ if (STORE_ENABLE_LOGS) {
277
+ console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
278
+ }
252
279
  if (this.initializationTimer) {
253
280
  clearTimeout(this.initializationTimer);
254
281
  this.initializationTimer = null;
@@ -281,8 +308,19 @@ class BridgeStore {
281
308
  this.storeName = storeName;
282
309
  this.readyCallbacks = readyCallbacks;
283
310
  this.setupStateSync();
311
+ this.setupReconnectListener();
284
312
  this.initialize();
285
313
  }
314
+ setupReconnectListener() {
315
+ if (this.bridge.on) {
316
+ this.bridge.on("bridge:connected", () => {
317
+ if (STORE_ENABLE_LOGS) {
318
+ console.log(`BridgeStore[${this.storeName}]: Bridge reconnected, re-initializing...`);
319
+ }
320
+ this.forceInitialize();
321
+ });
322
+ }
323
+ }
286
324
  setupStateSync() {
287
325
  if (this.bridge.on) {
288
326
  this.bridge.on(`store:${this.storeName}:stateChanged`, () => {
@@ -298,42 +336,59 @@ class BridgeStore {
298
336
  this.notifyListeners();
299
337
  }
300
338
  }).catch((error) => {
301
- console.error(`BridgeStore[${this.storeName}]: Failed to sync state:`, error);
339
+ if (STORE_ENABLE_LOGS) {
340
+ console.error(`BridgeStore[${this.storeName}]: Failed to sync state:`, error);
341
+ }
302
342
  }).finally(() => {
303
343
  this.pendingStateSync = false;
304
344
  });
305
345
  });
306
346
  } else {
307
- console.warn(`BridgeStore[${this.storeName}]: Bridge does not support event listening`);
347
+ if (STORE_ENABLE_LOGS) {
348
+ console.warn(`BridgeStore[${this.storeName}]: Bridge does not support event listening`);
349
+ }
308
350
  }
309
351
  }
310
352
  setState(partial, replace) {
311
353
  let actualUpdate;
312
354
  if (typeof partial === "function") {
313
355
  if (this.currentState === null) {
314
- console.warn("BridgeStore: Cannot execute function update, state not initialized");
356
+ if (STORE_ENABLE_LOGS) {
357
+ console.warn("BridgeStore: Cannot execute function update, state not initialized");
358
+ }
315
359
  return;
316
360
  }
317
- actualUpdate = partial(this.currentState);
361
+ if (globalThis.__CHROMA_ENABLE_LOGS__ !== false) {
362
+ console.warn("BridgeStore: Cannot execute function update, state not initialized");
363
+ }
318
364
  } else {
319
365
  actualUpdate = partial;
320
366
  }
321
367
  if (!this.bridge.isConnected) {
322
- console.warn(
323
- `BridgeStore[${this.storeName}]: Bridge disconnected, state update queued locally only`
324
- );
325
- this.applyOptimisticUpdate(actualUpdate, replace);
326
- return;
368
+ if (STORE_ENABLE_LOGS) {
369
+ console.warn(
370
+ `BridgeStore[${this.storeName}]: Bridge disconnected, state update queued locally only`
371
+ );
372
+ }
373
+ if (globalThis.__CHROMA_ENABLE_LOGS__ !== false) {
374
+ console.warn(
375
+ `BridgeStore[${this.storeName}]: Bridge disconnected, state update queued locally only`
376
+ );
377
+ }
327
378
  }
328
379
  const stateBeforeUpdate = this.currentState ? { ...this.currentState } : null;
329
380
  this.applyOptimisticUpdate(actualUpdate, replace);
330
381
  const payload = { partial: actualUpdate, replace };
331
382
  this.bridge.send(`store:${this.storeName}:setState`, payload).catch((error) => {
332
- console.error(`BridgeStore[${this.storeName}]: Failed to update state via bridge:`, error);
383
+ if (STORE_ENABLE_LOGS) {
384
+ console.error(`BridgeStore[${this.storeName}]: Failed to update state via bridge:`, error);
385
+ }
333
386
  if (stateBeforeUpdate !== null) {
334
- console.warn(
335
- `BridgeStore[${this.storeName}]: Rolling back optimistic update due to bridge error`
336
- );
387
+ if (STORE_ENABLE_LOGS) {
388
+ console.warn(
389
+ `BridgeStore[${this.storeName}]: Rolling back optimistic update due to bridge error`
390
+ );
391
+ }
337
392
  this.previousState = this.currentState;
338
393
  this.currentState = stateBeforeUpdate;
339
394
  this.notifyListeners();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chromahq/store",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
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",