Browse Source

feat: 二次封装`localforage`支持设置过期时间,提供完整的类型提示

xiaoxian521 1 year ago
parent
commit
e10c9166ca
4 changed files with 279 additions and 0 deletions
  1. 1 0
      package.json
  2. 18 0
      pnpm-lock.yaml
  3. 94 0
      src/utils/localforage/index.ts
  4. 166 0
      src/utils/localforage/types.d.ts

+ 1 - 0
package.json

@@ -69,6 +69,7 @@
     "intro.js": "^7.2.0",
     "js-cookie": "^3.0.5",
     "jsbarcode": "^3.11.5",
+    "localforage": "^1.10.0",
     "md-editor-v3": "2.7.2",
     "mint-filter": "^4.0.3",
     "mitt": "^3.0.1",

+ 18 - 0
pnpm-lock.yaml

@@ -53,6 +53,7 @@ specifiers:
   js-cookie: ^3.0.5
   jsbarcode: ^3.11.5
   lint-staged: ^14.0.1
+  localforage: ^1.10.0
   md-editor-v3: 2.7.2
   mint-filter: ^4.0.3
   mitt: ^3.0.1
@@ -142,6 +143,7 @@ dependencies:
   intro.js: 7.2.0
   js-cookie: 3.0.5
   jsbarcode: 3.11.5
+  localforage: 1.10.0
   md-editor-v3: 2.7.2
   mint-filter: 4.0.3
   mitt: 3.0.1
@@ -4790,6 +4792,10 @@ packages:
     resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
     engines: {node: '>= 4'}
 
+  /immediate/3.0.6:
+    resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
+    dev: false
+
   /immer/9.0.21:
     resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
     dev: false
@@ -5696,6 +5702,12 @@ packages:
       type-check: 0.4.0
     dev: true
 
+  /lie/3.1.1:
+    resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
+    dependencies:
+      immediate: 3.0.6
+    dev: false
+
   /lilconfig/2.1.0:
     resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
     engines: {node: '>=10'}
@@ -5747,6 +5759,12 @@ packages:
     dev: false
     optional: true
 
+  /localforage/1.10.0:
+    resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
+    dependencies:
+      lie: 3.1.1
+    dev: false
+
   /locate-path/5.0.0:
     resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
     engines: {node: '>=8'}

+ 94 - 0
src/utils/localforage/index.ts

@@ -0,0 +1,94 @@
+import forage from "localforage";
+import { LocalForage, ProxyStorage, ExpiresData } from "./types.d";
+
+class StorageProxy implements ProxyStorage {
+  protected storage: LocalForage;
+  constructor(storageModel) {
+    this.storage = storageModel;
+    this.storage.config({
+      // driver: [forage.LOCALSTORAGE],
+      name: "pure-admin"
+    });
+  }
+
+  /**
+   * @description 将对应键名的数据保存到离线仓库
+   * @param k 键名
+   * @param v 键值
+   * @param m 缓存时间(单位`分`,默认`0`分钟,永久缓存)
+   */
+  public async setItem<T>(k: string, v: T, m = 0): Promise<T> {
+    return new Promise((resolve, reject) => {
+      this.storage
+        .setItem(k, {
+          data: v,
+          expires: new Date().getTime() + m * 60 * 1000
+        })
+        .then(value => {
+          resolve(value.data);
+        })
+        .catch(err => {
+          reject(err);
+        });
+    });
+  }
+
+  /**
+   * @description 从离线仓库中获取对应键名的值
+   * @param k 键名
+   */
+  public async getItem<T>(k: string): Promise<T> {
+    return new Promise((resolve, reject) => {
+      this.storage
+        .getItem(k)
+        .then((value: ExpiresData<T>) => {
+          const data =
+            value.expires > new Date().getTime() || value.expires === 0
+              ? value.data
+              : null;
+          resolve(data);
+        })
+        .catch(err => {
+          reject(err);
+        });
+    });
+  }
+
+  /**
+   * @description 从离线仓库中删除对应键名的值
+   * @param k 键名
+   */
+  public async removeItem(k: string) {
+    return new Promise<void>((resolve, reject) => {
+      this.storage
+        .removeItem(k)
+        .then(() => {
+          resolve();
+        })
+        .catch(err => {
+          reject(err);
+        });
+    });
+  }
+
+  /**
+   * @description 从离线仓库中删除所有的键名,重置数据库
+   */
+  public async clear() {
+    return new Promise<void>((resolve, reject) => {
+      this.storage
+        .clear()
+        .then(() => {
+          resolve();
+        })
+        .catch(err => {
+          reject(err);
+        });
+    });
+  }
+}
+
+/**
+ * 二次封装 [localforage](https://localforage.docschina.org/) 支持设置过期时间,提供完整的类型提示
+ */
+export const localForage = () => new StorageProxy(forage);

+ 166 - 0
src/utils/localforage/types.d.ts

@@ -0,0 +1,166 @@
+// https://github.com/localForage/localForage/blob/master/typings/localforage.d.ts
+
+interface LocalForageDbInstanceOptions {
+  name?: string;
+
+  storeName?: string;
+}
+
+interface LocalForageOptions extends LocalForageDbInstanceOptions {
+  driver?: string | string[];
+
+  size?: number;
+
+  version?: number;
+
+  description?: string;
+}
+
+interface LocalForageDbMethodsCore {
+  getItem<T>(
+    key: string,
+    callback?: (err: any, value: T | null) => void
+  ): Promise<T | null>;
+
+  setItem<T>(
+    key: string,
+    value: T,
+    callback?: (err: any, value: T) => void
+  ): Promise<T>;
+
+  removeItem(key: string, callback?: (err: any) => void): Promise<void>;
+
+  clear(callback?: (err: any) => void): Promise<void>;
+
+  length(callback?: (err: any, numberOfKeys: number) => void): Promise<number>;
+
+  key(
+    keyIndex: number,
+    callback?: (err: any, key: string) => void
+  ): Promise<string>;
+
+  keys(callback?: (err: any, keys: string[]) => void): Promise<string[]>;
+
+  iterate<T, U>(
+    iteratee: (value: T, key: string, iterationNumber: number) => U,
+    callback?: (err: any, result: U) => void
+  ): Promise<U>;
+}
+
+interface LocalForageDropInstanceFn {
+  (
+    dbInstanceOptions?: LocalForageDbInstanceOptions,
+    callback?: (err: any) => void
+  ): Promise<void>;
+}
+
+interface LocalForageDriverMethodsOptional {
+  dropInstance?: LocalForageDropInstanceFn;
+}
+
+// duplicating LocalForageDriverMethodsOptional to preserve TS v2.0 support,
+// since Partial<> isn't supported there
+interface LocalForageDbMethodsOptional {
+  dropInstance: LocalForageDropInstanceFn;
+}
+
+interface LocalForageDriverDbMethods
+  extends LocalForageDbMethodsCore,
+    LocalForageDriverMethodsOptional {}
+
+interface LocalForageDriverSupportFunc {
+  (): Promise<boolean>;
+}
+
+interface LocalForageDriver extends LocalForageDriverDbMethods {
+  _driver: string;
+
+  _initStorage(options: LocalForageOptions): void;
+
+  _support?: boolean | LocalForageDriverSupportFunc;
+}
+
+interface LocalForageSerializer {
+  serialize<T>(
+    value: T | ArrayBuffer | Blob,
+    callback: (value: string, error: any) => void
+  ): void;
+
+  deserialize<T>(value: string): T | ArrayBuffer | Blob;
+
+  stringToBuffer(serializedString: string): ArrayBuffer;
+
+  bufferToString(buffer: ArrayBuffer): string;
+}
+
+interface LocalForageDbMethods
+  extends LocalForageDbMethodsCore,
+    LocalForageDbMethodsOptional {}
+
+export interface LocalForage extends LocalForageDbMethods {
+  LOCALSTORAGE: string;
+  WEBSQL: string;
+  INDEXEDDB: string;
+
+  /**
+   * Set and persist localForage options. This must be called before any other calls to localForage are made, but can be called after localForage is loaded.
+   * If you set any config values with this method they will persist after driver changes, so you can call config() then setDriver()
+   * @param {LocalForageOptions} options?
+   */
+  config(options: LocalForageOptions): boolean;
+  config(options: string): any;
+  config(): LocalForageOptions;
+
+  /**
+   * Create a new instance of localForage to point to a different store.
+   * All the configuration options used by config are supported.
+   * @param {LocalForageOptions} options
+   */
+  createInstance(options: LocalForageOptions): LocalForage;
+
+  driver(): string;
+
+  /**
+   * Force usage of a particular driver or drivers, if available.
+   * @param {string} driver
+   */
+  setDriver(
+    driver: string | string[],
+    callback?: () => void,
+    errorCallback?: (error: any) => void
+  ): Promise<void>;
+
+  defineDriver(
+    driver: LocalForageDriver,
+    callback?: () => void,
+    errorCallback?: (error: any) => void
+  ): Promise<void>;
+
+  /**
+   * Return a particular driver
+   * @param {string} driver
+   */
+  getDriver(driver: string): Promise<LocalForageDriver>;
+
+  getSerializer(
+    callback?: (serializer: LocalForageSerializer) => void
+  ): Promise<LocalForageSerializer>;
+
+  supports(driverName: string): boolean;
+
+  ready(callback?: (error: any) => void): Promise<void>;
+}
+
+// Customize
+
+export interface ProxyStorage {
+  setItem<T>(k: string, v: T, m: number): Promise<T>;
+  getItem<T>(k: string): Promise<T>;
+  removeItem(k: string): Promise<void>;
+  clear(): Promise<void>;
+}
+
+export interface ExpiresData<T> {
+  data: T;
+  expires: number;
+}