| 19 | * ); |
| 20 | */ |
| 21 | export const memoryStore = ( |
| 22 | initialStorage: Record<string, any> = {} |
| 23 | ): Store => { |
| 24 | // Use a flat Map to store key-value pairs directly without treating dots as nested paths |
| 25 | let storage = new Map<string, any>(Object.entries(initialStorage ?? {})); |
| 26 | const subscriptions: { [key: string]: Subscription } = {}; |
| 27 | let initialized = false; |
| 28 | let itemsToSetAfterInitialization: Record<string, unknown> = {}; |
| 29 | |
| 30 | const publish = (key: string, value: any) => { |
| 31 | Object.keys(subscriptions).forEach(id => { |
| 32 | if (!subscriptions[id]) return; // may happen if a component unmounts after a first subscriber was notified |
| 33 | if (subscriptions[id].key === key) { |
| 34 | subscriptions[id].callback(value); |
| 35 | } |
| 36 | }); |
| 37 | }; |
| 38 | |
| 39 | return { |
| 40 | setup: () => { |
| 41 | storage = new Map<string, any>(Object.entries(initialStorage)); |
| 42 | |
| 43 | // Because children might call setItem before the store is initialized, |
| 44 | // we store those calls parameters and apply them once the store is ready |
| 45 | if (Object.keys(itemsToSetAfterInitialization).length > 0) { |
| 46 | const items = Object.entries(itemsToSetAfterInitialization); |
| 47 | for (const [key, value] of items) { |
| 48 | storage.set(key, value); |
| 49 | publish(key, value); |
| 50 | } |
| 51 | itemsToSetAfterInitialization = {}; |
| 52 | } |
| 53 | |
| 54 | initialized = true; |
| 55 | }, |
| 56 | teardown: () => { |
| 57 | storage.clear(); |
| 58 | }, |
| 59 | getItem<T = any>(key: string, defaultValue?: T): T { |
| 60 | return storage.has(key) |
| 61 | ? (storage.get(key) as T) |
| 62 | : (defaultValue as T); |
| 63 | }, |
| 64 | setItem<T = any>(key: string, value: T): void { |
| 65 | // Because children might call setItem before the store is initialized, |
| 66 | // we store those calls parameters and apply them once the store is ready |
| 67 | if (!initialized) { |
| 68 | itemsToSetAfterInitialization[key] = value; |
| 69 | return; |
| 70 | } |
| 71 | storage.set(key, value); |
| 72 | publish(key, value); |
| 73 | }, |
| 74 | removeItem(key: string): void { |
| 75 | storage.delete(key); |
| 76 | publish(key, undefined); |
| 77 | }, |
| 78 | removeItems(keyPrefix: string): void { |