150 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import serialize from 'serialize-javascript';
import { getConfig } from '@editor/utils/config';
import BaseService from './BaseService';
interface Options {
namespace?: string;
protocol?: Protocol;
}
export enum Protocol {
OBJECT = 'object',
JSON = 'json',
STRING = 'string',
NUMBER = 'number',
BOOLEAN = 'boolean',
}
/**
* 数据存储服务
*/
export class WebStorage extends BaseService {
private storage: Storage = globalThis.localStorage;
private namespace = 'tmagic';
constructor() {
super([
{ name: 'getStorage', isAsync: false },
{ name: 'getNamespace', isAsync: false },
{ name: 'clear', isAsync: false },
{ name: 'getItem', isAsync: false },
{ name: 'removeItem', isAsync: false },
{ name: 'setItem', isAsync: false },
]);
}
/**
* 获取数据存储对象,可以通过
* const storageService = new StorageService();
* storageService.usePlugin({
* // 替换存储对象为 sessionStorage
* async afterGetStorage(): Promise<Storage> {
* return window.sessionStorage;
* },
* });
*/
public getStorage(): Storage {
return this.storage;
}
public getNamespace(): string {
return this.namespace;
}
/**
* 清理支持storageService.usePlugin
*/
public clear(): void {
const storage = this.getStorage();
storage.clear();
}
/**
* 获取存储项支持storageService.usePlugin
*/
public getItem(key: string, options: Options = {}): any {
const storage = this.getStorage();
const namespace = this.getNamespace();
const { protocol = options.protocol, item } = this.getValueAndProtocol(
storage.getItem(`${options.namespace || namespace}:${key}`),
);
if (item === null) return null;
switch (protocol) {
case Protocol.OBJECT:
return getConfig('parseDSL')(`(${item})`);
case Protocol.JSON:
return JSON.parse(item);
case Protocol.NUMBER:
return Number(item);
case Protocol.BOOLEAN:
return Boolean(item);
default:
return item;
}
}
/**
* 获取指定索引位置的key
*/
public key(index: number): string | null {
const storage = this.getStorage();
return storage.key(index);
}
/**
* 移除存储项支持storageService.usePlugin
*/
public removeItem(key: string, options: Options = {}): void {
const storage = this.getStorage();
const namespace = this.getNamespace();
storage.removeItem(`${options.namespace || namespace}:${key}`);
}
/**
* 设置存储项支持storageService.usePlugin
*/
public setItem(key: string, value: any, options: Options = {}): void {
const storage = this.getStorage();
const namespace = this.getNamespace();
let item = value;
const protocol = options.protocol ? `${options.protocol}:` : '';
if (typeof value === Protocol.STRING || typeof value === Protocol.NUMBER) {
item = `${protocol}${value}`;
} else {
item = `${protocol}${serialize(value)}`;
}
storage.setItem(`${options.namespace || namespace}:${key}`, item);
}
public destroy() {
this.removeAllListeners();
this.removeAllPlugins();
}
private getValueAndProtocol(value: string | null) {
let protocol = '';
if (value === null) {
return {
item: value,
protocol,
};
}
const item = value.replace(new RegExp(`^(${Object.values(Protocol).join('|')})(:)(.+)`), (_$0, $1, _$2, $3) => {
protocol = $1;
return $3;
});
return {
protocol,
item,
};
}
}
export type StorageService = WebStorage;
export default new WebStorage();