@chromahq/store 1.0.61 → 1.0.63
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 +13 -141
- package/dist/index.es.js +13 -141
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -31,7 +31,6 @@ function chromeStoragePersist(options = {}) {
|
|
|
31
31
|
const loadPersistedState = async () => {
|
|
32
32
|
try {
|
|
33
33
|
if (!chrome?.storage?.local) {
|
|
34
|
-
console.warn(`Chrome storage not available for "${key}", using memory only`);
|
|
35
34
|
isInitialized = true;
|
|
36
35
|
setupPersistence();
|
|
37
36
|
return;
|
|
@@ -116,7 +115,6 @@ function useStoreReset(store) {
|
|
|
116
115
|
return store.reset;
|
|
117
116
|
}
|
|
118
117
|
|
|
119
|
-
const STORE_ENABLE_LOGS = typeof globalThis !== "undefined" && globalThis.__CHROMA_ENABLE_LOGS__ === false ? false : true;
|
|
120
118
|
class BridgeStore {
|
|
121
119
|
// Consider state stale after 30s hidden
|
|
122
120
|
constructor(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
|
|
@@ -156,22 +154,13 @@ class BridgeStore {
|
|
|
156
154
|
this.isInitializing = true;
|
|
157
155
|
try {
|
|
158
156
|
if (this.initializationAttempts > this.maxInitializationAttempts) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
);
|
|
163
|
-
}
|
|
157
|
+
console.error(
|
|
158
|
+
`BridgeStore[${this.storeName}]: Max initialization attempts (${this.maxInitializationAttempts}) reached, giving up`
|
|
159
|
+
);
|
|
164
160
|
this.isInitializing = false;
|
|
165
161
|
return;
|
|
166
162
|
}
|
|
167
163
|
if (!this.bridge.isConnected) {
|
|
168
|
-
if (this.initializationAttempts === 1 || this.initializationAttempts % 3 === 0) {
|
|
169
|
-
if (STORE_ENABLE_LOGS) {
|
|
170
|
-
console.log(
|
|
171
|
-
`BridgeStore[${this.storeName}]: Waiting for bridge connection (attempt ${this.initializationAttempts}/${this.maxInitializationAttempts})...`
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
164
|
const delay = Math.min(500 * Math.pow(2, this.initializationAttempts - 1), 5e3);
|
|
176
165
|
this.isInitializing = false;
|
|
177
166
|
this.initializationTimer = setTimeout(() => this.initialize(), delay);
|
|
@@ -186,28 +175,18 @@ class BridgeStore {
|
|
|
186
175
|
this.notifyListeners();
|
|
187
176
|
this.ready = true;
|
|
188
177
|
this.isInitializing = false;
|
|
189
|
-
if (STORE_ENABLE_LOGS) {
|
|
190
|
-
console.log(`BridgeStore[${this.storeName}]: Initialized successfully`);
|
|
191
|
-
}
|
|
192
178
|
this.notifyReady();
|
|
193
179
|
} catch (error) {
|
|
194
180
|
this.isInitializing = false;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
);
|
|
200
|
-
}
|
|
181
|
+
console.error(
|
|
182
|
+
`BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
|
|
183
|
+
error
|
|
184
|
+
);
|
|
201
185
|
if (this.initializationAttempts < this.maxInitializationAttempts) {
|
|
202
186
|
const delay = Math.min(1e3 * Math.pow(2, this.initializationAttempts - 1), 1e4);
|
|
203
|
-
if (STORE_ENABLE_LOGS) {
|
|
204
|
-
console.log(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
|
|
205
|
-
}
|
|
206
187
|
this.initializationTimer = setTimeout(() => this.initialize(), delay);
|
|
207
188
|
} else {
|
|
208
|
-
|
|
209
|
-
console.error(`BridgeStore[${this.storeName}]: Max attempts reached, cannot retry`);
|
|
210
|
-
}
|
|
189
|
+
console.error(`BridgeStore[${this.storeName}]: Max attempts reached, cannot retry`);
|
|
211
190
|
}
|
|
212
191
|
}
|
|
213
192
|
};
|
|
@@ -215,9 +194,6 @@ class BridgeStore {
|
|
|
215
194
|
this.pendingStateSync = false;
|
|
216
195
|
this.notifyListeners = () => {
|
|
217
196
|
if (!this.listeners) {
|
|
218
|
-
if (STORE_ENABLE_LOGS) {
|
|
219
|
-
console.warn("BridgeStore: listeners not initialized");
|
|
220
|
-
}
|
|
221
197
|
return;
|
|
222
198
|
}
|
|
223
199
|
if (this.currentState && this.previousState) {
|
|
@@ -229,9 +205,7 @@ class BridgeStore {
|
|
|
229
205
|
};
|
|
230
206
|
this.subscribe = (listener) => {
|
|
231
207
|
if (!this.listeners) {
|
|
232
|
-
|
|
233
|
-
console.error("BridgeStore: Cannot subscribe, listeners not initialized");
|
|
234
|
-
}
|
|
208
|
+
console.error("BridgeStore: Cannot subscribe, listeners not initialized");
|
|
235
209
|
return () => {
|
|
236
210
|
};
|
|
237
211
|
}
|
|
@@ -301,11 +275,6 @@ class BridgeStore {
|
|
|
301
275
|
this.reset = () => {
|
|
302
276
|
if (this.initialState !== null) {
|
|
303
277
|
if (!this.bridge.isConnected) {
|
|
304
|
-
if (STORE_ENABLE_LOGS) {
|
|
305
|
-
console.warn(
|
|
306
|
-
`BridgeStore[${this.storeName}]: Bridge disconnected, reset applied locally only`
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
278
|
this.previousState = this.currentState;
|
|
310
279
|
this.currentState = { ...this.initialState };
|
|
311
280
|
this.notifyListeners();
|
|
@@ -316,22 +285,13 @@ class BridgeStore {
|
|
|
316
285
|
this.currentState = { ...this.initialState };
|
|
317
286
|
this.notifyListeners();
|
|
318
287
|
this.bridge.send(`store:${this.storeName}:reset`).catch((error) => {
|
|
319
|
-
|
|
320
|
-
console.error(`BridgeStore[${this.storeName}]: Failed to reset state via bridge:`, error);
|
|
321
|
-
}
|
|
288
|
+
console.error(`BridgeStore[${this.storeName}]: Failed to reset state via bridge:`, error);
|
|
322
289
|
if (stateBeforeReset !== null) {
|
|
323
|
-
if (STORE_ENABLE_LOGS) {
|
|
324
|
-
console.warn(`BridgeStore[${this.storeName}]: Rolling back reset due to bridge error`);
|
|
325
|
-
}
|
|
326
290
|
this.previousState = this.currentState;
|
|
327
291
|
this.currentState = stateBeforeReset;
|
|
328
292
|
this.notifyListeners();
|
|
329
293
|
}
|
|
330
294
|
});
|
|
331
|
-
} else {
|
|
332
|
-
if (STORE_ENABLE_LOGS) {
|
|
333
|
-
console.warn(`BridgeStore[${this.storeName}]: Cannot reset, initial state not available`);
|
|
334
|
-
}
|
|
335
295
|
}
|
|
336
296
|
};
|
|
337
297
|
this.notifyReady = () => {
|
|
@@ -342,9 +302,6 @@ class BridgeStore {
|
|
|
342
302
|
* Force re-initialization of the store (useful for debugging or after reconnection)
|
|
343
303
|
*/
|
|
344
304
|
this.forceInitialize = async () => {
|
|
345
|
-
if (STORE_ENABLE_LOGS) {
|
|
346
|
-
console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
|
|
347
|
-
}
|
|
348
305
|
if (this.initializationTimer) {
|
|
349
306
|
clearTimeout(this.initializationTimer);
|
|
350
307
|
this.initializationTimer = null;
|
|
@@ -379,11 +336,6 @@ class BridgeStore {
|
|
|
379
336
|
if (this.bridge === newBridge) {
|
|
380
337
|
return;
|
|
381
338
|
}
|
|
382
|
-
if (STORE_ENABLE_LOGS) {
|
|
383
|
-
console.log(
|
|
384
|
-
`BridgeStore[${this.storeName}]: Updating bridge reference and re-registering listeners`
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
339
|
this.bridge = newBridge;
|
|
388
340
|
this.reregisterEventListeners();
|
|
389
341
|
};
|
|
@@ -401,11 +353,6 @@ class BridgeStore {
|
|
|
401
353
|
setupReconnectListener() {
|
|
402
354
|
if (this.bridge.on) {
|
|
403
355
|
this.disconnectHandler = () => {
|
|
404
|
-
if (STORE_ENABLE_LOGS) {
|
|
405
|
-
console.log(
|
|
406
|
-
`BridgeStore[${this.storeName}]: Bridge disconnected, marking store as not ready`
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
356
|
this.ready = false;
|
|
410
357
|
if (this.stateSyncDebounceTimer) {
|
|
411
358
|
clearTimeout(this.stateSyncDebounceTimer);
|
|
@@ -420,11 +367,6 @@ class BridgeStore {
|
|
|
420
367
|
};
|
|
421
368
|
this.bridge.on("bridge:disconnected", this.disconnectHandler);
|
|
422
369
|
this.reconnectHandler = () => {
|
|
423
|
-
if (STORE_ENABLE_LOGS) {
|
|
424
|
-
console.log(
|
|
425
|
-
`BridgeStore[${this.storeName}]: Bridge reconnected, re-registering listeners and re-initializing...`
|
|
426
|
-
);
|
|
427
|
-
}
|
|
428
370
|
if (this.reconnectDelayTimer) {
|
|
429
371
|
clearTimeout(this.reconnectDelayTimer);
|
|
430
372
|
this.reconnectDelayTimer = null;
|
|
@@ -447,9 +389,6 @@ class BridgeStore {
|
|
|
447
389
|
if (this.bridge.off) {
|
|
448
390
|
this.bridge.off(eventKey, this.stateChangedHandler);
|
|
449
391
|
}
|
|
450
|
-
if (STORE_ENABLE_LOGS) {
|
|
451
|
-
console.log(`BridgeStore[${this.storeName}]: Re-registering listener for '${eventKey}'`);
|
|
452
|
-
}
|
|
453
392
|
this.bridge.on(eventKey, this.stateChangedHandler);
|
|
454
393
|
}
|
|
455
394
|
if (this.disconnectHandler) {
|
|
@@ -471,11 +410,6 @@ class BridgeStore {
|
|
|
471
410
|
if (document.visibilityState === "visible") {
|
|
472
411
|
const hiddenDuration = Date.now() - this.lastVisibleAt;
|
|
473
412
|
if (hiddenDuration > this.staleThresholdMs && this.ready && this.bridge.isConnected) {
|
|
474
|
-
if (STORE_ENABLE_LOGS) {
|
|
475
|
-
console.log(
|
|
476
|
-
`BridgeStore[${this.storeName}]: Tab visible after ${Math.round(hiddenDuration / 1e3)}s, refreshing state`
|
|
477
|
-
);
|
|
478
|
-
}
|
|
479
413
|
this.fetchAndApplyState();
|
|
480
414
|
}
|
|
481
415
|
this.lastVisibleAt = Date.now();
|
|
@@ -488,16 +422,8 @@ class BridgeStore {
|
|
|
488
422
|
*/
|
|
489
423
|
applyBroadcastState(newState) {
|
|
490
424
|
if (!newState || typeof newState !== "object") {
|
|
491
|
-
if (STORE_ENABLE_LOGS) {
|
|
492
|
-
console.warn(`BridgeStore[${this.storeName}]: Invalid broadcast state, ignoring`);
|
|
493
|
-
}
|
|
494
425
|
return;
|
|
495
426
|
}
|
|
496
|
-
if (STORE_ENABLE_LOGS) {
|
|
497
|
-
console.log(
|
|
498
|
-
`BridgeStore[${this.storeName}]: Applying broadcast state, notifying ${this.listeners?.size ?? 0} listeners`
|
|
499
|
-
);
|
|
500
|
-
}
|
|
501
427
|
this.previousState = this.currentState;
|
|
502
428
|
this.currentState = newState;
|
|
503
429
|
this.notifyListeners();
|
|
@@ -518,9 +444,7 @@ class BridgeStore {
|
|
|
518
444
|
this.notifyListeners();
|
|
519
445
|
}
|
|
520
446
|
}).catch((error) => {
|
|
521
|
-
|
|
522
|
-
console.error(`BridgeStore[${this.storeName}]: Failed to sync state:`, error);
|
|
523
|
-
}
|
|
447
|
+
console.error(`BridgeStore[${this.storeName}]: Failed to sync state:`, error);
|
|
524
448
|
}).finally(() => {
|
|
525
449
|
this.pendingStateSync = false;
|
|
526
450
|
});
|
|
@@ -528,12 +452,6 @@ class BridgeStore {
|
|
|
528
452
|
setupStateSync() {
|
|
529
453
|
if (this.bridge.on) {
|
|
530
454
|
this.stateChangedHandler = (payload) => {
|
|
531
|
-
if (STORE_ENABLE_LOGS) {
|
|
532
|
-
console.log(`BridgeStore[${this.storeName}]: Received stateChanged broadcast`, {
|
|
533
|
-
hasPayload: !!payload,
|
|
534
|
-
payloadType: typeof payload
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
455
|
if (this.stateSyncDebounceTimer) {
|
|
538
456
|
clearTimeout(this.stateSyncDebounceTimer);
|
|
539
457
|
}
|
|
@@ -547,49 +465,25 @@ class BridgeStore {
|
|
|
547
465
|
}, this.stateSyncDebounceMs);
|
|
548
466
|
};
|
|
549
467
|
const eventKey = `store:${this.storeName}:stateChanged`;
|
|
550
|
-
if (STORE_ENABLE_LOGS) {
|
|
551
|
-
console.log(`BridgeStore[${this.storeName}]: Registering listener for '${eventKey}'`);
|
|
552
|
-
}
|
|
553
468
|
this.bridge.on(eventKey, this.stateChangedHandler);
|
|
554
|
-
} else {
|
|
555
|
-
if (STORE_ENABLE_LOGS) {
|
|
556
|
-
console.warn(`BridgeStore[${this.storeName}]: Bridge does not support event listening`);
|
|
557
|
-
}
|
|
558
469
|
}
|
|
559
470
|
}
|
|
560
471
|
setState(partial, replace) {
|
|
561
472
|
let actualUpdate;
|
|
562
473
|
if (typeof partial === "function") {
|
|
563
474
|
if (this.currentState === null) {
|
|
564
|
-
if (STORE_ENABLE_LOGS) {
|
|
565
|
-
console.warn("BridgeStore: Cannot execute function update, state not initialized");
|
|
566
|
-
}
|
|
567
475
|
return;
|
|
568
476
|
}
|
|
569
477
|
actualUpdate = partial(this.currentState);
|
|
570
478
|
} else {
|
|
571
479
|
actualUpdate = partial;
|
|
572
480
|
}
|
|
573
|
-
if (!this.bridge.isConnected) {
|
|
574
|
-
if (STORE_ENABLE_LOGS) {
|
|
575
|
-
console.warn(
|
|
576
|
-
`BridgeStore[${this.storeName}]: Bridge disconnected, state update queued locally only`
|
|
577
|
-
);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
481
|
const stateBeforeUpdate = this.currentState ? { ...this.currentState } : null;
|
|
581
482
|
this.applyOptimisticUpdate(actualUpdate, replace);
|
|
582
483
|
const payload = { partial: actualUpdate, replace };
|
|
583
484
|
this.bridge.send(`store:${this.storeName}:setState`, payload).catch((error) => {
|
|
584
|
-
|
|
585
|
-
console.error(`BridgeStore[${this.storeName}]: Failed to update state via bridge:`, error);
|
|
586
|
-
}
|
|
485
|
+
console.error(`BridgeStore[${this.storeName}]: Failed to update state via bridge:`, error);
|
|
587
486
|
if (stateBeforeUpdate !== null) {
|
|
588
|
-
if (STORE_ENABLE_LOGS) {
|
|
589
|
-
console.warn(
|
|
590
|
-
`BridgeStore[${this.storeName}]: Rolling back optimistic update due to bridge error`
|
|
591
|
-
);
|
|
592
|
-
}
|
|
593
487
|
this.previousState = this.currentState;
|
|
594
488
|
this.currentState = stateBeforeUpdate;
|
|
595
489
|
this.notifyListeners();
|
|
@@ -612,18 +506,12 @@ const storeCache = /* @__PURE__ */ new Map();
|
|
|
612
506
|
function createBridgeStore(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
|
|
613
507
|
if (storeCache.has(storeName)) {
|
|
614
508
|
const cached = storeCache.get(storeName);
|
|
615
|
-
if (STORE_ENABLE_LOGS) {
|
|
616
|
-
console.log(`BridgeStore[${storeName}]: Returning cached instance (singleton)`);
|
|
617
|
-
}
|
|
618
509
|
cached.updateBridge(bridge);
|
|
619
510
|
readyCallbacks.forEach((cb) => cached.onReady(cb));
|
|
620
511
|
return cached;
|
|
621
512
|
}
|
|
622
513
|
const store = new BridgeStore(bridge, initialState, storeName, readyCallbacks);
|
|
623
514
|
storeCache.set(storeName, store);
|
|
624
|
-
if (STORE_ENABLE_LOGS) {
|
|
625
|
-
console.log(`BridgeStore[${storeName}]: Created new instance (cached)`);
|
|
626
|
-
}
|
|
627
515
|
return store;
|
|
628
516
|
}
|
|
629
517
|
function clearStoreCache() {
|
|
@@ -632,9 +520,6 @@ function clearStoreCache() {
|
|
|
632
520
|
function destroyStore(storeName) {
|
|
633
521
|
const store = storeCache.get(storeName);
|
|
634
522
|
if (store) {
|
|
635
|
-
if (STORE_ENABLE_LOGS) {
|
|
636
|
-
console.log(`BridgeStore[${storeName}]: Destroying store and removing from cache`);
|
|
637
|
-
}
|
|
638
523
|
store.destroy();
|
|
639
524
|
storeCache.delete(storeName);
|
|
640
525
|
}
|
|
@@ -809,8 +694,6 @@ class StoreBuilder {
|
|
|
809
694
|
reset: () => {
|
|
810
695
|
if (initialState !== null) {
|
|
811
696
|
store.setState(initialState, true);
|
|
812
|
-
} else {
|
|
813
|
-
console.warn("ServiceWorkerStore: Cannot reset, initial state not available");
|
|
814
697
|
}
|
|
815
698
|
},
|
|
816
699
|
setBridge: (bridge) => {
|
|
@@ -855,24 +738,14 @@ function autoRegisterStoreHandlers(store, storeName = "default") {
|
|
|
855
738
|
if (typeof store.setState !== "function") {
|
|
856
739
|
throw new Error("autoRegisterStoreHandlers: store must have setState method");
|
|
857
740
|
}
|
|
858
|
-
console.log(`[Store] Creating handlers for store "${storeName}"`, {
|
|
859
|
-
hasGetState: typeof store.getState === "function",
|
|
860
|
-
hasSetState: typeof store.setState === "function"
|
|
861
|
-
});
|
|
862
741
|
class AutoGetStoreStateMessage {
|
|
863
742
|
handle() {
|
|
864
|
-
console.log(`[Store] GetState handler called for "${storeName}"`);
|
|
865
743
|
if (!store) {
|
|
866
744
|
console.error(`[Store] Store instance not available for "${storeName}"`);
|
|
867
745
|
throw new Error("Store instance not available");
|
|
868
746
|
}
|
|
869
747
|
try {
|
|
870
|
-
|
|
871
|
-
console.log(`[Store] GetState returning state for "${storeName}"`, {
|
|
872
|
-
hasState: state !== void 0 && state !== null,
|
|
873
|
-
stateType: typeof state
|
|
874
|
-
});
|
|
875
|
-
return state;
|
|
748
|
+
return store.getState();
|
|
876
749
|
} catch (error) {
|
|
877
750
|
console.error(`[Store] GetState failed for "${storeName}":`, error);
|
|
878
751
|
throw error;
|
|
@@ -917,7 +790,6 @@ function autoRegisterStoreHandlers(store, storeName = "default") {
|
|
|
917
790
|
}
|
|
918
791
|
class AutoResetStoreMessage {
|
|
919
792
|
handle() {
|
|
920
|
-
console.log(`[Store] Reset handler called for "${storeName}"`);
|
|
921
793
|
if (!store) {
|
|
922
794
|
console.error(`[Store] Store instance not available for "${storeName}"`);
|
|
923
795
|
throw new Error("Store instance not available");
|
package/dist/index.es.js
CHANGED
|
@@ -11,7 +11,6 @@ function chromeStoragePersist(options = {}) {
|
|
|
11
11
|
const loadPersistedState = async () => {
|
|
12
12
|
try {
|
|
13
13
|
if (!chrome?.storage?.local) {
|
|
14
|
-
console.warn(`Chrome storage not available for "${key}", using memory only`);
|
|
15
14
|
isInitialized = true;
|
|
16
15
|
setupPersistence();
|
|
17
16
|
return;
|
|
@@ -96,7 +95,6 @@ function useStoreReset(store) {
|
|
|
96
95
|
return store.reset;
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
const STORE_ENABLE_LOGS = typeof globalThis !== "undefined" && globalThis.__CHROMA_ENABLE_LOGS__ === false ? false : true;
|
|
100
98
|
class BridgeStore {
|
|
101
99
|
// Consider state stale after 30s hidden
|
|
102
100
|
constructor(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
|
|
@@ -136,22 +134,13 @@ class BridgeStore {
|
|
|
136
134
|
this.isInitializing = true;
|
|
137
135
|
try {
|
|
138
136
|
if (this.initializationAttempts > this.maxInitializationAttempts) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
);
|
|
143
|
-
}
|
|
137
|
+
console.error(
|
|
138
|
+
`BridgeStore[${this.storeName}]: Max initialization attempts (${this.maxInitializationAttempts}) reached, giving up`
|
|
139
|
+
);
|
|
144
140
|
this.isInitializing = false;
|
|
145
141
|
return;
|
|
146
142
|
}
|
|
147
143
|
if (!this.bridge.isConnected) {
|
|
148
|
-
if (this.initializationAttempts === 1 || this.initializationAttempts % 3 === 0) {
|
|
149
|
-
if (STORE_ENABLE_LOGS) {
|
|
150
|
-
console.log(
|
|
151
|
-
`BridgeStore[${this.storeName}]: Waiting for bridge connection (attempt ${this.initializationAttempts}/${this.maxInitializationAttempts})...`
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
144
|
const delay = Math.min(500 * Math.pow(2, this.initializationAttempts - 1), 5e3);
|
|
156
145
|
this.isInitializing = false;
|
|
157
146
|
this.initializationTimer = setTimeout(() => this.initialize(), delay);
|
|
@@ -166,28 +155,18 @@ class BridgeStore {
|
|
|
166
155
|
this.notifyListeners();
|
|
167
156
|
this.ready = true;
|
|
168
157
|
this.isInitializing = false;
|
|
169
|
-
if (STORE_ENABLE_LOGS) {
|
|
170
|
-
console.log(`BridgeStore[${this.storeName}]: Initialized successfully`);
|
|
171
|
-
}
|
|
172
158
|
this.notifyReady();
|
|
173
159
|
} catch (error) {
|
|
174
160
|
this.isInitializing = false;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
);
|
|
180
|
-
}
|
|
161
|
+
console.error(
|
|
162
|
+
`BridgeStore[${this.storeName}]: Failed to initialize (attempt ${this.initializationAttempts}):`,
|
|
163
|
+
error
|
|
164
|
+
);
|
|
181
165
|
if (this.initializationAttempts < this.maxInitializationAttempts) {
|
|
182
166
|
const delay = Math.min(1e3 * Math.pow(2, this.initializationAttempts - 1), 1e4);
|
|
183
|
-
if (STORE_ENABLE_LOGS) {
|
|
184
|
-
console.log(`BridgeStore[${this.storeName}]: Retrying initialization in ${delay}ms...`);
|
|
185
|
-
}
|
|
186
167
|
this.initializationTimer = setTimeout(() => this.initialize(), delay);
|
|
187
168
|
} else {
|
|
188
|
-
|
|
189
|
-
console.error(`BridgeStore[${this.storeName}]: Max attempts reached, cannot retry`);
|
|
190
|
-
}
|
|
169
|
+
console.error(`BridgeStore[${this.storeName}]: Max attempts reached, cannot retry`);
|
|
191
170
|
}
|
|
192
171
|
}
|
|
193
172
|
};
|
|
@@ -195,9 +174,6 @@ class BridgeStore {
|
|
|
195
174
|
this.pendingStateSync = false;
|
|
196
175
|
this.notifyListeners = () => {
|
|
197
176
|
if (!this.listeners) {
|
|
198
|
-
if (STORE_ENABLE_LOGS) {
|
|
199
|
-
console.warn("BridgeStore: listeners not initialized");
|
|
200
|
-
}
|
|
201
177
|
return;
|
|
202
178
|
}
|
|
203
179
|
if (this.currentState && this.previousState) {
|
|
@@ -209,9 +185,7 @@ class BridgeStore {
|
|
|
209
185
|
};
|
|
210
186
|
this.subscribe = (listener) => {
|
|
211
187
|
if (!this.listeners) {
|
|
212
|
-
|
|
213
|
-
console.error("BridgeStore: Cannot subscribe, listeners not initialized");
|
|
214
|
-
}
|
|
188
|
+
console.error("BridgeStore: Cannot subscribe, listeners not initialized");
|
|
215
189
|
return () => {
|
|
216
190
|
};
|
|
217
191
|
}
|
|
@@ -281,11 +255,6 @@ class BridgeStore {
|
|
|
281
255
|
this.reset = () => {
|
|
282
256
|
if (this.initialState !== null) {
|
|
283
257
|
if (!this.bridge.isConnected) {
|
|
284
|
-
if (STORE_ENABLE_LOGS) {
|
|
285
|
-
console.warn(
|
|
286
|
-
`BridgeStore[${this.storeName}]: Bridge disconnected, reset applied locally only`
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
258
|
this.previousState = this.currentState;
|
|
290
259
|
this.currentState = { ...this.initialState };
|
|
291
260
|
this.notifyListeners();
|
|
@@ -296,22 +265,13 @@ class BridgeStore {
|
|
|
296
265
|
this.currentState = { ...this.initialState };
|
|
297
266
|
this.notifyListeners();
|
|
298
267
|
this.bridge.send(`store:${this.storeName}:reset`).catch((error) => {
|
|
299
|
-
|
|
300
|
-
console.error(`BridgeStore[${this.storeName}]: Failed to reset state via bridge:`, error);
|
|
301
|
-
}
|
|
268
|
+
console.error(`BridgeStore[${this.storeName}]: Failed to reset state via bridge:`, error);
|
|
302
269
|
if (stateBeforeReset !== null) {
|
|
303
|
-
if (STORE_ENABLE_LOGS) {
|
|
304
|
-
console.warn(`BridgeStore[${this.storeName}]: Rolling back reset due to bridge error`);
|
|
305
|
-
}
|
|
306
270
|
this.previousState = this.currentState;
|
|
307
271
|
this.currentState = stateBeforeReset;
|
|
308
272
|
this.notifyListeners();
|
|
309
273
|
}
|
|
310
274
|
});
|
|
311
|
-
} else {
|
|
312
|
-
if (STORE_ENABLE_LOGS) {
|
|
313
|
-
console.warn(`BridgeStore[${this.storeName}]: Cannot reset, initial state not available`);
|
|
314
|
-
}
|
|
315
275
|
}
|
|
316
276
|
};
|
|
317
277
|
this.notifyReady = () => {
|
|
@@ -322,9 +282,6 @@ class BridgeStore {
|
|
|
322
282
|
* Force re-initialization of the store (useful for debugging or after reconnection)
|
|
323
283
|
*/
|
|
324
284
|
this.forceInitialize = async () => {
|
|
325
|
-
if (STORE_ENABLE_LOGS) {
|
|
326
|
-
console.debug(`BridgeStore[${this.storeName}]: Force re-initialization requested`);
|
|
327
|
-
}
|
|
328
285
|
if (this.initializationTimer) {
|
|
329
286
|
clearTimeout(this.initializationTimer);
|
|
330
287
|
this.initializationTimer = null;
|
|
@@ -359,11 +316,6 @@ class BridgeStore {
|
|
|
359
316
|
if (this.bridge === newBridge) {
|
|
360
317
|
return;
|
|
361
318
|
}
|
|
362
|
-
if (STORE_ENABLE_LOGS) {
|
|
363
|
-
console.log(
|
|
364
|
-
`BridgeStore[${this.storeName}]: Updating bridge reference and re-registering listeners`
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
319
|
this.bridge = newBridge;
|
|
368
320
|
this.reregisterEventListeners();
|
|
369
321
|
};
|
|
@@ -381,11 +333,6 @@ class BridgeStore {
|
|
|
381
333
|
setupReconnectListener() {
|
|
382
334
|
if (this.bridge.on) {
|
|
383
335
|
this.disconnectHandler = () => {
|
|
384
|
-
if (STORE_ENABLE_LOGS) {
|
|
385
|
-
console.log(
|
|
386
|
-
`BridgeStore[${this.storeName}]: Bridge disconnected, marking store as not ready`
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
336
|
this.ready = false;
|
|
390
337
|
if (this.stateSyncDebounceTimer) {
|
|
391
338
|
clearTimeout(this.stateSyncDebounceTimer);
|
|
@@ -400,11 +347,6 @@ class BridgeStore {
|
|
|
400
347
|
};
|
|
401
348
|
this.bridge.on("bridge:disconnected", this.disconnectHandler);
|
|
402
349
|
this.reconnectHandler = () => {
|
|
403
|
-
if (STORE_ENABLE_LOGS) {
|
|
404
|
-
console.log(
|
|
405
|
-
`BridgeStore[${this.storeName}]: Bridge reconnected, re-registering listeners and re-initializing...`
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
350
|
if (this.reconnectDelayTimer) {
|
|
409
351
|
clearTimeout(this.reconnectDelayTimer);
|
|
410
352
|
this.reconnectDelayTimer = null;
|
|
@@ -427,9 +369,6 @@ class BridgeStore {
|
|
|
427
369
|
if (this.bridge.off) {
|
|
428
370
|
this.bridge.off(eventKey, this.stateChangedHandler);
|
|
429
371
|
}
|
|
430
|
-
if (STORE_ENABLE_LOGS) {
|
|
431
|
-
console.log(`BridgeStore[${this.storeName}]: Re-registering listener for '${eventKey}'`);
|
|
432
|
-
}
|
|
433
372
|
this.bridge.on(eventKey, this.stateChangedHandler);
|
|
434
373
|
}
|
|
435
374
|
if (this.disconnectHandler) {
|
|
@@ -451,11 +390,6 @@ class BridgeStore {
|
|
|
451
390
|
if (document.visibilityState === "visible") {
|
|
452
391
|
const hiddenDuration = Date.now() - this.lastVisibleAt;
|
|
453
392
|
if (hiddenDuration > this.staleThresholdMs && this.ready && this.bridge.isConnected) {
|
|
454
|
-
if (STORE_ENABLE_LOGS) {
|
|
455
|
-
console.log(
|
|
456
|
-
`BridgeStore[${this.storeName}]: Tab visible after ${Math.round(hiddenDuration / 1e3)}s, refreshing state`
|
|
457
|
-
);
|
|
458
|
-
}
|
|
459
393
|
this.fetchAndApplyState();
|
|
460
394
|
}
|
|
461
395
|
this.lastVisibleAt = Date.now();
|
|
@@ -468,16 +402,8 @@ class BridgeStore {
|
|
|
468
402
|
*/
|
|
469
403
|
applyBroadcastState(newState) {
|
|
470
404
|
if (!newState || typeof newState !== "object") {
|
|
471
|
-
if (STORE_ENABLE_LOGS) {
|
|
472
|
-
console.warn(`BridgeStore[${this.storeName}]: Invalid broadcast state, ignoring`);
|
|
473
|
-
}
|
|
474
405
|
return;
|
|
475
406
|
}
|
|
476
|
-
if (STORE_ENABLE_LOGS) {
|
|
477
|
-
console.log(
|
|
478
|
-
`BridgeStore[${this.storeName}]: Applying broadcast state, notifying ${this.listeners?.size ?? 0} listeners`
|
|
479
|
-
);
|
|
480
|
-
}
|
|
481
407
|
this.previousState = this.currentState;
|
|
482
408
|
this.currentState = newState;
|
|
483
409
|
this.notifyListeners();
|
|
@@ -498,9 +424,7 @@ class BridgeStore {
|
|
|
498
424
|
this.notifyListeners();
|
|
499
425
|
}
|
|
500
426
|
}).catch((error) => {
|
|
501
|
-
|
|
502
|
-
console.error(`BridgeStore[${this.storeName}]: Failed to sync state:`, error);
|
|
503
|
-
}
|
|
427
|
+
console.error(`BridgeStore[${this.storeName}]: Failed to sync state:`, error);
|
|
504
428
|
}).finally(() => {
|
|
505
429
|
this.pendingStateSync = false;
|
|
506
430
|
});
|
|
@@ -508,12 +432,6 @@ class BridgeStore {
|
|
|
508
432
|
setupStateSync() {
|
|
509
433
|
if (this.bridge.on) {
|
|
510
434
|
this.stateChangedHandler = (payload) => {
|
|
511
|
-
if (STORE_ENABLE_LOGS) {
|
|
512
|
-
console.log(`BridgeStore[${this.storeName}]: Received stateChanged broadcast`, {
|
|
513
|
-
hasPayload: !!payload,
|
|
514
|
-
payloadType: typeof payload
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
435
|
if (this.stateSyncDebounceTimer) {
|
|
518
436
|
clearTimeout(this.stateSyncDebounceTimer);
|
|
519
437
|
}
|
|
@@ -527,49 +445,25 @@ class BridgeStore {
|
|
|
527
445
|
}, this.stateSyncDebounceMs);
|
|
528
446
|
};
|
|
529
447
|
const eventKey = `store:${this.storeName}:stateChanged`;
|
|
530
|
-
if (STORE_ENABLE_LOGS) {
|
|
531
|
-
console.log(`BridgeStore[${this.storeName}]: Registering listener for '${eventKey}'`);
|
|
532
|
-
}
|
|
533
448
|
this.bridge.on(eventKey, this.stateChangedHandler);
|
|
534
|
-
} else {
|
|
535
|
-
if (STORE_ENABLE_LOGS) {
|
|
536
|
-
console.warn(`BridgeStore[${this.storeName}]: Bridge does not support event listening`);
|
|
537
|
-
}
|
|
538
449
|
}
|
|
539
450
|
}
|
|
540
451
|
setState(partial, replace) {
|
|
541
452
|
let actualUpdate;
|
|
542
453
|
if (typeof partial === "function") {
|
|
543
454
|
if (this.currentState === null) {
|
|
544
|
-
if (STORE_ENABLE_LOGS) {
|
|
545
|
-
console.warn("BridgeStore: Cannot execute function update, state not initialized");
|
|
546
|
-
}
|
|
547
455
|
return;
|
|
548
456
|
}
|
|
549
457
|
actualUpdate = partial(this.currentState);
|
|
550
458
|
} else {
|
|
551
459
|
actualUpdate = partial;
|
|
552
460
|
}
|
|
553
|
-
if (!this.bridge.isConnected) {
|
|
554
|
-
if (STORE_ENABLE_LOGS) {
|
|
555
|
-
console.warn(
|
|
556
|
-
`BridgeStore[${this.storeName}]: Bridge disconnected, state update queued locally only`
|
|
557
|
-
);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
461
|
const stateBeforeUpdate = this.currentState ? { ...this.currentState } : null;
|
|
561
462
|
this.applyOptimisticUpdate(actualUpdate, replace);
|
|
562
463
|
const payload = { partial: actualUpdate, replace };
|
|
563
464
|
this.bridge.send(`store:${this.storeName}:setState`, payload).catch((error) => {
|
|
564
|
-
|
|
565
|
-
console.error(`BridgeStore[${this.storeName}]: Failed to update state via bridge:`, error);
|
|
566
|
-
}
|
|
465
|
+
console.error(`BridgeStore[${this.storeName}]: Failed to update state via bridge:`, error);
|
|
567
466
|
if (stateBeforeUpdate !== null) {
|
|
568
|
-
if (STORE_ENABLE_LOGS) {
|
|
569
|
-
console.warn(
|
|
570
|
-
`BridgeStore[${this.storeName}]: Rolling back optimistic update due to bridge error`
|
|
571
|
-
);
|
|
572
|
-
}
|
|
573
467
|
this.previousState = this.currentState;
|
|
574
468
|
this.currentState = stateBeforeUpdate;
|
|
575
469
|
this.notifyListeners();
|
|
@@ -592,18 +486,12 @@ const storeCache = /* @__PURE__ */ new Map();
|
|
|
592
486
|
function createBridgeStore(bridge, initialState, storeName = "default", readyCallbacks = /* @__PURE__ */ new Set()) {
|
|
593
487
|
if (storeCache.has(storeName)) {
|
|
594
488
|
const cached = storeCache.get(storeName);
|
|
595
|
-
if (STORE_ENABLE_LOGS) {
|
|
596
|
-
console.log(`BridgeStore[${storeName}]: Returning cached instance (singleton)`);
|
|
597
|
-
}
|
|
598
489
|
cached.updateBridge(bridge);
|
|
599
490
|
readyCallbacks.forEach((cb) => cached.onReady(cb));
|
|
600
491
|
return cached;
|
|
601
492
|
}
|
|
602
493
|
const store = new BridgeStore(bridge, initialState, storeName, readyCallbacks);
|
|
603
494
|
storeCache.set(storeName, store);
|
|
604
|
-
if (STORE_ENABLE_LOGS) {
|
|
605
|
-
console.log(`BridgeStore[${storeName}]: Created new instance (cached)`);
|
|
606
|
-
}
|
|
607
495
|
return store;
|
|
608
496
|
}
|
|
609
497
|
function clearStoreCache() {
|
|
@@ -612,9 +500,6 @@ function clearStoreCache() {
|
|
|
612
500
|
function destroyStore(storeName) {
|
|
613
501
|
const store = storeCache.get(storeName);
|
|
614
502
|
if (store) {
|
|
615
|
-
if (STORE_ENABLE_LOGS) {
|
|
616
|
-
console.log(`BridgeStore[${storeName}]: Destroying store and removing from cache`);
|
|
617
|
-
}
|
|
618
503
|
store.destroy();
|
|
619
504
|
storeCache.delete(storeName);
|
|
620
505
|
}
|
|
@@ -789,8 +674,6 @@ class StoreBuilder {
|
|
|
789
674
|
reset: () => {
|
|
790
675
|
if (initialState !== null) {
|
|
791
676
|
store.setState(initialState, true);
|
|
792
|
-
} else {
|
|
793
|
-
console.warn("ServiceWorkerStore: Cannot reset, initial state not available");
|
|
794
677
|
}
|
|
795
678
|
},
|
|
796
679
|
setBridge: (bridge) => {
|
|
@@ -835,24 +718,14 @@ function autoRegisterStoreHandlers(store, storeName = "default") {
|
|
|
835
718
|
if (typeof store.setState !== "function") {
|
|
836
719
|
throw new Error("autoRegisterStoreHandlers: store must have setState method");
|
|
837
720
|
}
|
|
838
|
-
console.log(`[Store] Creating handlers for store "${storeName}"`, {
|
|
839
|
-
hasGetState: typeof store.getState === "function",
|
|
840
|
-
hasSetState: typeof store.setState === "function"
|
|
841
|
-
});
|
|
842
721
|
class AutoGetStoreStateMessage {
|
|
843
722
|
handle() {
|
|
844
|
-
console.log(`[Store] GetState handler called for "${storeName}"`);
|
|
845
723
|
if (!store) {
|
|
846
724
|
console.error(`[Store] Store instance not available for "${storeName}"`);
|
|
847
725
|
throw new Error("Store instance not available");
|
|
848
726
|
}
|
|
849
727
|
try {
|
|
850
|
-
|
|
851
|
-
console.log(`[Store] GetState returning state for "${storeName}"`, {
|
|
852
|
-
hasState: state !== void 0 && state !== null,
|
|
853
|
-
stateType: typeof state
|
|
854
|
-
});
|
|
855
|
-
return state;
|
|
728
|
+
return store.getState();
|
|
856
729
|
} catch (error) {
|
|
857
730
|
console.error(`[Store] GetState failed for "${storeName}":`, error);
|
|
858
731
|
throw error;
|
|
@@ -897,7 +770,6 @@ function autoRegisterStoreHandlers(store, storeName = "default") {
|
|
|
897
770
|
}
|
|
898
771
|
class AutoResetStoreMessage {
|
|
899
772
|
handle() {
|
|
900
|
-
console.log(`[Store] Reset handler called for "${storeName}"`);
|
|
901
773
|
if (!store) {
|
|
902
774
|
console.error(`[Store] Store instance not available for "${storeName}"`);
|
|
903
775
|
throw new Error("Store instance not available");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chromahq/store",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.63",
|
|
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",
|