react-wire-persisted 2.1.0 → 3.1.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.
@@ -1,17 +1,20 @@
1
1
  /**
2
2
  * Base class to allow storage access
3
- * @see `LocalStorageProvider.js` for an example implementation
3
+ * @see `LocalStorageProvider.ts` for an example implementation
4
4
  */
5
5
  /** biome-ignore-all lint/correctness/noUnusedFunctionParameters: WIP next PR will switch to TypeScript */
6
- class StorageProvider {
6
+ export abstract class RWPStorageProvider {
7
+ namespace: string | null
8
+ registry: Record<string, unknown>
9
+
7
10
  /**
8
11
  * Initializes the class
9
- * @param {String} namespace Namespace to prefix all keys with. Mostly used for the logging & reset functions
12
+ * @param {String} namespace Namespace to prefix all keys with. Mostly used for the logging and reset functions
10
13
  * @param {Object} registry (Optional) Initialize the storage provider with an existing registry
11
14
  */
12
- constructor(namespace, registry) {
15
+ protected constructor(namespace: string, registry: Record<string, unknown>) {
13
16
  // Simulate being an abstract class
14
- if (new.target === StorageProvider)
17
+ if (new.target === RWPStorageProvider)
15
18
  throw TypeError(`StorageProvider is abstract. Extend this class to implement it`)
16
19
 
17
20
  this.namespace = namespace || null
@@ -24,14 +27,14 @@ class StorageProvider {
24
27
  * @param {String} namespace New namespace for this storage provider
25
28
  */
26
29
  /* istanbul ignore next */
27
- setNamespace(namespace) {}
30
+ abstract setNamespace(namespace: string | null): void
28
31
 
29
32
  /**
30
- * Registers an item with it's initial value. This is used for logging, resetting, etc.
31
- * @param {String} key Storage item's key
32
- * @param {*} initialValue Storage item's initial value
33
+ * Registers an item with its initial value. This is used for logging, resetting, etc.
34
+ * @param {String} key InternalStorage item's key
35
+ * @param {*} initialValue InternalStorage item's initial value
33
36
  */
34
- register(key, initialValue) {
37
+ register<T>(key: string, initialValue: T | null) {
35
38
  this.registry[key] = initialValue
36
39
  }
37
40
 
@@ -40,7 +43,7 @@ class StorageProvider {
40
43
  * @param {String} key Key for the item to retrieve
41
44
  */
42
45
  /* istanbul ignore next */
43
- getItem(key) {}
46
+ abstract getItem<T>(key: string): T | null
44
47
 
45
48
  /**
46
49
  * Stores a value
@@ -48,7 +51,7 @@ class StorageProvider {
48
51
  * @param {String} value Item's value to store
49
52
  */
50
53
  /* istanbul ignore next */
51
- setItem(key, value) {}
54
+ abstract setItem<T>(key: string, value: T | null): void
52
55
 
53
56
  /**
54
57
  * Removes an item from storage
@@ -56,14 +59,14 @@ class StorageProvider {
56
59
  * @param {Boolean} fromRegistry (Optional) If the item should also be removed from the registry
57
60
  */
58
61
  /* istanbul ignore next */
59
- removeItem(key, fromRegistry = false) {}
62
+ abstract removeItem(key: string, fromRegistry: boolean): void
60
63
 
61
64
  /**
62
- * Gets all stored keys & values
65
+ * Gets all stored keys and values
63
66
  * If a `namespace` was set, only keys prefixed with the namespace will be returned
64
67
  */
65
68
  /* istanbul ignore next */
66
- getAll() {}
69
+ abstract getAll(): Record<string, unknown>
67
70
 
68
71
  /**
69
72
  *
@@ -72,7 +75,7 @@ class StorageProvider {
72
75
  * @param {Boolean} clearRegistry (Optional) If the registry should also be cleared
73
76
  */
74
77
  /* istanbul ignore next */
75
- _resetAll(useInitialValues = true, excludedKeys = [], clearRegistry = false) {}
78
+ abstract _resetAll(useInitialValues: boolean, excludedKeys: string[], clearRegistry: boolean): void
76
79
 
77
80
  /**
78
81
  * Resets all values to their initial values
@@ -80,7 +83,7 @@ class StorageProvider {
80
83
  * @param {String[]} excludedKeys (Optional) List of keys to exclude
81
84
  */
82
85
  /* istanbul ignore next */
83
- resetAll(excludedKeys = []) {}
86
+ abstract resetAll(excludedKeys: string[]): void
84
87
 
85
88
  /**
86
89
  * Removes all items from local storage.
@@ -88,7 +91,15 @@ class StorageProvider {
88
91
  * @param {String[]} excludedKeys (Optional) List of keys to exclude
89
92
  */
90
93
  /* istanbul ignore next */
91
- removeAll(excludedKeys = []) {}
94
+ abstract removeAll(excludedKeys: string[]): void
95
+
96
+ upgradeToRealStorage(): boolean {
97
+ return false
98
+ }
99
+
100
+ isUsingFakeStorage(): boolean {
101
+ return false
102
+ }
92
103
  }
93
104
 
94
- export default StorageProvider
105
+ export default RWPStorageProvider
@@ -1,21 +1,28 @@
1
- import { createWire } from '@forminator/react-wire'
2
- import LocalStorageProvider from './providers/LocalStorageProvider.js'
3
- import { getHasHydratedStorage, getIsClient, markStorageAsHydrated } from './utils/index.js'
1
+ import { createWire, type Defined, type Wire } from '@forminator/react-wire'
2
+ import LocalStorageProvider from '@/providers/LocalStorageProvider'
3
+ import type RWPStorageProvider from '@/providers/RWPStorageProvider'
4
+ import type { PersistedWire, RWPOptions, WireLikeObject } from '@/types'
5
+ import { getHasHydratedStorage, getIsClient, markStorageAsHydrated } from '@/utils'
4
6
 
5
7
  // Generate unique instance ID
6
8
  const instanceId = Math.random().toString(36).substring(7)
7
- const rwpLog = (...args) => {
9
+ const rwpLog = (...args: unknown[]) => {
8
10
  if (typeof globalThis !== 'undefined' && globalThis.__RWP_LOGGING_ENABLED__ !== false) {
9
11
  console.log(...args)
10
12
  }
11
13
  }
12
14
 
13
- export const defaultOptions = {
15
+ export const defaultOptions: RWPOptions = {
14
16
  logging: {
15
17
  enabled: false,
16
18
  },
19
+ storageProvider: LocalStorageProvider,
17
20
  }
18
21
 
22
+ let options: RWPOptions = { ...defaultOptions }
23
+ let storage: RWPStorageProvider
24
+ const pendingLogs: unknown[][] = []
25
+
19
26
  // Set global logging flag on startup
20
27
  if (typeof globalThis !== 'undefined' && globalThis.__RWP_LOGGING_ENABLED__ === undefined) {
21
28
  globalThis.__RWP_LOGGING_ENABLED__ = defaultOptions.logging.enabled
@@ -23,26 +30,21 @@ if (typeof globalThis !== 'undefined' && globalThis.__RWP_LOGGING_ENABLED__ ===
23
30
 
24
31
  rwpLog('[RWP] Module initialized, instance ID:', instanceId)
25
32
 
26
- const Provider = LocalStorageProvider
27
-
28
33
  // Make storage global so all instances share the same storage after upgrade
29
34
  rwpLog('[RWP] About to check global storage, instanceId:', instanceId)
30
- let storage
31
35
  try {
32
36
  if (!globalThis.__RWP_STORAGE__) {
33
37
  rwpLog('[RWP] Creating global storage in instance:', instanceId)
34
- globalThis.__RWP_STORAGE__ = new Provider()
38
+ globalThis.__RWP_STORAGE__ = new LocalStorageProvider('__internal_rwp_storage__')
35
39
  } else {
36
40
  rwpLog('[RWP] Using existing global storage in instance:', instanceId)
37
41
  }
38
42
  storage = globalThis.__RWP_STORAGE__
39
- rwpLog('[RWP] Storage assigned successfully')
43
+ rwpLog('[RWP] InternalStorage assigned successfully')
40
44
  } catch (error) {
41
45
  if (globalThis.__RWP_LOGGING_ENABLED__) console.error('[RWP] Error setting up global storage:', error)
42
- storage = new Provider()
46
+ storage = new LocalStorageProvider('__internal_rwp_storage__')
43
47
  }
44
- let options = { ...defaultOptions }
45
- const pendingLogs = []
46
48
 
47
49
  // Use a global registry to handle multiple module instances
48
50
  // This ensures all instances share the same wire registry
@@ -56,38 +58,32 @@ if (typeof globalThis !== 'undefined') {
56
58
  }
57
59
 
58
60
  // Registry to track wire instances for hydration refresh
59
- const registeredWires = globalThis.__RWP_REGISTERED_WIRES__ || new Map()
61
+ const registeredWires = globalThis.__RWP_REGISTERED_WIRES__ || new Map<string, WireLikeObject>()
60
62
  rwpLog('[RWP] registeredWires Map reference in instance:', instanceId, 'size:', registeredWires.size)
61
63
 
62
- /**
63
- * Gets the namespace of the storage provider
64
- *
65
- * @returns {String}
66
- */
67
- export const getNamespace = () => storage.namespace
64
+ export const getNamespace = (): string | null => storage.namespace
68
65
 
69
- /**
70
- * Gets the current storage provider class instance
71
- *
72
- * @returns {StorageProvider}
73
- */
74
- export const getStorage = () => storage
75
-
76
- export const getOptions = () => options
66
+ export const getStorage = (): RWPStorageProvider => storage
77
67
 
78
68
  /**
79
69
  * Sets the namespace for the storage provider
80
70
  *
81
71
  * @param {String} namespace The namespace for the storage provider
82
72
  */
83
- export const setNamespace = (namespace) => {
73
+ export const setNamespace = (namespace: string) => {
84
74
  rwpLog('[RWP] setNamespace() called with:', namespace, 'registered wires before:', registeredWires.size)
75
+ const currentNamespace = namespace || getNamespace()
76
+
77
+ if (!currentNamespace) throw new Error('react-wire-persisted: Cannot set namespace to null or undefined')
78
+
85
79
  storage.setNamespace(namespace)
86
- storage = new Provider(namespace || getNamespace())
87
- rwpLog('[RWP] setNamespace() done, registered wires after:', registeredWires.size)
80
+ storage = new LocalStorageProvider(currentNamespace)
81
+ rwpLog(`[RWP] setNamespace() done, registered wires after:`, registeredWires.size)
88
82
  }
89
83
 
90
- export const setOptions = (value) => {
84
+ export const getOptions = (): RWPOptions => options
85
+
86
+ export const setOptions = (value: Partial<RWPOptions>) => {
91
87
  options = {
92
88
  ...options,
93
89
  ...value,
@@ -101,7 +97,7 @@ export const setOptions = (value) => {
101
97
  console.info('Flushing', pendingLogs.length, 'pending logs')
102
98
  while (pendingLogs.length)
103
99
  /* istanbul ignore next */
104
- console.log(...pendingLogs.shift())
100
+ console.log(...(pendingLogs.shift() || []))
105
101
  }
106
102
  }
107
103
 
@@ -113,7 +109,7 @@ const refreshAllWires = () => {
113
109
  rwpLog('[RWP] refreshAllWires() called in instance:', instanceId, 'registered wires:', registeredWires.size)
114
110
  log('react-wire-persisted: refreshAllWires() called, registered wires:', registeredWires.size)
115
111
 
116
- registeredWires.forEach((wire, key) => {
112
+ registeredWires.forEach((wire: Wire<unknown> | WireLikeObject, key: string) => {
117
113
  const storedValue = storage.getItem(key)
118
114
  const currentValue = wire.getValue()
119
115
 
@@ -141,9 +137,9 @@ const refreshAllWires = () => {
141
137
  * Attempts to upgrade the storage provider from fake storage to real localStorage
142
138
  * This should be called on the client side after hydration
143
139
  *
144
- * @returns {Boolean} True if upgrade was successful
140
+ * @returns true if upgrade was successful
145
141
  */
146
- export const upgradeStorage = () => {
142
+ export const upgradeStorage = (): boolean => {
147
143
  rwpLog('[RWP] upgradeStorage() called in instance:', instanceId, {
148
144
  isClient: getIsClient(),
149
145
  isUsingFakeStorage: storage.isUsingFakeStorage(),
@@ -173,7 +169,7 @@ export const upgradeStorage = () => {
173
169
  return upgraded
174
170
  }
175
171
 
176
- const log = (...args) => {
172
+ const log = (...args: unknown[]) => {
177
173
  /* istanbul ignore next */
178
174
  if (options.logging.enabled)
179
175
  /* istanbul ignore next */
@@ -182,28 +178,28 @@ const log = (...args) => {
182
178
  }
183
179
 
184
180
  /**
185
- * Creates a persisted Wire using the `StorageProvider` that is currently set
181
+ * Creates a persisted Wire using the `RWPStorageProvider` that is currently set
186
182
  * Defaults to `localStorage` via `LocalStorageProvider`
187
183
  *
188
184
  * @param {String} key Unique key for storing this value
189
185
  * @param {*} value Initial value of this Wire
190
186
  * @returns A new Wire decorated with localStorage functionality
191
187
  */
192
- export const createPersistedWire = (key, value = null) => {
188
+ export const createPersistedWire = <T = null>(key: string, value: T = null as T): PersistedWire<T> => {
193
189
  rwpLog('[RWP] createPersistedWire() called in instance:', instanceId, 'key:', key, 'value:', value)
194
190
 
195
191
  // This check helps ensure no accidental key typos occur
196
- if (!key && typeof key !== 'number') throw new Error(`createPersistedWire: Key cannot be a falsey value (${key}}`)
192
+ if (!key) throw new Error(`createPersistedWire: Key cannot be a falsey value (${key}}`)
197
193
 
198
194
  // Track this writable entry so we can easily clear all
199
195
  storage.register(key, value)
200
196
 
201
197
  // The actual Wire backing object
202
- const wire = createWire(value)
198
+ const wire = createWire<T>(value)
203
199
 
204
200
  const getValue = () => wire.getValue()
205
201
 
206
- const setValue = (newValue) => {
202
+ const setValue = (newValue: Defined<T>) => {
207
203
  rwpLog(
208
204
  '[RWP] setValue called in instance:',
209
205
  instanceId,
@@ -216,19 +212,19 @@ export const createPersistedWire = (key, value = null) => {
216
212
  return wire.setValue(newValue)
217
213
  }
218
214
 
219
- const subscribe = (fn) => {
220
- wire.subscribe(fn)
215
+ const subscribe = (callback: (value: Defined<T>) => void) => {
216
+ return wire.subscribe(callback)
221
217
  }
222
218
 
223
219
  // Always start with default value to ensure SSR consistency
224
- let initialValue = value
220
+ let initialValue: T = value
225
221
 
226
222
  // Only read from storage if we've hydrated OR if storage is already using real localStorage
227
223
  // (prevents hydration mismatch in SSR, but allows normal behavior in client-only apps)
228
224
  const canReadStorage = getHasHydratedStorage() || !storage.isUsingFakeStorage()
229
225
 
230
226
  if (canReadStorage && getIsClient()) {
231
- const storedValue = storage.getItem(key)
227
+ const storedValue = storage.getItem<T>(key)
232
228
 
233
229
  if (storedValue !== null) initialValue = storedValue
234
230
  }
@@ -241,7 +237,7 @@ export const createPersistedWire = (key, value = null) => {
241
237
  canReadStorage,
242
238
  })
243
239
 
244
- if (initialValue !== value) setValue(initialValue)
240
+ if (initialValue !== value && initialValue !== undefined) setValue(initialValue as Defined<T>)
245
241
 
246
242
  // Register wire for post-hydration refresh
247
243
  registeredWires.set(key, {
package/src/types.ts ADDED
@@ -0,0 +1,19 @@
1
+ import type { Wire } from '@forminator/react-wire'
2
+ import type RWPStorageProvider from '@/providers/RWPStorageProvider'
3
+
4
+ export type RWPOptions = {
5
+ logging: { enabled: boolean }
6
+ storageProvider?: typeof RWPStorageProvider
7
+ }
8
+
9
+ export type PersistedWire<T> = Wire<T>
10
+
11
+ export interface InternalStorage {
12
+ getItem: (key: string) => string | null
13
+ setItem: (key: string, value: string) => void
14
+ removeItem: (key: string) => void
15
+ }
16
+
17
+ export type AnyStorage = InternalStorage | Storage
18
+
19
+ export type WireLikeObject = Pick<Wire<unknown>, 'getValue' | 'setValue' | 'subscribe'>
@@ -0,0 +1,17 @@
1
+ import type { InternalStorage } from '@/types'
2
+
3
+ const storage: Record<string, string> = {
4
+ __IS_FAKE_LOCAL_STORAGE__: 'true',
5
+ }
6
+
7
+ export const fakeLocalStorage: InternalStorage = {
8
+ getItem: (key: string): string | null => storage[key],
9
+ setItem: (key: string, value: string): void => {
10
+ storage[key] = value
11
+ },
12
+ removeItem: (key: string): void => {
13
+ delete storage[key]
14
+ },
15
+ // Make Object.keys() work properly for _resetAll method
16
+ ...storage,
17
+ }
@@ -1,6 +1,6 @@
1
- export * from './fakeLocalStorage.js'
2
- export * from './isomorphic.js'
3
- export * from './keys.js'
1
+ export * from './fakeLocalStorage'
2
+ export * from './isomorphic'
3
+ export * from './keys'
4
4
 
5
5
  /**
6
6
  * Checks if a value is a primitive type
@@ -8,7 +8,7 @@ export * from './keys.js'
8
8
  * @param {*} val Value to check
9
9
  * @returns {Boolean} True if value is a primitive type
10
10
  */
11
- export const isPrimitive = (val) => {
11
+ export const isPrimitive = (val: unknown): boolean => {
12
12
  const type = typeof val
13
13
 
14
14
  if (val === null) return true
@@ -2,9 +2,9 @@
2
2
  * Utilities for handling server-side rendering and client-side hydration
3
3
  */
4
4
 
5
- let isClient = false
6
- let hasHydrated = false
7
- let hasHydratedStorage = false
5
+ let isClient: boolean = false
6
+ let hasHydrated: boolean = false
7
+ let hasHydratedStorage: boolean = false
8
8
 
9
9
  // Detect if we're running in a browser environment
10
10
  if (typeof window !== 'undefined') {
@@ -21,29 +21,29 @@ if (typeof window !== 'undefined') {
21
21
  /**
22
22
  * Check if we're running in a browser environment
23
23
  */
24
- export const getIsClient = () => isClient
24
+ export const getIsClient = (): boolean => isClient
25
25
 
26
26
  /**
27
27
  * Check if the client has finished hydrating
28
28
  */
29
- export const getHasHydrated = () => hasHydrated
29
+ export const getHasHydrated = (): boolean => hasHydrated
30
30
 
31
31
  /**
32
32
  * Check if storage has been hydrated (safe to read from real localStorage)
33
33
  */
34
- export const getHasHydratedStorage = () => hasHydratedStorage
34
+ export const getHasHydratedStorage = (): boolean => hasHydratedStorage
35
35
 
36
36
  /**
37
37
  * Mark storage as hydrated (called after upgradeStorage)
38
38
  */
39
- export const markStorageAsHydrated = () => {
39
+ export const markStorageAsHydrated = (): void => {
40
40
  hasHydratedStorage = true
41
41
  }
42
42
 
43
43
  /**
44
44
  * Check if localStorage is available and safe to use
45
45
  */
46
- export const isLocalStorageAvailable = () => {
46
+ export const isLocalStorageAvailable = (): boolean => {
47
47
  if (!isClient) return false
48
48
 
49
49
  try {
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Convenience map of keys
3
+ */
4
+ const storageKeys: Record<string, string> = {}
5
+
6
+ /**
7
+ * Adds a key to the keys map
8
+ *
9
+ * @param {String} value Key name
10
+ */
11
+ export const addKey = (value: string): void => {
12
+ storageKeys[value] = value
13
+ }
14
+
15
+ /**
16
+ * Adds a key to the keys map
17
+ * (Alias for `addKey`)
18
+ *
19
+ * @param {String} value Key name
20
+ */
21
+ export const key = (value: string) => addKey(value)
22
+
23
+ /**
24
+ * Convenience method to get internally managed storage keys
25
+ *
26
+ * @returns {Object} InternalStorage keys map
27
+ */
28
+ export const getKeys = (): Record<string, string> => storageKeys
29
+
30
+ /**
31
+ * Helper utility to prefix all keys in a map to use a namespace
32
+ *
33
+ * @param {String} namespace InternalStorage namespace prefix
34
+ * @param {Object} keys (Optional) InternalStorage key/values. Defaults to the internally managed keys map
35
+ */
36
+ export const getPrefixedKeys = (namespace: string, keys: Record<string, string> | null = null) => {
37
+ const items = keys || storageKeys
38
+
39
+ if (!namespace) return items
40
+
41
+ return Object.keys(items).reduce(
42
+ (acc, it) => {
43
+ acc[it] = `${namespace}.${items[it]}`
44
+
45
+ return acc
46
+ },
47
+ {} as Record<string, string>,
48
+ )
49
+ }
@@ -1,45 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useRef } from 'react'
4
- import { upgradeStorage } from '../react-wire-persisted.js'
5
- import { getHasHydrated, getIsClient } from '../utils/index.js'
6
-
7
- /**
8
- * A Next.js App Router compatible component that handles automatic storage upgrade
9
- * after hydration. Use this in your root layout.
10
- *
11
- * @param {Object} props Component props
12
- * @param {React.ReactNode} props.children Child components to render
13
- * @param {Function} props.onUpgrade Callback called when storage is upgraded
14
- * @param {Boolean} props.autoUpgrade Whether to automatically upgrade storage (default: true)
15
- */
16
- export function HydrationProvider({ children, onUpgrade, autoUpgrade = true }) {
17
- const hasUpgraded = useRef(false)
18
-
19
- useEffect(() => {
20
- if (!autoUpgrade || hasUpgraded.current || !getIsClient()) {
21
- return
22
- }
23
-
24
- const attemptUpgrade = () => {
25
- if (getHasHydrated() && !hasUpgraded.current) {
26
- const upgraded = upgradeStorage()
27
-
28
- if (upgraded) {
29
- hasUpgraded.current = true
30
- onUpgrade?.()
31
- }
32
- }
33
- }
34
-
35
- // Try to upgrade immediately if already hydrated
36
- attemptUpgrade()
37
-
38
- // Also try after a short delay to ensure DOM is ready
39
- const timeoutId = setTimeout(attemptUpgrade, 0)
40
-
41
- return () => clearTimeout(timeoutId)
42
- }, [autoUpgrade, onUpgrade])
43
-
44
- return children
45
- }
@@ -1 +0,0 @@
1
- export { HydrationProvider } from './HydrationProvider.js'
@@ -1,14 +0,0 @@
1
- import { fakeLocalStorage } from '../utils/index.js'
2
- import LocalStorageProvider from './LocalStorageProvider.js'
3
-
4
- class MemoryStorageProvider extends LocalStorageProvider {
5
- constructor(namespace = null, registry = {}) {
6
- super(namespace, registry)
7
- }
8
-
9
- getStorage() {
10
- return fakeLocalStorage
11
- }
12
- }
13
-
14
- export default MemoryStorageProvider
@@ -1,15 +0,0 @@
1
- const storage = {
2
- __IS_FAKE_LOCAL_STORAGE__: true,
3
- }
4
-
5
- export const fakeLocalStorage = {
6
- getItem: (key) => storage[key],
7
- setItem: (key, value) => {
8
- storage[key] = value
9
- },
10
- removeItem: (key) => {
11
- delete storage[key]
12
- },
13
- // Make Object.keys() work properly for _resetAll method
14
- ...storage,
15
- }
package/src/utils/keys.js DELETED
@@ -1,46 +0,0 @@
1
- /**
2
- * Convenience map of keys
3
- */
4
- const storageKeys = {}
5
-
6
- /**
7
- * Adds a key to the keys map
8
- *
9
- * @param {String} value Key name
10
- */
11
- export const addKey = (value) => {
12
- storageKeys[value] = value
13
- }
14
-
15
- /**
16
- * Adds a key to the keys map
17
- * (Alias for `addKey`)
18
- *
19
- * @param {String} value Key name
20
- */
21
- export const key = (value) => addKey(value)
22
-
23
- /**
24
- * Convenience method to get internally managed storage keys
25
- *
26
- * @returns {Object} Storage keys map
27
- */
28
- export const getKeys = () => storageKeys
29
-
30
- /**
31
- * Helper utility to prefix all keys in a map to use a namespace
32
- *
33
- * @param {String} namespace Storage namespace prefix
34
- * @param {Object} keys (Optional) Storage key/values. Defaults to the internally managed keys map
35
- */
36
- export const getPrefixedKeys = (namespace, keys = null) => {
37
- const items = keys || storageKeys
38
-
39
- if (!namespace) return items
40
-
41
- return Object.keys(items).reduce((acc, it) => {
42
- acc[it] = `${namespace}.${items[it]}`
43
-
44
- return acc
45
- }, {})
46
- }