init query login
This commit is contained in:
200
dist/query-login.d.ts
vendored
Normal file
200
dist/query-login.d.ts
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
import { Query } from '@kevisual/query';
|
||||
import { DataOpts, Result } from '@kevisual/query/query';
|
||||
|
||||
type CacheLoginUser = {
|
||||
user?: any;
|
||||
id?: string;
|
||||
accessToken?: string;
|
||||
refreshToken?: string;
|
||||
};
|
||||
type CacheLogin = {
|
||||
loginUsers: CacheLoginUser[];
|
||||
} & CacheLoginUser;
|
||||
interface CacheStore<T = any> {
|
||||
name: string;
|
||||
cacheData: CacheLogin;
|
||||
cache: T;
|
||||
/**
|
||||
* @update 获取缓存
|
||||
*/
|
||||
get(key: string): Promise<any>;
|
||||
/**
|
||||
* @update 设置缓存
|
||||
*/
|
||||
set(key: string, value: CacheLogin): Promise<CacheLogin>;
|
||||
/**
|
||||
* @update 删除缓存
|
||||
*/
|
||||
del(): Promise<void>;
|
||||
/**
|
||||
* 设置当前用户
|
||||
*/
|
||||
setLoginUser(user: CacheLoginUser): Promise<void>;
|
||||
/**
|
||||
* 获取当前用户
|
||||
*/
|
||||
getCurrentUser(): Promise<CacheLoginUser>;
|
||||
/**
|
||||
* 获取当前用户列表
|
||||
*/
|
||||
getCurrentUserList(): Promise<CacheLoginUser[]>;
|
||||
/**
|
||||
* 获取缓存的refreshToken
|
||||
*/
|
||||
getRefreshToken(): Promise<string>;
|
||||
/**
|
||||
* 获取缓存的accessToken
|
||||
*/
|
||||
getAccessToken(): Promise<string>;
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
init(): Promise<void>;
|
||||
/**
|
||||
* 清除当前用户
|
||||
*/
|
||||
clearCurrentUser(): Promise<void>;
|
||||
/**
|
||||
* 清除所有用户
|
||||
*/
|
||||
clearAll(): Promise<void>;
|
||||
}
|
||||
|
||||
type QueryLoginOpts = {
|
||||
query?: Query;
|
||||
isBrowser?: boolean;
|
||||
onLoad?: () => void;
|
||||
storage?: Storage;
|
||||
};
|
||||
type QueryLoginData = {
|
||||
username?: string;
|
||||
password: string;
|
||||
email?: string;
|
||||
};
|
||||
type QueryLoginResult = {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
};
|
||||
declare class QueryLogin {
|
||||
query: Query;
|
||||
cache: CacheStore;
|
||||
isBrowser: boolean;
|
||||
load?: boolean;
|
||||
storage: Storage;
|
||||
onLoad?: () => void;
|
||||
constructor(opts?: QueryLoginOpts);
|
||||
setQuery(query: Query): void;
|
||||
init(): Promise<void>;
|
||||
post<T = any>(data: any, opts?: DataOpts): Promise<{
|
||||
code: number;
|
||||
data?: T;
|
||||
message?: string;
|
||||
success: boolean;
|
||||
noMsg?: boolean;
|
||||
showError: (fn?: () => void) => void;
|
||||
}>;
|
||||
/**
|
||||
* 登录,
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
login(data: QueryLoginData): Promise<{
|
||||
code: number;
|
||||
data?: QueryLoginResult;
|
||||
message?: string;
|
||||
success: boolean;
|
||||
noMsg?: boolean;
|
||||
showError: (fn?: () => void) => void;
|
||||
}>;
|
||||
/**
|
||||
* 登陆成功,需要获取用户信息进行缓存
|
||||
* @param param0
|
||||
*/
|
||||
beforeSetLoginUser({ accessToken, refreshToken, check401 }: {
|
||||
accessToken?: string;
|
||||
refreshToken?: string;
|
||||
check401?: boolean;
|
||||
}): Promise<void>;
|
||||
queryRefreshToken(refreshToken?: string): Promise<{
|
||||
code: number;
|
||||
data?: any;
|
||||
message?: string;
|
||||
success: boolean;
|
||||
noMsg?: boolean;
|
||||
showError: (fn?: () => void) => void;
|
||||
} | {
|
||||
code: number;
|
||||
message: string;
|
||||
data: any;
|
||||
}>;
|
||||
/**
|
||||
* 检查401错误,并刷新token, 如果refreshToken存在,则刷新token, 否则返回401
|
||||
* @param response
|
||||
* @param ctx
|
||||
* @param refetch
|
||||
* @returns
|
||||
*/
|
||||
afterCheck401ToRefreshToken(response: Result, ctx?: {
|
||||
req?: any;
|
||||
res?: any;
|
||||
fetch?: any;
|
||||
}, refetch?: boolean): Promise<any>;
|
||||
/**
|
||||
* 获取用户信息
|
||||
* @param token
|
||||
* @returns
|
||||
*/
|
||||
getMe(token?: string, check401?: boolean): Promise<{
|
||||
code: number;
|
||||
data?: any;
|
||||
message?: string;
|
||||
success: boolean;
|
||||
noMsg?: boolean;
|
||||
showError: (fn?: () => void) => void;
|
||||
}>;
|
||||
/**
|
||||
* 请求更新,切换用户, 使用switchUser
|
||||
* @param username
|
||||
* @returns
|
||||
*/
|
||||
private postSwitchUser;
|
||||
/**
|
||||
* 切换用户
|
||||
* @param username
|
||||
* @returns
|
||||
*/
|
||||
switchUser(username: string): Promise<{
|
||||
code: number;
|
||||
data?: any;
|
||||
message?: string;
|
||||
success: boolean;
|
||||
noMsg?: boolean;
|
||||
showError: (fn?: () => void) => void;
|
||||
} | {
|
||||
code: number;
|
||||
data: {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
};
|
||||
success: boolean;
|
||||
message: string;
|
||||
}>;
|
||||
logout(): Promise<{
|
||||
code: number;
|
||||
data?: Result;
|
||||
message?: string;
|
||||
success: boolean;
|
||||
noMsg?: boolean;
|
||||
showError: (fn?: () => void) => void;
|
||||
}>;
|
||||
hasUser(username: string): Promise<{
|
||||
code: number;
|
||||
data?: Result;
|
||||
message?: string;
|
||||
success: boolean;
|
||||
noMsg?: boolean;
|
||||
showError: (fn?: () => void) => void;
|
||||
}>;
|
||||
}
|
||||
|
||||
export { QueryLogin, type QueryLoginData, type QueryLoginResult };
|
||||
318
dist/query-login.js
vendored
Normal file
318
dist/query-login.js
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
// src/query-login.ts
|
||||
import { Query } from "@kevisual/query";
|
||||
import { setBaseResponse } from "@kevisual/query/query";
|
||||
|
||||
// src/login-cache.ts
|
||||
import { MyCache } from "@kevisual/cache";
|
||||
var LoginCacheStore = class {
|
||||
cache;
|
||||
name;
|
||||
cacheData;
|
||||
constructor(name) {
|
||||
this.cache = new MyCache(name);
|
||||
this.cacheData = {
|
||||
loginUsers: [],
|
||||
user: void 0,
|
||||
id: void 0,
|
||||
accessToken: void 0,
|
||||
refreshToken: void 0
|
||||
};
|
||||
this.name = name;
|
||||
}
|
||||
/**
|
||||
* 设置缓存
|
||||
* @param key
|
||||
* @param value
|
||||
* @returns
|
||||
*/
|
||||
async set(key, value) {
|
||||
await this.cache.set(key, value);
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* 删除缓存
|
||||
*/
|
||||
async del() {
|
||||
await this.cache.del();
|
||||
}
|
||||
get(key) {
|
||||
return this.cache.get(key);
|
||||
}
|
||||
async init() {
|
||||
this.cacheData = await this.get(this.name) || {
|
||||
loginUsers: [],
|
||||
user: null,
|
||||
id: null,
|
||||
accessToken: null,
|
||||
refreshToken: null
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 设置当前用户
|
||||
* @param user
|
||||
*/
|
||||
async setLoginUser(user) {
|
||||
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);
|
||||
}
|
||||
this.cacheData.loginUsers.push(user);
|
||||
this.cacheData.user = user.user;
|
||||
this.cacheData.id = user.id;
|
||||
this.cacheData.accessToken = user.accessToken;
|
||||
this.cacheData.refreshToken = user.refreshToken;
|
||||
await this.set(this.name, this.cacheData);
|
||||
}
|
||||
getCurrentUser() {
|
||||
const cacheData = this.cacheData;
|
||||
return Promise.resolve(cacheData.user);
|
||||
}
|
||||
getCurrentUserList() {
|
||||
return Promise.resolve(this.cacheData.loginUsers.filter((u) => u?.id));
|
||||
}
|
||||
getRefreshToken() {
|
||||
const cacheData = this.cacheData;
|
||||
return Promise.resolve(cacheData.refreshToken || "");
|
||||
}
|
||||
getAccessToken() {
|
||||
const cacheData = this.cacheData;
|
||||
return Promise.resolve(cacheData.accessToken || "");
|
||||
}
|
||||
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);
|
||||
}
|
||||
this.cacheData.user = void 0;
|
||||
this.cacheData.id = void 0;
|
||||
this.cacheData.accessToken = void 0;
|
||||
this.cacheData.refreshToken = void 0;
|
||||
await this.set(this.name, this.cacheData);
|
||||
}
|
||||
async clearAll() {
|
||||
this.cacheData.loginUsers = [];
|
||||
this.cacheData.user = void 0;
|
||||
this.cacheData.id = void 0;
|
||||
this.cacheData.accessToken = void 0;
|
||||
this.cacheData.refreshToken = void 0;
|
||||
await this.set(this.name, this.cacheData);
|
||||
}
|
||||
};
|
||||
|
||||
// src/query-login.ts
|
||||
var QueryLogin = class {
|
||||
query;
|
||||
cache;
|
||||
isBrowser;
|
||||
load;
|
||||
storage;
|
||||
onLoad;
|
||||
constructor(opts) {
|
||||
this.query = opts?.query || new Query();
|
||||
this.cache = new LoginCacheStore("login");
|
||||
this.isBrowser = opts?.isBrowser ?? true;
|
||||
this.init();
|
||||
this.onLoad = opts?.onLoad;
|
||||
this.storage = opts?.storage || localStorage;
|
||||
}
|
||||
setQuery(query) {
|
||||
this.query = query;
|
||||
}
|
||||
async init() {
|
||||
await this.cache.init();
|
||||
this.load = true;
|
||||
this.onLoad?.();
|
||||
}
|
||||
async post(data, opts) {
|
||||
return this.query.post({ path: "user", ...data }, opts);
|
||||
}
|
||||
/**
|
||||
* 登录,
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
async login(data) {
|
||||
const res = await this.post({ key: "login", ...data });
|
||||
if (res.code === 200) {
|
||||
const { accessToken, refreshToken } = res?.data || {};
|
||||
this.storage.setItem("token", accessToken || "");
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken });
|
||||
}
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* 登陆成功,需要获取用户信息进行缓存
|
||||
* @param param0
|
||||
*/
|
||||
async beforeSetLoginUser({ accessToken, refreshToken, check401 }) {
|
||||
if (accessToken && refreshToken) {
|
||||
const resUser = await this.getMe(accessToken, check401);
|
||||
if (resUser.code === 200) {
|
||||
const user = resUser.data;
|
||||
if (user) {
|
||||
this.cache.setLoginUser({
|
||||
user,
|
||||
id: user.id,
|
||||
accessToken,
|
||||
refreshToken
|
||||
});
|
||||
} else {
|
||||
console.error("\u767B\u5F55\u5931\u8D25");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async queryRefreshToken(refreshToken) {
|
||||
const _refreshToken = refreshToken || this.cache.getRefreshToken();
|
||||
let data = { refreshToken: _refreshToken };
|
||||
if (!_refreshToken) {
|
||||
await this.cache.clearCurrentUser();
|
||||
return {
|
||||
code: 401,
|
||||
message: "\u8BF7\u5148\u767B\u5F55",
|
||||
data: {}
|
||||
};
|
||||
}
|
||||
return this.post(
|
||||
{ key: "refreshToken", data },
|
||||
{
|
||||
afterResponse: async (response, ctx) => {
|
||||
setBaseResponse(response);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 检查401错误,并刷新token, 如果refreshToken存在,则刷新token, 否则返回401
|
||||
* @param response
|
||||
* @param ctx
|
||||
* @param refetch
|
||||
* @returns
|
||||
*/
|
||||
async afterCheck401ToRefreshToken(response, ctx, refetch) {
|
||||
const that = this;
|
||||
if (response?.code === 401) {
|
||||
const hasRefreshToken = await that.cache.getRefreshToken();
|
||||
if (hasRefreshToken) {
|
||||
const res = await that.queryRefreshToken(hasRefreshToken);
|
||||
if (res.code === 200) {
|
||||
const { accessToken, refreshToken } = res?.data || {};
|
||||
that.storage.setItem("token", accessToken || "");
|
||||
await that.beforeSetLoginUser({ accessToken, refreshToken, check401: false });
|
||||
if (refetch && ctx && ctx.req && ctx.req.url && ctx.fetch) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||||
const url = ctx.req?.url;
|
||||
const body = ctx.req?.body;
|
||||
const headers = ctx.req?.headers;
|
||||
const res2 = await ctx.fetch(url, {
|
||||
method: "POST",
|
||||
body,
|
||||
headers: { ...headers, Authorization: `Bearer ${accessToken}` }
|
||||
});
|
||||
setBaseResponse(res2);
|
||||
return res2;
|
||||
}
|
||||
} else {
|
||||
that.storage.removeItem("token");
|
||||
await that.cache.clearCurrentUser();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
/**
|
||||
* 获取用户信息
|
||||
* @param token
|
||||
* @returns
|
||||
*/
|
||||
async getMe(token, check401 = true) {
|
||||
const _token = token || this.storage.getItem("token");
|
||||
const that = this;
|
||||
return that.post(
|
||||
{ key: "me" },
|
||||
{
|
||||
beforeRequest: async (config) => {
|
||||
if (config.headers) {
|
||||
config.headers["Authorization"] = `Bearer ${_token}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
afterResponse: async (response, ctx) => {
|
||||
if (response?.code === 401 && check401) {
|
||||
return await that.afterCheck401ToRefreshToken(response, ctx);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 请求更新,切换用户, 使用switchUser
|
||||
* @param username
|
||||
* @returns
|
||||
*/
|
||||
async postSwitchUser(username) {
|
||||
return this.post({ key: "switchCheck", data: { username } });
|
||||
}
|
||||
/**
|
||||
* 切换用户
|
||||
* @param username
|
||||
* @returns
|
||||
*/
|
||||
async switchUser(username) {
|
||||
const localUserList = await this.cache.getCurrentUserList();
|
||||
const user = localUserList.find((userItem) => userItem.user.username === username);
|
||||
if (user) {
|
||||
this.storage.setItem("token", user.accessToken || "");
|
||||
await this.beforeSetLoginUser({ accessToken: user.accessToken, refreshToken: user.refreshToken });
|
||||
return {
|
||||
code: 200,
|
||||
data: {
|
||||
accessToken: user.accessToken,
|
||||
refreshToken: user.refreshToken
|
||||
},
|
||||
success: true,
|
||||
message: "\u5207\u6362\u7528\u6237\u6210\u529F"
|
||||
};
|
||||
}
|
||||
const res = await this.postSwitchUser(username);
|
||||
if (res.code === 200) {
|
||||
const { accessToken, refreshToken } = res?.data || {};
|
||||
this.storage.setItem("token", accessToken || "");
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken });
|
||||
}
|
||||
return res;
|
||||
}
|
||||
async logout() {
|
||||
this.storage.removeItem("token");
|
||||
this.cache.del();
|
||||
return this.post({ key: "logout" });
|
||||
}
|
||||
async hasUser(username) {
|
||||
const that = this;
|
||||
return this.post(
|
||||
{
|
||||
path: "org",
|
||||
key: "hasUser",
|
||||
data: {
|
||||
username
|
||||
}
|
||||
},
|
||||
{
|
||||
afterResponse: async (response, ctx) => {
|
||||
if (response?.code === 401) {
|
||||
const res = await that.afterCheck401ToRefreshToken(response, ctx, true);
|
||||
return res;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
export {
|
||||
QueryLogin
|
||||
};
|
||||
Reference in New Issue
Block a user