From 08f74445da17994596b32ff415f0d9eba9d82849 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 31 Jul 2025 11:02:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 4 +- pnpm-lock.yaml | 25 +++++++++++++ src/common/filters/all-exception.filter.ts | 3 ++ .../interceptors/response.interceptor.ts | 3 ++ src/config/config.service.ts | 5 +++ src/core/auto-update/auto-update.service.ts | 2 +- src/core/persistence/persistence.service.ts | 11 ++++++ src/core/redis/redis.service.ts | 37 ++++++++++++++++++- src/core/system/system.service.ts | 3 ++ src/types/ws.ts | 18 +++++++++ 10 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src/types/ws.ts diff --git a/package.json b/package.json index 9f6451c..2da34c4 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "simple-git": "^3.28.0", - "ssh2": "^1.16.0" + "ssh2": "^1.16.0", + "ws": "^8.18.3" }, "devDependencies": { "@eslint/eslintrc": "^3.2.0", @@ -40,6 +41,7 @@ "@types/jest": "^29.5.14", "@types/node": "^22.16.4", "@types/supertest": "^6.0.2", + "@types/ws": "^8.18.1", "eslint": "^9.18.0", "eslint-config-prettier": "^10.0.1", "eslint-plugin-prettier": "^5.2.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66f192a..8e0dda4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ dependencies: ssh2: specifier: ^1.16.0 version: 1.16.0 + ws: + specifier: ^8.18.3 + version: 8.18.3 devDependencies: '@eslint/eslintrc': @@ -76,6 +79,9 @@ devDependencies: '@types/supertest': specifier: ^6.0.2 version: 6.0.3 + '@types/ws': + specifier: ^8.18.1 + version: 8.18.1 eslint: specifier: ^9.18.0 version: 9.31.0 @@ -2008,6 +2014,12 @@ packages: '@types/superagent': 8.1.9 dev: true + /@types/ws@8.18.1: + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + dependencies: + '@types/node': 22.16.5 + dev: true + /@types/yargs-parser@21.0.3: resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} dev: true @@ -6487,6 +6499,19 @@ packages: signal-exit: 3.0.7 dev: true + /ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} diff --git a/src/common/filters/all-exception.filter.ts b/src/common/filters/all-exception.filter.ts index 6d6e6d1..7261b62 100644 --- a/src/common/filters/all-exception.filter.ts +++ b/src/common/filters/all-exception.filter.ts @@ -6,6 +6,9 @@ import { HttpStatus, } from '@nestjs/common'; +/** + * 异常类 + */ @Catch() export class AllExceptionsFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { diff --git a/src/common/interceptors/response.interceptor.ts b/src/common/interceptors/response.interceptor.ts index 6ba1dc4..9975776 100644 --- a/src/common/interceptors/response.interceptor.ts +++ b/src/common/interceptors/response.interceptor.ts @@ -7,6 +7,9 @@ import { import { Observable, map } from 'rxjs'; import { ApiResponse } from '../response-format'; +/** + * 规范返回格式 + */ @Injectable() export class ResponseInterceptor implements NestInterceptor> diff --git a/src/config/config.service.ts b/src/config/config.service.ts index e270c0d..74ff027 100644 --- a/src/config/config.service.ts +++ b/src/config/config.service.ts @@ -14,6 +14,11 @@ export class AppConfigService implements OnModuleInit { this.checkRequiredVariables(); } + /** + * 获取环境变量 + * @param key 键值 + * @param defaultValue 默认 + */ get(key: string, defaultValue?: T): T | undefined { const value = this.nestConfigService.get(key); if (value === undefined || value === null) { diff --git a/src/core/auto-update/auto-update.service.ts b/src/core/auto-update/auto-update.service.ts index 2dfdf07..fda190f 100644 --- a/src/core/auto-update/auto-update.service.ts +++ b/src/core/auto-update/auto-update.service.ts @@ -22,7 +22,7 @@ export class AutoUpdateService { } /** - * 检查是否有远程更新 + * 检查远程更新 */ async checkForUpdates(): Promise { try { diff --git a/src/core/persistence/persistence.service.ts b/src/core/persistence/persistence.service.ts index a0aa509..f19ccc7 100644 --- a/src/core/persistence/persistence.service.ts +++ b/src/core/persistence/persistence.service.ts @@ -28,6 +28,12 @@ export class PersistenceService { } } + /** + * 将数据保存到本地 带格式化 + * @param dataName 数据名 -> 文件夹名 + * @param data 内容 + * @param fileName 文件名 + */ public async writeDataLocal( dataName: string, data: T, @@ -44,6 +50,11 @@ export class PersistenceService { } } + /** + * 从本地读取数据 带解析 + * @param dataName 数据名 -> 文件夹名 + * @param fileName 文件名 + */ public async readDataLocal( dataName: string, fileName: string, diff --git a/src/core/redis/redis.service.ts b/src/core/redis/redis.service.ts index 8eed121..a0e5b4f 100644 --- a/src/core/redis/redis.service.ts +++ b/src/core/redis/redis.service.ts @@ -63,7 +63,7 @@ export class RedisService implements OnModuleInit { this.client.on('ready', () => { this.isConnected = true; - this.logger.debug('Redis连接就绪!'); + this.logger.log('Redis连接就绪!'); }); this.client.on('reconnecting', () => { @@ -71,6 +71,9 @@ export class RedisService implements OnModuleInit { }); } + /** + * 等待redis就绪 + */ public async waitUntilReady(): Promise { if (this.isConnected) return; return new Promise((resolve) => { @@ -80,6 +83,9 @@ export class RedisService implements OnModuleInit { }); } + /** + * 获取单一redis实例 + */ public getClient(): Redis { if (!this.isConnected) { this.logger.error('Redis未连接'); @@ -87,11 +93,20 @@ export class RedisService implements OnModuleInit { return this.client; } + /** + * 断开连接 + */ public async disconnect(): Promise { await this.client.quit(); this.isConnected = false; } + /** + * 储存对象 + * @param key 键 + * @param value 键值 + * @param ttl 缓存时间 + */ public async setObject( key: string, value: T, @@ -104,6 +119,10 @@ export class RedisService implements OnModuleInit { } } + /** + * 从redis中获取对象 + * @param key 键 + */ public async getObject(key: string): Promise { const serialized = await this.client.get(key); if (!serialized) return undefined; @@ -111,6 +130,11 @@ export class RedisService implements OnModuleInit { return RedisUtils.reviveDates(deserialized); } + /** + * 更新redis中的呃对象 + * @param key + * @param updates + */ public async update(key: string, updates: T): Promise { const existing = await this.getObject(key); if (!existing) { @@ -121,6 +145,11 @@ export class RedisService implements OnModuleInit { return updated; } + /** + * 从本地或redis获取对象 + * @param key 键 / 文件夹名 + * @param fileName 文件名 + */ public async fetch(key: string, fileName: string): Promise { const data = await this.getObject(key); if (data) return data; @@ -134,6 +163,12 @@ export class RedisService implements OnModuleInit { this.logger.error(`数据${key}不存在`); } + /** + * 保存对象 + * @param key 键 + * @param data 内容 + * @param fileName 文件名 + */ public async persistData( key: string, data: T, diff --git a/src/core/system/system.service.ts b/src/core/system/system.service.ts index 59ee3ea..8405238 100644 --- a/src/core/system/system.service.ts +++ b/src/core/system/system.service.ts @@ -56,6 +56,9 @@ export class SystemService { process.exit(0); } + /** + * 检查更新 + */ async checkUpdate(): Promise { const updated = await this.autoUpdateService.checkForUpdates(); if (updated) { diff --git a/src/types/ws.ts b/src/types/ws.ts new file mode 100644 index 0000000..43419eb --- /dev/null +++ b/src/types/ws.ts @@ -0,0 +1,18 @@ +import WebSocket from 'ws'; + +export interface AuthenticatedSocket extends WebSocket { + isAuthed?: boolean; + clientId?: string; + heartbeat?: NodeJS.Timeout; +} + +export interface WSMessage { + type: string; + [key: string]: unknown; +} + +export interface AuthMessage extends WSMessage { + type: 'auth'; + secret: string; + clientId: string; +}