Skip to content
ts
import { reactive } from 'vue';

interface StorageOptions {
  namespace?: string;
  storage?: Storage;
}

const DEFAULT_NAMESPACE = 'APP_';
const DEFAULT_STORAGE = window.localStorage;
const DEFAULT_EXPIRES = 7 * 24 * 60 * 60 * 1000; // 7 天

export function createStorage(options: StorageOptions = {}) {
  const { namespace = DEFAULT_NAMESPACE, storage = DEFAULT_STORAGE } = options;
  const key = (name: string) => `${namespace}:${name}`;

  const set = <T>(name: string, value: T, expires: number | null = DEFAULT_EXPIRES) => {
    const data = {
      value,
      expires: typeof expires === 'number' ? Date.now() + expires : null,
    };
    storage.setItem(key(name), JSON.stringify(data));
  };

  const get = <T>(name: string): T => {
    const data = storage.getItem(key(name));
    if (data) {
      const { value, expires } = JSON.parse(data);
      if (!expires || Date.now() < expires) {
        return value;
      }
      remove(name);
    }
    return null as any;
  };

  const remove = (name: string) => {
    storage.removeItem(key(name));
  };

  const clear = () => {
    storage.clear();
  };

  return reactive({
    set,
    get,
    remove,
    clear,
  });
}