AndrewWalsh/react-persist-store

View on GitHub
src/persist-store.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import { EventEmitter2 as EventEmitter } from "eventemitter2";

import createNamespacedStore from "./create-namespaced-store";
import createInternalAPI from "./create-internal-api";
import createClientAPI from "./create-client-api";
import usePersistStore from "./use-persist-store";

import type { Options, CreateStore } from "./types";

/** The default namespace used by store2 */
const NAMESPACE = "ns_store_lib_internal";

const defaultOptions: Required<Options> = {
  storage: "local",
  namespace: NAMESPACE,
};

/**
 * Create a store with defaultValues and get a function to access a key in that store
 * @param {Store} defaultValues A Store object that contains the default values for the store
 * @param {Options} Options for the store, such as "storage" or "namespace"
 * @returns A function that accepts a top level key in the store, and returns a function that takes no arguments and returns a Client interface to said key
 * @example
 * const store = createStore({ myNamespace: { foo: "bar" }  });
 * const useFoo = store("myNamespace");
 *
 * // In a component
 * const { data, update, clearAll } = useFoo()
 */
const createStore: CreateStore = (defaultValues, options) => {
  type S = typeof defaultValues;
  const config = { ...defaultOptions, ...options };
  const { storage, namespace } = config;
  const localStore = createNamespacedStore(namespace, storage);

  return (key) => {
    const emitter = new EventEmitter();
    return () => {
      type K = typeof key;
      type V = S[K];

      const internalAPI = createInternalAPI<S, K, V>(key, emitter);

      const data =
        (localStore.has(key) && (localStore.get(key) as V)) ||
        defaultValues[key];

      const clientAPI = createClientAPI<S, K, V>(
        key,
        emitter,
        data,
        localStore,
        defaultValues
      );

      return usePersistStore<V>(clientAPI, internalAPI);
    };
  };
};

export default createStore;