From 900bb5e845c3ad44defbd427cae3d44a4a43321f Mon Sep 17 00:00:00 2001 From: ivarlovlie Date: Sat, 25 Feb 2023 13:15:44 +0100 Subject: feat: Initial commit --- code/app/src/utilities/persistent-store.ts | 111 +++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 code/app/src/utilities/persistent-store.ts (limited to 'code/app/src/utilities/persistent-store.ts') diff --git a/code/app/src/utilities/persistent-store.ts b/code/app/src/utilities/persistent-store.ts new file mode 100644 index 0000000..3f56312 --- /dev/null +++ b/code/app/src/utilities/persistent-store.ts @@ -0,0 +1,111 @@ +import { browser } from "$app/environment"; +import { writable as _writable, readable as _readable } from "svelte/store"; +import type { Writable, Readable, StartStopNotifier } from "svelte/store"; +import { log_debug, log_info } from "./logger"; + +enum StoreType { + SESSION = 0, + LOCAL = 1 +} + +interface StoreOptions { + store?: StoreType; +} + +interface WritableStoreInit { + name: string, + initialState: T, + options?: StoreOptions +} + +interface ReadableStoreInit { + name: string, + initialState: T, + callback: StartStopNotifier, + options?: StoreOptions +} + +function get_store(type: StoreType): Storage { + if (!browser) return undefined; + switch (type) { + case StoreType.SESSION: + return window.sessionStorage; + case StoreType.LOCAL: + return window.localStorage; + } +} + +function prepared_store_value(value: any): string { + try { + return JSON.stringify(value); + } catch (e) { + console.error(e); + return "__INVALID__"; + } +} + +function get_store_value(init: WritableStoreInit | ReadableStoreInit): any { + try { + const storage = get_store(init.options.store); + if (!storage) return; + const value = storage.getItem(init.name); + if (!value) return false; + return JSON.parse(value); + } catch (e) { + console.error(e); + return { __INVALID__: true }; + } +} + +function hydrate(store: Writable, init: WritableStoreInit | ReadableStoreInit): void { + const value = get_store_value(init); + if (value && store.set) store.set(value); +} + +function subscribe(store: Writable | Readable, init: WritableStoreInit | ReadableStoreInit): void { + const storage = get_store(init.options.store); + if (!storage) return; + if (!store.subscribe) return; + store.subscribe((state: any) => { + storage.setItem(init.name, prepared_store_value(state)); + }); +} + +function create_writable_persistent(init: WritableStoreInit): Writable { + if (!browser) { + log_info("WARN: Persistent store is only available in the browser"); + return; + } + if (init.options === undefined) throw new Error("init is a required parameter"); + log_debug("creating writable store with options: ", init); + const store = _writable(init.initialState); + hydrate(store, init); + subscribe(store, init); + return store; +} + +function create_readable_persistent(init: ReadableStoreInit): Readable { + if (!browser) { + log_info("WARN: Persistent store is only available in the browser"); + return; + } + if (init.options === undefined) throw new Error("init is a required parameter"); + log_debug("Creating readable store with options: ", init); + const store = _readable(init.initialState, init.callback); + // hydrate(store, options); + subscribe(store, init); + return store; +} + +export { + create_writable_persistent, + create_readable_persistent, + StoreType, +}; + +export type { + WritableStoreInit as WritableStore, + ReadableStoreInit as ReadableStore, + StoreOptions, +}; + -- cgit v1.3