Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async Persistence #91

Open
robinweser opened this issue Sep 19, 2024 · 1 comment
Open

Async Persistence #91

robinweser opened this issue Sep 19, 2024 · 1 comment

Comments

@robinweser
Copy link
Owner

Right now, the persistence middleware only supports sync storages such as localStorage or sessionStorage. If we'd want to use e.g. IndexedDB it would fail due to the sync nature.

@robinweser
Copy link
Owner Author

Could work like this:

import { Middleware, MiddlewareContext } from "alveron";

type SyntheticStorage<T = any> = {
  getItem: (key: string) => Promise<T>;
  setItem: (key: string, value: T) => void;
};
type Config<T> = {
  key: string;
  getStorage: () => Storage | SyntheticStorage;
  actions?: Array<string>;
  onHydrated?: (data?: T) => void;
  encode?: (data?: T) => any;
  decode?: (data: any) => T;
};

export default function persistence<T>({
  key,
  getStorage,
  actions,
  onHydrated,
  encode = JSON.stringify,
  decode = JSON.parse,
}: Config<T>): Middleware {
  function middleware(nextState: any, { action }: MiddlewareContext) {
    if (actions && Array.isArray(actions) && !actions.includes(action)) {
      return nextState;
    }

    const storage = getStorage();

    if (storage) {
      try {
        storage.setItem(key, encode(nextState));
      } catch (e) {}
    }

    return nextState;
  }

  function effect(setState: any) {
    const storage = getStorage();

    if (storage) {
      const isAsync = storage.getItem.constructor.name === "AsyncFunction";

      async function getData() {
        if (isAsync) {
          return await storage.getItem(key);
        } else {
          return storage.getItem(key);
        }
      }

      async function hydrate() {
        const data = await getData();

        let parsedData;
        if (data) {
          try {
            parsedData = decode(data);
            setState(parsedData);
          } catch (e) {}
        }

        if (onHydrated) {
          onHydrated(parsedData);
        }
      }

      hydrate();
    }
  }

  return {
    middleware,
    effect,
  };
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant