Просмотр исходного кода

WIP: impl sync-to-storage middleware

Yuki Takei 4 лет назад
Родитель
Сommit
359a03c0dc
1 измененных файлов с 92 добавлено и 0 удалено
  1. 92 0
      packages/app/src/stores/middlewares/sync-to-storage.ts

+ 92 - 0
packages/app/src/stores/middlewares/sync-to-storage.ts

@@ -0,0 +1,92 @@
+import { useSWRConfig, Middleware } from 'swr';
+
+const generateKeyInStorage = (key: string): string => {
+  return `swr-cache-${key}`;
+};
+
+export type IStorageSerializer<Data> = {
+  serialize: (value: Data) => string,
+  deserialize: (value: string | null) => Data,
+}
+
+
+const createSyncToStorageMiddlware = <Data>(
+  storage: Storage,
+  storageSerializer: IStorageSerializer<Data> = {
+    serialize: JSON.stringify,
+    deserialize: JSON.parse,
+  },
+): Middleware => {
+  return (useSWRNext) => {
+    return (key, fetcher, config) => {
+      const keyInStorage = generateKeyInStorage(key.toString());
+      let initData;
+
+      // retrieve initial data from storage
+      const itemInStorage = storage.getItem(keyInStorage);
+      if (itemInStorage != null) {
+        initData = storageSerializer.deserialize(itemInStorage);
+      }
+
+      const swrNext = useSWRNext(key, fetcher, {
+        fallbackData: initData,
+        ...config,
+      });
+
+      return {
+        ...swrNext,
+        mutate: (data, shouldRevalidate) => {
+          return swrNext.mutate(data, shouldRevalidate)
+            .then((value) => {
+              storage.setItem(generateKeyInStorage(keyInStorage), storageSerializer.serialize(value));
+              return value;
+            });
+        },
+      };
+    };
+  };
+};
+
+// const createStorageProvider = <Data>(
+//   storage: Storage,
+//   storageSerializer: IStorageSerializer<Data> = {
+//     serialize: JSON.stringify,
+//     deserialize: JSON.parse,
+//   },
+// ): Cache<Data> => {
+//   const map: Map<string, Data> = new Map();
+
+//   return {
+//     get(key: string): Data | undefined {
+//       if (!map.has(key)) {
+//         let newCachedData = null;
+
+//         // retrieve from storage
+//         const itemInStorage = storage.getItem(generateKeyInStorage(key));
+//         if (itemInStorage != null) {
+//           newCachedData = storageSerializer.deserialize(itemInStorage);
+//         }
+
+//         // set
+//         map.set(key, newCachedData);
+//       }
+//       return map.get(key);
+//     },
+//     set(key: string, value: Data): void {
+//       map.set(key, value);
+//       storage.setItem(generateKeyInStorage(key), storageSerializer.serialize(value));
+//     },
+//     delete(key: string): void {
+//       map.delete(key);
+//       storage.removeItem(generateKeyInStorage(key));
+//     },
+//   };
+// };
+
+// export const localStorageProvider = <Data>(option?: { storageSerializer?: IStorageSerializer<Data> }): Cache<Data> => {
+//   return createStorageProvider(localStorage, option?.storageSerializer);
+// };
+
+// export const sessionStorageProvider = <Data>(storageSerializer?: IStorageSerializer<Data>): Cache<Data> => {
+//   return createStorageProvider(sessionStorage, storageSerializer);
+// };