mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-22 22:36:06 +08:00
修改服务启动逻辑
This commit is contained in:
parent
729b405b0f
commit
d871585eee
16
.env.example
16
.env.example
|
@ -1,14 +1,12 @@
|
||||||
UPDATE_PORT=5300
|
GRPC_PORT=5500
|
||||||
PUBLIC_PORT=5400
|
|
||||||
CRON_PORT=5500
|
|
||||||
BACK_PORT=5600
|
BACK_PORT=5600
|
||||||
PORT=5700
|
PORT=5700
|
||||||
|
|
||||||
LOG_LEVEL='debug'
|
LOG_LEVEL='info'
|
||||||
|
|
||||||
SECRET='whyour'
|
JWT_SECRET=
|
||||||
|
JWT_EXPIRES_IN=
|
||||||
|
|
||||||
QINIU_AK=''
|
QINIU_AK=
|
||||||
QINIU_SK=''
|
QINIU_SK=
|
||||||
QINIU_SCOPE=''
|
QINIU_SCOPE=
|
||||||
TEMP=''
|
|
||||||
|
|
10
.umirc.ts
10
.umirc.ts
|
@ -16,16 +16,6 @@ export default defineConfig({
|
||||||
favicons: [`https://qn.whyour.cn/favicon.svg`],
|
favicons: [`https://qn.whyour.cn/favicon.svg`],
|
||||||
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
|
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
|
||||||
proxy: {
|
proxy: {
|
||||||
[`${baseUrl}api/update`]: {
|
|
||||||
target: 'http://127.0.0.1:5300/',
|
|
||||||
changeOrigin: true,
|
|
||||||
pathRewrite: { [`^${baseUrl}api/update`]: '/api' },
|
|
||||||
},
|
|
||||||
[`${baseUrl}api/public`]: {
|
|
||||||
target: 'http://127.0.0.1:5400/',
|
|
||||||
changeOrigin: true,
|
|
||||||
pathRewrite: { [`^${baseUrl}api/public`]: '/api' },
|
|
||||||
},
|
|
||||||
[`${baseUrl}api`]: {
|
[`${baseUrl}api`]: {
|
||||||
target: 'http://127.0.0.1:5600/',
|
target: 'http://127.0.0.1:5600/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
|
9
back.d.ts
vendored
9
back.d.ts
vendored
|
@ -1,9 +0,0 @@
|
||||||
import 'express';
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
namespace Express {
|
|
||||||
interface Request {
|
|
||||||
platform: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
27
back/api/health.ts
Normal file
27
back/api/health.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { Router } from 'express';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
import { HealthService } from '../services/health';
|
||||||
|
import Container from 'typedi';
|
||||||
|
const route = Router();
|
||||||
|
|
||||||
|
export default (app: Router) => {
|
||||||
|
app.use('/', route);
|
||||||
|
|
||||||
|
route.get('/health', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const healthService = Container.get(HealthService);
|
||||||
|
const health = await healthService.check();
|
||||||
|
res.status(200).send({
|
||||||
|
code: 200,
|
||||||
|
data: health,
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
Logger.error('Health check failed:', err);
|
||||||
|
res.status(500).send({
|
||||||
|
code: 500,
|
||||||
|
message: 'Health check failed',
|
||||||
|
error: err.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
|
@ -9,6 +9,8 @@ import open from './open';
|
||||||
import dependence from './dependence';
|
import dependence from './dependence';
|
||||||
import system from './system';
|
import system from './system';
|
||||||
import subscription from './subscription';
|
import subscription from './subscription';
|
||||||
|
import update from './update';
|
||||||
|
import health from './health';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const app = Router();
|
const app = Router();
|
||||||
|
@ -22,6 +24,8 @@ export default () => {
|
||||||
dependence(app);
|
dependence(app);
|
||||||
system(app);
|
system(app);
|
||||||
subscription(app);
|
subscription(app);
|
||||||
|
update(app);
|
||||||
|
health(app);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
};
|
};
|
||||||
|
|
51
back/api/update.ts
Normal file
51
back/api/update.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import { NextFunction, Request, Response, Router } from 'express';
|
||||||
|
import Container from 'typedi';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
import SystemService from '../services/system';
|
||||||
|
const route = Router();
|
||||||
|
|
||||||
|
export default (app: Router) => {
|
||||||
|
app.use('/update', route);
|
||||||
|
|
||||||
|
route.put(
|
||||||
|
'/reload',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const systemService = Container.get(SystemService);
|
||||||
|
const result = await systemService.reloadSystem();
|
||||||
|
res.send(result);
|
||||||
|
} catch (e) {
|
||||||
|
Logger.error('🔥 error: %o', e);
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
route.put(
|
||||||
|
'/system',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const systemService = Container.get(SystemService);
|
||||||
|
const result = await systemService.reloadSystem('system');
|
||||||
|
res.send(result);
|
||||||
|
} catch (e) {
|
||||||
|
Logger.error('🔥 error: %o', e);
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
route.put(
|
||||||
|
'/data',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const systemService = Container.get(SystemService);
|
||||||
|
const result = await systemService.reloadSystem('data');
|
||||||
|
res.send(result);
|
||||||
|
} catch (e) {
|
||||||
|
Logger.error('🔥 error: %o', e);
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
100
back/app.ts
100
back/app.ts
|
@ -1,30 +1,92 @@
|
||||||
import 'reflect-metadata'; // We need this in order to use @Decorators
|
import 'reflect-metadata';
|
||||||
import config from './config';
|
import compression from 'compression';
|
||||||
|
import cors from 'cors';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
import helmet from 'helmet';
|
||||||
|
import { Container } from 'typedi';
|
||||||
|
import config from './config';
|
||||||
import Logger from './loaders/logger';
|
import Logger from './loaders/logger';
|
||||||
|
import { monitoringMiddleware } from './middlewares/monitoring';
|
||||||
|
import { GrpcServerService } from './services/grpc';
|
||||||
|
import { HttpServerService } from './services/http';
|
||||||
|
import { metricsService } from './services/metrics';
|
||||||
|
|
||||||
async function startServer() {
|
class Application {
|
||||||
const app = express();
|
private app: express.Application;
|
||||||
|
private server: any;
|
||||||
|
private httpServerService: HttpServerService;
|
||||||
|
private grpcServerService: GrpcServerService;
|
||||||
|
private isShuttingDown = false;
|
||||||
|
|
||||||
await require('./loaders/db').default();
|
constructor() {
|
||||||
|
this.app = express();
|
||||||
|
this.httpServerService = Container.get(HttpServerService);
|
||||||
|
this.grpcServerService = Container.get(GrpcServerService);
|
||||||
|
}
|
||||||
|
|
||||||
await require('./loaders/initFile').default();
|
async start() {
|
||||||
|
try {
|
||||||
|
await this.initializeDatabase();
|
||||||
|
this.setupMiddlewares();
|
||||||
|
await this.initializeServices();
|
||||||
|
this.setupGracefulShutdown();
|
||||||
|
|
||||||
await require('./loaders/app').default({ expressApp: app });
|
|
||||||
|
|
||||||
const server = app
|
|
||||||
.listen(config.port, '0.0.0.0', () => {
|
|
||||||
Logger.debug(`✌️ 后端服务启动成功!`);
|
|
||||||
console.debug(`✌️ 后端服务启动成功!`);
|
|
||||||
process.send?.('ready');
|
process.send?.('ready');
|
||||||
})
|
} catch (error) {
|
||||||
.on('error', (err) => {
|
Logger.error('Failed to start application:', error);
|
||||||
Logger.error(err);
|
|
||||||
console.error(err);
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await require('./loaders/server').default({ server });
|
private async initializeDatabase() {
|
||||||
|
await require('./loaders/db').default();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupMiddlewares() {
|
||||||
|
this.app.use(helmet());
|
||||||
|
this.app.use(cors(config.cors));
|
||||||
|
this.app.use(compression());
|
||||||
|
this.app.use(monitoringMiddleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async initializeServices() {
|
||||||
|
await this.grpcServerService.initialize();
|
||||||
|
|
||||||
|
await require('./loaders/app').default({ app: this.app });
|
||||||
|
|
||||||
|
this.server = await this.httpServerService.initialize(
|
||||||
|
this.app,
|
||||||
|
config.port,
|
||||||
|
);
|
||||||
|
|
||||||
|
await require('./loaders/server').default({ server: this.server });
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupGracefulShutdown() {
|
||||||
|
const shutdown = async () => {
|
||||||
|
if (this.isShuttingDown) return;
|
||||||
|
this.isShuttingDown = true;
|
||||||
|
|
||||||
|
Logger.info('Shutting down services...');
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
this.grpcServerService.shutdown(),
|
||||||
|
this.httpServerService.shutdown(),
|
||||||
|
]);
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('Error during shutdown:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
process.on('SIGTERM', shutdown);
|
||||||
|
process.on('SIGINT', shutdown);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startServer();
|
const app = new Application();
|
||||||
|
app.start().catch((error) => {
|
||||||
|
Logger.error('Application failed to start:', error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
|
@ -2,12 +2,60 @@ import dotenv from 'dotenv';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { createRandomString } from './share';
|
import { createRandomString } from './share';
|
||||||
|
|
||||||
|
dotenv.config({
|
||||||
|
path: path.join(__dirname, '../../.env'),
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Config {
|
||||||
|
port: number;
|
||||||
|
grpcPort: number;
|
||||||
|
nodeEnv: string;
|
||||||
|
isDevelopment: boolean;
|
||||||
|
isProduction: boolean;
|
||||||
|
jwt: {
|
||||||
|
secret: string;
|
||||||
|
expiresIn?: string;
|
||||||
|
};
|
||||||
|
cors: {
|
||||||
|
origin: string[];
|
||||||
|
methods: string[];
|
||||||
|
};
|
||||||
|
logs: {
|
||||||
|
level: string;
|
||||||
|
};
|
||||||
|
api: {
|
||||||
|
prefix: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
port: parseInt(process.env.BACK_PORT || '5600', 10),
|
||||||
|
grpcPort: parseInt(process.env.GRPC_PORT || '5500', 10),
|
||||||
|
nodeEnv: process.env.NODE_ENV || 'development',
|
||||||
|
isDevelopment: process.env.NODE_ENV === 'development',
|
||||||
|
isProduction: process.env.NODE_ENV === 'production',
|
||||||
|
logs: {
|
||||||
|
level: process.env.LOG_LEVEL || 'silly',
|
||||||
|
},
|
||||||
|
api: {
|
||||||
|
prefix: '/api',
|
||||||
|
},
|
||||||
|
jwt: {
|
||||||
|
secret: process.env.JWT_SECRET || createRandomString(16, 32),
|
||||||
|
expiresIn: process.env.JWT_EXPIRES_IN,
|
||||||
|
},
|
||||||
|
cors: {
|
||||||
|
origin: process.env.CORS_ORIGIN
|
||||||
|
? process.env.CORS_ORIGIN.split(',')
|
||||||
|
: ['*'],
|
||||||
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
if (!process.env.QL_DIR) {
|
if (!process.env.QL_DIR) {
|
||||||
// 声明QL_DIR环境变量
|
|
||||||
let qlHomePath = path.join(__dirname, '../../');
|
let qlHomePath = path.join(__dirname, '../../');
|
||||||
// 生产环境
|
|
||||||
if (qlHomePath.endsWith('/static/')) {
|
if (qlHomePath.endsWith('/static/')) {
|
||||||
qlHomePath = path.join(qlHomePath, '../');
|
qlHomePath = path.join(qlHomePath, '../');
|
||||||
}
|
}
|
||||||
|
@ -65,17 +113,8 @@ if (envFound.error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
port: parseInt(process.env.BACK_PORT as string, 10),
|
...config,
|
||||||
cronPort: parseInt(process.env.CRON_PORT as string, 10),
|
jwt: config.jwt,
|
||||||
publicPort: parseInt(process.env.PUBLIC_PORT as string, 10),
|
|
||||||
updatePort: parseInt(process.env.UPDATE_PORT as string, 10),
|
|
||||||
secret: process.env.SECRET || createRandomString(16, 32),
|
|
||||||
logs: {
|
|
||||||
level: process.env.LOG_LEVEL || 'silly',
|
|
||||||
},
|
|
||||||
api: {
|
|
||||||
prefix: '/api',
|
|
||||||
},
|
|
||||||
rootPath,
|
rootPath,
|
||||||
tmpPath,
|
tmpPath,
|
||||||
dataPath,
|
dataPath,
|
||||||
|
@ -118,6 +157,7 @@ export default {
|
||||||
bakPath,
|
bakPath,
|
||||||
apiWhiteList: [
|
apiWhiteList: [
|
||||||
'/api/user/login',
|
'/api/user/login',
|
||||||
|
'/api/health',
|
||||||
'/open/auth/token',
|
'/open/auth/token',
|
||||||
'/api/user/two-factor/login',
|
'/api/user/two-factor/login',
|
||||||
'/api/system',
|
'/api/system',
|
||||||
|
|
|
@ -4,7 +4,7 @@ import got from 'got';
|
||||||
import iconv from 'iconv-lite';
|
import iconv from 'iconv-lite';
|
||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
import psTreeFun from 'pstree.remy';
|
import psTreeFun from 'ps-tree';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import { load } from 'js-yaml';
|
import { load } from 'js-yaml';
|
||||||
import config from './index';
|
import config from './index';
|
||||||
|
@ -462,11 +462,11 @@ export function parseBody(
|
||||||
|
|
||||||
export function psTree(pid: number): Promise<number[]> {
|
export function psTree(pid: number): Promise<number[]> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
psTreeFun(pid, (err: any, pids: number[]) => {
|
psTreeFun(pid, (err: any, children) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
resolve(pids.filter((x) => !isNaN(x)));
|
resolve(children.map((x) => Number(x.PID)).filter((x) => !isNaN(x)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
7
back/index.d.ts
vendored
7
back/index.d.ts
vendored
|
@ -1,7 +0,0 @@
|
||||||
declare namespace Express {
|
|
||||||
interface Request {
|
|
||||||
platform: 'desktop' | 'mobile';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'pstree.remy';
|
|
|
@ -5,25 +5,24 @@ import initData from './initData';
|
||||||
import { Application } from 'express';
|
import { Application } from 'express';
|
||||||
import linkDeps from './deps';
|
import linkDeps from './deps';
|
||||||
import initTask from './initTask';
|
import initTask from './initTask';
|
||||||
|
import initFile from './initFile';
|
||||||
|
|
||||||
export default async ({ expressApp }: { expressApp: Application }) => {
|
export default async ({ app }: { app: Application }) => {
|
||||||
depInjectorLoader();
|
depInjectorLoader();
|
||||||
Logger.info('✌️ Dependency loaded');
|
Logger.info('✌️ Dependency loaded');
|
||||||
console.log('✌️ Dependency loaded');
|
|
||||||
|
|
||||||
await initData();
|
|
||||||
Logger.info('✌️ Init data loaded');
|
|
||||||
console.log('✌️ Init data loaded');
|
|
||||||
|
|
||||||
await linkDeps();
|
await linkDeps();
|
||||||
Logger.info('✌️ Link deps loaded');
|
Logger.info('✌️ Link deps loaded');
|
||||||
console.log('✌️ Link deps loaded');
|
|
||||||
|
initFile();
|
||||||
|
Logger.info('✌️ Init file loaded');
|
||||||
|
|
||||||
|
await initData();
|
||||||
|
Logger.info('✌️ Init data loaded');
|
||||||
|
|
||||||
initTask();
|
initTask();
|
||||||
Logger.info('✌️ Init task loaded');
|
Logger.info('✌️ Init task loaded');
|
||||||
console.log('✌️ Init task loaded');
|
|
||||||
|
|
||||||
expressLoader({ app: expressApp });
|
expressLoader({ app });
|
||||||
Logger.info('✌️ Express loaded');
|
Logger.info('✌️ Express loaded');
|
||||||
console.log('✌️ Express loaded');
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,10 +57,8 @@ export default async () => {
|
||||||
await sequelize.query('alter table Crontabs add column task_after TEXT');
|
await sequelize.query('alter table Crontabs add column task_after TEXT');
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
|
|
||||||
console.log('✌️ DB loaded');
|
|
||||||
Logger.info('✌️ DB loaded');
|
Logger.info('✌️ DB loaded');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('✌️ DB load failed');
|
Logger.error('✌️ DB load failed', error);
|
||||||
Logger.error(error);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,9 +7,7 @@ import { UnauthorizedError, expressjwt } from 'express-jwt';
|
||||||
import { getPlatform, getToken } from '../config/util';
|
import { getPlatform, getToken } from '../config/util';
|
||||||
import rewrite from 'express-urlrewrite';
|
import rewrite from 'express-urlrewrite';
|
||||||
import { errors } from 'celebrate';
|
import { errors } from 'celebrate';
|
||||||
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
||||||
import { serveEnv } from '../config/serverEnv';
|
import { serveEnv } from '../config/serverEnv';
|
||||||
import Logger from './logger';
|
|
||||||
import { IKeyvStore, shareStore } from '../shared/store';
|
import { IKeyvStore, shareStore } from '../shared/store';
|
||||||
|
|
||||||
export default ({ app }: { app: Application }) => {
|
export default ({ app }: { app: Application }) => {
|
||||||
|
@ -18,22 +16,12 @@ export default ({ app }: { app: Application }) => {
|
||||||
app.get(`${config.api.prefix}/env.js`, serveEnv);
|
app.get(`${config.api.prefix}/env.js`, serveEnv);
|
||||||
app.use(`${config.api.prefix}/static`, express.static(config.uploadPath));
|
app.use(`${config.api.prefix}/static`, express.static(config.uploadPath));
|
||||||
|
|
||||||
app.use(
|
|
||||||
'/api/public',
|
|
||||||
createProxyMiddleware({
|
|
||||||
target: `http://0.0.0.0:${config.publicPort}/api`,
|
|
||||||
changeOrigin: true,
|
|
||||||
pathRewrite: { '/api/public': '' },
|
|
||||||
logger: Logger,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
app.use(bodyParser.json({ limit: '50mb' }));
|
app.use(bodyParser.json({ limit: '50mb' }));
|
||||||
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
|
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
expressjwt({
|
expressjwt({
|
||||||
secret: config.secret,
|
secret: config.jwt.secret,
|
||||||
algorithms: ['HS384'],
|
algorithms: ['HS384'],
|
||||||
}).unless({
|
}).unless({
|
||||||
path: [...config.apiWhiteList, /^\/open\//],
|
path: [...config.apiWhiteList, /^\/open\//],
|
||||||
|
@ -50,7 +38,7 @@ export default ({ app }: { app: Application }) => {
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(async (req, res, next) => {
|
app.use(async (req: Request, res, next) => {
|
||||||
const headerToken = getToken(req);
|
const headerToken = getToken(req);
|
||||||
if (req.path.startsWith('/open/')) {
|
if (req.path.startsWith('/open/')) {
|
||||||
const apps = await shareStore.getApps();
|
const apps = await shareStore.getApps();
|
||||||
|
|
|
@ -122,5 +122,4 @@ export default async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.info('✌️ Init file down');
|
Logger.info('✌️ Init file down');
|
||||||
console.log('✌️ Init file down');
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,35 +4,60 @@ import config from '../config';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
const levelMap: Record<string, string> = {
|
const levelMap: Record<string, string> = {
|
||||||
info: '\ue6f5',
|
info: 'ℹ️', // info图标
|
||||||
warn: '\ue880',
|
warn: '⚠️', // 警告图标
|
||||||
error: '\ue602',
|
error: '❌', // 错误图标
|
||||||
debug: '\ue67f'
|
debug: '🐛', // debug调试图标
|
||||||
}
|
|
||||||
|
|
||||||
const customFormat = winston.format.combine(
|
|
||||||
winston.format.splat(),
|
|
||||||
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
|
|
||||||
winston.format.align(),
|
|
||||||
winston.format.printf((i) => `[${levelMap[i.level]}${i.level}] [${[i.timestamp]}]: ${i.message}`),
|
|
||||||
);
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
format: customFormat,
|
|
||||||
datePattern: "YYYY-MM-DD",
|
|
||||||
maxSize: "20m",
|
|
||||||
maxFiles: "7d",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const baseFormat = [
|
||||||
|
winston.format.splat(),
|
||||||
|
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
|
||||||
|
winston.format.align(),
|
||||||
|
];
|
||||||
|
|
||||||
|
const consoleFormat = winston.format.combine(
|
||||||
|
winston.format.colorize({ level: true }),
|
||||||
|
...baseFormat,
|
||||||
|
winston.format.printf((info) => {
|
||||||
|
return `[${info.level} ${info.timestamp}]:${info.message}`;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const plainFormat = winston.format.combine(
|
||||||
|
winston.format.uncolorize(),
|
||||||
|
...baseFormat,
|
||||||
|
winston.format.printf((info) => {
|
||||||
|
return `[${levelMap[info.level] || ''}${info.level} ${info.timestamp}]:${
|
||||||
|
info.message
|
||||||
|
}`;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const consoleTransport = new winston.transports.Console({
|
||||||
|
format: consoleFormat,
|
||||||
|
level: 'debug',
|
||||||
|
});
|
||||||
|
|
||||||
|
const fileTransport = new winston.transports.DailyRotateFile({
|
||||||
|
filename: path.join(config.systemLogPath, '%DATE%.log'),
|
||||||
|
datePattern: 'YYYY-MM-DD',
|
||||||
|
maxSize: '20m',
|
||||||
|
maxFiles: '7d',
|
||||||
|
format: plainFormat,
|
||||||
|
level: config.logs.level || 'info',
|
||||||
|
});
|
||||||
|
|
||||||
const LoggerInstance = winston.createLogger({
|
const LoggerInstance = winston.createLogger({
|
||||||
level: config.logs.level,
|
level: 'debug',
|
||||||
levels: winston.config.npm.levels,
|
levels: winston.config.npm.levels,
|
||||||
transports: [
|
transports: [consoleTransport, fileTransport],
|
||||||
new winston.transports.DailyRotateFile({
|
exceptionHandlers: [consoleTransport, fileTransport],
|
||||||
filename: path.join(config.systemLogPath, '%DATE%.log'),
|
rejectionHandlers: [consoleTransport, fileTransport],
|
||||||
...defaultOptions,
|
});
|
||||||
})
|
|
||||||
],
|
LoggerInstance.on('error', (error) => {
|
||||||
|
console.error('Logger error:', error);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default LoggerInstance;
|
export default LoggerInstance;
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
import bodyParser from 'body-parser';
|
|
||||||
import { errors } from 'celebrate';
|
|
||||||
import cors from 'cors';
|
|
||||||
import { Application, NextFunction, Request, Response } from 'express';
|
|
||||||
import { expressjwt } from 'express-jwt';
|
|
||||||
import Container from 'typedi';
|
|
||||||
import config from '../config';
|
|
||||||
import SystemService from '../services/system';
|
|
||||||
import Logger from './logger';
|
|
||||||
|
|
||||||
export default ({ app }: { app: Application }) => {
|
|
||||||
app.set('trust proxy', 'loopback');
|
|
||||||
app.use(cors());
|
|
||||||
|
|
||||||
app.use(bodyParser.json({ limit: '50mb' }));
|
|
||||||
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
expressjwt({
|
|
||||||
secret: config.secret,
|
|
||||||
algorithms: ['HS384'],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
app.put(
|
|
||||||
'/api/reload',
|
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
|
||||||
try {
|
|
||||||
const systemService = Container.get(SystemService);
|
|
||||||
const result = await systemService.reloadSystem();
|
|
||||||
res.send(result);
|
|
||||||
} catch (e) {
|
|
||||||
Logger.error('🔥 error: %o', e);
|
|
||||||
return next(e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
app.put(
|
|
||||||
'/api/system',
|
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
|
||||||
try {
|
|
||||||
const systemService = Container.get(SystemService);
|
|
||||||
const result = await systemService.reloadSystem('system');
|
|
||||||
res.send(result);
|
|
||||||
} catch (e) {
|
|
||||||
Logger.error('🔥 error: %o', e);
|
|
||||||
return next(e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
app.put(
|
|
||||||
'/api/data',
|
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
|
||||||
try {
|
|
||||||
const systemService = Container.get(SystemService);
|
|
||||||
const result = await systemService.reloadSystem('data');
|
|
||||||
res.send(result);
|
|
||||||
} catch (e) {
|
|
||||||
Logger.error('🔥 error: %o', e);
|
|
||||||
return next(e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
|
||||||
const err: any = new Error('Not Found');
|
|
||||||
err['status'] = 404;
|
|
||||||
next(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(errors());
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
(
|
|
||||||
err: Error & { status: number },
|
|
||||||
req: Request,
|
|
||||||
res: Response,
|
|
||||||
next: NextFunction,
|
|
||||||
) => {
|
|
||||||
if (err.name === 'UnauthorizedError') {
|
|
||||||
return res
|
|
||||||
.status(err.status)
|
|
||||||
.send({ code: 401, message: err.message })
|
|
||||||
.end();
|
|
||||||
}
|
|
||||||
return next(err);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
(
|
|
||||||
err: Error & { status: number },
|
|
||||||
req: Request,
|
|
||||||
res: Response,
|
|
||||||
next: NextFunction,
|
|
||||||
) => {
|
|
||||||
res.status(err.status || 500);
|
|
||||||
res.json({
|
|
||||||
code: err.status || 500,
|
|
||||||
message: err.message,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
};
|
|
80
back/middlewares/monitoring.ts
Normal file
80
back/middlewares/monitoring.ts
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
import { performance } from 'perf_hooks';
|
||||||
|
import { metricsService } from '../services/metrics';
|
||||||
|
|
||||||
|
interface RequestMetrics {
|
||||||
|
method: string;
|
||||||
|
path: string;
|
||||||
|
duration: number;
|
||||||
|
statusCode: number;
|
||||||
|
timestamp: number;
|
||||||
|
platform?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestMetrics: RequestMetrics[] = [];
|
||||||
|
|
||||||
|
export const monitoringMiddleware = (
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction,
|
||||||
|
) => {
|
||||||
|
const start = performance.now();
|
||||||
|
const originalEnd = res.end;
|
||||||
|
|
||||||
|
res.end = function (chunk?: any, encoding?: any, cb?: any) {
|
||||||
|
const duration = performance.now() - start;
|
||||||
|
const metric: RequestMetrics = {
|
||||||
|
method: req.method,
|
||||||
|
path: req.path,
|
||||||
|
duration,
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
platform: req.platform,
|
||||||
|
};
|
||||||
|
|
||||||
|
requestMetrics.push(metric);
|
||||||
|
metricsService.record('http_request', duration, {
|
||||||
|
method: req.method,
|
||||||
|
path: req.path,
|
||||||
|
statusCode: res.statusCode.toString(),
|
||||||
|
...(req.platform && { platform: req.platform }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (requestMetrics.length > 1000) {
|
||||||
|
requestMetrics.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duration > 1000) {
|
||||||
|
Logger.warn(
|
||||||
|
`Slow request detected: ${req.method} ${
|
||||||
|
req.path
|
||||||
|
} took ${duration.toFixed(2)}ms`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return originalEnd.call(this, chunk, encoding, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMetrics = () => {
|
||||||
|
return {
|
||||||
|
totalRequests: requestMetrics.length,
|
||||||
|
averageDuration:
|
||||||
|
requestMetrics.reduce((acc, curr) => acc + curr.duration, 0) /
|
||||||
|
requestMetrics.length,
|
||||||
|
requestsByMethod: requestMetrics.reduce((acc, curr) => {
|
||||||
|
acc[curr.method] = (acc[curr.method] || 0) + 1;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, number>),
|
||||||
|
requestsByPlatform: requestMetrics.reduce((acc, curr) => {
|
||||||
|
if (curr.platform) {
|
||||||
|
acc[curr.platform] = (acc[curr.platform] || 0) + 1;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, number>),
|
||||||
|
recentRequests: requestMetrics.slice(-10),
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,35 +0,0 @@
|
||||||
import express from 'express';
|
|
||||||
import Logger from './loaders/logger';
|
|
||||||
import config from './config';
|
|
||||||
import { HealthClient } from './protos/health';
|
|
||||||
import { credentials } from '@grpc/grpc-js';
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
const client = new HealthClient(
|
|
||||||
`0.0.0.0:${config.cronPort}`,
|
|
||||||
credentials.createInsecure(),
|
|
||||||
{ 'grpc.enable_http_proxy': 0 },
|
|
||||||
);
|
|
||||||
|
|
||||||
app.get('/api/health', (req, res) => {
|
|
||||||
client.check({ service: 'cron' }, (err, response) => {
|
|
||||||
if (err) {
|
|
||||||
return res.status(200).send({ code: 500, error: err });
|
|
||||||
}
|
|
||||||
return res.status(200).send({ code: 200, data: response });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app
|
|
||||||
.listen(config.publicPort, '0.0.0.0', async () => {
|
|
||||||
await require('./loaders/db').default();
|
|
||||||
|
|
||||||
Logger.debug(`✌️ 公共服务启动成功!`);
|
|
||||||
console.debug(`✌️ 公共服务启动成功!`);
|
|
||||||
process.send?.('ready');
|
|
||||||
})
|
|
||||||
.on('error', (err) => {
|
|
||||||
Logger.error(err);
|
|
||||||
console.error(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
|
@ -10,7 +10,7 @@ import config from '../config';
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
private client = new CronClient(
|
private client = new CronClient(
|
||||||
`0.0.0.0:${config.cronPort}`,
|
`0.0.0.0:${config.grpcPort}`,
|
||||||
credentials.createInsecure(),
|
credentials.createInsecure(),
|
||||||
{ 'grpc.enable_http_proxy': 0 },
|
{ 'grpc.enable_http_proxy': 0 },
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { Server, ServerCredentials } from '@grpc/grpc-js';
|
|
||||||
import { CronService } from '../protos/cron';
|
|
||||||
import { addCron } from './addCron';
|
|
||||||
import { delCron } from './delCron';
|
|
||||||
import { HealthService } from '../protos/health';
|
|
||||||
import { check } from './health';
|
|
||||||
import config from '../config';
|
|
||||||
import Logger from '../loaders/logger';
|
|
||||||
import { ApiService } from '../protos/api';
|
|
||||||
import * as Api from './api';
|
|
||||||
|
|
||||||
const server = new Server({ 'grpc.enable_http_proxy': 0 });
|
|
||||||
server.addService(HealthService, { check });
|
|
||||||
server.addService(CronService, { addCron, delCron });
|
|
||||||
server.addService(ApiService, Api);
|
|
||||||
server.bindAsync(
|
|
||||||
`0.0.0.0:${config.cronPort}`,
|
|
||||||
ServerCredentials.createInsecure(),
|
|
||||||
(err, port) => {
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
Logger.debug(`✌️ 定时服务启动成功!`);
|
|
||||||
console.debug(`✌️ 定时服务启动成功!`);
|
|
||||||
process.send?.('ready');
|
|
||||||
},
|
|
||||||
);
|
|
64
back/services/grpc.ts
Normal file
64
back/services/grpc.ts
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { Server, ServerCredentials } from '@grpc/grpc-js';
|
||||||
|
import { CronService } from '../protos/cron';
|
||||||
|
import { HealthService } from '../protos/health';
|
||||||
|
import { ApiService } from '../protos/api';
|
||||||
|
import { addCron } from '../schedule/addCron';
|
||||||
|
import { delCron } from '../schedule/delCron';
|
||||||
|
import { check } from '../schedule/health';
|
||||||
|
import * as Api from '../schedule/api';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
import { promisify } from 'util';
|
||||||
|
import config from '../config';
|
||||||
|
import { metricsService } from './metrics';
|
||||||
|
import { Service } from 'typedi';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class GrpcServerService {
|
||||||
|
private server: Server = new Server({ 'grpc.enable_http_proxy': 0 });
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
try {
|
||||||
|
this.server.addService(HealthService, { check });
|
||||||
|
this.server.addService(CronService, { addCron, delCron });
|
||||||
|
this.server.addService(ApiService, Api);
|
||||||
|
|
||||||
|
const grpcPort = config.grpcPort;
|
||||||
|
const bindAsync = promisify(this.server.bindAsync).bind(this.server);
|
||||||
|
await bindAsync(
|
||||||
|
`0.0.0.0:${grpcPort}`,
|
||||||
|
ServerCredentials.createInsecure(),
|
||||||
|
);
|
||||||
|
Logger.debug(`✌️ gRPC service started successfully`);
|
||||||
|
|
||||||
|
metricsService.record('grpc_service_start', 1, {
|
||||||
|
port: grpcPort.toString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return grpcPort;
|
||||||
|
} catch (err) {
|
||||||
|
Logger.error('Failed to start gRPC service:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async shutdown() {
|
||||||
|
try {
|
||||||
|
if (this.server) {
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
this.server.tryShutdown(() => {
|
||||||
|
Logger.debug('gRPC service stopped');
|
||||||
|
metricsService.record('grpc_service_stop', 1);
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
Logger.error('Error while shutting down gRPC service:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getServer() {
|
||||||
|
return this.server;
|
||||||
|
}
|
||||||
|
}
|
72
back/services/health.ts
Normal file
72
back/services/health.ts
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import { Service } from 'typedi';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
import { GrpcServerService } from './grpc';
|
||||||
|
import { HttpServerService } from './http';
|
||||||
|
|
||||||
|
interface HealthStatus {
|
||||||
|
status: 'ok' | 'error';
|
||||||
|
services: {
|
||||||
|
http: boolean;
|
||||||
|
grpc: boolean;
|
||||||
|
};
|
||||||
|
metrics: {
|
||||||
|
uptime: number;
|
||||||
|
memory: {
|
||||||
|
used: number;
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class HealthService {
|
||||||
|
private startTime = Date.now();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private grpcServerService: GrpcServerService,
|
||||||
|
private httpServerService: HttpServerService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async check(): Promise<HealthStatus> {
|
||||||
|
const status: HealthStatus = {
|
||||||
|
status: 'ok',
|
||||||
|
services: {
|
||||||
|
http: true,
|
||||||
|
grpc: true,
|
||||||
|
},
|
||||||
|
metrics: {
|
||||||
|
uptime: Math.floor((Date.now() - this.startTime) / 1000),
|
||||||
|
memory: {
|
||||||
|
used: process.memoryUsage().heapUsed,
|
||||||
|
total: process.memoryUsage().heapTotal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const httpServer = this.httpServerService.getServer();
|
||||||
|
if (!httpServer) {
|
||||||
|
status.services.http = false;
|
||||||
|
status.status = 'error';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
status.services.http = false;
|
||||||
|
status.status = 'error';
|
||||||
|
Logger.error('HTTP server check failed:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const grpcServer = this.grpcServerService.getServer();
|
||||||
|
if (!grpcServer) {
|
||||||
|
status.services.grpc = false;
|
||||||
|
status.status = 'error';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
status.services.grpc = false;
|
||||||
|
status.status = 'error';
|
||||||
|
Logger.error('gRPC server check failed:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
53
back/services/http.ts
Normal file
53
back/services/http.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import express from 'express';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
import { metricsService } from './metrics';
|
||||||
|
import { Service } from 'typedi';
|
||||||
|
import { Server } from 'http';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class HttpServerService {
|
||||||
|
private server?: Server = undefined;
|
||||||
|
|
||||||
|
async initialize(expressApp: express.Application, port: number) {
|
||||||
|
try {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.server = expressApp.listen(port, '0.0.0.0', () => {
|
||||||
|
Logger.debug(`✌️ HTTP service started successfully`);
|
||||||
|
metricsService.record('http_service_start', 1, {
|
||||||
|
port: port.toString(),
|
||||||
|
});
|
||||||
|
resolve(this.server);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.server.on('error', (err: Error) => {
|
||||||
|
Logger.error('Failed to start HTTP service:', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
Logger.error('Failed to start HTTP service:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async shutdown() {
|
||||||
|
try {
|
||||||
|
if (this.server) {
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
this.server?.close(() => {
|
||||||
|
Logger.debug('HTTP service stopped');
|
||||||
|
metricsService.record('http_service_stop', 1);
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
Logger.error('Error while shutting down HTTP service:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getServer() {
|
||||||
|
return this.server;
|
||||||
|
}
|
||||||
|
}
|
92
back/services/metrics.ts
Normal file
92
back/services/metrics.ts
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
import { performance } from 'perf_hooks';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
|
||||||
|
interface Metric {
|
||||||
|
name: string;
|
||||||
|
value: number;
|
||||||
|
timestamp: number;
|
||||||
|
tags?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MetricsService {
|
||||||
|
private metrics: Metric[] = [];
|
||||||
|
private static instance: MetricsService;
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
// 定期清理旧数据
|
||||||
|
setInterval(() => {
|
||||||
|
const oneHourAgo = Date.now() - 3600000;
|
||||||
|
this.metrics = this.metrics.filter(m => m.timestamp > oneHourAgo);
|
||||||
|
}, 60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getInstance(): MetricsService {
|
||||||
|
if (!MetricsService.instance) {
|
||||||
|
MetricsService.instance = new MetricsService();
|
||||||
|
}
|
||||||
|
return MetricsService.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
record(name: string, value: number, tags?: Record<string, string>) {
|
||||||
|
this.metrics.push({
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
tags,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
measure(name: string, fn: () => void, tags?: Record<string, string>) {
|
||||||
|
const start = performance.now();
|
||||||
|
try {
|
||||||
|
fn();
|
||||||
|
} finally {
|
||||||
|
const duration = performance.now() - start;
|
||||||
|
this.record(name, duration, tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async measureAsync(name: string, fn: () => Promise<void>, tags?: Record<string, string>) {
|
||||||
|
const start = performance.now();
|
||||||
|
try {
|
||||||
|
await fn();
|
||||||
|
} finally {
|
||||||
|
const duration = performance.now() - start;
|
||||||
|
this.record(name, duration, tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getMetrics(name?: string, tags?: Record<string, string>) {
|
||||||
|
let filtered = this.metrics;
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
filtered = filtered.filter(m => m.name === name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tags) {
|
||||||
|
filtered = filtered.filter(m => {
|
||||||
|
if (!m.tags) return false;
|
||||||
|
return Object.entries(tags).every(([key, value]) => m.tags![key] === value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
count: filtered.length,
|
||||||
|
average: filtered.reduce((acc, curr) => acc + curr.value, 0) / filtered.length,
|
||||||
|
min: Math.min(...filtered.map(m => m.value)),
|
||||||
|
max: Math.max(...filtered.map(m => m.value)),
|
||||||
|
metrics: filtered,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
report() {
|
||||||
|
const report = {
|
||||||
|
timestamp: Date.now(),
|
||||||
|
metrics: this.getMetrics(),
|
||||||
|
};
|
||||||
|
Logger.info('性能指标报告:', report);
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const metricsService = MetricsService.getInstance();
|
|
@ -357,8 +357,15 @@ export default class SystemService {
|
||||||
|
|
||||||
public async reloadSystem(target?: 'system' | 'data') {
|
public async reloadSystem(target?: 'system' | 'data') {
|
||||||
const cmd = `real_time=true ql reload ${target || ''}`;
|
const cmd = `real_time=true ql reload ${target || ''}`;
|
||||||
const cp = spawn(cmd, { shell: '/bin/bash' });
|
const cp = spawn(cmd, {
|
||||||
|
shell: '/bin/bash',
|
||||||
|
detached: true,
|
||||||
|
stdio: 'ignore',
|
||||||
|
});
|
||||||
cp.unref();
|
cp.unref();
|
||||||
|
setTimeout(() => {
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
return { code: 200 };
|
return { code: 200 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,9 +93,9 @@ export default class UserService {
|
||||||
}
|
}
|
||||||
if (username === cUsername && password === cPassword) {
|
if (username === cUsername && password === cPassword) {
|
||||||
const data = createRandomString(50, 100);
|
const data = createRandomString(50, 100);
|
||||||
const expiration = twoFactorActivated ? 60 : 20;
|
const expiration = twoFactorActivated ? '60d' : '20d';
|
||||||
let token = jwt.sign({ data }, config.secret as any, {
|
let token = jwt.sign({ data }, config.jwt.secret, {
|
||||||
expiresIn: 60 * 60 * 24 * expiration,
|
expiresIn: config.jwt.expiresIn || expiration,
|
||||||
algorithm: 'HS384',
|
algorithm: 'HS384',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -131,7 +131,14 @@ export default class UserService {
|
||||||
this.getLoginLog();
|
this.getLoginLog();
|
||||||
return {
|
return {
|
||||||
code: 200,
|
code: 200,
|
||||||
data: { token, lastip, lastaddr, lastlogon, retries, platform },
|
data: {
|
||||||
|
token,
|
||||||
|
lastip,
|
||||||
|
lastaddr,
|
||||||
|
lastlogon,
|
||||||
|
retries,
|
||||||
|
platform,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
await this.updateAuthInfo(content, {
|
await this.updateAuthInfo(content, {
|
||||||
|
|
|
@ -37,7 +37,7 @@ class TaskLimit {
|
||||||
concurrency: Math.max(os.cpus().length, 4),
|
concurrency: Math.max(os.cpus().length, 4),
|
||||||
});
|
});
|
||||||
private client = new ApiClient(
|
private client = new ApiClient(
|
||||||
`0.0.0.0:${config.cronPort}`,
|
`0.0.0.0:${config.grpcPort}`,
|
||||||
credentials.createInsecure(),
|
credentials.createInsecure(),
|
||||||
{ 'grpc.enable_http_proxy': 0 },
|
{ 'grpc.enable_http_proxy': 0 },
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'reflect-metadata';
|
||||||
import OpenService from './services/open';
|
import OpenService from './services/open';
|
||||||
import { Container } from 'typedi';
|
import { Container } from 'typedi';
|
||||||
import LoggerInstance from './loaders/logger';
|
import LoggerInstance from './loaders/logger';
|
||||||
import fs from 'fs';
|
|
||||||
import config from './config';
|
import config from './config';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2017",
|
"target": "es2017",
|
||||||
"lib": ["ESNext"],
|
"lib": ["ESNext"],
|
||||||
"typeRoots": ["./node_modules/celebrate/lib", "./node_modules/@types"],
|
"typeRoots": [
|
||||||
|
"./types",
|
||||||
|
"../node_modules/celebrate/lib",
|
||||||
|
"../node_modules/@types"
|
||||||
|
],
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
|
@ -13,12 +17,11 @@
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"pretty": true,
|
"pretty": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "./static/build",
|
"outDir": "../static/build",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"noEmit": false,
|
"noEmit": false,
|
||||||
"esModuleInterop": true
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"include": ["./back/**/*", "./back.d.ts"],
|
"include": ["./**/*"],
|
||||||
"exclude": ["node_modules"],
|
"exclude": ["node_modules"]
|
||||||
"files": ["./back/index.d.ts"]
|
|
||||||
}
|
}
|
11
back/types/express.d.ts
vendored
Normal file
11
back/types/express.d.ts
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/// <reference types="express" />
|
||||||
|
|
||||||
|
export {};
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace Express {
|
||||||
|
interface Request {
|
||||||
|
platform: 'desktop' | 'mobile';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
import 'reflect-metadata'; // We need this in order to use @Decorators
|
|
||||||
import config from './config';
|
|
||||||
import express from 'express';
|
|
||||||
import depInjectorLoader from './loaders/depInjector';
|
|
||||||
import Logger from './loaders/logger';
|
|
||||||
|
|
||||||
|
|
||||||
async function startServer() {
|
|
||||||
const app = express();
|
|
||||||
depInjectorLoader();
|
|
||||||
|
|
||||||
await require('./loaders/update').default({ app });
|
|
||||||
|
|
||||||
app
|
|
||||||
.listen(config.updatePort, '0.0.0.0', () => {
|
|
||||||
Logger.debug(`✌️ 更新服务启动成功!`);
|
|
||||||
console.debug(`✌️ 更新服务启动成功!`);
|
|
||||||
process.send?.('ready');
|
|
||||||
})
|
|
||||||
.on('error', (err) => {
|
|
||||||
Logger.error(err);
|
|
||||||
console.error(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
startServer();
|
|
|
@ -86,6 +86,6 @@ COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
|
||||||
WORKDIR ${QL_DIR}
|
WORKDIR ${QL_DIR}
|
||||||
|
|
||||||
HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
|
HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
|
||||||
CMD curl -sf --noproxy '*' http://127.0.0.1:5400/api/health || exit 1
|
CMD curl -sf --noproxy '*' http://127.0.0.1:5600/api/health || exit 1
|
||||||
|
|
||||||
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
|
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
|
||||||
|
|
|
@ -86,6 +86,6 @@ COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
|
||||||
WORKDIR ${QL_DIR}
|
WORKDIR ${QL_DIR}
|
||||||
|
|
||||||
HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
|
HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
|
||||||
CMD curl -sf --noproxy '*' http://127.0.0.1:5400/api/health || exit 1
|
CMD curl -sf --noproxy '*' http://127.0.0.1:5600/api/health || exit 1
|
||||||
|
|
||||||
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
|
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
|
||||||
|
|
|
@ -21,7 +21,6 @@ nginx -s reload 2>/dev/null || nginx -c /etc/nginx/nginx.conf
|
||||||
echo -e "nginx启动成功...\n"
|
echo -e "nginx启动成功...\n"
|
||||||
|
|
||||||
echo -e "======================4. 启动pm2服务========================\n"
|
echo -e "======================4. 启动pm2服务========================\n"
|
||||||
reload_update
|
|
||||||
reload_pm2
|
reload_pm2
|
||||||
|
|
||||||
if [[ $AutoStartBot == true ]]; then
|
if [[ $AutoStartBot == true ]]; then
|
||||||
|
|
|
@ -2,14 +2,6 @@ upstream baseApi {
|
||||||
server 0.0.0.0:5600;
|
server 0.0.0.0:5600;
|
||||||
}
|
}
|
||||||
|
|
||||||
upstream publicApi {
|
|
||||||
server 0.0.0.0:5400;
|
|
||||||
}
|
|
||||||
|
|
||||||
upstream updateApi {
|
|
||||||
server 0.0.0.0:5300;
|
|
||||||
}
|
|
||||||
|
|
||||||
map $http_upgrade $connection_upgrade {
|
map $http_upgrade $connection_upgrade {
|
||||||
default keep-alive;
|
default keep-alive;
|
||||||
'websocket' upgrade;
|
'websocket' upgrade;
|
||||||
|
@ -20,30 +12,6 @@ server {
|
||||||
IPV6_CONFIG
|
IPV6_CONFIG
|
||||||
ssl_session_timeout 5m;
|
ssl_session_timeout 5m;
|
||||||
|
|
||||||
location QL_BASE_URLapi/update/ {
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_pass http://updateApi/api/;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_redirect default;
|
|
||||||
proxy_connect_timeout 1800;
|
|
||||||
proxy_send_timeout 1800;
|
|
||||||
proxy_read_timeout 1800;
|
|
||||||
}
|
|
||||||
|
|
||||||
location QL_BASE_URLapi/public/ {
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_pass http://publicApi/api/;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_redirect default;
|
|
||||||
proxy_connect_timeout 1800;
|
|
||||||
proxy_send_timeout 1800;
|
|
||||||
proxy_read_timeout 1800;
|
|
||||||
}
|
|
||||||
|
|
||||||
location QL_BASE_URLapi/ {
|
location QL_BASE_URLapi/ {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: 'schedule',
|
name: 'qinglong',
|
||||||
max_restarts: 10,
|
max_restarts: 5,
|
||||||
kill_timeout: 15000,
|
kill_timeout: 1000,
|
||||||
wait_ready: true,
|
wait_ready: true,
|
||||||
listen_timeout: 10000,
|
listen_timeout: 5000,
|
||||||
source_map_support: true,
|
source_map_support: true,
|
||||||
time: true,
|
time: true,
|
||||||
script: 'static/build/schedule/index.js',
|
script: 'static/build/app.js',
|
||||||
env: {
|
env: {
|
||||||
http_proxy: '',
|
http_proxy: '',
|
||||||
https_proxy: '',
|
https_proxy: '',
|
||||||
|
@ -18,25 +18,5 @@ module.exports = {
|
||||||
ALL_PROXY: '',
|
ALL_PROXY: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'public',
|
|
||||||
max_restarts: 10,
|
|
||||||
kill_timeout: 15000,
|
|
||||||
wait_ready: true,
|
|
||||||
listen_timeout: 10000,
|
|
||||||
source_map_support: true,
|
|
||||||
time: true,
|
|
||||||
script: 'static/build/public.js',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'panel',
|
|
||||||
max_restarts: 10,
|
|
||||||
kill_timeout: 15000,
|
|
||||||
wait_ready: true,
|
|
||||||
listen_timeout: 10000,
|
|
||||||
source_map_support: true,
|
|
||||||
time: true,
|
|
||||||
script: 'static/build/app.js',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"watch": ["back", ".env"],
|
"watch": ["back", ".env"],
|
||||||
"ext": "js,ts,json",
|
"ext": "js,ts,json",
|
||||||
"exec": "ts-node -P tsconfig.back.json ./back/app.ts"
|
"exec": "ts-node -P ./back/tsconfig.json ./back/app.ts"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
apps: [
|
|
||||||
{
|
|
||||||
name: 'update',
|
|
||||||
max_restarts: 10,
|
|
||||||
kill_timeout: 15000,
|
|
||||||
wait_ready: true,
|
|
||||||
listen_timeout: 10000,
|
|
||||||
time: true,
|
|
||||||
script: 'static/build/update.js',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
18
package.json
18
package.json
|
@ -2,17 +2,11 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "concurrently -n w: npm:start:*",
|
"start": "concurrently -n w: npm:start:*",
|
||||||
"start:update": "ts-node -P tsconfig.back.json ./back/update.ts",
|
|
||||||
"start:public": "ts-node -P tsconfig.back.json ./back/public.ts",
|
|
||||||
"start:rpc": "ts-node -P tsconfig.back.json ./back/schedule/index.ts",
|
|
||||||
"start:back": "nodemon",
|
"start:back": "nodemon",
|
||||||
"start:front": "max dev",
|
"start:front": "max dev",
|
||||||
"build:front": "max build",
|
"build:front": "max build",
|
||||||
"build:back": "tsc -p tsconfig.back.json",
|
"build:back": "tsc -p back/tsconfig.json",
|
||||||
"panel": "npm run build:back && node static/build/app.js",
|
"panel": "npm run build:back && node static/build/app.js",
|
||||||
"schedule": "npm run build:back && node static/build/schedule/index.js",
|
|
||||||
"public": "npm run build:back && node static/build/public.js",
|
|
||||||
"update": "npm run build:back && node static/build/update.js",
|
|
||||||
"gen:proto": "protoc --experimental_allow_proto3_optional --plugin=./node_modules/.bin/protoc-gen-ts_proto ./back/protos/*.proto --ts_proto_out=./ --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true,snakeToCamel=false",
|
"gen:proto": "protoc --experimental_allow_proto3_optional --plugin=./node_modules/.bin/protoc-gen-ts_proto ./back/protos/*.proto --ts_proto_out=./ --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true,snakeToCamel=false",
|
||||||
"gen:api": "python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./back/protos/api.proto",
|
"gen:api": "python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./back/protos/api.proto",
|
||||||
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
|
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
|
||||||
|
@ -89,7 +83,7 @@
|
||||||
"nodemailer": "^6.9.16",
|
"nodemailer": "^6.9.16",
|
||||||
"p-queue-cjs": "7.3.4",
|
"p-queue-cjs": "7.3.4",
|
||||||
"@bufbuild/protobuf": "^2.2.3",
|
"@bufbuild/protobuf": "^2.2.3",
|
||||||
"pstree.remy": "^1.1.8",
|
"ps-tree": "^1.2.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"sequelize": "^6.37.5",
|
"sequelize": "^6.37.5",
|
||||||
"serve-handler": "^6.1.6",
|
"serve-handler": "^6.1.6",
|
||||||
|
@ -104,7 +98,9 @@
|
||||||
"ip2region": "2.3.0",
|
"ip2region": "2.3.0",
|
||||||
"keyv": "^5.2.3",
|
"keyv": "^5.2.3",
|
||||||
"@keyv/sqlite": "^4.0.1",
|
"@keyv/sqlite": "^4.0.1",
|
||||||
"proper-lockfile": "^4.1.2"
|
"proper-lockfile": "^4.1.2",
|
||||||
|
"compression": "^1.7.4",
|
||||||
|
"helmet": "^6.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"moment": "2.30.1",
|
"moment": "2.30.1",
|
||||||
|
@ -138,6 +134,7 @@
|
||||||
"@types/uuid": "^8.3.4",
|
"@types/uuid": "^8.3.4",
|
||||||
"@types/request-ip": "0.0.41",
|
"@types/request-ip": "0.0.41",
|
||||||
"@types/proper-lockfile": "^4.1.4",
|
"@types/proper-lockfile": "^4.1.4",
|
||||||
|
"@types/ps-tree": "^1.1.6",
|
||||||
"@uiw/codemirror-extensions-langs": "^4.21.9",
|
"@uiw/codemirror-extensions-langs": "^4.21.9",
|
||||||
"@uiw/react-codemirror": "^4.21.9",
|
"@uiw/react-codemirror": "^4.21.9",
|
||||||
"@umijs/max": "^4.4.4",
|
"@umijs/max": "^4.4.4",
|
||||||
|
@ -176,6 +173,7 @@
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.2.2",
|
||||||
"vh-check": "^2.0.5",
|
"vh-check": "^2.0.5",
|
||||||
"virtualizedtableforantd4": "1.3.0",
|
"virtualizedtableforantd4": "1.3.0",
|
||||||
"yorkie": "^2.0.0"
|
"@types/compression": "^1.7.2",
|
||||||
|
"@types/helmet": "^4.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
206
pnpm-lock.yaml
206
pnpm-lock.yaml
|
@ -32,6 +32,9 @@ dependencies:
|
||||||
chokidar:
|
chokidar:
|
||||||
specifier: ^4.0.1
|
specifier: ^4.0.1
|
||||||
version: 4.0.1
|
version: 4.0.1
|
||||||
|
compression:
|
||||||
|
specifier: ^1.7.4
|
||||||
|
version: 1.7.5
|
||||||
cors:
|
cors:
|
||||||
specifier: ^2.8.5
|
specifier: ^2.8.5
|
||||||
version: 2.8.5
|
version: 2.8.5
|
||||||
|
@ -65,6 +68,9 @@ dependencies:
|
||||||
got:
|
got:
|
||||||
specifier: ^11.8.2
|
specifier: ^11.8.2
|
||||||
version: 11.8.6
|
version: 11.8.6
|
||||||
|
helmet:
|
||||||
|
specifier: ^6.0.1
|
||||||
|
version: 6.2.0
|
||||||
hpagent:
|
hpagent:
|
||||||
specifier: ^1.2.0
|
specifier: ^1.2.0
|
||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
|
@ -104,9 +110,9 @@ dependencies:
|
||||||
proper-lockfile:
|
proper-lockfile:
|
||||||
specifier: ^4.1.2
|
specifier: ^4.1.2
|
||||||
version: 4.1.2
|
version: 4.1.2
|
||||||
pstree.remy:
|
ps-tree:
|
||||||
specifier: ^1.1.8
|
specifier: ^1.2.0
|
||||||
version: 1.1.8
|
version: 1.2.0
|
||||||
reflect-metadata:
|
reflect-metadata:
|
||||||
specifier: ^0.2.2
|
specifier: ^0.2.2
|
||||||
version: 0.2.2
|
version: 0.2.2
|
||||||
|
@ -163,6 +169,9 @@ devDependencies:
|
||||||
'@types/body-parser':
|
'@types/body-parser':
|
||||||
specifier: ^1.19.2
|
specifier: ^1.19.2
|
||||||
version: 1.19.5
|
version: 1.19.5
|
||||||
|
'@types/compression':
|
||||||
|
specifier: ^1.7.2
|
||||||
|
version: 1.7.5
|
||||||
'@types/cors':
|
'@types/cors':
|
||||||
specifier: ^2.8.12
|
specifier: ^2.8.12
|
||||||
version: 2.8.17
|
version: 2.8.17
|
||||||
|
@ -178,6 +187,9 @@ devDependencies:
|
||||||
'@types/file-saver':
|
'@types/file-saver':
|
||||||
specifier: 2.0.2
|
specifier: 2.0.2
|
||||||
version: 2.0.2
|
version: 2.0.2
|
||||||
|
'@types/helmet':
|
||||||
|
specifier: ^4.0.0
|
||||||
|
version: 4.0.0
|
||||||
'@types/js-yaml':
|
'@types/js-yaml':
|
||||||
specifier: ^4.0.5
|
specifier: ^4.0.5
|
||||||
version: 4.0.9
|
version: 4.0.9
|
||||||
|
@ -202,6 +214,9 @@ devDependencies:
|
||||||
'@types/proper-lockfile':
|
'@types/proper-lockfile':
|
||||||
specifier: ^4.1.4
|
specifier: ^4.1.4
|
||||||
version: 4.1.4
|
version: 4.1.4
|
||||||
|
'@types/ps-tree':
|
||||||
|
specifier: ^1.1.6
|
||||||
|
version: 1.1.6
|
||||||
'@types/qrcode.react':
|
'@types/qrcode.react':
|
||||||
specifier: ^1.0.2
|
specifier: ^1.0.2
|
||||||
version: 1.0.5
|
version: 1.0.5
|
||||||
|
@ -349,9 +364,6 @@ devDependencies:
|
||||||
virtualizedtableforantd4:
|
virtualizedtableforantd4:
|
||||||
specifier: 1.3.0
|
specifier: 1.3.0
|
||||||
version: 1.3.0(antd@4.24.16)(react-dom@18.3.1)(react@18.3.1)
|
version: 1.3.0(antd@4.24.16)(react-dom@18.3.1)(react@18.3.1)
|
||||||
yorkie:
|
|
||||||
specifier: ^2.0.0
|
|
||||||
version: 2.0.0
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
|
@ -3808,6 +3820,12 @@ packages:
|
||||||
'@types/responselike': 1.0.3
|
'@types/responselike': 1.0.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/compression@1.7.5:
|
||||||
|
resolution: {integrity: sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/express': 4.17.21
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/connect@3.4.38:
|
/@types/connect@3.4.38:
|
||||||
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -3878,6 +3896,13 @@ packages:
|
||||||
resolution: {integrity: sha512-oOMFT8vmCTFncsF1engrs04jatz8/Anwx3De9uxnOK4chgSEgWBvFtpSoJo8u3784JNO+ql5tzRR6phHoRnscQ==}
|
resolution: {integrity: sha512-oOMFT8vmCTFncsF1engrs04jatz8/Anwx3De9uxnOK4chgSEgWBvFtpSoJo8u3784JNO+ql5tzRR6phHoRnscQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/helmet@4.0.0:
|
||||||
|
resolution: {integrity: sha512-ONIn/nSNQA57yRge3oaMQESef/6QhoeX7llWeDli0UZIfz8TQMkfNPTXA8VnnyeA1WUjG2pGqdjEIueYonMdfQ==}
|
||||||
|
deprecated: This is a stub types definition. helmet provides its own type definitions, so you do not need this installed.
|
||||||
|
dependencies:
|
||||||
|
helmet: 6.2.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/hoist-non-react-statics@3.3.5:
|
/@types/hoist-non-react-statics@3.3.5:
|
||||||
resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==}
|
resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -4011,6 +4036,10 @@ packages:
|
||||||
'@types/retry': 0.12.5
|
'@types/retry': 0.12.5
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/ps-tree@1.1.6:
|
||||||
|
resolution: {integrity: sha512-PtrlVaOaI44/3pl3cvnlK+GxOM3re2526TJvPvh7W+keHIXdV4TE0ylpPBAcvFQCbGitaTXwL9u+RF7qtVeazQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/qrcode.react@1.0.5:
|
/@types/qrcode.react@1.0.5:
|
||||||
resolution: {integrity: sha512-BghPtnlwvrvq8QkGa1H25YnN+5OIgCKFuQruncGWLGJYOzeSKiix/4+B9BtfKF2wf5ja8yfyWYA3OXju995G8w==}
|
resolution: {integrity: sha512-BghPtnlwvrvq8QkGa1H25YnN+5OIgCKFuQruncGWLGJYOzeSKiix/4+B9BtfKF2wf5ja8yfyWYA3OXju995G8w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -6144,10 +6173,6 @@ packages:
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/ci-info@1.6.0:
|
|
||||||
resolution: {integrity: sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ci-info@3.9.0:
|
/ci-info@3.9.0:
|
||||||
resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
|
resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -6343,7 +6368,6 @@ packages:
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db: 1.53.0
|
mime-db: 1.53.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/compression-webpack-plugin@9.2.0:
|
/compression-webpack-plugin@9.2.0:
|
||||||
resolution: {integrity: sha512-R/Oi+2+UHotGfu72fJiRoVpuRifZT0tTC6UqFD/DUo+mv8dbOow9rVOuTvDv5nPPm3GZhHL/fKkwxwIHnJ8Nyw==}
|
resolution: {integrity: sha512-R/Oi+2+UHotGfu72fJiRoVpuRifZT0tTC6UqFD/DUo+mv8dbOow9rVOuTvDv5nPPm3GZhHL/fKkwxwIHnJ8Nyw==}
|
||||||
|
@ -6371,7 +6395,6 @@ packages:
|
||||||
vary: 1.1.2
|
vary: 1.1.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
|
||||||
|
|
||||||
/compute-scroll-into-view@1.0.20:
|
/compute-scroll-into-view@1.0.20:
|
||||||
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
|
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
|
||||||
|
@ -6581,14 +6604,6 @@ packages:
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/cross-spawn@5.1.0:
|
|
||||||
resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==}
|
|
||||||
dependencies:
|
|
||||||
lru-cache: 4.1.5
|
|
||||||
shebang-command: 1.2.0
|
|
||||||
which: 1.3.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/cross-spawn@7.0.6:
|
/cross-spawn@7.0.6:
|
||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
@ -7107,6 +7122,10 @@ packages:
|
||||||
detect-libc: 1.0.3
|
detect-libc: 1.0.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/duplexer@0.1.2:
|
||||||
|
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/duplexify@4.1.3:
|
/duplexify@4.1.3:
|
||||||
resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==}
|
resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7755,6 +7774,18 @@ packages:
|
||||||
es5-ext: 0.10.64
|
es5-ext: 0.10.64
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/event-stream@3.3.4:
|
||||||
|
resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==}
|
||||||
|
dependencies:
|
||||||
|
duplexer: 0.1.2
|
||||||
|
from: 0.1.7
|
||||||
|
map-stream: 0.1.0
|
||||||
|
pause-stream: 0.0.11
|
||||||
|
split: 0.3.3
|
||||||
|
stream-combiner: 0.0.4
|
||||||
|
through: 2.3.8
|
||||||
|
dev: false
|
||||||
|
|
||||||
/eventemitter3@4.0.7:
|
/eventemitter3@4.0.7:
|
||||||
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
|
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -7785,19 +7816,6 @@ packages:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/execa@0.8.0:
|
|
||||||
resolution: {integrity: sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dependencies:
|
|
||||||
cross-spawn: 5.1.0
|
|
||||||
get-stream: 3.0.0
|
|
||||||
is-stream: 1.1.0
|
|
||||||
npm-run-path: 2.0.2
|
|
||||||
p-finally: 1.0.0
|
|
||||||
signal-exit: 3.0.7
|
|
||||||
strip-eof: 1.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/execa@5.1.1:
|
/execa@5.1.1:
|
||||||
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
@ -8186,6 +8204,10 @@ packages:
|
||||||
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
|
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
/from@0.1.7:
|
||||||
|
resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fs-extra@10.1.0:
|
/fs-extra@10.1.0:
|
||||||
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
|
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
@ -8297,11 +8319,6 @@ packages:
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/get-stream@3.0.0:
|
|
||||||
resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/get-stream@5.2.0:
|
/get-stream@5.2.0:
|
||||||
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
|
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -8558,6 +8575,10 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/helmet@6.2.0:
|
||||||
|
resolution: {integrity: sha512-DWlwuXLLqbrIOltR6tFQXShj/+7Cyp0gLi6uAb8qMdFh/YBBFbKSgQ6nbXmScYd8emMctuthmgIa7tUfo9Rtyg==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
/history@5.3.0:
|
/history@5.3.0:
|
||||||
resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==}
|
resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -8995,13 +9016,6 @@ packages:
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/is-ci@1.2.1:
|
|
||||||
resolution: {integrity: sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
ci-info: 1.6.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-core-module@2.15.1:
|
/is-core-module@2.15.1:
|
||||||
resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
|
resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
@ -9190,11 +9204,6 @@ packages:
|
||||||
call-bind: 1.0.7
|
call-bind: 1.0.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/is-stream@1.1.0:
|
|
||||||
resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-stream@2.0.1:
|
/is-stream@2.0.1:
|
||||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -9883,13 +9892,6 @@ packages:
|
||||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/lru-cache@4.1.5:
|
|
||||||
resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==}
|
|
||||||
dependencies:
|
|
||||||
pseudomap: 1.0.2
|
|
||||||
yallist: 2.1.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/lru-cache@5.1.1:
|
/lru-cache@5.1.1:
|
||||||
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -9971,6 +9973,10 @@ packages:
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/map-stream@0.1.0:
|
||||||
|
resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mathml-tag-names@2.1.3:
|
/mathml-tag-names@2.1.3:
|
||||||
resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
|
resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -10071,7 +10077,6 @@ packages:
|
||||||
/mime-db@1.53.0:
|
/mime-db@1.53.0:
|
||||||
resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==}
|
resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/mime-types@2.1.18:
|
/mime-types@2.1.18:
|
||||||
resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==}
|
resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==}
|
||||||
|
@ -10521,11 +10526,6 @@ packages:
|
||||||
validate-npm-package-license: 3.0.4
|
validate-npm-package-license: 3.0.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/normalize-path@1.0.0:
|
|
||||||
resolution: {integrity: sha512-7WyT0w8jhpDStXRq5836AMmihQwq2nrUVQrgjvUo/p/NZf9uy/MeJ246lBJVmWuYXMlJuG9BNZHF0hWjfTbQUA==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/normalize-path@3.0.0:
|
/normalize-path@3.0.0:
|
||||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -10549,13 +10549,6 @@ packages:
|
||||||
resolution: {integrity: sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==}
|
resolution: {integrity: sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/npm-run-path@2.0.2:
|
|
||||||
resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dependencies:
|
|
||||||
path-key: 2.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/npm-run-path@4.0.1:
|
/npm-run-path@4.0.1:
|
||||||
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -10695,7 +10688,6 @@ packages:
|
||||||
/on-headers@1.0.2:
|
/on-headers@1.0.2:
|
||||||
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
|
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/once@1.4.0:
|
/once@1.4.0:
|
||||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||||
|
@ -10779,11 +10771,6 @@ packages:
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/p-finally@1.0.0:
|
|
||||||
resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/p-limit@2.3.0:
|
/p-limit@2.3.0:
|
||||||
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
|
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -10917,11 +10904,6 @@ packages:
|
||||||
resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==}
|
resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/path-key@2.0.1:
|
|
||||||
resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/path-key@3.1.1:
|
/path-key@3.1.1:
|
||||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -10978,7 +10960,6 @@ packages:
|
||||||
resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==}
|
resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
through: 2.3.8
|
through: 2.3.8
|
||||||
dev: true
|
|
||||||
|
|
||||||
/pbkdf2@3.1.2:
|
/pbkdf2@3.1.2:
|
||||||
resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==}
|
resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==}
|
||||||
|
@ -11786,12 +11767,17 @@ packages:
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/pseudomap@1.0.2:
|
/ps-tree@1.2.0:
|
||||||
resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
|
resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==}
|
||||||
dev: true
|
engines: {node: '>= 0.10'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
event-stream: 3.3.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/pstree.remy@1.1.8:
|
/pstree.remy@1.1.8:
|
||||||
resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==}
|
resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/public-encrypt@4.0.3:
|
/public-encrypt@4.0.3:
|
||||||
resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==}
|
resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==}
|
||||||
|
@ -13635,24 +13621,12 @@ packages:
|
||||||
resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
|
resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/shebang-command@1.2.0:
|
|
||||||
resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dependencies:
|
|
||||||
shebang-regex: 1.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/shebang-command@2.0.0:
|
/shebang-command@2.0.0:
|
||||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
shebang-regex: 3.0.0
|
shebang-regex: 3.0.0
|
||||||
|
|
||||||
/shebang-regex@1.0.0:
|
|
||||||
resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/shebang-regex@3.0.0:
|
/shebang-regex@3.0.0:
|
||||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -13894,6 +13868,12 @@ packages:
|
||||||
engines: {node: '>= 10.x'}
|
engines: {node: '>= 10.x'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/split@0.3.3:
|
||||||
|
resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==}
|
||||||
|
dependencies:
|
||||||
|
through: 2.3.8
|
||||||
|
dev: false
|
||||||
|
|
||||||
/sprintf-js@1.0.3:
|
/sprintf-js@1.0.3:
|
||||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -13953,6 +13933,12 @@ packages:
|
||||||
readable-stream: 2.3.8
|
readable-stream: 2.3.8
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/stream-combiner@0.0.4:
|
||||||
|
resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==}
|
||||||
|
dependencies:
|
||||||
|
duplexer: 0.1.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/stream-http@2.8.3:
|
/stream-http@2.8.3:
|
||||||
resolution: {integrity: sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==}
|
resolution: {integrity: sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -14077,11 +14063,6 @@ packages:
|
||||||
ansi-regex: 6.1.0
|
ansi-regex: 6.1.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/strip-eof@1.0.0:
|
|
||||||
resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/strip-final-newline@2.0.0:
|
/strip-final-newline@2.0.0:
|
||||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -14092,11 +14073,6 @@ packages:
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/strip-indent@2.0.0:
|
|
||||||
resolution: {integrity: sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/strip-indent@3.0.0:
|
/strip-indent@3.0.0:
|
||||||
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
|
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -14420,7 +14396,6 @@ packages:
|
||||||
|
|
||||||
/through@2.3.8:
|
/through@2.3.8:
|
||||||
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/timers-browserify@2.0.12:
|
/timers-browserify@2.0.12:
|
||||||
resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==}
|
resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==}
|
||||||
|
@ -15341,10 +15316,6 @@ packages:
|
||||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
/yallist@2.1.2:
|
|
||||||
resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yallist@3.1.1:
|
/yallist@3.1.1:
|
||||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -15393,17 +15364,6 @@ packages:
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/yorkie@2.0.0:
|
|
||||||
resolution: {integrity: sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
requiresBuild: true
|
|
||||||
dependencies:
|
|
||||||
execa: 0.8.0
|
|
||||||
is-ci: 1.2.1
|
|
||||||
normalize-path: 1.0.0
|
|
||||||
strip-indent: 2.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/zod-validation-error@2.1.0(zod@3.23.8):
|
/zod-validation-error@2.1.0(zod@3.23.8):
|
||||||
resolution: {integrity: sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==}
|
resolution: {integrity: sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
|
@ -81,7 +81,6 @@ main() {
|
||||||
check_ql
|
check_ql
|
||||||
check_nginx
|
check_nginx
|
||||||
check_pm2
|
check_pm2
|
||||||
reload_update
|
|
||||||
reload_pm2
|
reload_pm2
|
||||||
echo -e "\n=====> 检测结束\n"
|
echo -e "\n=====> 检测结束\n"
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,13 +308,6 @@ reload_pm2() {
|
||||||
pm2 startOrGracefulReload ecosystem.config.js
|
pm2 startOrGracefulReload ecosystem.config.js
|
||||||
}
|
}
|
||||||
|
|
||||||
reload_update() {
|
|
||||||
cd $dir_root
|
|
||||||
restore_env_vars
|
|
||||||
pm2 flush &>/dev/null
|
|
||||||
pm2 startOrGracefulReload other.config.js
|
|
||||||
}
|
|
||||||
|
|
||||||
diff_time() {
|
diff_time() {
|
||||||
local format="$1"
|
local format="$1"
|
||||||
local begin_time="$2"
|
local begin_time="$2"
|
||||||
|
|
|
@ -227,7 +227,10 @@ usage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
reload_qinglong() {
|
reload_qinglong() {
|
||||||
|
echo -e "[reload_qinglong] deleting Triggered at $(date)" >>${dir_log}/reload.log
|
||||||
|
sleep 3
|
||||||
delete_pm2
|
delete_pm2
|
||||||
|
echo -e "[reload_qinglong] deleted Triggered at $(date)" >>${dir_log}/reload.log
|
||||||
|
|
||||||
local reload_target="${1}"
|
local reload_target="${1}"
|
||||||
local primary_branch="master"
|
local primary_branch="master"
|
||||||
|
@ -247,8 +250,9 @@ reload_qinglong() {
|
||||||
rm -rf ${dir_data}/*
|
rm -rf ${dir_data}/*
|
||||||
mv -f ${dir_tmp}/data/* ${dir_data}/
|
mv -f ${dir_tmp}/data/* ${dir_data}/
|
||||||
fi
|
fi
|
||||||
|
echo -e "[reload_qinglong] starting Triggered at $(date)" >>${dir_log}/reload.log
|
||||||
reload_pm2
|
reload_pm2
|
||||||
|
echo -e "[reload_qinglong] started Triggered at $(date)\n" >>${dir_log}/reload.log
|
||||||
}
|
}
|
||||||
|
|
||||||
## 更新 qinglong
|
## 更新 qinglong
|
||||||
|
@ -309,15 +313,7 @@ check_update_dep() {
|
||||||
echo -e "更新包下载成功..."
|
echo -e "更新包下载成功..."
|
||||||
|
|
||||||
if [[ "$needRestart" == 'true' ]]; then
|
if [[ "$needRestart" == 'true' ]]; then
|
||||||
delete_pm2
|
reload_qinglong "system"
|
||||||
|
|
||||||
rm -rf ${dir_root}/back ${dir_root}/cli ${dir_root}/docker ${dir_root}/sample ${dir_root}/shell ${dir_root}/src
|
|
||||||
mv -f ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
|
|
||||||
rm -rf $dir_static/*
|
|
||||||
mv -f ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/
|
|
||||||
cp -f $file_config_sample $dir_config/config.sample.sh
|
|
||||||
|
|
||||||
reload_pm2
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "\n依赖检测安装失败,请检查网络...\n"
|
echo -e "\n依赖检测安装失败,请检查网络...\n"
|
||||||
|
|
|
@ -101,9 +101,9 @@ export default function () {
|
||||||
|
|
||||||
const getHealthStatus = () => {
|
const getHealthStatus = () => {
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}public/health`)
|
.get(`${config.apiPrefix}health`)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res?.data?.status === 1) {
|
if (res?.data?.status === 'ok') {
|
||||||
getSystemInfo();
|
getSystemInfo();
|
||||||
} else {
|
} else {
|
||||||
history.push('/error');
|
history.push('/error');
|
||||||
|
|
|
@ -17,9 +17,9 @@ const Error = () => {
|
||||||
const getHealthStatus = (needLoading: boolean = true) => {
|
const getHealthStatus = (needLoading: boolean = true) => {
|
||||||
needLoading && setLoading(true);
|
needLoading && setLoading(true);
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}public/health`)
|
.get(`${config.apiPrefix}health`)
|
||||||
.then(({ error, data }) => {
|
.then(({ error, data }) => {
|
||||||
if (data?.status === 1) {
|
if (data?.status === 'ok') {
|
||||||
if (retryTimes.current > 1) {
|
if (retryTimes.current > 1) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
|
|
|
@ -6,10 +6,10 @@ import {
|
||||||
} from '@codemirror/view';
|
} from '@codemirror/view';
|
||||||
import { RangeSet, RangeSetBuilder } from '@codemirror/state';
|
import { RangeSet, RangeSetBuilder } from '@codemirror/state';
|
||||||
|
|
||||||
const infoWord = /\[\ue6f5info\]/g;
|
const infoWord = /\[ℹ️info/g;
|
||||||
const debugWord = /\[\ue67fdebug\]/g;
|
const debugWord = /\[⚠️debug/g;
|
||||||
const warnWord = /\[\ue880warn\]/g;
|
const warnWord = /\[❌warn/g;
|
||||||
const errorWord = /\[\ue602error\]/g;
|
const errorWord = /\[🐛error/g;
|
||||||
|
|
||||||
const customWordClassMap = {
|
const customWordClassMap = {
|
||||||
info: 'system-log-info',
|
info: 'system-log-info',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user