Files
query-awesome/query/query-login/login-cache.ts

235 lines
5.9 KiB
TypeScript

export interface Cache {
/**
* @update 获取缓存
*/
get(key: string): Promise<any>;
/**
* @update 设置缓存
*/
set(key: string, value: any): Promise<any>;
/**
* @update 删除缓存
*/
del(): Promise<void>;
/**
* 初始化
*/
init?: () => Promise<any>;
}
export type User = {
avatar?: string;
description?: string;
id?: string;
needChangePassword?: boolean;
orgs?: string[];
type?: string;
username?: string;
};
export type CacheLoginUser = {
user?: User;
id?: string;
accessToken?: string;
refreshToken?: string;
accessTokenExpiresIn?: number;
createdAt?: number;
};
type CacheLogin = {
loginUsers: CacheLoginUser[];
} & CacheLoginUser;
export type CacheStore<T extends Cache = Cache> = {
name: string;
/**
* 缓存数据
* @important 需要先调用init
*/
cacheData: CacheLogin;
/**
* 实际操作的cache, 需要先调用init
*/
cache: T;
/**
* 设置当前用户
*/
setLoginUser(user: CacheLoginUser): Promise<void>;
/**
* 获取当前用户
*/
getCurrentUser(): Promise<User>;
/**
* 获取当前用户列表
*/
getCurrentUserList(): Promise<CacheLoginUser[]>;
/**
* 获取缓存的refreshToken
*/
getRefreshToken(): Promise<string>;
/**
* 获取缓存的accessToken
*/
getAccessToken(): Promise<string>;
/**
* 清除当前用户
*/
clearCurrentUser(): Promise<void>;
/**
* 清除所有用户
*/
clearAll(): Promise<void>;
getValue(): Promise<CacheLogin>;
setValue(value: CacheLogin): Promise<CacheLogin>;
delValue(): Promise<void>;
init(): Promise<CacheLogin>;
getIsExpired(): Promise<boolean>;
};
export type LoginCacheStoreOpts<T extends Cache = Cache> = {
name: string;
cache: T;
};
const defaultCacheData: CacheLogin = {
loginUsers: [],
user: undefined,
id: undefined,
accessToken: undefined,
refreshToken: undefined,
accessTokenExpiresIn: undefined,
createdAt: undefined,
}
export class LoginCacheStore<T extends Cache = Cache> implements CacheStore<T> {
cache: T;
name: string;
cacheData: CacheLogin;
constructor(opts: LoginCacheStoreOpts<T>) {
if (!opts.cache) {
throw new Error('cache is required');
}
// @ts-ignore
this.cache = opts.cache;
this.cacheData = { ...defaultCacheData };
this.name = opts.name;
}
/**
* 设置缓存
* @param key
* @param value
* @returns
accessTokenExpiresIn: undefined,
createdAt: undefined,
};
this.name = opts.name;
}
/**
* 设置缓存
* @param key
* @param value
* @returns
*/
async setValue(value: CacheLogin) {
await this.cache.set(this.name, value);
this.cacheData = value;
return value;
}
/**
* 删除缓存
*/
async delValue() {
await this.cache.del();
this.cacheData = { ...defaultCacheData };
}
getValue(): Promise<CacheLogin> {
return this.cache.get(this.name);
}
/**
* 初始化,设置默认值
*/
async init() {
const defaultData: CacheLogin = { ...this.cacheData };
if (this.cache.init) {
try {
const cacheData = await this.cache.init();
this.cacheData = cacheData || defaultData;
} catch (error) {
console.log('cacheInit error', error);
}
} else {
this.cacheData = (await this.getValue()) || defaultData;
}
return this.cacheData;
}
/**
* 设置当前用户
* @param user
*/
async setLoginUser(loginUser: CacheLoginUser) {
const has = this.cacheData.loginUsers.find((u) => u.id === loginUser.id);
if (has) {
this.cacheData.loginUsers = this.cacheData?.loginUsers?.filter((u) => u?.id && u.id !== loginUser.id);
}
this.cacheData.loginUsers.push(loginUser);
this.cacheData.user = loginUser.user;
this.cacheData.id = loginUser.id;
this.cacheData.accessToken = loginUser.accessToken;
this.cacheData.refreshToken = loginUser.refreshToken;
this.cacheData.accessTokenExpiresIn = loginUser.accessTokenExpiresIn;
this.cacheData.createdAt = loginUser.createdAt;
await this.setValue(this.cacheData);
}
getCurrentUser(): Promise<CacheLoginUser> {
const cacheData = this.cacheData;
return Promise.resolve(cacheData.user!);
}
getCurrentUserList(): Promise<CacheLoginUser[]> {
return Promise.resolve(this.cacheData.loginUsers.filter((u) => u?.id));
}
getRefreshToken(): Promise<string> {
const cacheData = this.cacheData;
return Promise.resolve(cacheData.refreshToken || '');
}
getAccessToken(): Promise<string> {
const cacheData = this.cacheData;
return Promise.resolve(cacheData.accessToken || '');
}
getIsExpired(): Promise<boolean> {
const cacheData = this.cacheData;
if (!cacheData.accessToken) {
return Promise.resolve(true);
}
if (!cacheData.createdAt || !cacheData.accessTokenExpiresIn) {
return Promise.resolve(false);
}
const now = Date.now();
const expiresIn = cacheData.createdAt + cacheData.accessTokenExpiresIn * 1000;
return Promise.resolve(now >= expiresIn);
}
async clearCurrentUser() {
const user = await this.getCurrentUser();
const has = this.cacheData.loginUsers.find((u) => u.id === user.id);
if (has) {
this.cacheData.loginUsers = this.cacheData?.loginUsers?.filter((u) => u?.id && u.id !== user.id);
}
const hasOther = this.cacheData.loginUsers.length > 0;
const current = this.cacheData.loginUsers[this.cacheData.loginUsers.length - 1];
if (hasOther && current) {
this.cacheData.user = current.user;
this.cacheData.id = current.id;
this.cacheData.accessToken = current.accessToken;
this.cacheData.refreshToken = current.refreshToken;
this.cacheData.accessTokenExpiresIn = current.accessTokenExpiresIn;
this.cacheData.createdAt = current.createdAt;
} else {
this.cacheData = { ...defaultCacheData };
}
await this.setValue(this.cacheData);
}
async clearAll() {
this.cacheData = { ...defaultCacheData };
await this.setValue(this.cacheData);
}
}