init query login
This commit is contained in:
commit
2cbd309c2a
2
.npmrc
Normal file
2
.npmrc
Normal file
@ -0,0 +1,2 @@
|
||||
//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
|
||||
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
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
|
||||
};
|
11
index.html
Normal file
11
index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Query Login</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="src/test/login.ts" type="module"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
17
node_modules/.bin/jiti
generated
vendored
Executable file
17
node_modules/.bin/jiti
generated
vendored
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/lib/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/jiti@2.4.2/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/lib/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/jiti@2.4.2/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/lib/jiti-cli.mjs" "$@"
|
||||
else
|
||||
exec node "$basedir/../../../../node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/lib/jiti-cli.mjs" "$@"
|
||||
fi
|
17
node_modules/.bin/rollup
generated
vendored
Executable file
17
node_modules/.bin/rollup
generated
vendored
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/rollup@4.36.0/node_modules/rollup/dist/bin/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/rollup@4.36.0/node_modules/rollup/dist/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/rollup@4.36.0/node_modules/rollup/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/rollup@4.36.0/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/rollup@4.36.0/node_modules/rollup/dist/bin/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/rollup@4.36.0/node_modules/rollup/dist/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/rollup@4.36.0/node_modules/rollup/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/rollup@4.36.0/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/rollup@4.36.0/node_modules/rollup/dist/bin/rollup" "$@"
|
||||
else
|
||||
exec node "$basedir/../../../../node_modules/.pnpm/rollup@4.36.0/node_modules/rollup/dist/bin/rollup" "$@"
|
||||
fi
|
17
node_modules/.bin/tsc
generated
vendored
Executable file
17
node_modules/.bin/tsc
generated
vendored
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/bin/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/bin/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/bin/tsc" "$@"
|
||||
else
|
||||
exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/bin/tsc" "$@"
|
||||
fi
|
17
node_modules/.bin/tsserver
generated
vendored
Executable file
17
node_modules/.bin/tsserver
generated
vendored
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/bin/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/bin/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/typescript@5.8.2/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/bin/tsserver" "$@"
|
||||
else
|
||||
exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.8.2/node_modules/typescript/bin/tsserver" "$@"
|
||||
fi
|
17
node_modules/.bin/tsup
generated
vendored
Executable file
17
node_modules/.bin/tsup
generated
vendored
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup/dist/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup/dist/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../tsup/dist/cli-default.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../tsup/dist/cli-default.js" "$@"
|
||||
fi
|
17
node_modules/.bin/tsup-node
generated
vendored
Executable file
17
node_modules/.bin/tsup-node
generated
vendored
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup/dist/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup/dist/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../tsup/dist/cli-node.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../tsup/dist/cli-node.js" "$@"
|
||||
fi
|
17
node_modules/.bin/yaml
generated
vendored
Executable file
17
node_modules/.bin/yaml
generated
vendored
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/yaml@2.5.1/node_modules/yaml/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/yaml@2.5.1/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/home/ubuntu/kevisual/center/node_modules/.pnpm/yaml@2.5.1/node_modules/yaml/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/yaml@2.5.1/node_modules:/home/ubuntu/kevisual/center/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/yaml@2.5.1/node_modules/yaml/bin.mjs" "$@"
|
||||
else
|
||||
exec node "$basedir/../../../../node_modules/.pnpm/yaml@2.5.1/node_modules/yaml/bin.mjs" "$@"
|
||||
fi
|
199
node_modules/.vite/deps/@kevisual_cache.js
generated
vendored
Normal file
199
node_modules/.vite/deps/@kevisual_cache.js
generated
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
import {
|
||||
__publicField
|
||||
} from "./chunk-V6TY7KAL.js";
|
||||
|
||||
// ../../node_modules/.pnpm/@kevisual+cache@0.0.1_rollup@4.36.0_tslib@2.8.1_typescript@5.8.2/node_modules/@kevisual/cache/dist/cache.js
|
||||
function promisifyRequest(request) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.oncomplete = request.onsuccess = () => resolve(request.result);
|
||||
request.onabort = request.onerror = () => reject(request.error);
|
||||
});
|
||||
}
|
||||
function createStore(dbName, storeName) {
|
||||
const request = indexedDB.open(dbName);
|
||||
request.onupgradeneeded = () => request.result.createObjectStore(storeName);
|
||||
const dbp = promisifyRequest(request);
|
||||
return (txMode, callback) => dbp.then((db) => callback(db.transaction(storeName, txMode).objectStore(storeName)));
|
||||
}
|
||||
var defaultGetStoreFunc;
|
||||
function defaultGetStore() {
|
||||
if (!defaultGetStoreFunc) {
|
||||
defaultGetStoreFunc = createStore("keyval-store", "keyval");
|
||||
}
|
||||
return defaultGetStoreFunc;
|
||||
}
|
||||
function get(key, customStore = defaultGetStore()) {
|
||||
return customStore("readonly", (store) => promisifyRequest(store.get(key)));
|
||||
}
|
||||
function set(key, value, customStore = defaultGetStore()) {
|
||||
return customStore("readwrite", (store) => {
|
||||
store.put(value, key);
|
||||
return promisifyRequest(store.transaction);
|
||||
});
|
||||
}
|
||||
function setMany(entries2, customStore = defaultGetStore()) {
|
||||
return customStore("readwrite", (store) => {
|
||||
entries2.forEach((entry) => store.put(entry[1], entry[0]));
|
||||
return promisifyRequest(store.transaction);
|
||||
});
|
||||
}
|
||||
function getMany(keys2, customStore = defaultGetStore()) {
|
||||
return customStore("readonly", (store) => Promise.all(keys2.map((key) => promisifyRequest(store.get(key)))));
|
||||
}
|
||||
function update(key, updater, customStore = defaultGetStore()) {
|
||||
return customStore("readwrite", (store) => (
|
||||
// Need to create the promise manually.
|
||||
// If I try to chain promises, the transaction closes in browsers
|
||||
// that use a promise polyfill (IE10/11).
|
||||
new Promise((resolve, reject) => {
|
||||
store.get(key).onsuccess = function() {
|
||||
try {
|
||||
store.put(updater(this.result), key);
|
||||
resolve(promisifyRequest(store.transaction));
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
};
|
||||
})
|
||||
));
|
||||
}
|
||||
function del(key, customStore = defaultGetStore()) {
|
||||
return customStore("readwrite", (store) => {
|
||||
store.delete(key);
|
||||
return promisifyRequest(store.transaction);
|
||||
});
|
||||
}
|
||||
function delMany(keys2, customStore = defaultGetStore()) {
|
||||
return customStore("readwrite", (store) => {
|
||||
keys2.forEach((key) => store.delete(key));
|
||||
return promisifyRequest(store.transaction);
|
||||
});
|
||||
}
|
||||
function clear(customStore = defaultGetStore()) {
|
||||
return customStore("readwrite", (store) => {
|
||||
store.clear();
|
||||
return promisifyRequest(store.transaction);
|
||||
});
|
||||
}
|
||||
function eachCursor(store, callback) {
|
||||
store.openCursor().onsuccess = function() {
|
||||
if (!this.result)
|
||||
return;
|
||||
callback(this.result);
|
||||
this.result.continue();
|
||||
};
|
||||
return promisifyRequest(store.transaction);
|
||||
}
|
||||
function keys(customStore = defaultGetStore()) {
|
||||
return customStore("readonly", (store) => {
|
||||
if (store.getAllKeys) {
|
||||
return promisifyRequest(store.getAllKeys());
|
||||
}
|
||||
const items = [];
|
||||
return eachCursor(store, (cursor) => items.push(cursor.key)).then(() => items);
|
||||
});
|
||||
}
|
||||
function values(customStore = defaultGetStore()) {
|
||||
return customStore("readonly", (store) => {
|
||||
if (store.getAll) {
|
||||
return promisifyRequest(store.getAll());
|
||||
}
|
||||
const items = [];
|
||||
return eachCursor(store, (cursor) => items.push(cursor.value)).then(() => items);
|
||||
});
|
||||
}
|
||||
function entries(customStore = defaultGetStore()) {
|
||||
return customStore("readonly", (store) => {
|
||||
if (store.getAll && store.getAllKeys) {
|
||||
return Promise.all([
|
||||
promisifyRequest(store.getAllKeys()),
|
||||
promisifyRequest(store.getAll())
|
||||
]).then(([keys2, values2]) => keys2.map((key, i) => [key, values2[i]]));
|
||||
}
|
||||
const items = [];
|
||||
return customStore("readonly", (store2) => eachCursor(store2, (cursor) => items.push([cursor.key, cursor.value])).then(() => items));
|
||||
});
|
||||
}
|
||||
var idb = Object.freeze({
|
||||
__proto__: null,
|
||||
clear,
|
||||
createStore,
|
||||
del,
|
||||
delMany,
|
||||
entries,
|
||||
get,
|
||||
getMany,
|
||||
keys,
|
||||
promisifyRequest,
|
||||
set,
|
||||
setMany,
|
||||
update,
|
||||
values
|
||||
});
|
||||
var CacheWorkspace = class {
|
||||
constructor() {
|
||||
__publicField(this, "storage");
|
||||
__publicField(this, "data", null);
|
||||
this.storage = idb;
|
||||
}
|
||||
async get(name) {
|
||||
const data = await get(name);
|
||||
this.data = data;
|
||||
return data;
|
||||
}
|
||||
async set(name, data) {
|
||||
this.data = data;
|
||||
await set(name, data);
|
||||
}
|
||||
async del(name) {
|
||||
this.data = null;
|
||||
await del(name);
|
||||
}
|
||||
/**
|
||||
* Clear all values in the store.
|
||||
*/
|
||||
async clear() {
|
||||
await clear();
|
||||
}
|
||||
};
|
||||
var MyCache = class extends CacheWorkspace {
|
||||
constructor(name) {
|
||||
super();
|
||||
__publicField(this, "name");
|
||||
__publicField(this, "updatedAt");
|
||||
this.name = name || "my-cache";
|
||||
}
|
||||
async getData() {
|
||||
const cache = await super.get(this.name);
|
||||
this.updatedAt = cache.updatedAt;
|
||||
if (cache.expireTime && cache.expireTime < Date.now()) {
|
||||
await super.del(this.name);
|
||||
return {};
|
||||
}
|
||||
return cache.data;
|
||||
}
|
||||
/**
|
||||
* 设置缓存数据,默认过期时间为10天
|
||||
* @param data
|
||||
* @param opts
|
||||
*/
|
||||
async setData(data, opts) {
|
||||
const now = Date.now();
|
||||
const expireTime = now + ((opts == null ? void 0 : opts.expireTime) || 1e3 * 60 * 60 * 24 * 10);
|
||||
const newData = {
|
||||
data,
|
||||
updatedAt: Date.now(),
|
||||
expireTime
|
||||
};
|
||||
await super.set(this.name, newData);
|
||||
this.updatedAt = newData.updatedAt;
|
||||
}
|
||||
async del() {
|
||||
await super.del(this.name);
|
||||
}
|
||||
};
|
||||
export {
|
||||
CacheWorkspace,
|
||||
MyCache
|
||||
};
|
||||
//# sourceMappingURL=@kevisual_cache.js.map
|
7
node_modules/.vite/deps/@kevisual_cache.js.map
generated
vendored
Normal file
7
node_modules/.vite/deps/@kevisual_cache.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
357
node_modules/.vite/deps/@kevisual_query.js
generated
vendored
Normal file
357
node_modules/.vite/deps/@kevisual_query.js
generated
vendored
Normal file
@ -0,0 +1,357 @@
|
||||
import {
|
||||
__publicField
|
||||
} from "./chunk-V6TY7KAL.js";
|
||||
|
||||
// ../../node_modules/.pnpm/@kevisual+query@0.0.12_ws@8.18.1/node_modules/@kevisual/query/dist/query-browser.js
|
||||
var adapter = async (opts, overloadOpts) => {
|
||||
const controller = new AbortController();
|
||||
const signal = controller.signal;
|
||||
const timeout = opts.timeout || 6e4 * 3;
|
||||
const timer = setTimeout(() => {
|
||||
controller.abort();
|
||||
}, timeout);
|
||||
return fetch(opts.url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...opts.headers
|
||||
},
|
||||
body: JSON.stringify(opts.body),
|
||||
signal,
|
||||
...overloadOpts
|
||||
}).then((response) => {
|
||||
const contentType = response.headers.get("Content-Type");
|
||||
if (contentType && contentType.includes("application/json")) {
|
||||
return response.json();
|
||||
} else {
|
||||
return response.text();
|
||||
}
|
||||
}).catch((err) => {
|
||||
if (err.name === "AbortError") {
|
||||
console.log("Request timed out and was aborted");
|
||||
}
|
||||
console.error(err);
|
||||
return {
|
||||
code: 500
|
||||
};
|
||||
}).finally(() => {
|
||||
clearTimeout(timer);
|
||||
});
|
||||
};
|
||||
var createStoreImpl = (createState) => {
|
||||
let state;
|
||||
const listeners = /* @__PURE__ */ new Set();
|
||||
const setState = (partial, replace) => {
|
||||
const nextState = typeof partial === "function" ? partial(state) : partial;
|
||||
if (!Object.is(nextState, state)) {
|
||||
const previousState = state;
|
||||
state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
|
||||
listeners.forEach((listener) => listener(state, previousState));
|
||||
}
|
||||
};
|
||||
const getState = () => state;
|
||||
const getInitialState = () => initialState;
|
||||
const subscribe = (listener) => {
|
||||
listeners.add(listener);
|
||||
return () => listeners.delete(listener);
|
||||
};
|
||||
const api = { setState, getState, getInitialState, subscribe };
|
||||
const initialState = state = createState(setState, getState, api);
|
||||
return api;
|
||||
};
|
||||
var createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
|
||||
var parseWsUrl = (url) => {
|
||||
try {
|
||||
new URL(url);
|
||||
return url;
|
||||
} catch (e) {
|
||||
const _url = new URL(url, location.origin);
|
||||
if (_url.protocol === "http:") {
|
||||
_url.protocol = "ws:";
|
||||
}
|
||||
if (_url.protocol === "https:") {
|
||||
_url.protocol = "wss:";
|
||||
}
|
||||
return _url.href;
|
||||
}
|
||||
};
|
||||
var QueryWs = class {
|
||||
constructor(opts) {
|
||||
__publicField(this, "url");
|
||||
__publicField(this, "store");
|
||||
__publicField(this, "ws");
|
||||
const url = (opts == null ? void 0 : opts.url) || "/api/router";
|
||||
if (opts == null ? void 0 : opts.store) {
|
||||
this.store = opts.store;
|
||||
} else {
|
||||
const store = createStore((set) => ({
|
||||
connected: false,
|
||||
status: "connecting",
|
||||
setConnected: (connected) => set({ connected }),
|
||||
setStatus: (status) => set({ status })
|
||||
}));
|
||||
this.store = store;
|
||||
}
|
||||
const wsUrl = parseWsUrl(url);
|
||||
if ((opts == null ? void 0 : opts.ws) && opts.ws instanceof WebSocket) {
|
||||
this.ws = opts.ws;
|
||||
} else {
|
||||
this.ws = new WebSocket(wsUrl);
|
||||
}
|
||||
this.connect();
|
||||
}
|
||||
/**
|
||||
* 连接 WebSocket
|
||||
*/
|
||||
async connect(opts) {
|
||||
const store = this.store;
|
||||
const connected = store.getState().connected;
|
||||
if (connected) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const ws = this.ws || new WebSocket(this.url);
|
||||
const timeout = (opts == null ? void 0 : opts.timeout) || 5 * 60 * 1e3;
|
||||
let timer = setTimeout(() => {
|
||||
console.error("WebSocket 连接超时");
|
||||
reject("timeout");
|
||||
}, timeout);
|
||||
ws.onopen = () => {
|
||||
store.getState().setConnected(true);
|
||||
store.getState().setStatus("connected");
|
||||
resolve(true);
|
||||
clearTimeout(timer);
|
||||
};
|
||||
ws.onclose = () => {
|
||||
store.getState().setConnected(false);
|
||||
store.getState().setStatus("disconnected");
|
||||
this.ws = null;
|
||||
};
|
||||
});
|
||||
}
|
||||
listenConnect(callback) {
|
||||
const store = this.store;
|
||||
const { connected } = store.getState();
|
||||
if (connected) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
const subscriptionOne = (selector, listener) => {
|
||||
const unsubscribe = store.subscribe((newState, oldState) => {
|
||||
if (selector(newState) !== selector(oldState)) {
|
||||
listener(newState, oldState);
|
||||
unsubscribe();
|
||||
}
|
||||
});
|
||||
return unsubscribe;
|
||||
};
|
||||
const cancel = subscriptionOne((state) => state.connected, () => {
|
||||
callback();
|
||||
});
|
||||
return cancel;
|
||||
}
|
||||
onMessage(fn, opts) {
|
||||
const ws = this.ws;
|
||||
const isJson = (opts == null ? void 0 : opts.isJson) ?? true;
|
||||
const selector = opts == null ? void 0 : opts.selector;
|
||||
const parseIfJson = (data) => {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch (e) {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
const listener = (event) => {
|
||||
const received = parseIfJson(event.data);
|
||||
if (typeof received === "string" && !isJson) {
|
||||
fn(received, event);
|
||||
} else if (typeof received === "object" && isJson) {
|
||||
fn(selector ? selector(received) : received, event);
|
||||
} else ;
|
||||
};
|
||||
ws.addEventListener("message", listener);
|
||||
return () => {
|
||||
ws.removeEventListener("message", listener);
|
||||
};
|
||||
}
|
||||
close() {
|
||||
var _a;
|
||||
const ws = this.ws;
|
||||
const store = this.store;
|
||||
(_a = ws == null ? void 0 : ws.close) == null ? void 0 : _a.call(ws);
|
||||
this.ws = null;
|
||||
store.getState().setConnected(false);
|
||||
store.getState().setStatus("disconnected");
|
||||
}
|
||||
send(data, opts) {
|
||||
const ws = this.ws;
|
||||
const isJson = (opts == null ? void 0 : opts.isJson) ?? true;
|
||||
const wrapper = opts == null ? void 0 : opts.wrapper;
|
||||
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
||||
console.error("WebSocket is not open");
|
||||
return;
|
||||
}
|
||||
if (isJson) {
|
||||
ws.send(JSON.stringify(wrapper ? wrapper(data) : data));
|
||||
} else {
|
||||
ws.send(data);
|
||||
}
|
||||
}
|
||||
getOpen() {
|
||||
if (!this.ws) {
|
||||
return false;
|
||||
}
|
||||
return this.ws.readyState === WebSocket.OPEN;
|
||||
}
|
||||
};
|
||||
var setBaseResponse = (res) => {
|
||||
res.success = res.code === 200;
|
||||
res.showError = (fn) => {
|
||||
if (!res.success && !res.noMsg) {
|
||||
fn == null ? void 0 : fn();
|
||||
}
|
||||
};
|
||||
};
|
||||
var Query = class {
|
||||
constructor(opts) {
|
||||
__publicField(this, "adapter");
|
||||
__publicField(this, "url");
|
||||
__publicField(this, "beforeRequest");
|
||||
__publicField(this, "afterResponse");
|
||||
__publicField(this, "headers");
|
||||
__publicField(this, "timeout");
|
||||
this.adapter = (opts == null ? void 0 : opts.adapter) || adapter;
|
||||
this.url = (opts == null ? void 0 : opts.url) || "/api/router";
|
||||
this.headers = (opts == null ? void 0 : opts.headers) || {
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
this.timeout = (opts == null ? void 0 : opts.timeout) || 6e4 * 3;
|
||||
}
|
||||
/**
|
||||
* 发送 get 请求,转到 post 请求
|
||||
* T是请求类型自定义
|
||||
* S是返回类型自定义
|
||||
* @param params 请求参数
|
||||
* @param options 请求配置
|
||||
* @returns 请求结果
|
||||
*/
|
||||
async get(params, options) {
|
||||
return this.post(params, options);
|
||||
}
|
||||
/**
|
||||
* 发送 post 请求
|
||||
* T是请求类型自定义
|
||||
* S是返回类型自定义
|
||||
* @param body 请求体
|
||||
* @param options 请求配置
|
||||
* @returns 请求结果
|
||||
*/
|
||||
async post(body, options) {
|
||||
const url = (options == null ? void 0 : options.url) || this.url;
|
||||
const headers = { ...this.headers, ...options == null ? void 0 : options.headers };
|
||||
const adapter2 = (options == null ? void 0 : options.adapter) || this.adapter;
|
||||
const beforeRequest = (options == null ? void 0 : options.beforeRequest) || this.beforeRequest;
|
||||
const afterResponse = (options == null ? void 0 : options.afterResponse) || this.afterResponse;
|
||||
const timeout = (options == null ? void 0 : options.timeout) || this.timeout;
|
||||
const req = {
|
||||
url,
|
||||
headers,
|
||||
body,
|
||||
timeout
|
||||
};
|
||||
try {
|
||||
if (beforeRequest) {
|
||||
await beforeRequest(req);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("request beforeFn error", e, req);
|
||||
return {
|
||||
code: 500,
|
||||
success: false,
|
||||
message: "api request beforeFn error",
|
||||
showError: () => {
|
||||
}
|
||||
};
|
||||
}
|
||||
return adapter2(req).then(async (res) => {
|
||||
try {
|
||||
setBaseResponse(res);
|
||||
if (afterResponse) {
|
||||
return await afterResponse(res, {
|
||||
req,
|
||||
res,
|
||||
fetch: adapter2
|
||||
});
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
console.error("request error", e, req);
|
||||
return {
|
||||
code: 500,
|
||||
success: false,
|
||||
message: "api request afterFn error",
|
||||
showError: () => {
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 请求前处理,设置请求前处理函数
|
||||
* @param fn 处理函数
|
||||
*/
|
||||
before(fn) {
|
||||
this.beforeRequest = fn;
|
||||
}
|
||||
/**
|
||||
* 请求后处理,设置请求后处理函数
|
||||
* @param fn 处理函数
|
||||
*/
|
||||
after(fn) {
|
||||
this.afterResponse = fn;
|
||||
}
|
||||
};
|
||||
var QueryClient = class extends Query {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
__publicField(this, "tokenName");
|
||||
__publicField(this, "storage");
|
||||
__publicField(this, "token");
|
||||
// 默认不使用ws
|
||||
__publicField(this, "qws");
|
||||
this.tokenName = (opts == null ? void 0 : opts.tokenName) || "token";
|
||||
this.storage = (opts == null ? void 0 : opts.storage) || localStorage;
|
||||
this.beforeRequest = async (opts2) => {
|
||||
const token = this.token || this.getToken();
|
||||
if (token) {
|
||||
opts2.headers = {
|
||||
...opts2.headers,
|
||||
Authorization: `Bearer ${token}`
|
||||
};
|
||||
}
|
||||
return opts2;
|
||||
};
|
||||
if (opts == null ? void 0 : opts.io) {
|
||||
this.createWs();
|
||||
}
|
||||
}
|
||||
createWs(opts) {
|
||||
this.qws = new QueryWs({ url: this.url, ...opts });
|
||||
}
|
||||
getToken() {
|
||||
return this.storage.getItem(this.tokenName);
|
||||
}
|
||||
saveToken(token) {
|
||||
this.storage.setItem(this.tokenName, token);
|
||||
}
|
||||
removeToken() {
|
||||
this.storage.removeItem(this.tokenName);
|
||||
}
|
||||
};
|
||||
export {
|
||||
Query,
|
||||
QueryClient,
|
||||
QueryWs,
|
||||
adapter
|
||||
};
|
||||
//# sourceMappingURL=@kevisual_query.js.map
|
7
node_modules/.vite/deps/@kevisual_query.js.map
generated
vendored
Normal file
7
node_modules/.vite/deps/@kevisual_query.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
153
node_modules/.vite/deps/@kevisual_query_query.js
generated
vendored
Normal file
153
node_modules/.vite/deps/@kevisual_query_query.js
generated
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
import {
|
||||
__publicField
|
||||
} from "./chunk-V6TY7KAL.js";
|
||||
|
||||
// ../../node_modules/.pnpm/@kevisual+query@0.0.12_ws@8.18.1/node_modules/@kevisual/query/dist/query.js
|
||||
var adapter = async (opts, overloadOpts) => {
|
||||
const controller = new AbortController();
|
||||
const signal = controller.signal;
|
||||
const timeout = opts.timeout || 6e4 * 3;
|
||||
const timer = setTimeout(() => {
|
||||
controller.abort();
|
||||
}, timeout);
|
||||
return fetch(opts.url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...opts.headers
|
||||
},
|
||||
body: JSON.stringify(opts.body),
|
||||
signal,
|
||||
...overloadOpts
|
||||
}).then((response) => {
|
||||
const contentType = response.headers.get("Content-Type");
|
||||
if (contentType && contentType.includes("application/json")) {
|
||||
return response.json();
|
||||
} else {
|
||||
return response.text();
|
||||
}
|
||||
}).catch((err) => {
|
||||
if (err.name === "AbortError") {
|
||||
console.log("Request timed out and was aborted");
|
||||
}
|
||||
console.error(err);
|
||||
return {
|
||||
code: 500
|
||||
};
|
||||
}).finally(() => {
|
||||
clearTimeout(timer);
|
||||
});
|
||||
};
|
||||
var setBaseResponse = (res) => {
|
||||
res.success = res.code === 200;
|
||||
res.showError = (fn) => {
|
||||
if (!res.success && !res.noMsg) {
|
||||
fn == null ? void 0 : fn();
|
||||
}
|
||||
};
|
||||
};
|
||||
var Query = class {
|
||||
constructor(opts) {
|
||||
__publicField(this, "adapter");
|
||||
__publicField(this, "url");
|
||||
__publicField(this, "beforeRequest");
|
||||
__publicField(this, "afterResponse");
|
||||
__publicField(this, "headers");
|
||||
__publicField(this, "timeout");
|
||||
this.adapter = (opts == null ? void 0 : opts.adapter) || adapter;
|
||||
this.url = (opts == null ? void 0 : opts.url) || "/api/router";
|
||||
this.headers = (opts == null ? void 0 : opts.headers) || {
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
this.timeout = (opts == null ? void 0 : opts.timeout) || 6e4 * 3;
|
||||
}
|
||||
/**
|
||||
* 发送 get 请求,转到 post 请求
|
||||
* T是请求类型自定义
|
||||
* S是返回类型自定义
|
||||
* @param params 请求参数
|
||||
* @param options 请求配置
|
||||
* @returns 请求结果
|
||||
*/
|
||||
async get(params, options) {
|
||||
return this.post(params, options);
|
||||
}
|
||||
/**
|
||||
* 发送 post 请求
|
||||
* T是请求类型自定义
|
||||
* S是返回类型自定义
|
||||
* @param body 请求体
|
||||
* @param options 请求配置
|
||||
* @returns 请求结果
|
||||
*/
|
||||
async post(body, options) {
|
||||
const url = (options == null ? void 0 : options.url) || this.url;
|
||||
const headers = { ...this.headers, ...options == null ? void 0 : options.headers };
|
||||
const adapter2 = (options == null ? void 0 : options.adapter) || this.adapter;
|
||||
const beforeRequest = (options == null ? void 0 : options.beforeRequest) || this.beforeRequest;
|
||||
const afterResponse = (options == null ? void 0 : options.afterResponse) || this.afterResponse;
|
||||
const timeout = (options == null ? void 0 : options.timeout) || this.timeout;
|
||||
const req = {
|
||||
url,
|
||||
headers,
|
||||
body,
|
||||
timeout
|
||||
};
|
||||
try {
|
||||
if (beforeRequest) {
|
||||
await beforeRequest(req);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("request beforeFn error", e, req);
|
||||
return {
|
||||
code: 500,
|
||||
success: false,
|
||||
message: "api request beforeFn error",
|
||||
showError: () => {
|
||||
}
|
||||
};
|
||||
}
|
||||
return adapter2(req).then(async (res) => {
|
||||
try {
|
||||
setBaseResponse(res);
|
||||
if (afterResponse) {
|
||||
return await afterResponse(res, {
|
||||
req,
|
||||
res,
|
||||
fetch: adapter2
|
||||
});
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
console.error("request error", e, req);
|
||||
return {
|
||||
code: 500,
|
||||
success: false,
|
||||
message: "api request afterFn error",
|
||||
showError: () => {
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 请求前处理,设置请求前处理函数
|
||||
* @param fn 处理函数
|
||||
*/
|
||||
before(fn) {
|
||||
this.beforeRequest = fn;
|
||||
}
|
||||
/**
|
||||
* 请求后处理,设置请求后处理函数
|
||||
* @param fn 处理函数
|
||||
*/
|
||||
after(fn) {
|
||||
this.afterResponse = fn;
|
||||
}
|
||||
};
|
||||
export {
|
||||
Query,
|
||||
adapter,
|
||||
setBaseResponse
|
||||
};
|
||||
//# sourceMappingURL=@kevisual_query_query.js.map
|
7
node_modules/.vite/deps/@kevisual_query_query.js.map
generated
vendored
Normal file
7
node_modules/.vite/deps/@kevisual_query_query.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
31
node_modules/.vite/deps/_metadata.json
generated
vendored
Normal file
31
node_modules/.vite/deps/_metadata.json
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"hash": "7676c9c1",
|
||||
"configHash": "073ff67a",
|
||||
"lockfileHash": "7b5b51fa",
|
||||
"browserHash": "6d161b56",
|
||||
"optimized": {
|
||||
"@kevisual/cache": {
|
||||
"src": "../../../../../node_modules/.pnpm/@kevisual+cache@0.0.1_rollup@4.36.0_tslib@2.8.1_typescript@5.8.2/node_modules/@kevisual/cache/dist/cache.js",
|
||||
"file": "@kevisual_cache.js",
|
||||
"fileHash": "c8f5b09b",
|
||||
"needsInterop": false
|
||||
},
|
||||
"@kevisual/query": {
|
||||
"src": "../../../../../node_modules/.pnpm/@kevisual+query@0.0.12_ws@8.18.1/node_modules/@kevisual/query/dist/query-browser.js",
|
||||
"file": "@kevisual_query.js",
|
||||
"fileHash": "54f36b5c",
|
||||
"needsInterop": false
|
||||
},
|
||||
"@kevisual/query/query": {
|
||||
"src": "../../../../../node_modules/.pnpm/@kevisual+query@0.0.12_ws@8.18.1/node_modules/@kevisual/query/dist/query.js",
|
||||
"file": "@kevisual_query_query.js",
|
||||
"fileHash": "d243262a",
|
||||
"needsInterop": false
|
||||
}
|
||||
},
|
||||
"chunks": {
|
||||
"chunk-V6TY7KAL": {
|
||||
"file": "chunk-V6TY7KAL.js"
|
||||
}
|
||||
}
|
||||
}
|
8
node_modules/.vite/deps/chunk-V6TY7KAL.js
generated
vendored
Normal file
8
node_modules/.vite/deps/chunk-V6TY7KAL.js
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
||||
|
||||
export {
|
||||
__publicField
|
||||
};
|
||||
//# sourceMappingURL=chunk-V6TY7KAL.js.map
|
7
node_modules/.vite/deps/chunk-V6TY7KAL.js.map
generated
vendored
Normal file
7
node_modules/.vite/deps/chunk-V6TY7KAL.js.map
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": [],
|
||||
"sourcesContent": [],
|
||||
"mappings": "",
|
||||
"names": []
|
||||
}
|
3
node_modules/.vite/deps/package.json
generated
vendored
Normal file
3
node_modules/.vite/deps/package.json
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
1
node_modules/@kevisual/cache
generated
vendored
Symbolic link
1
node_modules/@kevisual/cache
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../node_modules/.pnpm/@kevisual+cache@0.0.1_rollup@4.36.0_tslib@2.8.1_typescript@5.8.2/node_modules/@kevisual/cache
|
1
node_modules/@kevisual/query
generated
vendored
Symbolic link
1
node_modules/@kevisual/query
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../node_modules/.pnpm/@kevisual+query@0.0.12_ws@8.18.1/node_modules/@kevisual/query
|
1
node_modules/@types/node
generated
vendored
Symbolic link
1
node_modules/@types/node
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../node_modules/.pnpm/@types+node@22.13.11/node_modules/@types/node
|
1
node_modules/tsup
generated
vendored
Symbolic link
1
node_modules/tsup
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.2_yaml@2.5.1/node_modules/tsup
|
31
package.json
Normal file
31
package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@kevisual/query-login",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "dist/query-login.js",
|
||||
"types": "dist/query-login.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"watch": "tsup --watch"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "abearxiong <xiongxiao@xiongxiao.me>",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@kevisual/query": "^0.0.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.13.11",
|
||||
"tsup": "^8.4.0"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist/query-login.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kevisual/cache": "^0.0.1"
|
||||
}
|
||||
}
|
159
src/login-cache.ts
Normal file
159
src/login-cache.ts
Normal file
@ -0,0 +1,159 @@
|
||||
import { MyCache } from '@kevisual/cache';
|
||||
|
||||
export type CacheLoginUser = {
|
||||
user?: any;
|
||||
id?: string;
|
||||
accessToken?: string;
|
||||
refreshToken?: string;
|
||||
};
|
||||
type CacheLogin = {
|
||||
loginUsers: CacheLoginUser[];
|
||||
} & CacheLoginUser;
|
||||
|
||||
export 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>;
|
||||
}
|
||||
export class LoginCacheStore implements CacheStore<MyCache<any>> {
|
||||
cache: MyCache<any>;
|
||||
name: string;
|
||||
cacheData: CacheLogin;
|
||||
constructor(name: string) {
|
||||
this.cache = new MyCache(name);
|
||||
this.cacheData = {
|
||||
loginUsers: [],
|
||||
user: undefined,
|
||||
id: undefined,
|
||||
accessToken: undefined,
|
||||
refreshToken: undefined,
|
||||
};
|
||||
this.name = name;
|
||||
}
|
||||
/**
|
||||
* 设置缓存
|
||||
* @param key
|
||||
* @param value
|
||||
* @returns
|
||||
*/
|
||||
async set(key: string, value: CacheLogin) {
|
||||
await this.cache.set(key, value);
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* 删除缓存
|
||||
*/
|
||||
async del() {
|
||||
await this.cache.del();
|
||||
}
|
||||
get(key: string): Promise<CacheLogin> {
|
||||
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: CacheLoginUser) {
|
||||
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(): 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 || '');
|
||||
}
|
||||
|
||||
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 = undefined;
|
||||
this.cacheData.id = undefined;
|
||||
this.cacheData.accessToken = undefined;
|
||||
this.cacheData.refreshToken = undefined;
|
||||
await this.set(this.name, this.cacheData);
|
||||
}
|
||||
async clearAll() {
|
||||
this.cacheData.loginUsers = [];
|
||||
this.cacheData.user = undefined;
|
||||
this.cacheData.id = undefined;
|
||||
this.cacheData.accessToken = undefined;
|
||||
this.cacheData.refreshToken = undefined;
|
||||
await this.set(this.name, this.cacheData);
|
||||
}
|
||||
}
|
236
src/query-login.ts
Normal file
236
src/query-login.ts
Normal file
@ -0,0 +1,236 @@
|
||||
import { Query } from '@kevisual/query';
|
||||
import type { Result, DataOpts } from '@kevisual/query/query';
|
||||
import { setBaseResponse } from '@kevisual/query/query';
|
||||
import { LoginCacheStore, CacheStore } from './login-cache.ts';
|
||||
|
||||
type QueryLoginOpts = {
|
||||
query?: Query;
|
||||
isBrowser?: boolean;
|
||||
onLoad?: () => void;
|
||||
storage?: Storage;
|
||||
};
|
||||
export type QueryLoginData = {
|
||||
username?: string;
|
||||
password: string;
|
||||
email?: string;
|
||||
};
|
||||
export type QueryLoginResult = {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
};
|
||||
|
||||
export class QueryLogin {
|
||||
query: Query;
|
||||
cache: CacheStore;
|
||||
isBrowser: boolean;
|
||||
load?: boolean;
|
||||
storage: Storage;
|
||||
onLoad?: () => void;
|
||||
|
||||
constructor(opts?: QueryLoginOpts) {
|
||||
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: Query) {
|
||||
this.query = query;
|
||||
}
|
||||
async init() {
|
||||
await this.cache.init();
|
||||
this.load = true;
|
||||
this.onLoad?.();
|
||||
}
|
||||
async post<T = any>(data: any, opts?: DataOpts) {
|
||||
return this.query.post<T>({ path: 'user', ...data }, opts);
|
||||
}
|
||||
/**
|
||||
* 登录,
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
async login(data: QueryLoginData) {
|
||||
const res = await this.post<QueryLoginResult>({ 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 }: { accessToken?: string; refreshToken?: string; check401?: boolean }) {
|
||||
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('登录失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async queryRefreshToken(refreshToken?: string) {
|
||||
const _refreshToken = refreshToken || this.cache.getRefreshToken();
|
||||
let data = { refreshToken: _refreshToken };
|
||||
if (!_refreshToken) {
|
||||
await this.cache.clearCurrentUser();
|
||||
return {
|
||||
code: 401,
|
||||
message: '请先登录',
|
||||
data: {} as any,
|
||||
};
|
||||
}
|
||||
return this.post(
|
||||
{ key: 'refreshToken', data },
|
||||
{
|
||||
afterResponse: async (response, ctx) => {
|
||||
setBaseResponse(response);
|
||||
return response as any;
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 检查401错误,并刷新token, 如果refreshToken存在,则刷新token, 否则返回401
|
||||
* @param response
|
||||
* @param ctx
|
||||
* @param refetch
|
||||
* @returns
|
||||
*/
|
||||
async afterCheck401ToRefreshToken(response: Result, ctx?: { req?: any; res?: any; fetch?: any }, refetch?: boolean) {
|
||||
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 res = await ctx.fetch(url, {
|
||||
method: 'POST',
|
||||
body: body,
|
||||
headers: { ...headers, Authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
setBaseResponse(res);
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
that.storage.removeItem('token');
|
||||
await that.cache.clearCurrentUser();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return response as any;
|
||||
}
|
||||
/**
|
||||
* 获取用户信息
|
||||
* @param token
|
||||
* @returns
|
||||
*/
|
||||
async getMe(token?: string, check401: boolean = 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 as any;
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 请求更新,切换用户, 使用switchUser
|
||||
* @param username
|
||||
* @returns
|
||||
*/
|
||||
private async postSwitchUser(username: string) {
|
||||
return this.post({ key: 'switchCheck', data: { username } });
|
||||
}
|
||||
/**
|
||||
* 切换用户
|
||||
* @param username
|
||||
* @returns
|
||||
*/
|
||||
async switchUser(username: string) {
|
||||
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: '切换用户成功',
|
||||
};
|
||||
}
|
||||
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<Result>({ key: 'logout' });
|
||||
}
|
||||
async hasUser(username: string) {
|
||||
const that = this;
|
||||
return this.post<Result>(
|
||||
{
|
||||
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 as any;
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
22
src/test/login.ts
Normal file
22
src/test/login.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { QueryLogin } from '../query-login.ts';
|
||||
import { Query } from '@kevisual/query';
|
||||
const query = new Query({
|
||||
url: 'https://kevisual.silkyai.cn/api/router',
|
||||
});
|
||||
query.before(async (options) => {
|
||||
console.log('before', options);
|
||||
const token = localStorage.getItem('token');
|
||||
if (token) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
}
|
||||
return options;
|
||||
});
|
||||
const queryLogin = new QueryLogin({
|
||||
query,
|
||||
isBrowser: true,
|
||||
});
|
||||
// @ts-ignore
|
||||
window.queryLogin = queryLogin;
|
28
tsconfig.json
Normal file
28
tsconfig.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "nodenext",
|
||||
"target": "esnext",
|
||||
"noImplicitAny": false,
|
||||
"outDir": "./dist",
|
||||
"sourceMap": false,
|
||||
"allowJs": true,
|
||||
"newLine": "LF",
|
||||
"baseUrl": "./",
|
||||
"typeRoots": [
|
||||
"node_modules/@types",
|
||||
],
|
||||
"declaration": true,
|
||||
"noEmit": false,
|
||||
"allowImportingTsExtensions": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"moduleResolution": "NodeNext",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"esModuleInterop": true,
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
13
tsup.config.ts
Normal file
13
tsup.config.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/query-login.ts'],
|
||||
|
||||
splitting: false,
|
||||
sourcemap: false,
|
||||
clean: true,
|
||||
format: 'esm',
|
||||
dts: true,
|
||||
outDir: 'dist',
|
||||
tsconfig: 'tsconfig.json',
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user