@choksheak/react-utils 0.2.8 → 0.3.0

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.
Files changed (55) hide show
  1. package/package.json +50 -2
  2. package/sharedQuery.cjs +119 -130
  3. package/sharedQuery.d.mts +14 -8
  4. package/sharedQuery.d.ts +12 -6
  5. package/sharedQuery.min.cjs +1 -1
  6. package/sharedQuery.min.cjs.map +1 -1
  7. package/sharedQuery.min.mjs +1 -1
  8. package/sharedQuery.min.mjs.map +1 -1
  9. package/sharedQuery.mjs +117 -129
  10. package/sharedState.cjs +69 -101
  11. package/sharedState.d.mts +7 -3
  12. package/sharedState.d.ts +5 -2
  13. package/sharedState.min.cjs +1 -1
  14. package/sharedState.min.cjs.map +1 -1
  15. package/sharedState.min.mjs +1 -1
  16. package/sharedState.min.mjs.map +1 -1
  17. package/sharedState.mjs +67 -100
  18. package/storage.cjs +90 -0
  19. package/storage.d.mts +19 -0
  20. package/storage.d.ts +16 -0
  21. package/storage.min.cjs +2 -0
  22. package/storage.min.cjs.map +1 -0
  23. package/storage.min.mjs +2 -0
  24. package/storage.min.mjs.map +1 -0
  25. package/storage.mjs +65 -0
  26. package/{utils/stringify.cjs → stringify.cjs} +1 -1
  27. package/stringify.min.cjs.map +1 -0
  28. package/stringify.min.mjs.map +1 -0
  29. package/{utils/stringify.mjs → stringify.mjs} +1 -1
  30. package/{utils/useDeepMemo.cjs → useDeepMemo.cjs} +1 -1
  31. package/useDeepMemo.d.mts +7 -0
  32. package/useDeepMemo.d.ts +5 -0
  33. package/useDeepMemo.min.cjs.map +1 -0
  34. package/useDeepMemo.min.mjs.map +1 -0
  35. package/{utils/useDeepMemo.mjs → useDeepMemo.mjs} +1 -1
  36. package/utils/storage.cjs +0 -162
  37. package/utils/storage.d.mts +0 -46
  38. package/utils/storage.d.ts +0 -44
  39. package/utils/storage.min.cjs +0 -2
  40. package/utils/storage.min.cjs.map +0 -1
  41. package/utils/storage.min.mjs +0 -2
  42. package/utils/storage.min.mjs.map +0 -1
  43. package/utils/storage.mjs +0 -134
  44. package/utils/stringify.min.cjs.map +0 -1
  45. package/utils/stringify.min.mjs.map +0 -1
  46. package/utils/useDeepMemo.d.mts +0 -4
  47. package/utils/useDeepMemo.d.ts +0 -2
  48. package/utils/useDeepMemo.min.cjs.map +0 -1
  49. package/utils/useDeepMemo.min.mjs.map +0 -1
  50. /package/{utils/stringify.d.mts → stringify.d.mts} +0 -0
  51. /package/{utils/stringify.d.ts → stringify.d.ts} +0 -0
  52. /package/{utils/stringify.min.cjs → stringify.min.cjs} +0 -0
  53. /package/{utils/stringify.min.mjs → stringify.min.mjs} +0 -0
  54. /package/{utils/useDeepMemo.min.cjs → useDeepMemo.min.cjs} +0 -0
  55. /package/{utils/useDeepMemo.min.mjs → useDeepMemo.min.mjs} +0 -0
package/sharedQuery.mjs CHANGED
@@ -13,108 +13,71 @@ import {
13
13
  import { MS_PER_DAY } from "@choksheak/ts-utils/timeConstants";
14
14
  import { useSyncExternalStore } from "react";
15
15
 
16
- // src/utils/storage.ts
16
+ // src/storage.ts
17
17
  import { kvStore } from "@choksheak/ts-utils/kvStore";
18
+ import { LocalStore } from "@choksheak/ts-utils/localStore";
18
19
  function getStorageAdapter(options, defaultStoreExpiryMs) {
19
- const { localStorageKey, indexedDbKey, storeExpiryMs, store } = options ?? {};
20
- if (store) {
21
- return store;
22
- }
23
- const expiryMs = storeExpiryMs || defaultStoreExpiryMs;
24
- if (localStorageKey) {
25
- return new LocalStorageAdapter(localStorageKey, expiryMs);
26
- }
27
- if (indexedDbKey) {
28
- return new IndexedDbAdapter(indexedDbKey, expiryMs);
29
- }
30
- return null;
31
- }
32
- var LocalStorageAdapter = class {
33
- constructor(keyPrefix, expiryMs) {
34
- this.keyPrefix = keyPrefix;
35
- this.expiryMs = expiryMs;
36
- }
37
- save(key, value) {
38
- if (typeof window === "undefined") return;
39
- const fullKey = this.keyPrefix + ":" + key;
40
- window.localStorage.setItem(
41
- fullKey,
42
- JSON.stringify({
43
- value,
44
- expiresAt: this.expiryMs ? Date.now() + this.expiryMs : 0
45
- })
46
- );
47
- }
48
- load(key) {
49
- if (typeof window === "undefined") return void 0;
50
- const fullKey = this.keyPrefix + ":" + key;
51
- const raw = window.localStorage.getItem(fullKey);
52
- if (!raw) return void 0;
53
- try {
54
- const box = JSON.parse(raw);
55
- if (!box || box.expiresAt && Date.now() >= box.expiresAt) {
56
- window.localStorage.removeItem(fullKey);
57
- return void 0;
20
+ const { store } = options ?? {};
21
+ if (!store) {
22
+ return null;
23
+ }
24
+ if ("persistTo" in store && typeof store.persistTo === "string" && "key" in store && typeof store.key === "string") {
25
+ const expiryMs = store.expiryMs || defaultStoreExpiryMs;
26
+ switch (store.persistTo) {
27
+ case "localStorage": {
28
+ const adapter = new LocalStore(store.key, {
29
+ defaultExpiryMs: expiryMs
30
+ });
31
+ return {
32
+ set: (key, value) => {
33
+ if (typeof window === "undefined") return;
34
+ adapter.set(key, value);
35
+ },
36
+ get: (key) => {
37
+ if (typeof window === "undefined") return void 0;
38
+ return adapter.get(key);
39
+ },
40
+ delete: (key) => {
41
+ if (typeof window === "undefined") return;
42
+ adapter.delete(key);
43
+ },
44
+ clear: () => {
45
+ if (typeof window === "undefined") return;
46
+ adapter.clear();
47
+ }
48
+ };
58
49
  }
59
- return box.value;
60
- } catch {
61
- window.localStorage.removeItem(fullKey);
62
- return void 0;
63
- }
64
- }
65
- delete(key) {
66
- if (typeof window === "undefined") return;
67
- const fullKey = this.keyPrefix + ":" + key;
68
- window.localStorage.removeItem(fullKey);
69
- }
70
- clear() {
71
- if (typeof window === "undefined") return;
72
- for (const key of Object.keys(window.localStorage)) {
73
- if (key.startsWith(this.keyPrefix)) {
74
- window.localStorage.removeItem(key);
50
+ case "indexedDb": {
51
+ const keyPrefix = store.key + ":";
52
+ return {
53
+ set: async (key, value) => {
54
+ if (typeof window === "undefined") return;
55
+ await kvStore.set(keyPrefix + key, value, expiryMs);
56
+ },
57
+ get: async (key) => {
58
+ if (typeof window === "undefined") return void 0;
59
+ return await kvStore.get(keyPrefix + key);
60
+ },
61
+ delete: async (key) => {
62
+ if (typeof window === "undefined") return;
63
+ await kvStore.delete(keyPrefix + key);
64
+ },
65
+ clear: async () => {
66
+ if (typeof window === "undefined") return;
67
+ await kvStore.clear();
68
+ }
69
+ };
75
70
  }
71
+ default:
72
+ store.persistTo;
73
+ throw new Error(`Unknown store.adapter ${store.persistTo}`);
76
74
  }
77
75
  }
78
- };
79
- var IndexedDbAdapter = class {
80
- constructor(keyPrefix, expiryMs) {
81
- this.keyPrefix = keyPrefix;
82
- this.expiryMs = expiryMs;
83
- }
84
- async save(key, value) {
85
- if (typeof window === "undefined") return;
86
- const fullKey = this.keyPrefix + ":" + key;
87
- await kvStore.set(fullKey, JSON.stringify(value), this.expiryMs);
88
- }
89
- async load(key) {
90
- if (typeof window === "undefined") return void 0;
91
- const fullKey = this.keyPrefix + ":" + key;
92
- const raw = await kvStore.get(fullKey);
93
- if (raw === void 0) return void 0;
94
- try {
95
- return JSON.parse(raw);
96
- } catch {
97
- await kvStore.delete(fullKey);
98
- return void 0;
99
- }
100
- }
101
- async delete(key) {
102
- if (typeof window === "undefined") return;
103
- const fullKey = this.keyPrefix + ":" + key;
104
- await kvStore.delete(fullKey);
105
- }
106
- async clear() {
107
- if (typeof window === "undefined") return;
108
- await kvStore.forEach(async (k) => {
109
- if (k.startsWith(this.keyPrefix)) {
110
- await kvStore.delete(k);
111
- }
112
- });
113
- }
114
- };
76
+ return store;
77
+ }
115
78
 
116
79
  // src/sharedState.ts
117
- var SharedStateDefaults = {
80
+ var SharedStateConfig = {
118
81
  /**
119
82
  * Default duration for storage expiration in milliseconds. Initial value
120
83
  * is 30 days, but can be changed to anything.
@@ -181,14 +144,14 @@ var SharedState = class {
181
144
  this.pubSubKey = String(stateKey++);
182
145
  this.storageAdapter = getStorageAdapter(
183
146
  options,
184
- SharedStateDefaults.storeExpiryMs
147
+ SharedStateConfig.storeExpiryMs
185
148
  );
186
149
  this.setValueBounded = (next) => {
187
150
  this.setValue(next);
188
151
  };
189
152
  pubSubStore.setNoNotify(this.pubSubKey, defaultValue);
190
153
  const lazyLoad = options?.lazyLoad;
191
- const lazy = lazyLoad !== void 0 ? lazyLoad : SharedStateDefaults.lazyLoad;
154
+ const lazy = lazyLoad !== void 0 ? lazyLoad : SharedStateConfig.lazyLoad;
192
155
  if (!lazy) {
193
156
  void this.initDefaultValueOnce();
194
157
  }
@@ -213,19 +176,19 @@ var SharedState = class {
213
176
  next = next(prev);
214
177
  }
215
178
  pubSubStore.set(this.pubSubKey, next);
216
- void this.storageAdapter?.save(STORAGE_KEY, next);
179
+ void this.storageAdapter?.set(STORAGE_KEY, next);
217
180
  }
218
181
  // Remove the value of the shared state. Actually this just sets the value
219
182
  // back to the given default value.
220
183
  delete() {
221
184
  pubSubStore.set(this.pubSubKey, this.defaultValue);
222
- void this.storageAdapter?.save(STORAGE_KEY, this.defaultValue);
185
+ void this.storageAdapter?.set(STORAGE_KEY, this.defaultValue);
223
186
  }
224
187
  // Initial default handling
225
188
  async initDefaultValueOnce() {
226
189
  if (this.initDone) return;
227
190
  this.initDone = true;
228
- const v = await this.storageAdapter?.load(STORAGE_KEY);
191
+ const v = await this.storageAdapter?.get(STORAGE_KEY);
229
192
  pubSubStore.set(this.pubSubKey, v !== void 0 ? v : this.defaultValue);
230
193
  }
231
194
  };
@@ -243,7 +206,7 @@ function useSharedState(state) {
243
206
  return [value, state.setValueBounded];
244
207
  }
245
208
 
246
- // src/utils/stringify.ts
209
+ // src/stringify.ts
247
210
  function stringifyDeterministicForKeys(params) {
248
211
  const cache = /* @__PURE__ */ new Set();
249
212
  return JSON.stringify(params, (_, value) => {
@@ -274,7 +237,7 @@ function stringifyDeterministicForKeys(params) {
274
237
  });
275
238
  }
276
239
 
277
- // src/utils/useDeepMemo.ts
240
+ // src/useDeepMemo.ts
278
241
  import isEqual from "lodash/isEqual";
279
242
  import { useMemo, useState } from "react";
280
243
  function useDeepMemo(value) {
@@ -289,7 +252,7 @@ function useDeepMemo(value) {
289
252
  }
290
253
 
291
254
  // src/sharedQuery.ts
292
- var SharedQueryDefaults = {
255
+ var SharedQueryConfig = {
293
256
  /** Refetch on every page load. */
294
257
  staleMs: 0,
295
258
  /** Keep in cache for a long time. */
@@ -305,6 +268,9 @@ var SharedQueryDefaults = {
305
268
  /** Default to log to console. */
306
269
  log: (...args) => console.log("[sharedQuery]", ...args)
307
270
  };
271
+ function configureSharedQuery(config) {
272
+ Object.assign(SharedQueryConfig, config);
273
+ }
308
274
  var SharedQuery = class {
309
275
  inflightQueries = /* @__PURE__ */ new Map();
310
276
  queryState;
@@ -326,29 +292,27 @@ var SharedQuery = class {
326
292
  constructor(options) {
327
293
  this.queryName = options.queryName;
328
294
  this.queryFn = options.queryFn;
329
- this.staleMs = options?.staleMs ?? SharedQueryDefaults.staleMs;
330
- this.expiryMs = options?.expiryMs ?? SharedQueryDefaults.expiryMs;
331
- this.refetchOnStale = options?.refetchOnStale ?? SharedQueryDefaults.refetchOnStale;
332
- if (!options.localStorageKey && !options.indexedDbKey) {
333
- const persistTo = options.persistTo ?? SharedQueryDefaults.persistTo;
334
- if (persistTo === "localStorage") {
335
- options.localStorageKey = options.queryName;
336
- } else if (persistTo === "indexedDb") {
337
- options.indexedDbKey = options.queryName;
295
+ this.staleMs = options?.staleMs ?? SharedQueryConfig.staleMs;
296
+ this.expiryMs = options?.expiryMs ?? SharedQueryConfig.expiryMs;
297
+ this.refetchOnStale = options?.refetchOnStale ?? SharedQueryConfig.refetchOnStale;
298
+ if (!options.store) {
299
+ const persistTo = options.persistTo ?? SharedQueryConfig.persistTo;
300
+ if (persistTo) {
301
+ options.store = {
302
+ persistTo,
303
+ key: options.queryName,
304
+ expiryMs: this.expiryMs
305
+ };
338
306
  }
339
307
  }
340
- this.maxSize = options?.maxSize ?? SharedQueryDefaults.maxSize;
341
- this.maxBytes = options?.maxBytes ?? SharedQueryDefaults.maxBytes;
308
+ this.maxSize = options?.maxSize ?? SharedQueryConfig.maxSize;
309
+ this.maxBytes = options?.maxBytes ?? SharedQueryConfig.maxBytes;
342
310
  this.keepLastNonEmptyData = Boolean(options?.keepLastNonEmptyData);
343
- this.log = options?.log ?? SharedQueryDefaults.log;
311
+ this.log = options?.log ?? SharedQueryConfig.log;
344
312
  this.queryState = sharedState(
345
313
  {},
346
314
  // defaultValue
347
- {
348
- ...options,
349
- // Fallback to use expiryMs for the storeExpiryMs.
350
- storeExpiryMs: options?.storeExpiryMs || this.expiryMs
351
- }
315
+ options
352
316
  );
353
317
  }
354
318
  /** Returns a key to identify requests based on the given args. */
@@ -459,7 +423,14 @@ var SharedQuery = class {
459
423
  }
460
424
  /** Get the current stored data for a query key. */
461
425
  getData(queryKey) {
462
- return this.queryState.getSnapshot()?.[queryKey]?.data;
426
+ const stateValue = this.queryState.getSnapshot()?.[queryKey];
427
+ if (stateValue?.lastUpdatedMs) {
428
+ if (this.isExpired(stateValue.lastUpdatedMs)) {
429
+ this.deleteData(queryKey);
430
+ return void 0;
431
+ }
432
+ }
433
+ return stateValue?.data;
463
434
  }
464
435
  /** Set the data directly if the user obtained it from somewhere else. */
465
436
  setData(queryKey, data, dataUpdatedMs = Date.now()) {
@@ -542,25 +513,41 @@ var SharedQuery = class {
542
513
  );
543
514
  const newState = { ...oldState };
544
515
  let needUpdate = false;
545
- const entriesByTimeAscending = Object.entries(newState).sort(
546
- (entry1, entry2) => entry1[1].lastUpdatedMs - entry2[1].lastUpdatedMs
547
- );
548
- for (const [key] of entriesByTimeAscending) {
516
+ const deleteKeyIfNotMounted = (key, expired) => {
549
517
  if (this.mountedKeys.has(key)) {
550
518
  this.log(`Cannot clean up ${key} as it is mounted`);
551
- continue;
519
+ return;
552
520
  }
553
521
  const byteSize = getByteSize(key) + getByteSize(newState[key]);
554
522
  this.log(
555
- `Cleaning up unmounted ${key} (byteSize=${byteSize.toLocaleString()})`
523
+ `Cleaning up unmounted${expired ? ", expired" : ""} ${key} (byteSize=${byteSize.toLocaleString()})`
556
524
  );
557
525
  numToCut--;
558
526
  bytesToCut -= byteSize;
559
527
  delete newState[key];
560
528
  needUpdate = true;
561
- if (numToCut <= 0 && bytesToCut <= 0) {
529
+ };
530
+ let entriesByTimeAscending = Object.entries(newState).sort(
531
+ (entry1, entry2) => entry1[1].lastUpdatedMs - entry2[1].lastUpdatedMs
532
+ );
533
+ for (const [key] of entriesByTimeAscending) {
534
+ if (!this.isExpired(newState[key].lastUpdatedMs)) {
562
535
  break;
563
536
  }
537
+ deleteKeyIfNotMounted(key, true);
538
+ }
539
+ if (numToCut > 0 || bytesToCut > 0) {
540
+ if (needUpdate) {
541
+ entriesByTimeAscending = Object.entries(newState).sort(
542
+ (entry1, entry2) => entry1[1].lastUpdatedMs - entry2[1].lastUpdatedMs
543
+ );
544
+ }
545
+ for (const [key] of entriesByTimeAscending) {
546
+ deleteKeyIfNotMounted(key, false);
547
+ if (numToCut <= 0 && bytesToCut <= 0) {
548
+ break;
549
+ }
550
+ }
564
551
  }
565
552
  if (!needUpdate) {
566
553
  this.log(
@@ -586,7 +573,7 @@ var DEFAULT_QUERY_STATE_ENTRY = {
586
573
  lastUpdatedMs: 0,
587
574
  loading: true
588
575
  };
589
- function useSharedQuery(query, args = []) {
576
+ function useSharedQuery(query, ...args) {
590
577
  const stableArgs = useDeepMemo(args);
591
578
  const [queryState, setQueryState] = useSharedState(query.queryState);
592
579
  const isMounted = useRef(true);
@@ -702,7 +689,8 @@ function useSharedQuery(query, args = []) {
702
689
  }
703
690
  export {
704
691
  SharedQuery,
705
- SharedQueryDefaults,
692
+ SharedQueryConfig,
693
+ configureSharedQuery,
706
694
  sharedQuery,
707
695
  useSharedQuery
708
696
  };
package/sharedState.cjs CHANGED
@@ -21,7 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var sharedState_exports = {};
22
22
  __export(sharedState_exports, {
23
23
  SharedState: () => SharedState,
24
- SharedStateDefaults: () => SharedStateDefaults,
24
+ SharedStateConfig: () => SharedStateConfig,
25
+ configureSharedState: () => configureSharedState,
25
26
  sharedState: () => sharedState,
26
27
  useSharedState: () => useSharedState,
27
28
  useSharedStateSetter: () => useSharedStateSetter,
@@ -31,108 +32,71 @@ module.exports = __toCommonJS(sharedState_exports);
31
32
  var import_timeConstants = require("@choksheak/ts-utils/timeConstants");
32
33
  var import_react = require("react");
33
34
 
34
- // src/utils/storage.ts
35
+ // src/storage.ts
35
36
  var import_kvStore = require("@choksheak/ts-utils/kvStore");
37
+ var import_localStore = require("@choksheak/ts-utils/localStore");
36
38
  function getStorageAdapter(options, defaultStoreExpiryMs) {
37
- const { localStorageKey, indexedDbKey, storeExpiryMs, store } = options ?? {};
38
- if (store) {
39
- return store;
40
- }
41
- const expiryMs = storeExpiryMs || defaultStoreExpiryMs;
42
- if (localStorageKey) {
43
- return new LocalStorageAdapter(localStorageKey, expiryMs);
44
- }
45
- if (indexedDbKey) {
46
- return new IndexedDbAdapter(indexedDbKey, expiryMs);
47
- }
48
- return null;
49
- }
50
- var LocalStorageAdapter = class {
51
- constructor(keyPrefix, expiryMs) {
52
- this.keyPrefix = keyPrefix;
53
- this.expiryMs = expiryMs;
54
- }
55
- save(key, value) {
56
- if (typeof window === "undefined") return;
57
- const fullKey = this.keyPrefix + ":" + key;
58
- window.localStorage.setItem(
59
- fullKey,
60
- JSON.stringify({
61
- value,
62
- expiresAt: this.expiryMs ? Date.now() + this.expiryMs : 0
63
- })
64
- );
65
- }
66
- load(key) {
67
- if (typeof window === "undefined") return void 0;
68
- const fullKey = this.keyPrefix + ":" + key;
69
- const raw = window.localStorage.getItem(fullKey);
70
- if (!raw) return void 0;
71
- try {
72
- const box = JSON.parse(raw);
73
- if (!box || box.expiresAt && Date.now() >= box.expiresAt) {
74
- window.localStorage.removeItem(fullKey);
75
- return void 0;
39
+ const { store } = options ?? {};
40
+ if (!store) {
41
+ return null;
42
+ }
43
+ if ("persistTo" in store && typeof store.persistTo === "string" && "key" in store && typeof store.key === "string") {
44
+ const expiryMs = store.expiryMs || defaultStoreExpiryMs;
45
+ switch (store.persistTo) {
46
+ case "localStorage": {
47
+ const adapter = new import_localStore.LocalStore(store.key, {
48
+ defaultExpiryMs: expiryMs
49
+ });
50
+ return {
51
+ set: (key, value) => {
52
+ if (typeof window === "undefined") return;
53
+ adapter.set(key, value);
54
+ },
55
+ get: (key) => {
56
+ if (typeof window === "undefined") return void 0;
57
+ return adapter.get(key);
58
+ },
59
+ delete: (key) => {
60
+ if (typeof window === "undefined") return;
61
+ adapter.delete(key);
62
+ },
63
+ clear: () => {
64
+ if (typeof window === "undefined") return;
65
+ adapter.clear();
66
+ }
67
+ };
76
68
  }
77
- return box.value;
78
- } catch {
79
- window.localStorage.removeItem(fullKey);
80
- return void 0;
81
- }
82
- }
83
- delete(key) {
84
- if (typeof window === "undefined") return;
85
- const fullKey = this.keyPrefix + ":" + key;
86
- window.localStorage.removeItem(fullKey);
87
- }
88
- clear() {
89
- if (typeof window === "undefined") return;
90
- for (const key of Object.keys(window.localStorage)) {
91
- if (key.startsWith(this.keyPrefix)) {
92
- window.localStorage.removeItem(key);
69
+ case "indexedDb": {
70
+ const keyPrefix = store.key + ":";
71
+ return {
72
+ set: async (key, value) => {
73
+ if (typeof window === "undefined") return;
74
+ await import_kvStore.kvStore.set(keyPrefix + key, value, expiryMs);
75
+ },
76
+ get: async (key) => {
77
+ if (typeof window === "undefined") return void 0;
78
+ return await import_kvStore.kvStore.get(keyPrefix + key);
79
+ },
80
+ delete: async (key) => {
81
+ if (typeof window === "undefined") return;
82
+ await import_kvStore.kvStore.delete(keyPrefix + key);
83
+ },
84
+ clear: async () => {
85
+ if (typeof window === "undefined") return;
86
+ await import_kvStore.kvStore.clear();
87
+ }
88
+ };
93
89
  }
90
+ default:
91
+ store.persistTo;
92
+ throw new Error(`Unknown store.adapter ${store.persistTo}`);
94
93
  }
95
94
  }
96
- };
97
- var IndexedDbAdapter = class {
98
- constructor(keyPrefix, expiryMs) {
99
- this.keyPrefix = keyPrefix;
100
- this.expiryMs = expiryMs;
101
- }
102
- async save(key, value) {
103
- if (typeof window === "undefined") return;
104
- const fullKey = this.keyPrefix + ":" + key;
105
- await import_kvStore.kvStore.set(fullKey, JSON.stringify(value), this.expiryMs);
106
- }
107
- async load(key) {
108
- if (typeof window === "undefined") return void 0;
109
- const fullKey = this.keyPrefix + ":" + key;
110
- const raw = await import_kvStore.kvStore.get(fullKey);
111
- if (raw === void 0) return void 0;
112
- try {
113
- return JSON.parse(raw);
114
- } catch {
115
- await import_kvStore.kvStore.delete(fullKey);
116
- return void 0;
117
- }
118
- }
119
- async delete(key) {
120
- if (typeof window === "undefined") return;
121
- const fullKey = this.keyPrefix + ":" + key;
122
- await import_kvStore.kvStore.delete(fullKey);
123
- }
124
- async clear() {
125
- if (typeof window === "undefined") return;
126
- await import_kvStore.kvStore.forEach(async (k) => {
127
- if (k.startsWith(this.keyPrefix)) {
128
- await import_kvStore.kvStore.delete(k);
129
- }
130
- });
131
- }
132
- };
95
+ return store;
96
+ }
133
97
 
134
98
  // src/sharedState.ts
135
- var SharedStateDefaults = {
99
+ var SharedStateConfig = {
136
100
  /**
137
101
  * Default duration for storage expiration in milliseconds. Initial value
138
102
  * is 30 days, but can be changed to anything.
@@ -144,6 +108,9 @@ var SharedStateDefaults = {
144
108
  */
145
109
  lazyLoad: false
146
110
  };
111
+ function configureSharedState(config) {
112
+ Object.assign(SharedStateConfig, config);
113
+ }
147
114
  var PubSubStore = class {
148
115
  dataByKey = /* @__PURE__ */ new Map();
149
116
  subscribersByKey = /* @__PURE__ */ new Map();
@@ -199,14 +166,14 @@ var SharedState = class {
199
166
  this.pubSubKey = String(stateKey++);
200
167
  this.storageAdapter = getStorageAdapter(
201
168
  options,
202
- SharedStateDefaults.storeExpiryMs
169
+ SharedStateConfig.storeExpiryMs
203
170
  );
204
171
  this.setValueBounded = (next) => {
205
172
  this.setValue(next);
206
173
  };
207
174
  pubSubStore.setNoNotify(this.pubSubKey, defaultValue);
208
175
  const lazyLoad = options?.lazyLoad;
209
- const lazy = lazyLoad !== void 0 ? lazyLoad : SharedStateDefaults.lazyLoad;
176
+ const lazy = lazyLoad !== void 0 ? lazyLoad : SharedStateConfig.lazyLoad;
210
177
  if (!lazy) {
211
178
  void this.initDefaultValueOnce();
212
179
  }
@@ -231,19 +198,19 @@ var SharedState = class {
231
198
  next = next(prev);
232
199
  }
233
200
  pubSubStore.set(this.pubSubKey, next);
234
- void this.storageAdapter?.save(STORAGE_KEY, next);
201
+ void this.storageAdapter?.set(STORAGE_KEY, next);
235
202
  }
236
203
  // Remove the value of the shared state. Actually this just sets the value
237
204
  // back to the given default value.
238
205
  delete() {
239
206
  pubSubStore.set(this.pubSubKey, this.defaultValue);
240
- void this.storageAdapter?.save(STORAGE_KEY, this.defaultValue);
207
+ void this.storageAdapter?.set(STORAGE_KEY, this.defaultValue);
241
208
  }
242
209
  // Initial default handling
243
210
  async initDefaultValueOnce() {
244
211
  if (this.initDone) return;
245
212
  this.initDone = true;
246
- const v = await this.storageAdapter?.load(STORAGE_KEY);
213
+ const v = await this.storageAdapter?.get(STORAGE_KEY);
247
214
  pubSubStore.set(this.pubSubKey, v !== void 0 ? v : this.defaultValue);
248
215
  }
249
216
  };
@@ -269,7 +236,8 @@ function useSharedStateSetter(state) {
269
236
  // Annotate the CommonJS export names for ESM import in node:
270
237
  0 && (module.exports = {
271
238
  SharedState,
272
- SharedStateDefaults,
239
+ SharedStateConfig,
240
+ configureSharedState,
273
241
  sharedState,
274
242
  useSharedState,
275
243
  useSharedStateSetter,
package/sharedState.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Dispatch, SetStateAction } from 'react';
2
- import { StorageOptions } from './utils/storage.mjs';
2
+ import { StorageOptions } from './storage.mjs';
3
+ import '@choksheak/ts-utils/storageAdapter';
3
4
 
4
5
  /**
5
6
  * @packageDocumentation
@@ -48,7 +49,7 @@ import { StorageOptions } from './utils/storage.mjs';
48
49
  /**
49
50
  * These values are configurable by the user at any time.
50
51
  */
51
- declare const SharedStateDefaults: {
52
+ declare const SharedStateConfig: {
52
53
  /**
53
54
  * Default duration for storage expiration in milliseconds. Initial value
54
55
  * is 30 days, but can be changed to anything.
@@ -60,6 +61,9 @@ declare const SharedStateDefaults: {
60
61
  */
61
62
  lazyLoad: boolean;
62
63
  };
64
+ type SharedStateConfig = typeof SharedStateConfig;
65
+ /** Convenience function to update global defaults. */
66
+ declare function configureSharedState(config: Partial<SharedStateConfig>): void;
63
67
  /** Options to configure a shared state. */
64
68
  type SharedStateOptions<T> = {
65
69
  lazyLoad?: boolean;
@@ -115,4 +119,4 @@ declare function useSharedStateValue<T>(state: SharedState<T>): T;
115
119
  */
116
120
  declare function useSharedStateSetter<T>(state: SharedState<T>): Dispatch<SetStateAction<T>>;
117
121
 
118
- export { SharedState, SharedStateDefaults, type SharedStateOptions, sharedState, useSharedState, useSharedStateSetter, useSharedStateValue };
122
+ export { SharedState, SharedStateConfig, type SharedStateOptions, configureSharedState, sharedState, useSharedState, useSharedStateSetter, useSharedStateValue };
package/sharedState.d.ts CHANGED
@@ -40,13 +40,13 @@
40
40
  * ```
41
41
  */
42
42
  import { Dispatch, SetStateAction } from "react";
43
- import { StorageOptions } from "./utils/storage";
43
+ import { StorageOptions } from "./storage";
44
44
  /************************************************************************/
45
45
  /************************************************************************/
46
46
  /**
47
47
  * These values are configurable by the user at any time.
48
48
  */
49
- export declare const SharedStateDefaults: {
49
+ export declare const SharedStateConfig: {
50
50
  /**
51
51
  * Default duration for storage expiration in milliseconds. Initial value
52
52
  * is 30 days, but can be changed to anything.
@@ -58,6 +58,9 @@ export declare const SharedStateDefaults: {
58
58
  */
59
59
  lazyLoad: boolean;
60
60
  };
61
+ export type SharedStateConfig = typeof SharedStateConfig;
62
+ /** Convenience function to update global defaults. */
63
+ export declare function configureSharedState(config: Partial<SharedStateConfig>): void;
61
64
  /** Options to configure a shared state. */
62
65
  export type SharedStateOptions<T> = {
63
66
  lazyLoad?: boolean;