From af44c787b8a7ff784830cf3f44479c286c6d492e Mon Sep 17 00:00:00 2001 From: Sriram Hariharan Date: Tue, 23 Apr 2024 23:47:56 -0500 Subject: [PATCH] updated use hook to now allow pulling in the entire object --- package.json | 2 +- src/storage/createStore.ts | 62 ++++++++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index c6ca5be..9d25fa8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chrome-extension-toolkit", - "version": "0.0.65", + "version": "0.0.66", "description": "A template for creating npm packages using TypeScript and VSCode", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/storage/createStore.ts b/src/storage/createStore.ts index 8f60700..6a322ff 100644 --- a/src/storage/createStore.ts +++ b/src/storage/createStore.ts @@ -12,6 +12,7 @@ export type StoreDefaults = { * Represents a change in data within the store. */ export type DataChange = { + key: string; /** * The old value of the data. This will be undefined if the data was just initialized. */ @@ -85,17 +86,22 @@ export type Store = { * @param key the key to get the value of * @returns a tuple containing the value of the specified key, and a function to set the value */ - use>(key: K): [D, (value: D) => Promise]; + use : T>( + key: K + ): [D, (value: D) => Promise]; /** * A react hook that allows you to get and set the value of the specified key in the store from a functional component. * @param key the key to get the value of * @param defaultValue the default value to use if the key is not already set */ - use( + use( key: K, - defaultValue: Serializable - ): [Serializable, (value: Serializable) => Promise]; + defaultValue: K extends keyof T ? Serializable : T + ): [ + K extends keyof T ? Serializable : T, + (value: K extends keyof T ? Serializable : T) => Promise + ]; /** * Subscribes to changes in the specified key in the store, and calls the specified function when the key changes. @@ -239,6 +245,12 @@ function createStore( }) ); } + // now we need to remove the storeId from the keys + Object.keys(fullStore).forEach(actualKey => { + const newKey = actualKey.replace(`${storeId}:`, ''); + fullStore[newKey] = fullStore[actualKey]; + delete fullStore[actualKey]; + }); return fullStore as Serializable; }; @@ -252,6 +264,7 @@ function createStore( if (!isEncrypted) { callback({ + key: key as string, oldValue: changes[actualKey].oldValue, newValue: changes[actualKey].newValue, }); @@ -264,6 +277,7 @@ function createStore( ]); callback({ + key: key as string, oldValue, newValue, }); @@ -278,26 +292,48 @@ function createStore( }; // @ts-ignore - store.use = (key: keyof T, defaultValue?: T[typeof key]) => { + store.use = (key: keyof T | null, defaultValue?: key extends null ? T : T[typeof key]) => { // this handles the case where a user might want to explicitly pass undefined as a default value // if the defaultValue is not passed, we will use the default value from the defaults object. // This way `value` will always be of the correct type that is expected. - const [value, setValue] = useState(arguments.length === 2 ? defaultValue : defaults[key]); + const [value, setValue] = useState( + // @ts-ignore + // eslint-disable-next-line no-nested-ternary + arguments.length === 2 ? defaultValue : key === null ? defaults : defaults[key] + ); useEffect(() => { - store.get(key).then(setValue as any); + if (key !== null) { + store.get(key).then(setValue as any); + + const onChanged = ({ newValue }: DataChange) => { + setValue(newValue as any); + }; + store.subscribe(key, onChanged); + return () => { + store.unsubscribe(onChanged); + }; + } - const onChanged = ({ newValue }: DataChange) => { - setValue(newValue as any); + store.all().then(setValue as any); + + const onChanged = (change: DataChange) => { + const newValue: any = { ...value }; + newValue[change.key] = change.newValue; }; - store.subscribe(key, onChanged); + // @ts-ignore + Object.keys(defaults).forEach(k => store.subscribe(k, onChanged)); return () => { store.unsubscribe(onChanged); }; }, [key]); - const set = async (newValue: T[typeof key]) => { - await store.set(key, newValue as any); + const set = async newValue => { + if (key === null) { + await store.set(newValue as any); + } else { + await store.set(key, newValue as any); + } setValue(newValue); }; @@ -366,7 +402,7 @@ export function createSessionStore(storeId: string, defaults: StoreDefaults('my-store', { // age: 0,