From 91620baf59b2cca4d7088a728b9554a39378bbe0 Mon Sep 17 00:00:00 2001 From: wanwu Date: Wed, 29 Oct 2025 13:47:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9B=E5=BB=BAService=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E4=BD=93=E8=BD=AC=E6=8D=A2=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converters/service-method-converter.js | 313 +++++++++++++ .../generators/business-logic-converter.js | 434 ------------------ .../migration-report.json | 18 - wwjcloud-nest-v1/wwjcloud/eslint-report.json | 1 - .../wwjcloud/startup-check.report.json | 12 - 5 files changed, 313 insertions(+), 465 deletions(-) create mode 100644 wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/service-method-converter.js delete mode 100644 wwjcloud-nest-v1/tools/java-to-nestjs-migration/generators/business-logic-converter.js delete mode 100644 wwjcloud-nest-v1/tools/java-to-nestjs-migration/migration-report.json delete mode 100644 wwjcloud-nest-v1/wwjcloud/eslint-report.json delete mode 100644 wwjcloud-nest-v1/wwjcloud/startup-check.report.json diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/service-method-converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/service-method-converter.js new file mode 100644 index 00000000..80a2f72b --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/service-method-converter.js @@ -0,0 +1,313 @@ +const NamingUtils = require('../utils/naming-utils'); + +/** + * Service方法体转换器 + * + * 职责:将Java Service方法体转换为TypeScript + * + * 核心功能: + * 1. 提取Java方法体 + * 2. Java语法 → TypeScript语法转换 + * 3. Java工具类 → NestJS Boot层映射 + */ +class ServiceMethodConverter { + constructor() { + this.namingUtils = new NamingUtils(); + } + + /** + * 转换Java方法体为TypeScript + * + * @param {string} javaMethodBody - Java方法体代码 + * @param {object} context - 上下文信息(Service类信息、依赖等) + * @returns {string} 转换后的TypeScript方法体 + */ + convertMethodBody(javaMethodBody, context = {}) { + if (!javaMethodBody || javaMethodBody.trim() === '') { + return ' // TODO: 实现业务逻辑\n return null;'; + } + + let tsBody = javaMethodBody; + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【阶段1】基础语法转换 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsBody = this.convertBasicSyntax(tsBody); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【阶段2】类型转换 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsBody = this.convertTypes(tsBody); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【阶段3】工具类映射(Java → NestJS Boot层) + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsBody = this.convertUtilityClasses(tsBody); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【阶段4】Mapper/Service调用转换 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsBody = this.convertDependencyCalls(tsBody, context); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【阶段5】添加缩进 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsBody = tsBody.split('\n').map(line => ' ' + line).join('\n'); + + return tsBody; + } + + /** + * 【阶段1】基础语法转换 + */ + convertBasicSyntax(javaBody) { + let tsBody = javaBody; + + // 1. 变量声明:Type varName = value; → const varName: Type = value; + tsBody = tsBody.replace( + /(\b(?:Integer|Long|String|Boolean|Double|Float|BigDecimal|Object|List<[^>]+>|Map<[^>]+>|[\w<>,\s]+))\s+(\w+)\s*=\s*([^;]+);/g, + (match, type, varName, value) => { + const tsType = this.mapJavaTypeToTypeScript(type); + return `const ${varName}: ${tsType} = ${value};`; + } + ); + + // 2. for-each循环:for (Type item : collection) → for (const item of collection) + tsBody = tsBody.replace(/for\s*\(\s*[\w<>,\s]+\s+(\w+)\s*:\s*([^)]+)\)/g, 'for (const $1 of $2)'); + + // 3. Java实例化:new ArrayList<>() → [] + tsBody = tsBody.replace(/new\s+ArrayList<[^>]*>\(\)/g, '[]'); + tsBody = tsBody.replace(/new\s+LinkedList<[^>]*>\(\)/g, '[]'); + tsBody = tsBody.replace(/new\s+HashMap<[^>]*>\(\)/g, '{}'); + tsBody = tsBody.replace(/new\s+HashSet<[^>]*>\(\)/g, 'new Set()'); + + // 4. Lambda表达式:item -> expression → item => expression + tsBody = tsBody.replace(/(\w+)\s*->\s*/g, '$1 => '); + tsBody = tsBody.replace(/\(([^)]+)\)\s*->\s*/g, '($1) => '); + + return tsBody; + } + + /** + * 【阶段2】类型转换 + */ + convertTypes(javaBody) { + let tsBody = javaBody; + + // 1. 基础类型 + tsBody = tsBody.replace(/\bInteger\b/g, 'number'); + tsBody = tsBody.replace(/\bLong\b/g, 'number'); + tsBody = tsBody.replace(/\bDouble\b/g, 'number'); + tsBody = tsBody.replace(/\bFloat\b/g, 'number'); + + // 2. Java对象类型 + tsBody = tsBody.replace(/\bJSONObject\b/g, 'Record'); + tsBody = tsBody.replace(/\bId\b/g, 'number'); + + // 3. Java类型转换语法:(Type) value → value + tsBody = tsBody.replace(/\(\s*(?:int|long|double|float|String|Integer|Long|Double|Float|number)\s*\)\s*/g, ''); + + return tsBody; + } + + /** + * 【阶段3】工具类映射 + */ + convertUtilityClasses(javaBody) { + let tsBody = javaBody; + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【配置访问】WebAppEnvs / GlobalConfig → ConfigService + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + // WebAppEnvs.get().property → this.config.get('property') + tsBody = tsBody.replace(/WebAppEnvs\.get\(\)\.(\w+)/g, (match, prop) => { + return `this.config.get('${prop}')`; + }); + tsBody = tsBody.replace(/WebAppEnvs\.get\(\)/g, 'this.config'); + + // GlobalConfig.property → this.config.get('property') + tsBody = tsBody.replace(/GlobalConfig\.(\w+)/g, (match, prop) => { + return `this.config.get('${prop}')`; + }); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【文件操作】Java File API → Node.js fs/path + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + tsBody = tsBody.replace(/new\s+File\(([^)]+)\)/g, '$1'); + tsBody = tsBody.replace(/(\w+)\.exists\(\)/g, 'fs.existsSync($1)'); + tsBody = tsBody.replace(/(\w+)\.isDirectory\(\)/g, 'fs.lstatSync($1).isDirectory()'); + tsBody = tsBody.replace(/(\w+)\.getName\(\)/g, 'path.basename($1)'); + tsBody = tsBody.replace(/(\w+)\.listFiles\(\)/g, 'fs.readdirSync($1)'); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【字符串方法】 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + // .equals() → === + tsBody = tsBody.replace(/([^!;,\s]+)\.equals\(([^)]+)\)/g, '$1 === $2'); + + // .equalsIgnoreCase() → .toLowerCase() === xxx.toLowerCase() + tsBody = tsBody.replace(/([a-zA-Z_$][\w$.()]+)\.equalsIgnoreCase\(([^)]+)\)/g, '$1.toLowerCase() === $2.toLowerCase()'); + + // .contains() → .includes() + tsBody = tsBody.replace(/\.contains\(/g, '.includes('); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【集合判空】 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + // CollectionUtil.isEmpty(list) → !list || list.length === 0 + tsBody = tsBody.replace(/(?:CollectionUtil|CollUtil)\.isEmpty\(([^)]+)\)/g, '(!$1 || $1.length === 0)'); + tsBody = tsBody.replace(/(?:CollectionUtil|CollUtil)\.isNotEmpty\(([^)]+)\)/g, '($1 && $1.length > 0)'); + + // list.isEmpty() → list.length === 0 + tsBody = tsBody.replace(/([a-zA-Z_$][\w$]*)\.isEmpty\(\)/g, '$1.length === 0'); + tsBody = tsBody.replace(/!([a-zA-Z_$][\w$]*)\.isEmpty\(\)/g, '$1.length > 0'); + + // StringUtils.isEmpty(str) → !str || str.trim() === '' + tsBody = tsBody.replace(/StringUtils\.isEmpty\(([^)]+)\)/g, '(!$1 || $1.trim() === \'\')'); + tsBody = tsBody.replace(/StringUtils\.isNotEmpty\(([^)]+)\)/g, '($1 && $1.trim() !== \'\')'); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【异常处理】 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + tsBody = tsBody.replace(/throw\s+new\s+CommonException\(/g, 'throw new BadRequestException('); + tsBody = tsBody.replace(/throw\s+new\s+AuthException\(/g, 'throw new UnauthorizedException('); + tsBody = tsBody.replace(/throw\s+new\s+RuntimeException\(/g, 'throw new Error('); + tsBody = tsBody.replace(/throw\s+new\s+Exception\(/g, 'throw new Error('); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【其他】 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + // System.out.println → console.log + tsBody = tsBody.replace(/System\.out\.println\(/g, 'console.log('); + tsBody = tsBody.replace(/System\.err\.println\(/g, 'console.error('); + + return tsBody; + } + + /** + * 【阶段4】Mapper/Service调用转换 + */ + convertDependencyCalls(javaBody, context) { + let tsBody = javaBody; + + // Mapper调用:xxxMapper.method() → this.xxxRepository.method() + if (context.dependencies) { + context.dependencies.forEach(dep => { + if (dep.includes('Mapper')) { + const mapperName = dep; + const repoName = this.namingUtils.toCamelCase(dep.replace('Mapper', 'Repository')); + tsBody = tsBody.replace(new RegExp(`${mapperName}\\.`, 'g'), `this.${repoName}.`); + } + }); + } + + // Service调用:xxxService.method() → this.xxxService.method() + if (context.dependencies) { + context.dependencies.forEach(dep => { + if (dep.includes('Service') && !dep.includes('ServiceImpl')) { + const serviceName = this.namingUtils.toCamelCase(dep); + tsBody = tsBody.replace(new RegExp(`${dep}\\.`, 'g'), `this.${serviceName}.`); + } + }); + } + + return tsBody; + } + + /** + * 映射Java类型到TypeScript + */ + mapJavaTypeToTypeScript(javaType) { + // 处理泛型 + if (javaType.includes('<')) { + const genericMatch = javaType.match(/^(\w+)<(.+)>$/); + if (genericMatch) { + const baseType = genericMatch[1]; + const genericType = genericMatch[2]; + + if (baseType === 'List' || baseType === 'ArrayList' || baseType === 'LinkedList') { + return `${this.mapJavaTypeToTypeScript(genericType)}[]`; + } else if (baseType === 'Map' || baseType === 'HashMap') { + return 'Record'; + } + } + } + + const typeMap = { + 'Integer': 'number', + 'int': 'number', + 'Long': 'number', + 'long': 'number', + 'Double': 'number', + 'double': 'number', + 'Float': 'number', + 'float': 'number', + 'BigDecimal': 'number', + 'String': 'string', + 'Boolean': 'boolean', + 'boolean': 'boolean', + 'Object': 'any', + 'void': 'void', + 'File': 'string', + 'JSONObject': 'Record', + 'Id': 'number', + 'Date': 'Date', + 'LocalDateTime': 'Date', + 'LocalDate': 'Date', + 'List': 'any[]', + 'Map': 'Record' + }; + + return typeMap[javaType] || javaType; + } + + /** + * 分析需要的imports + * + * @param {string} convertedBody - 转换后的TypeScript代码 + * @returns {object} 需要导入的模块 + */ + analyzeImports(convertedBody) { + const imports = { + nestjs: new Set(), + boot: new Set(), + nodeModules: new Set() + }; + + // NestJS异常 + if (convertedBody.includes('BadRequestException')) { + imports.nestjs.add('BadRequestException'); + } + if (convertedBody.includes('UnauthorizedException')) { + imports.nestjs.add('UnauthorizedException'); + } + + // Node.js模块 + if (convertedBody.includes('fs.')) { + imports.nodeModules.add('fs'); + } + if (convertedBody.includes('path.')) { + imports.nodeModules.add('path'); + } + + // ConfigService + if (convertedBody.includes('this.config.')) { + imports.boot.add('ConfigService'); + } + + return { + nestjs: Array.from(imports.nestjs), + boot: Array.from(imports.boot), + nodeModules: Array.from(imports.nodeModules) + }; + } +} + +module.exports = ServiceMethodConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/generators/business-logic-converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/generators/business-logic-converter.js deleted file mode 100644 index a6a2a8ba..00000000 --- a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/generators/business-logic-converter.js +++ /dev/null @@ -1,434 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const NamingUtils = require('../utils/naming-utils'); -const TypeMapper = require('../mappers/type-mapper'); - -/** - * 业务逻辑转换器 - * 将Java业务逻辑转换为NestJS业务逻辑 - */ -class BusinessLogicConverter { - constructor() { - this.namingUtils = new NamingUtils(); - this.typeMapper = new TypeMapper(); - } - - /** - * 转换Java方法到NestJS方法 - */ - convertMethod(javaMethod, javaClass) { - const methodName = this.namingUtils.generateMethodName(javaMethod.methodName); - const parameters = this.convertParameters(javaMethod.parameters); - const returnType = this.convertReturnType(javaMethod.returnType); - const body = this.convertMethodBody(javaMethod, javaClass); - - return { - methodName, - parameters, - returnType, - body, - decorators: this.generateMethodDecorators(javaMethod), - imports: this.generateMethodImports(javaMethod) - }; - } - - /** - * 转换方法参数 - */ - convertParameters(javaParameters) { - if (!javaParameters || javaParameters.length === 0) { - return ''; - } - - return javaParameters.map(param => { - const paramName = this.namingUtils.toCamelCase(param.name); - const paramType = this.typeMapper.mapType(param.type); - const decorator = this.generateParameterDecorator(param); - - return `${decorator} ${paramName}: ${paramType.typescript}`; - }).join(', '); - } - - /** - * 转换返回类型 - */ - convertReturnType(javaReturnType) { - if (!javaReturnType) { - return 'void'; - } - - const typeMapping = this.typeMapper.mapType(javaReturnType); - return typeMapping.typescript; - } - - /** - * 转换方法体 - */ - convertMethodBody(javaMethod, javaClass) { - const methodName = javaMethod.methodName; - const body = javaMethod.body || ''; - - // 根据方法名推断业务逻辑 - if (methodName.includes('create') || methodName.includes('add')) { - return this.convertCreateMethod(body, javaClass); - } - - if (methodName.includes('update') || methodName.includes('modify')) { - return this.convertUpdateMethod(body, javaClass); - } - - if (methodName.includes('delete') || methodName.includes('remove')) { - return this.convertDeleteMethod(body, javaClass); - } - - if (methodName.includes('find') || methodName.includes('get') || methodName.includes('query')) { - return this.convertQueryMethod(body, javaClass); - } - - if (methodName.includes('list') || methodName.includes('page')) { - return this.convertListMethod(body, javaClass); - } - - if (methodName.includes('count') || methodName.includes('exists')) { - return this.convertCountMethod(body, javaClass); - } - - // 默认转换 - return this.convertDefaultMethod(body, javaClass); - } - - /** - * 转换创建方法 - */ - convertCreateMethod(javaBody, javaClass) { - const entityName = this.namingUtils.generateEntityName(javaClass.className); - const repositoryName = this.namingUtils.toCamelCase(javaClass.className) + 'Repository'; - - return ` try { - const entity = this.${repositoryName}.create(data); - const result = await this.${repositoryName}.save(entity); - - // 发布领域事件 - await this.domainEventService.publish('${entityName}.created', result); - - return Result.success(result); - } catch (error) { - return Result.error('创建失败: ' + error.message); - }`; - } - - /** - * 转换更新方法 - */ - convertUpdateMethod(javaBody, javaClass) { - const entityName = this.namingUtils.generateEntityName(javaClass.className); - const repositoryName = this.namingUtils.toCamelCase(javaClass.className) + 'Repository'; - - return ` try { - const existingEntity = await this.${repositoryName}.findOne({ where: { id } }); - if (!existingEntity) { - return Result.error('记录不存在'); - } - - await this.${repositoryName}.update(id, data); - const result = await this.${repositoryName}.findOne({ where: { id } }); - - // 发布领域事件 - await this.domainEventService.publish('${entityName}.updated', result); - - return Result.success(result); - } catch (error) { - return Result.error('更新失败: ' + error.message); - }`; - } - - /** - * 转换删除方法 - */ - convertDeleteMethod(javaBody, javaClass) { - const entityName = this.namingUtils.generateEntityName(javaClass.className); - const repositoryName = this.namingUtils.toCamelCase(javaClass.className) + 'Repository'; - - return ` try { - const existingEntity = await this.${repositoryName}.findOne({ where: { id } }); - if (!existingEntity) { - return Result.error('记录不存在'); - } - - await this.${repositoryName}.delete(id); - - // 发布领域事件 - await this.domainEventService.publish('${entityName}.deleted', existingEntity); - - return Result.success({ message: '删除成功' }); - } catch (error) { - return Result.error('删除失败: ' + error.message); - }`; - } - - /** - * 转换查询方法 - */ - convertQueryMethod(javaBody, javaClass) { - const entityName = this.namingUtils.generateEntityName(javaClass.className); - const repositoryName = this.namingUtils.toCamelCase(javaClass.className) + 'Repository'; - - return ` try { - const result = await this.${repositoryName}.findOne({ where: { id } }); - - if (!result) { - return Result.error('记录不存在'); - } - - return Result.success(result); - } catch (error) { - return Result.error('查询失败: ' + error.message); - }`; - } - - /** - * 转换列表方法 - */ - convertListMethod(javaBody, javaClass) { - const entityName = this.namingUtils.generateEntityName(javaClass.className); - const repositoryName = this.namingUtils.toCamelCase(javaClass.className) + 'Repository'; - - return ` try { - const [data, total] = await this.${repositoryName}.findAndCount({ - skip: (page - 1) * limit, - take: limit, - where: this.buildWhereCondition(query) - }); - - return Result.success({ - currentPage: page, - perPage: limit, - total, - data - }); - } catch (error) { - return Result.error('查询失败: ' + error.message); - }`; - } - - /** - * 转换计数方法 - */ - convertCountMethod(javaBody, javaClass) { - const entityName = this.namingUtils.generateEntityName(javaClass.className); - const repositoryName = this.namingUtils.toCamelCase(javaClass.className) + 'Repository'; - - return ` try { - const count = await this.${repositoryName}.count({ - where: this.buildWhereCondition(query) - }); - - return Result.success(count); - } catch (error) { - return Result.error('统计失败: ' + error.message); - }`; - } - - /** - * 转换默认方法 - */ - convertDefaultMethod(javaBody, javaClass) { - return ` try { - // TODO: 实现业务逻辑 - return Result.success(null); - } catch (error) { - return Result.error('操作失败: ' + error.message); - }`; - } - - /** - * 生成方法装饰器 - */ - generateMethodDecorators(javaMethod) { - const decorators = []; - - // 根据方法名添加装饰器 - if (javaMethod.methodName.includes('create') || javaMethod.methodName.includes('add')) { - decorators.push('@Post()'); - } else if (javaMethod.methodName.includes('update') || javaMethod.methodName.includes('modify')) { - decorators.push('@Put()'); - } else if (javaMethod.methodName.includes('delete') || javaMethod.methodName.includes('remove')) { - decorators.push('@Delete()'); - } else { - decorators.push('@Get()'); - } - - // 添加API文档装饰器 - decorators.push('@ApiOperation({ summary: \'' + javaMethod.methodName + '\' })'); - decorators.push('@ApiResponse({ status: 200, description: \'成功\' })'); - - return decorators; - } - - /** - * 生成方法导入 - */ - generateMethodImports(javaMethod) { - const imports = []; - - // 根据方法名添加导入 - if (javaMethod.methodName.includes('create') || javaMethod.methodName.includes('add')) { - imports.push("import { Post } from '@nestjs/common';"); - } else if (javaMethod.methodName.includes('update') || javaMethod.methodName.includes('modify')) { - imports.push("import { Put } from '@nestjs/common';"); - } else if (javaMethod.methodName.includes('delete') || javaMethod.methodName.includes('remove')) { - imports.push("import { Delete } from '@nestjs/common';"); - } else { - imports.push("import { Get } from '@nestjs/common';"); - } - - // 添加API文档导入 - imports.push("import { ApiOperation, ApiResponse } from '@nestjs/swagger';"); - - return imports; - } - - /** - * 生成参数装饰器 - */ - generateParameterDecorator(javaParameter) { - if (javaParameter.annotation === '@RequestBody') { - return '@Body()'; - } else if (javaParameter.annotation === '@PathVariable') { - return '@Param()'; - } else if (javaParameter.annotation === '@RequestParam') { - return '@Query()'; - } else if (javaParameter.annotation === '@RequestHeader') { - return '@Headers()'; - } else if (javaParameter.annotation === '@CookieValue') { - return '@Cookies()'; - } - - return ''; - } - - /** - * 转换Java表达式到TypeScript表达式 - */ - convertExpression(javaExpression) { - let expression = javaExpression; - - // 转换Java语法到TypeScript语法 - expression = expression.replace(/\.equals\(/g, ' === '); - expression = expression.replace(/\.equalsIgnoreCase\(/g, '.toLowerCase() === '); - expression = expression.replace(/\.isEmpty\(\)/g, ' === \'\''); - expression = expression.replace(/\.isNotEmpty\(\)/g, ' !== \'\''); - expression = expression.replace(/\.size\(\)/g, '.length'); - expression = expression.replace(/\.length\(\)/g, '.length'); - - // 转换字符串操作 - expression = expression.replace(/\.substring\(/g, '.substring('); - expression = expression.replace(/\.indexOf\(/g, '.indexOf('); - expression = expression.replace(/\.contains\(/g, '.includes('); - expression = expression.replace(/\.startsWith\(/g, '.startsWith('); - expression = expression.replace(/\.endsWith\(/g, '.endsWith('); - - // 转换集合操作 - expression = expression.replace(/\.add\(/g, '.push('); - expression = expression.replace(/\.remove\(/g, '.splice('); - expression = expression.replace(/\.clear\(\)/g, '.length = 0'); - - // 转换空值检查 - expression = expression.replace(/== null/g, '=== null'); - expression = expression.replace(/!= null/g, '!== null'); - expression = expression.replace(/== undefined/g, '=== undefined'); - expression = expression.replace(/!= undefined/g, '!== undefined'); - - return expression; - } - - /** - * 转换Java条件语句到TypeScript条件语句 - */ - convertConditionalStatement(javaCondition) { - let condition = javaCondition; - - // 转换逻辑操作符 - condition = condition.replace(/&&/g, '&&'); - condition = condition.replace(/||/g, '||'); - condition = condition.replace(/!/g, '!'); - - // 转换比较操作符 - condition = condition.replace(/==/g, '==='); - condition = condition.replace(/!=/g, '!=='); - condition = condition.replace(/<=/g, '<='); - condition = condition.replace(/>=/g, '>='); - condition = condition.replace(//g, '>'); - - return condition; - } - - /** - * 转换Java循环语句到TypeScript循环语句 - */ - convertLoopStatement(javaLoop) { - let loop = javaLoop; - - // 转换for循环 - loop = loop.replace(/for\s*\(\s*int\s+(\w+)\s*=\s*(\d+)\s*;\s*\1\s*<\s*(\w+)\.length\s*;\s*\1\+\+\)/g, 'for (let $1 = $2; $1 < $3.length; $1++)'); - - // 转换增强for循环 - loop = loop.replace(/for\s*\(\s*(\w+)\s+(\w+)\s*:\s*(\w+)\s*\)/g, 'for (const $2 of $3)'); - - // 转换while循环 - loop = loop.replace(/while\s*\(/g, 'while ('); - - // 转换do-while循环 - loop = loop.replace(/do\s*\{/g, 'do {'); - loop = loop.replace(/\}\s*while\s*\(/g, '} while ('); - - return loop; - } - - /** - * 转换Java异常处理到TypeScript异常处理 - */ - convertExceptionHandling(javaException) { - let exception = javaException; - - // 转换try-catch语句 - exception = exception.replace(/try\s*\{/g, 'try {'); - exception = exception.replace(/catch\s*\(\s*(\w+)\s+(\w+)\s*\)/g, 'catch ($2)'); - exception = exception.replace(/finally\s*\{/g, 'finally {'); - - // 转换异常类型 - exception = exception.replace(/Exception/g, 'Error'); - exception = exception.replace(/RuntimeException/g, 'Error'); - exception = exception.replace(/IllegalArgumentException/g, 'Error'); - exception = exception.replace(/NullPointerException/g, 'Error'); - - return exception; - } - - /** - * 验证业务逻辑转换一致性 - */ - validateBusinessLogicConsistency(javaMethod, nestJSMethod) { - const issues = []; - - // 验证方法名 - if (javaMethod.methodName !== nestJSMethod.methodName) { - issues.push(`方法名不一致: ${javaMethod.methodName} vs ${nestJSMethod.methodName}`); - } - - // 验证参数数量 - if (javaMethod.parameters.length !== nestJSMethod.parameters.length) { - issues.push(`参数数量不一致: ${javaMethod.parameters.length} vs ${nestJSMethod.parameters.length}`); - } - - // 验证返回类型 - if (javaMethod.returnType !== nestJSMethod.returnType) { - issues.push(`返回类型不一致: ${javaMethod.returnType} vs ${nestJSMethod.returnType}`); - } - - return issues; - } -} - -module.exports = BusinessLogicConverter; diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/migration-report.json b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/migration-report.json deleted file mode 100644 index 4046c815..00000000 --- a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/migration-report.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "timestamp": "2025-10-29T02:54:59.685Z", - "stats": { - "startTime": "2025-10-29T02:54:58.550Z", - "endTime": null, - "filesProcessed": 1215, - "modulesGenerated": 6, - "errors": [] - }, - "modules": [ - "CommonModule - 通用功能模块", - "EntityModule - 实体模块", - "ServiceModule - 服务模块", - "ControllerModule - 控制器模块", - "ListenerModule - 监听器模块", - "JobModule - 任务模块" - ] -} \ No newline at end of file diff --git a/wwjcloud-nest-v1/wwjcloud/eslint-report.json b/wwjcloud-nest-v1/wwjcloud/eslint-report.json deleted file mode 100644 index 8a1a40ff..00000000 --- a/wwjcloud-nest-v1/wwjcloud/eslint-report.json +++ /dev/null @@ -1 +0,0 @@ -[{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/apps/api/src/app.module.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/apps/api/src/main.ts","messages":[{"ruleId":"@typescript-eslint/no-floating-promises","severity":2,"message":"Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator.","line":15,"column":1,"nodeType":"ExpressionStatement","messageId":"floatingVoid","endLine":15,"endColumn":13,"suggestions":[{"messageId":"floatingFixVoid","fix":{"range":[514,514],"text":"void "},"desc":"Add void operator to ignore."},{"messageId":"floatingFixAwait","fix":{"range":[514,514],"text":"await "},"desc":"Add await operator."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\nimport { BootHttp } from '@wwjCommon/http/boot-http';\nimport { ConfigService } from '@nestjs/config';\n\nasync function bootstrap() {\n const app = await NestFactory.create(AppModule);\n await BootHttp.start(app);\n const config = app.get(ConfigService);\n const raw = config.get('PORT');\n const port =\n typeof raw === 'number' ? raw : parseInt(String(raw ?? '3000'), 10) || 3000;\n await app.listen(port);\n}\nbootstrap();\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/apps/api/src/secure.controller.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-addon/src/index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-addon/src/registry.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":1,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":1,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[30,33],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[30,33],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export type AddonModuleType = any;\n\n// Keyed by lowercase addon name, e.g. { 'oss': OssAddonModule }\nexport const ADDON_REGISTRY: Record = {};\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-addon/src/wwjcloud-addon.module.ts","messages":[{"ruleId":"@typescript-eslint/no-unsafe-return","severity":2,"message":"Unsafe return of a value of type `any`.","line":21,"column":9,"nodeType":"ReturnStatement","messageId":"unsafeReturn","endLine":21,"endColumn":72},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[729,732],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[729,732],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":77,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":80,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[794,797],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[794,797],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Module, DynamicModule, ForwardReference, Type } from '@nestjs/common';\nimport { ADDON_REGISTRY } from './registry';\n\n@Module({\n imports: [],\n providers: [],\n exports: [],\n})\nexport class AddonModule {\n static register(): DynamicModule {\n const enabledKeys = Object.keys(process.env).filter(\n (k) =>\n /^ADDON_.+_ENABLED$/.test(k) &&\n ['true', '1', 'yes'].includes(String(process.env[k]).toLowerCase()),\n );\n\n const imports = enabledKeys\n .map((k) => {\n const m = k.match(/^ADDON_(.+)_ENABLED$/);\n const key = m ? m[1].toLowerCase() : undefined;\n return key && ADDON_REGISTRY[key] ? ADDON_REGISTRY[key] : null;\n })\n .filter(Boolean) as Array<\n Type | DynamicModule | Promise | ForwardReference\n >;\n\n return {\n module: AddonModule,\n imports,\n exports: [],\n };\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/events.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/healing/healing.module.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/healing/interfaces/healing.interface.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":20,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":23,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[161,164],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[161,164],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":21,"column":10,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":21,"endColumn":13,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[352,355],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[352,355],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":22,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":22,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[384,387],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[384,387],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":35,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":35,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[581,584],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[581,584],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":20,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":23,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[728,731],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[728,731],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":45,"column":17,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":45,"endColumn":20,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[759,762],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[759,762],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":64,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":64,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1130,1133],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1130,1133],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":73,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":73,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1291,1294],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1291,1294],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":8,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Healing Module Interfaces - AI 自愈模块接口定义\n */\n\n/**\n * 恢复策略接口\n */\nexport interface RecoveryStrategy {\n name: string;\n priority: number;\n canHandle(error: any): boolean;\n execute(context: RecoveryContext): Promise;\n getEstimatedTime(): number;\n}\n\n/**\n * 恢复上下文接口\n */\nexport interface RecoveryContext {\n taskId: string;\n error: any;\n metadata: Record;\n retryCount: number;\n maxRetries: number;\n startTime: number;\n}\n\n/**\n * 恢复结果接口\n */\nexport interface RecoveryResult {\n success: boolean;\n strategy: string;\n duration: number;\n result?: any;\n error?: string;\n nextAction?: 'retry' | 'escalate' | 'abort';\n}\n\n/**\n * 自愈监听器接口\n */\nexport interface SelfHealListener {\n canHandle(event: any): boolean;\n handle(event: any): Promise;\n getPriority(): number;\n}\n\n/**\n * 错误分析结果接口\n */\nexport interface ErrorAnalysis {\n errorType: string;\n severity: 'low' | 'medium' | 'high' | 'critical';\n category:\n | 'network'\n | 'database'\n | 'service'\n | 'validation'\n | 'system'\n | 'unknown';\n recoverable: boolean;\n suggestedStrategies: string[];\n metadata: Record;\n}\n\n/**\n * 健康检查结果接口\n */\nexport interface HealthCheckResult {\n component: string;\n status: 'healthy' | 'degraded' | 'unhealthy';\n details: Record;\n timestamp: number;\n responseTime?: number;\n}\n\n/**\n * 自愈统计信息接口\n */\nexport interface HealingStats {\n totalRecoveries: number;\n successfulRecoveries: number;\n failedRecoveries: number;\n averageRecoveryTime: number;\n strategiesUsed: Record;\n errorCategories: Record;\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/healing/listeners/ai-recovery.listener.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/healing/listeners/ai-self-heal.listener.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/healing/services/ai-recovery.service.ts","messages":[{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .message on an `any` value.","line":40,"column":52,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":40,"endColumn":59},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async arrow function has no 'await' expression.","line":45,"column":52,"nodeType":"ArrowFunctionExpression","messageId":"missingAwait","endLine":45,"endColumn":54,"suggestions":[{"messageId":"removeAsync","fix":{"range":[1560,1566],"text":""},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an error typed value.","line":180,"column":13,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":180,"endColumn":60},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type error typed assigned to a parameter of type `string | undefined`.","line":184,"column":9,"nodeType":"Identifier","messageId":"unsafeArgument","endLine":184,"endColumn":16},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an error typed value.","line":188,"column":9,"nodeType":"Property","messageId":"anyAssignment","endLine":188,"endColumn":26}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Injectable, Logger } from '@nestjs/common';\nimport { CacheService } from '@wwjCommon/cache/cache.service';\nimport { LockService } from '@wwjCommon/cache/lock.service';\nimport { MetricsService } from '@wwjCommon/metrics/metrics.service';\nimport {\n TASK_RECOVERY_COMPLETED_EVENT,\n TaskRecoveryRequestedPayload,\n TaskRecoveryCompletedPayload,\n TASK_FAILED_EVENT,\n TASK_RECOVERY_REQUESTED_EVENT,\n Severity,\n TaskFailedPayload,\n} from '@wwjAi';\nimport { EventBus } from '@wwjCommon/events/event-bus';\nimport { QueueService } from '@wwjCommon/queue/queue.service';\nimport { ConfigService } from '@nestjs/config';\nimport { AiStrategyService } from '@wwjAi';\n\nconst QUEUE_KEY = 'ai:recovery:queue';\nconst QUEUE_LOCK_KEY = 'ai:recovery:lock';\n\n@Injectable()\nexport class AiRecoveryService {\n private readonly logger = new Logger(AiRecoveryService.name);\n // metrics injected via constructor now\n\n constructor(\n private readonly cache: CacheService,\n private readonly lock: LockService,\n private readonly metrics: MetricsService,\n private readonly eventBus: EventBus,\n private readonly queue: QueueService,\n private readonly config: ConfigService,\n private readonly strategy: AiStrategyService,\n ) {}\n\n onModuleInit() {\n // 初始化可选的队列(BullMQ / Kafka)\n this.queue.init('ai-recovery').catch((err) => {\n this.logger.error(`Queue init failed: ${err?.message || err}`);\n });\n if (this.queue.isBullmq() || this.queue.isKafka()) {\n // 注册 Worker 处理恢复请求(BullMQ/Kafka 共用统一处理器)\n this.queue.registerWorker(\n async (data: TaskRecoveryRequestedPayload) => {\n const start = Date.now();\n this.logger.log(\n `Processing recovery (worker) for taskId=${data.taskId}`,\n );\n const durationMs = Date.now() - start;\n const payload: TaskRecoveryCompletedPayload = {\n taskId: data.taskId,\n strategy: data.strategy,\n result: 'success',\n durationMs,\n timestamp: Date.now(),\n };\n this.eventBus.emit(TASK_RECOVERY_COMPLETED_EVENT, payload);\n this.metrics?.observeAiEvent(\n TASK_RECOVERY_COMPLETED_EVENT,\n undefined,\n data.strategy,\n );\n },\n 1,\n 'ai-recovery',\n );\n }\n }\n\n async enqueue(req: TaskRecoveryRequestedPayload): Promise {\n // 若启用队列,优先走队列(BullMQ/Kafka)\n if (this.queue.isBullmq() || this.queue.isKafka()) {\n await this.queue.enqueue('ai.recovery', req);\n // BullMQ 可以返回计数,Kafka 不易获取队列深度,这里统一返回 0 或 BullMQ 等待数量\n if (this.queue.isBullmq()) {\n const counts = await this.queue.getQueueCounts();\n const waiting = counts?.waiting ?? 0;\n const delayed = counts?.delayed ?? 0;\n return waiting + delayed;\n }\n return 0;\n }\n // 默认使用内存/Redis 模拟队列\n const list =\n (await this.cache.get(QUEUE_KEY)) ?? [];\n list.push(req);\n await this.cache.set(QUEUE_KEY, list);\n this.logger.log(\n `Enqueued recovery request: taskId=${req.taskId}, strategy=${req.strategy}`,\n );\n return list.length;\n }\n\n async status() {\n if (this.queue.isBullmq()) {\n const counts = await this.queue.getQueueCounts();\n const waiting = counts?.waiting ?? 0;\n const delayed = counts?.delayed ?? 0;\n return { size: waiting + delayed };\n }\n if (this.queue.isKafka()) {\n // Kafka 模式下无法快速获取队列大小,返回 0 以表示“由后台异步处理”\n return { size: 0 };\n }\n const list =\n (await this.cache.get(QUEUE_KEY)) ?? [];\n return { size: list.length };\n }\n\n async processOne(): Promise {\n // 队列模式下由 Worker 自动处理,processOne 返回 false 表示无需手动触发\n if (this.queue.isBullmq() || this.queue.isKafka()) return false;\n\n const list =\n (await this.cache.get(QUEUE_KEY)) ?? [];\n if (list.length === 0) return false;\n\n const lockToken = await this.lock.acquire(QUEUE_LOCK_KEY, 5000);\n if (!lockToken) return false; // someone else is processing\n\n try {\n const req = list.shift()!;\n await this.cache.set(QUEUE_KEY, list);\n // simulate processing logic here\n const start = Date.now();\n this.logger.log(`Processed recovery for taskId=${req.taskId}`);\n const durationMs = Date.now() - start;\n this.logger.log(\n `Processed recovery request: taskId=${req.taskId}, strategy=${req.strategy}`,\n );\n const payload: TaskRecoveryCompletedPayload = {\n taskId: req.taskId,\n strategy: req.strategy,\n result: 'success',\n durationMs,\n timestamp: Date.now(),\n };\n this.eventBus.emit(TASK_RECOVERY_COMPLETED_EVENT, payload);\n this.metrics?.observeAiEvent(\n TASK_RECOVERY_COMPLETED_EVENT,\n undefined,\n req.strategy,\n );\n return true;\n } finally {\n await this.lock.release(QUEUE_LOCK_KEY, lockToken);\n }\n }\n\n async drain(max = 10): Promise {\n // 队列模式下由 Worker 自动处理,这里返回 0 表示无需手动 drain\n if (this.queue.isBullmq() || this.queue.isKafka()) return 0;\n\n let processed = 0;\n while (processed < max) {\n const ok = await this.processOne();\n if (!ok) break;\n processed++;\n }\n return processed;\n }\n async simulateFailure(params: {\n taskId?: string;\n severity?: Severity;\n reason?: string;\n }): Promise<{ ok: true; emitted: boolean }> {\n const taskId = params.taskId ?? 'demo-task';\n const severity: Severity = params.severity ?? 'medium';\n const reason = params.reason ?? 'demo failure';\n const payload: TaskFailedPayload = {\n taskId,\n reason,\n severity,\n timestamp: Date.now(),\n };\n this.eventBus.emit(TASK_FAILED_EVENT, payload);\n this.metrics?.observeAiEvent(TASK_FAILED_EVENT, severity);\n if (this.readBoolean('AI_SIMULATE_DIRECT_ENQUEUE')) {\n const decided = this.strategy.decideStrategy(payload);\n this.metrics?.observeAiEvent(\n TASK_RECOVERY_REQUESTED_EVENT,\n undefined,\n decided,\n );\n const request: TaskRecoveryRequestedPayload = {\n taskId,\n strategy: decided,\n requestedBy: 'manual',\n timestamp: Date.now(),\n };\n await this.enqueue(request);\n }\n return { ok: true, emitted: true };\n }\n private readBoolean(key: string): boolean {\n const v = this.config.get(key);\n if (typeof v === 'boolean') return v;\n if (typeof v === 'string')\n return ['true', '1', 'yes', 'on'].includes(v.toLowerCase());\n return false;\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/healing/services/ai-strategy.service.ts","messages":[{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an error typed value.","line":21,"column":11,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":21,"endColumn":43},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Computed name [evt.severity] resolves to an `error` typed value.","line":21,"column":19,"nodeType":"MemberExpression","messageId":"unsafeComputedMemberAccess","endLine":21,"endColumn":31},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .severity on an `error` typed value.","line":21,"column":23,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":21,"endColumn":31},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .metadata on an `error` typed value.","line":23,"column":22,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":23,"endColumn":30}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Injectable } from '@nestjs/common';\nimport { ConfigService } from '@nestjs/config';\nimport type { Severity, RecoveryStrategy, TaskFailedPayload } from '../types';\n\n@Injectable()\nexport class AiStrategyService {\n constructor(private readonly config: ConfigService) {}\n\n decideStrategy(evt: TaskFailedPayload): RecoveryStrategy {\n // allow override via env for quick testing\n const override = this.config.get('AI_STRATEGY_OVERRIDE');\n if (override && this.isValidStrategy(override)) {\n return override as RecoveryStrategy;\n }\n // simple mapping by severity; can be extended to rules by metadata\n const map: Record = {\n low: 'retry',\n medium: 'retry',\n high: 'fallback',\n };\n const s = map[evt.severity] ?? 'retry';\n // extend: if metadata.hint === 'reroute', do reroute\n const hint = evt.metadata?.hint as string | undefined;\n if (hint === 'reroute') return 'reroute';\n if (hint === 'restart') return 'restart';\n return s;\n }\n\n private isValidStrategy(v: string): boolean {\n return ['retry', 'restart', 'reroute', 'fallback', 'noop'].includes(v);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/healing/strategies/fallback.strategy.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":26,"column":20,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":26,"endColumn":23,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[506,509],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[506,509],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .code on an `any` value.","line":36,"column":16,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":36,"endColumn":20},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":36,"column":48,"nodeType":"MemberExpression","messageId":"unsafeArgument","endLine":36,"endColumn":58},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .code on an `any` value.","line":36,"column":54,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":36,"endColumn":58},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .severity on an `any` value.","line":41,"column":16,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":41,"endColumn":24},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .severity on an `any` value.","line":41,"column":46,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":41,"endColumn":54},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":58,"column":13,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":58,"endColumn":70},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":64,"column":9,"nodeType":"Property","messageId":"anyAssignment","endLine":64,"endColumn":31},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":93,"column":73,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":93,"endColumn":76,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2007,2010],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2007,2010],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":94,"column":11,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":94,"endColumn":61},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'handleDatabaseFallback' has no 'await' expression.","line":119,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":119,"endColumn":39,"suggestions":[{"messageId":"removeAsync","fix":{"range":[2608,2676],"text":"handleDatabaseFallback(context: RecoveryContext): any"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":119,"column":75,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":119,"endColumn":78,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2672,2675],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2672,2675],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":125,"column":7,"nodeType":"Property","messageId":"anyAssignment","endLine":125,"endColumn":49},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'handleApiFallback' has no 'await' expression.","line":134,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":134,"endColumn":34,"suggestions":[{"messageId":"removeAsync","fix":{"range":[3008,3071],"text":"handleApiFallback(context: RecoveryContext): any"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":134,"column":70,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":134,"endColumn":73,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3067,3070],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3067,3070],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":140,"column":7,"nodeType":"Property","messageId":"anyAssignment","endLine":140,"endColumn":75},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":149,"column":72,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":149,"endColumn":75,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3479,3482],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3479,3482],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":155,"column":7,"nodeType":"Property","messageId":"anyAssignment","endLine":155,"endColumn":52},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'handleFileFallback' has no 'await' expression.","line":164,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":164,"endColumn":35,"suggestions":[{"messageId":"removeAsync","fix":{"range":[3804,3868],"text":"handleFileFallback(context: RecoveryContext): any"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":164,"column":71,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":164,"endColumn":74,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3864,3867],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3864,3867],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":170,"column":7,"nodeType":"Property","messageId":"anyAssignment","endLine":170,"endColumn":50},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'handleGenericFallback' has no 'await' expression.","line":179,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":179,"endColumn":38,"suggestions":[{"messageId":"removeAsync","fix":{"range":[4191,4258],"text":"handleGenericFallback(context: RecoveryContext): any"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":179,"column":74,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":179,"endColumn":77,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4254,4257],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4254,4257],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":193,"column":72,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":193,"endColumn":75,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4606,4609],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4606,4609],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-call","severity":2,"message":"Unsafe call of a(n) `any` typed value.","line":198,"column":20,"nodeType":"MemberExpression","messageId":"unsafeCall","endLine":198,"endColumn":55}],"suppressedMessages":[],"errorCount":25,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Injectable, Logger } from '@nestjs/common';\nimport {\n RecoveryStrategy,\n RecoveryContext,\n RecoveryResult,\n} from '../interfaces/healing.interface';\n\n/**\n * Fallback Recovery Strategy - 降级恢复策略\n *\n * 职责:\n * - 提供服务降级方案\n * - 处理不可恢复的错误\n * - 确保系统基本功能可用\n */\n@Injectable()\nexport class FallbackStrategy implements RecoveryStrategy {\n private readonly logger = new Logger(FallbackStrategy.name);\n\n readonly name = 'fallback';\n readonly priority = 3;\n\n /**\n * 判断是否可以处理该错误\n */\n canHandle(error: any): boolean {\n // 需要降级处理的错误类型\n const fallbackErrors = [\n 'SERVICE_UNAVAILABLE',\n 'DEPENDENCY_FAILURE',\n 'RESOURCE_EXHAUSTED',\n 'CIRCUIT_BREAKER_OPEN',\n 'RATE_LIMIT_EXCEEDED',\n ];\n\n if (error?.code && fallbackErrors.includes(error.code)) {\n return true;\n }\n\n // 检查错误严重程度\n if (error?.severity === 'high' || error?.severity === 'critical') {\n return true;\n }\n\n return false;\n }\n\n /**\n * 执行降级恢复\n */\n async execute(context: RecoveryContext): Promise {\n const startTime = Date.now();\n\n this.logger.log(`Executing fallback strategy for task: ${context.taskId}`);\n\n try {\n // 根据任务类型选择降级方案\n const fallbackResult = await this.selectFallbackOption(context);\n\n return {\n success: true,\n strategy: this.name,\n duration: Date.now() - startTime,\n result: fallbackResult,\n nextAction: 'abort', // 降级后通常不再重试\n };\n } catch (error) {\n this.logger.error(\n `Fallback strategy failed for task: ${context.taskId}`,\n error,\n );\n\n return {\n success: false,\n strategy: this.name,\n duration: Date.now() - startTime,\n error: error instanceof Error ? error.message : 'Fallback failed',\n nextAction: 'abort',\n };\n }\n }\n\n /**\n * 获取预估执行时间\n */\n getEstimatedTime(): number {\n return 2000; // 2秒预估时间\n }\n\n /**\n * 选择降级方案\n */\n private async selectFallbackOption(context: RecoveryContext): Promise {\n const taskType = context.metadata?.taskType || 'unknown';\n\n this.logger.debug(`Selecting fallback option for task type: ${taskType}`);\n\n switch (taskType) {\n case 'database':\n return await this.handleDatabaseFallback(context);\n\n case 'api':\n return await this.handleApiFallback(context);\n\n case 'cache':\n return await this.handleCacheFallback(context);\n\n case 'file':\n return await this.handleFileFallback(context);\n\n default:\n return await this.handleGenericFallback(context);\n }\n }\n\n /**\n * 数据库降级处理\n */\n private async handleDatabaseFallback(context: RecoveryContext): Promise {\n this.logger.warn(`Database fallback for task: ${context.taskId}`);\n\n // 返回缓存数据或默认值\n return {\n fallbackType: 'database',\n data: context.metadata?.cachedData || null,\n message: 'Using cached data due to database unavailability',\n timestamp: Date.now(),\n };\n }\n\n /**\n * API 降级处理\n */\n private async handleApiFallback(context: RecoveryContext): Promise {\n this.logger.warn(`API fallback for task: ${context.taskId}`);\n\n // 返回默认响应或离线数据\n return {\n fallbackType: 'api',\n data: context.metadata?.defaultResponse || { status: 'unavailable' },\n message: 'Using default response due to API unavailability',\n timestamp: Date.now(),\n };\n }\n\n /**\n * 缓存降级处理\n */\n private async handleCacheFallback(context: RecoveryContext): Promise {\n this.logger.warn(`Cache fallback for task: ${context.taskId}`);\n\n // 直接访问数据源\n return {\n fallbackType: 'cache',\n data: await this.fetchFromDataSource(context),\n message: 'Bypassing cache and fetching from data source',\n timestamp: Date.now(),\n };\n }\n\n /**\n * 文件降级处理\n */\n private async handleFileFallback(context: RecoveryContext): Promise {\n this.logger.warn(`File fallback for task: ${context.taskId}`);\n\n // 使用备用文件或默认内容\n return {\n fallbackType: 'file',\n data: context.metadata?.backupContent || '',\n message: 'Using backup content due to file access failure',\n timestamp: Date.now(),\n };\n }\n\n /**\n * 通用降级处理\n */\n private async handleGenericFallback(context: RecoveryContext): Promise {\n this.logger.warn(`Generic fallback for task: ${context.taskId}`);\n\n return {\n fallbackType: 'generic',\n data: null,\n message: 'Service temporarily unavailable, please try again later',\n timestamp: Date.now(),\n };\n }\n\n /**\n * 从数据源获取数据\n */\n private async fetchFromDataSource(context: RecoveryContext): Promise {\n // 这里应该实现从原始数据源获取数据的逻辑\n // 具体实现取决于数据源类型\n\n if (context.metadata?.dataSourceFunction) {\n return await context.metadata.dataSourceFunction();\n }\n\n return null;\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/healing/strategies/retry.strategy.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":26,"column":20,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":26,"endColumn":23,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[492,495],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[492,495],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .code on an `any` value.","line":37,"column":16,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":37,"endColumn":20},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":37,"column":49,"nodeType":"MemberExpression","messageId":"unsafeArgument","endLine":37,"endColumn":59},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .code on an `any` value.","line":37,"column":55,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":37,"endColumn":59},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .message on an `any` value.","line":41,"column":16,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":41,"endColumn":23},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":42,"column":13,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":42,"endColumn":50},{"ruleId":"@typescript-eslint/no-unsafe-call","severity":2,"message":"Unsafe call of a(n) `any` typed value.","line":42,"column":23,"nodeType":"MemberExpression","messageId":"unsafeCall","endLine":42,"endColumn":48},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .message on an `any` value.","line":42,"column":29,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":42,"endColumn":36},{"ruleId":"@typescript-eslint/no-unsafe-return","severity":2,"message":"Unsafe return of a value of type `any`.","line":43,"column":7,"nodeType":"ReturnStatement","messageId":"unsafeReturn","endLine":48,"endColumn":9},{"ruleId":"@typescript-eslint/no-unsafe-call","severity":2,"message":"Unsafe call of a(n) `any` typed value.","line":44,"column":9,"nodeType":"MemberExpression","messageId":"unsafeCall","endLine":44,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .includes on an `any` value.","line":44,"column":17,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":44,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-call","severity":2,"message":"Unsafe call of a(n) `any` typed value.","line":45,"column":9,"nodeType":"MemberExpression","messageId":"unsafeCall","endLine":45,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .includes on an `any` value.","line":45,"column":17,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":45,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-call","severity":2,"message":"Unsafe call of a(n) `any` typed value.","line":46,"column":9,"nodeType":"MemberExpression","messageId":"unsafeCall","endLine":46,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .includes on an `any` value.","line":46,"column":17,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":46,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-call","severity":2,"message":"Unsafe call of a(n) `any` typed value.","line":47,"column":9,"nodeType":"MemberExpression","messageId":"unsafeCall","endLine":47,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .includes on an `any` value.","line":47,"column":17,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":47,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":85,"column":13,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":85,"endColumn":54},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":91,"column":9,"nodeType":"Property","messageId":"anyAssignment","endLine":91,"endColumn":15},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":135,"column":65,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":135,"endColumn":68,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3060,3063],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3060,3063],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-call","severity":2,"message":"Unsafe call of a(n) `any` typed value.","line":143,"column":20,"nodeType":"MemberExpression","messageId":"unsafeCall","endLine":143,"endColumn":53}],"suppressedMessages":[],"errorCount":21,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Injectable, Logger } from '@nestjs/common';\nimport {\n RecoveryStrategy,\n RecoveryContext,\n RecoveryResult,\n} from '../interfaces/healing.interface';\n\n/**\n * Retry Recovery Strategy - 重试恢复策略\n *\n * 职责:\n * - 处理可重试的错误\n * - 实现指数退避重试机制\n * - 监控重试成功率\n */\n@Injectable()\nexport class RetryStrategy implements RecoveryStrategy {\n private readonly logger = new Logger(RetryStrategy.name);\n\n readonly name = 'retry';\n readonly priority = 1;\n\n /**\n * 判断是否可以处理该错误\n */\n canHandle(error: any): boolean {\n // 可重试的错误类型\n const retryableErrors = [\n 'ECONNRESET',\n 'ETIMEDOUT',\n 'ENOTFOUND',\n 'ECONNREFUSED',\n 'NETWORK_ERROR',\n 'TEMPORARY_FAILURE',\n ];\n\n if (error?.code && retryableErrors.includes(error.code)) {\n return true;\n }\n\n if (error?.message) {\n const message = error.message.toLowerCase();\n return (\n message.includes('timeout') ||\n message.includes('connection') ||\n message.includes('network') ||\n message.includes('temporary')\n );\n }\n\n return false;\n }\n\n /**\n * 执行重试恢复\n */\n async execute(context: RecoveryContext): Promise {\n const startTime = Date.now();\n\n this.logger.log(\n `Executing retry strategy for task: ${context.taskId}, attempt: ${context.retryCount + 1}`,\n );\n\n try {\n // 计算退避延迟\n const delay = this.calculateBackoffDelay(context.retryCount);\n\n if (delay > 0) {\n this.logger.debug(`Waiting ${delay}ms before retry`);\n await this.sleep(delay);\n }\n\n // 检查是否超过最大重试次数\n if (context.retryCount >= context.maxRetries) {\n return {\n success: false,\n strategy: this.name,\n duration: Date.now() - startTime,\n error: 'Maximum retry attempts exceeded',\n nextAction: 'escalate',\n };\n }\n\n // 执行重试逻辑\n const result = await this.performRetry(context);\n\n return {\n success: true,\n strategy: this.name,\n duration: Date.now() - startTime,\n result,\n nextAction: 'retry',\n };\n } catch (error) {\n this.logger.error(\n `Retry strategy failed for task: ${context.taskId}`,\n error,\n );\n\n return {\n success: false,\n strategy: this.name,\n duration: Date.now() - startTime,\n error: error instanceof Error ? error.message : 'Unknown error',\n nextAction:\n context.retryCount < context.maxRetries ? 'retry' : 'escalate',\n };\n }\n }\n\n /**\n * 获取预估执行时间\n */\n getEstimatedTime(): number {\n return 5000; // 5秒预估时间\n }\n\n /**\n * 计算指数退避延迟\n */\n private calculateBackoffDelay(retryCount: number): number {\n // 指数退避:2^retryCount * 1000ms,最大30秒\n const baseDelay = 1000;\n const maxDelay = 30000;\n const delay = Math.min(baseDelay * Math.pow(2, retryCount), maxDelay);\n\n // 添加随机抖动,避免雷群效应\n const jitter = Math.random() * 0.1 * delay;\n return Math.floor(delay + jitter);\n }\n\n /**\n * 执行重试\n */\n private async performRetry(context: RecoveryContext): Promise {\n // 这里应该重新执行原始任务\n // 具体实现取决于任务类型和上下文\n\n this.logger.debug(`Performing retry for task: ${context.taskId}`);\n\n // 模拟重试逻辑\n if (context.metadata?.originalFunction) {\n return await context.metadata.originalFunction();\n }\n\n // 如果没有原始函数,返回成功标记\n return { retried: true, timestamp: Date.now() };\n }\n\n /**\n * 睡眠函数\n */\n private sleep(ms: number): Promise {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/index.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/manager/bootstrap/ai-bootstrap.provider.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/manager/controllers/ai.controller.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'TASK_FAILED_EVENT' is defined but never used.","line":9,"column":10,"nodeType":null,"messageId":"unusedVar","endLine":9,"endColumn":27},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'TASK_RECOVERY_REQUESTED_EVENT' is defined but never used.","line":9,"column":29,"nodeType":null,"messageId":"unusedVar","endLine":9,"endColumn":58},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'TaskFailedPayload' is defined but never used.","line":12,"column":3,"nodeType":null,"messageId":"unusedVar","endLine":12,"endColumn":20},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'TaskRecoveryRequestedPayload' is defined but never used.","line":13,"column":3,"nodeType":null,"messageId":"unusedVar","endLine":13,"endColumn":31}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Controller, Get, Query, UseGuards, Post } from '@nestjs/common';\nimport { RateLimitGuard } from '@wwjCommon/http/rate-limit.guard';\nimport { AiRecoveryService } from '../../healing/services/ai-recovery.service';\nimport { ApiTags } from '@nestjs/swagger';\nimport { ApiQuery } from '@nestjs/swagger';\nimport { IsInt, IsOptional, Min, IsString, IsIn } from 'class-validator';\nimport { Public, Roles } from '@wwjCommon/auth/decorators';\nimport { EventBus } from '@wwjCommon/events/event-bus';\nimport { TASK_FAILED_EVENT, TASK_RECOVERY_REQUESTED_EVENT } from '@wwjAi';\nimport type {\n Severity,\n TaskFailedPayload,\n TaskRecoveryRequestedPayload,\n} from '@wwjAi';\nimport { ConfigService } from '@nestjs/config';\nimport { MetricsService } from '@wwjCommon/metrics/metrics.service';\nimport { AuthGuard } from '@wwjCommon/auth/auth.guard';\nimport { RbacGuard } from '@wwjCommon/auth/rbac.guard';\nimport { AiStrategyService } from '@wwjAi';\n\nclass DrainQueryDto {\n @IsInt()\n @Min(1)\n @IsOptional()\n max?: number;\n}\n\nclass SimulateFailureQueryDto {\n @IsString()\n @IsOptional()\n taskId?: string;\n\n @IsString()\n @IsIn(['low', 'medium', 'high'])\n @IsOptional()\n severity?: Severity;\n\n @IsString()\n @IsOptional()\n reason?: string;\n}\n\n@UseGuards(AuthGuard, RbacGuard, RateLimitGuard)\n@ApiTags('AI')\n@Controller('ai/recovery')\nexport class AiController {\n constructor(\n private readonly recovery: AiRecoveryService,\n private readonly eventBus: EventBus,\n private readonly config: ConfigService,\n private readonly metrics: MetricsService,\n private readonly strategy: AiStrategyService,\n ) {}\n\n @Get('status')\n @Public()\n async status() {\n return await this.recovery.status();\n }\n\n @Get('process-one')\n @Post('process-one')\n @Roles('admin')\n async processOne() {\n const ok = await this.recovery.processOne();\n return { ok };\n }\n\n @Get('drain')\n @Post('drain')\n @Roles('admin')\n @ApiQuery({\n name: 'max',\n required: false,\n type: Number,\n description: '最大处理数量(默认10)',\n })\n async drain(@Query() query: DrainQueryDto) {\n const n = await this.recovery.drain(query.max ?? 10);\n return { processed: n };\n }\n\n @Get('simulate-failure')\n @Post('simulate-failure')\n @Roles('admin')\n @ApiQuery({ name: 'taskId', required: false, type: String })\n @ApiQuery({\n name: 'severity',\n required: false,\n enum: ['low', 'medium', 'high'],\n })\n @ApiQuery({ name: 'reason', required: false, type: String })\n async simulateFailure(\n @Query() q: SimulateFailureQueryDto,\n ): Promise<{ ok: true; emitted: boolean }> {\n // 委派到服务层,控制器不再直接发事件或打点\n return await this.recovery.simulateFailure({\n taskId: q.taskId,\n severity: q.severity,\n reason: q.reason,\n });\n }\n\n // 移除 readBoolean 与直接依赖 metrics/strategy\n private readBoolean(key: string): boolean {\n const v = this.config.get(key);\n if (typeof v === 'boolean') return v;\n if (typeof v === 'string') return v === 'true' || v === '1' || v === 'yes';\n return false;\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/manager/interfaces/ai-manager.interface.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":23,"column":29,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":23,"endColumn":32,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[356,359],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[356,359],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[643,646],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[643,646],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":29,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":32,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[876,879],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[876,879],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":66,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":66,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1049,1052],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1049,1052],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":77,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":77,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1218,1221],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1218,1221],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * AI Manager Interfaces - AI 管理模块接口定义\n */\n\n/**\n * 工作流程配置接口\n */\nexport interface WorkflowConfig {\n steps: string[];\n timeout: number;\n retryCount: number;\n parallel?: boolean;\n dependencies?: string[];\n}\n\n/**\n * 工作流程执行上下文接口\n */\nexport interface WorkflowContext {\n taskId: string;\n userId?: string;\n siteId?: number;\n metadata?: Record;\n startTime: number;\n}\n\n/**\n * 工作流程执行结果接口\n */\nexport interface WorkflowResult {\n success: boolean;\n steps: StepResult[];\n duration: number;\n error?: string;\n}\n\n/**\n * 步骤执行结果接口\n */\nexport interface StepResult {\n step: string;\n success: boolean;\n duration: number;\n result?: any;\n error?: string;\n}\n\n/**\n * 模块状态接口\n */\nexport interface ModuleState {\n name: string;\n status: 'initializing' | 'ready' | 'active' | 'error' | 'unavailable';\n version: string;\n lastUpdate: number;\n metadata?: Record;\n}\n\n/**\n * 任务协调请求接口\n */\nexport interface TaskCoordinationRequest {\n taskId: string;\n taskType: string;\n priority: 'low' | 'medium' | 'high' | 'critical';\n payload: any;\n requiredModules?: string[];\n timeout?: number;\n}\n\n/**\n * 任务协调结果接口\n */\nexport interface TaskCoordinationResult {\n taskId: string;\n success: boolean;\n result?: any;\n error?: string;\n duration: number;\n modulesUsed: string[];\n}\n\n/**\n * AI 管理器统计信息接口\n */\nexport interface AiManagerStats {\n modules: {\n total: number;\n active: number;\n error: number;\n };\n services: {\n total: number;\n healthy: number;\n byType: Record;\n };\n workflows: {\n active: string[];\n completed: number;\n failed: number;\n };\n tasks: {\n pending: number;\n byType: Record;\n oldestAge?: number;\n };\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/manager/manager.module.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/manager/services/ai-coordinator.service.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":19,"column":51,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":19,"endColumn":54,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[632,635],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[632,635],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'initializeModuleStates' has no 'await' expression.","line":37,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":37,"endColumn":39,"suggestions":[{"messageId":"removeAsync","fix":{"range":[1102,1147],"text":"initializeModuleStates(): void"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":84,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":84,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2163,2166],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2163,2166],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":85,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":85,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2181,2184],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2181,2184],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":100,"column":13,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":104,"endColumn":8},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":106,"column":66,"nodeType":"Property","messageId":"anyAssignment","endLine":106,"endColumn":72},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":113,"column":9,"nodeType":"Property","messageId":"anyAssignment","endLine":113,"endColumn":14},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkModuleAvailability' has no 'await' expression.","line":136,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":136,"endColumn":40,"suggestions":[{"messageId":"removeAsync","fix":{"range":[3472,3615],"text":"checkModuleAvailability(modules: string[]): {\n allAvailable: boolean;\n available: string[];\n unavailable: string[];\n }"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":166,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":166,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4155,4158],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4155,4158],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":167,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":167,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4173,4176],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4173,4176],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":169,"column":47,"nodeType":"Property","messageId":"anyAssignment","endLine":169,"endColumn":54},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":177,"column":11,"nodeType":"AssignmentExpression","messageId":"anyAssignment","endLine":180,"endColumn":12},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":183,"column":11,"nodeType":"AssignmentExpression","messageId":"anyAssignment","endLine":186,"endColumn":12},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":189,"column":11,"nodeType":"AssignmentExpression","messageId":"anyAssignment","endLine":192,"endColumn":12},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":195,"column":11,"nodeType":"AssignmentExpression","messageId":"anyAssignment","endLine":195,"endColumn":67},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":210,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":210,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5159,5162],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5159,5162],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":211,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":211,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5177,5180],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5177,5180],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":226,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":226,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5526,5529],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5526,5529],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .taskId on an `any` value.","line":227,"column":46,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":227,"endColumn":52},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .severity on an `any` value.","line":230,"column":17,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":230,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .taskId on an `any` value.","line":231,"column":53,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":231,"endColumn":59},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":232,"column":9,"nodeType":"Property","messageId":"anyAssignment","endLine":232,"endColumn":30},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":241,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":241,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5890,5893],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5890,5893],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .module on an `any` value.","line":243,"column":40,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":243,"endColumn":46},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .currentState on an `any` value.","line":243,"column":61,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":243,"endColumn":73},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":247,"column":27,"nodeType":"MemberExpression","messageId":"unsafeArgument","endLine":247,"endColumn":41},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .module on an `any` value.","line":247,"column":35,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":247,"endColumn":41},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":247,"column":43,"nodeType":"MemberExpression","messageId":"unsafeArgument","endLine":247,"endColumn":63},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .currentState on an `any` value.","line":247,"column":51,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":247,"endColumn":63},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .currentState on an `any` value.","line":251,"column":15,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":251,"endColumn":27},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .currentState on an `any` value.","line":252,"column":15,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":252,"endColumn":27},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":254,"column":35,"nodeType":"MemberExpression","messageId":"unsafeArgument","endLine":254,"endColumn":49},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .module on an `any` value.","line":254,"column":43,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":254,"endColumn":49},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'pauseModuleTasks' has no 'await' expression.","line":261,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":261,"endColumn":33,"suggestions":[{"messageId":"removeAsync","fix":{"range":[6336,6393],"text":"pauseModuleTasks(moduleName: string): void"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":265,"column":55,"nodeType":"MemberExpression","messageId":"unsafeArgument","endLine":265,"endColumn":68},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .taskType on an `any` value.","line":265,"column":60,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":265,"endColumn":68},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Computed name [task.taskType] resolves to an `any` value.","line":289,"column":14,"nodeType":"MemberExpression","messageId":"unsafeComputedMemberAccess","endLine":289,"endColumn":27},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .taskType on an `any` value.","line":289,"column":19,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":289,"endColumn":27},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Computed name [task.taskType] resolves to an `any` value.","line":289,"column":39,"nodeType":"MemberExpression","messageId":"unsafeComputedMemberAccess","endLine":289,"endColumn":52},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .taskType on an `any` value.","line":289,"column":44,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":289,"endColumn":52},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .startTime on an `any` value.","line":291,"column":37,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":291,"endColumn":46}],"suppressedMessages":[],"errorCount":41,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Injectable, Logger, OnModuleInit } from '@nestjs/common';\nimport { EventBus, OnEvent } from '@wwjCommon/events/event-bus';\nimport { AiRegistryService } from './ai-registry.service';\nimport { AiOrchestratorService } from './ai-orchestrator.service';\n\n/**\n * AI Coordinator Service - AI 协调服务\n *\n * 职责:\n * - 协调各 AI 模块间的通信\n * - 处理跨模块的事件和消息\n * - 管理模块间的依赖关系\n * - 提供统一的协调接口\n */\n@Injectable()\nexport class AiCoordinatorService implements OnModuleInit {\n private readonly logger = new Logger(AiCoordinatorService.name);\n private readonly moduleStates = new Map();\n private readonly pendingTasks = new Map();\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly registryService: AiRegistryService,\n private readonly orchestratorService: AiOrchestratorService,\n ) {}\n\n async onModuleInit() {\n this.logger.log('AI Coordinator Service initialized');\n await this.initializeModuleStates();\n // Mark manager as ready once coordinator has initialized\n this.updateModuleState('manager', 'ready');\n }\n\n /**\n * 初始化模块状态\n */\n private async initializeModuleStates(): Promise {\n const modules = ['healing', 'safe', 'tuner', 'manager'];\n\n for (const module of modules) {\n this.moduleStates.set(module, 'initializing');\n }\n\n this.logger.log('Module states initialized');\n }\n\n /**\n * 更新模块状态\n */\n updateModuleState(moduleName: string, state: string): void {\n const previousState = this.moduleStates.get(moduleName);\n this.moduleStates.set(moduleName, state);\n\n this.logger.log(\n `Module state updated: ${moduleName} ${previousState} -> ${state}`,\n );\n this.eventBus.emit('module.state.changed', {\n module: moduleName,\n previousState,\n currentState: state,\n });\n }\n\n /**\n * 获取模块状态\n */\n getModuleState(moduleName: string): string | undefined {\n return this.moduleStates.get(moduleName);\n }\n\n /**\n * 获取所有模块状态\n */\n getAllModuleStates(): Record {\n return Object.fromEntries(this.moduleStates);\n }\n\n /**\n * 协调任务执行\n */\n async coordinateTask(\n taskId: string,\n taskType: string,\n payload: any,\n ): Promise {\n this.logger.log(`Coordinating task: ${taskId} (${taskType})`);\n\n try {\n // 检查相关模块状态\n const requiredModules = this.getRequiredModules(taskType);\n const moduleCheck = await this.checkModuleAvailability(requiredModules);\n\n if (!moduleCheck.allAvailable) {\n throw new Error(\n `Required modules not available: ${moduleCheck.unavailable.join(', ')}`,\n );\n }\n\n // 执行任务协调\n const result = await this.executeCoordinatedTask(\n taskId,\n taskType,\n payload,\n );\n\n this.eventBus.emit('task.coordinated', { taskId, taskType, result });\n return result;\n } catch (error) {\n this.logger.error(`Task coordination failed: ${taskId}`, error);\n this.eventBus.emit('task.coordination.failed', {\n taskId,\n taskType,\n error,\n });\n throw error;\n }\n }\n\n /**\n * 获取任务所需模块\n */\n private getRequiredModules(taskType: string): string[] {\n const moduleMap: Record = {\n healing: ['healing', 'manager'],\n security: ['safe', 'manager'],\n performance: ['tuner', 'manager'],\n comprehensive: ['healing', 'safe', 'tuner', 'manager'],\n };\n\n return moduleMap[taskType] || ['manager'];\n }\n\n /**\n * 检查模块可用性\n */\n private async checkModuleAvailability(modules: string[]): Promise<{\n allAvailable: boolean;\n available: string[];\n unavailable: string[];\n }> {\n const available: string[] = [];\n const unavailable: string[] = [];\n\n for (const module of modules) {\n const state = this.moduleStates.get(module);\n if (state === 'ready' || state === 'active') {\n available.push(module);\n } else {\n unavailable.push(module);\n }\n }\n\n return {\n allAvailable: unavailable.length === 0,\n available,\n unavailable,\n };\n }\n\n /**\n * 执行协调任务\n */\n private async executeCoordinatedTask(\n taskId: string,\n taskType: string,\n payload: any,\n ): Promise {\n // 将任务添加到待处理队列\n this.pendingTasks.set(taskId, { taskType, payload, startTime: Date.now() });\n\n try {\n // 根据任务类型选择执行策略\n let result;\n\n switch (taskType) {\n case 'healing':\n result = await this.orchestratorService.executeWorkflow(\n 'healing',\n payload,\n );\n break;\n case 'security':\n result = await this.orchestratorService.executeWorkflow(\n 'security',\n payload,\n );\n break;\n case 'performance':\n result = await this.orchestratorService.executeWorkflow(\n 'performance',\n payload,\n );\n break;\n default:\n result = await this.executeCustomTask(taskType, payload);\n }\n\n return result;\n } finally {\n // 从待处理队列中移除\n this.pendingTasks.delete(taskId);\n }\n }\n\n /**\n * 执行自定义任务\n */\n private async executeCustomTask(\n taskType: string,\n payload: any,\n ): Promise {\n const services = this.registryService.getServicesByType(taskType);\n\n if (services.length === 0) {\n throw new Error(`No services available for task type: ${taskType}`);\n }\n\n // 执行第一个可用服务\n return await services[0].execute(payload);\n }\n\n /**\n * 处理任务失败事件\n */\n @OnEvent('task.failed')\n async handleTaskFailed(payload: any): Promise {\n this.logger.warn(`Task failed: ${payload.taskId}`);\n\n // 尝试协调恢复\n if (payload.severity === 'high') {\n await this.coordinateTask(`recovery-${payload.taskId}`, 'healing', {\n originalTask: payload,\n });\n }\n }\n\n /**\n * 处理模块状态变化事件\n */\n @OnEvent('module.state.changed')\n async handleModuleStateChanged(payload: any): Promise {\n this.logger.debug(\n `Module state changed: ${payload.module} -> ${payload.currentState}`,\n );\n\n // 同步内部状态映射,保持状态来源一致\n this.moduleStates.set(payload.module, payload.currentState);\n\n // 如果模块变为不可用,暂停相关任务\n if (\n payload.currentState === 'error' ||\n payload.currentState === 'unavailable'\n ) {\n await this.pauseModuleTasks(payload.module);\n }\n }\n\n /**\n * 暂停模块相关任务\n */\n private async pauseModuleTasks(moduleName: string): Promise {\n this.logger.warn(`Pausing tasks for module: ${moduleName}`);\n\n for (const [taskId, task] of this.pendingTasks) {\n const requiredModules = this.getRequiredModules(task.taskType);\n if (requiredModules.includes(moduleName)) {\n this.logger.warn(`Pausing task: ${taskId}`);\n this.eventBus.emit('task.paused', {\n taskId,\n reason: `Module unavailable: ${moduleName}`,\n });\n }\n }\n }\n\n /**\n * 获取待处理任务统计\n */\n getPendingTasksStats(): {\n total: number;\n byType: Record;\n oldestTask?: { id: string; age: number };\n } {\n const total = this.pendingTasks.size;\n const byType: Record = {};\n let oldestTask: { id: string; age: number } | undefined;\n\n for (const [taskId, task] of this.pendingTasks) {\n byType[task.taskType] = (byType[task.taskType] || 0) + 1;\n\n const age = Date.now() - task.startTime;\n if (!oldestTask || age > oldestTask.age) {\n oldestTask = { id: taskId, age };\n }\n }\n\n return { total, byType, oldestTask };\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/manager/services/ai-orchestrator.service.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":17,"column":54,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":17,"endColumn":57,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[506,509],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[506,509],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'registerDefaultWorkflows' has no 'await' expression.","line":41,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":41,"endColumn":41,"suggestions":[{"messageId":"removeAsync","fix":{"range":[997,1044],"text":"registerDefaultWorkflows(): void"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":67,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":67,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1613,1616],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1613,1616],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":75,"column":48,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":75,"endColumn":51,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1799,1802],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1799,1802],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":75,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":75,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1813,1816],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1813,1816],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":76,"column":11,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":76,"endColumn":52},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":84,"column":13,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":84,"endColumn":72},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":85,"column":56,"nodeType":"Property","messageId":"anyAssignment","endLine":85,"endColumn":62},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":89,"column":53,"nodeType":"Property","messageId":"anyAssignment","endLine":89,"endColumn":58},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":98,"column":15,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":98,"endColumn":18,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2440,2443],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2440,2443],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":99,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":99,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2458,2461],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2458,2461],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":100,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":100,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2476,2479],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2476,2479],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .steps on an `any` value.","line":103,"column":33,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":103,"endColumn":38},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":105,"column":13,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":105,"endColumn":71},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":105,"column":57,"nodeType":"Identifier","messageId":"unsafeArgument","endLine":105,"endColumn":61},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `never`.","line":106,"column":20,"nodeType":"Identifier","messageId":"unsafeArgument","endLine":106,"endColumn":30},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":115,"column":60,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":115,"endColumn":63,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2832,2835],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2832,2835],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":115,"column":74,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":115,"endColumn":77,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2846,2849],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2846,2849],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":18,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Injectable, Logger, OnModuleInit } from '@nestjs/common';\nimport { EventBus } from '@wwjCommon/events/event-bus';\nimport { AiRegistryService } from './ai-registry.service';\n\n/**\n * AI Orchestrator Service - AI 编排服务\n *\n * 职责:\n * - 协调各 AI 模块的工作流程\n * - 管理 AI 任务的执行顺序\n * - 处理模块间的依赖关系\n * - 监控和调度 AI 服务\n */\n@Injectable()\nexport class AiOrchestratorService implements OnModuleInit {\n private readonly logger = new Logger(AiOrchestratorService.name);\n private readonly activeWorkflows = new Map();\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly registryService: AiRegistryService,\n ) {}\n\n async onModuleInit() {\n this.logger.log('AI Orchestrator Service initialized');\n await this.initializeWorkflows();\n }\n\n /**\n * 初始化工作流程\n */\n private async initializeWorkflows(): Promise {\n this.logger.log('Initializing AI workflows...');\n // 注册默认工作流程\n await this.registerDefaultWorkflows();\n }\n\n /**\n * 注册默认工作流程\n */\n private async registerDefaultWorkflows(): Promise {\n // 自愈工作流程\n this.registerWorkflow('healing', {\n steps: ['detect', 'analyze', 'recover', 'verify'],\n timeout: 30000,\n retryCount: 3,\n });\n\n // 安全检查工作流程\n this.registerWorkflow('security', {\n steps: ['scan', 'analyze', 'protect', 'report'],\n timeout: 15000,\n retryCount: 2,\n });\n\n // 性能优化工作流程\n this.registerWorkflow('performance', {\n steps: ['monitor', 'analyze', 'optimize', 'validate'],\n timeout: 60000,\n retryCount: 1,\n });\n }\n\n /**\n * 注册工作流程\n */\n registerWorkflow(name: string, config: any): void {\n this.activeWorkflows.set(name, config);\n this.logger.log(`Workflow registered: ${name}`);\n }\n\n /**\n * 执行工作流程\n */\n async executeWorkflow(name: string, context: any): Promise {\n const workflow = this.activeWorkflows.get(name);\n if (!workflow) {\n throw new Error(`Workflow not found: ${name}`);\n }\n\n this.logger.log(`Executing workflow: ${name}`);\n\n try {\n const result = await this.processWorkflowSteps(workflow, context);\n this.eventBus.emit('workflow.completed', { name, result });\n return result;\n } catch (error) {\n this.logger.error(`Workflow execution failed: ${name}`, error);\n this.eventBus.emit('workflow.failed', { name, error });\n throw error;\n }\n }\n\n /**\n * 处理工作流程步骤\n */\n private async processWorkflowSteps(\n workflow: any,\n context: any,\n ): Promise {\n const results = [];\n\n for (const step of workflow.steps) {\n this.logger.debug(`Processing workflow step: ${step}`);\n const stepResult = await this.executeWorkflowStep(step, context);\n results.push(stepResult);\n }\n\n return results;\n }\n\n /**\n * 执行工作流程步骤\n */\n private async executeWorkflowStep(step: string, context: any): Promise {\n // 根据步骤类型调用相应的服务\n const services = this.registryService.getServicesByType(step);\n\n if (services.length === 0) {\n this.logger.warn(`No services found for step: ${step}`);\n return null;\n }\n\n // 执行第一个匹配的服务\n const service = services[0];\n return await service.execute(context);\n }\n\n /**\n * 获取活动工作流程\n */\n getActiveWorkflows(): string[] {\n return Array.from(this.activeWorkflows.keys());\n }\n\n /**\n * 停止工作流程\n */\n stopWorkflow(name: string): boolean {\n const removed = this.activeWorkflows.delete(name);\n if (removed) {\n this.logger.log(`Workflow stopped: ${name}`);\n this.eventBus.emit('workflow.stopped', { name });\n }\n return removed;\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/manager/services/ai-registry.service.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":16,"column":20,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":16,"endColumn":23,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[291,294],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[291,294],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":16,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":16,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[305,308],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[305,308],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'onModuleDestroy' has no 'await' expression.","line":43,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":43,"endColumn":24,"suggestions":[{"messageId":"removeAsync","fix":{"range":[979,985],"text":""},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'startHealthCheck' has no 'await' expression.","line":139,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":139,"endColumn":33,"suggestions":[{"messageId":"removeAsync","fix":{"range":[3083,3122],"text":"startHealthCheck(): void"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-misused-promises","severity":2,"message":"Promise returned in function argument where a void return was expected.","line":140,"column":44,"nodeType":"ArrowFunctionExpression","messageId":"voidReturnArgument","endLine":142,"endColumn":6},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":165,"column":56,"nodeType":"Property","messageId":"anyAssignment","endLine":165,"endColumn":61}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import {\n Injectable,\n Logger,\n OnModuleInit,\n OnModuleDestroy,\n} from '@nestjs/common';\nimport { EventBus } from '@wwjCommon/events/event-bus';\n\n/**\n * AI Service Interface - AI 服务接口\n */\nexport interface AiService {\n name: string;\n type: string;\n version: string;\n execute(context: any): Promise;\n isHealthy(): Promise;\n}\n\n/**\n * AI Registry Service - AI 注册服务\n *\n * 职责:\n * - 管理 AI 服务的注册和注销\n * - 提供服务发现功能\n * - 监控服务健康状态\n * - 维护服务元数据\n */\n@Injectable()\nexport class AiRegistryService implements OnModuleInit, OnModuleDestroy {\n private readonly logger = new Logger(AiRegistryService.name);\n private readonly services = new Map();\n private readonly servicesByType = new Map();\n private healthCheckInterval: NodeJS.Timeout | null = null;\n\n constructor(private readonly eventBus: EventBus) {}\n\n async onModuleInit() {\n this.logger.log('AI Registry Service initialized');\n await this.startHealthCheck();\n }\n\n async onModuleDestroy() {\n // 停止健康检查定时器,避免残留句柄\n if (this.healthCheckInterval) {\n clearInterval(this.healthCheckInterval);\n this.healthCheckInterval = null;\n this.logger.log('AI Registry Service health check stopped');\n }\n }\n\n /**\n * 注册 AI 服务\n */\n registerService(service: AiService): void {\n this.services.set(service.name, service);\n\n // 按类型分组\n if (!this.servicesByType.has(service.type)) {\n this.servicesByType.set(service.type, []);\n }\n this.servicesByType.get(service.type)!.push(service);\n\n this.logger.log(`Service registered: ${service.name} (${service.type})`);\n this.eventBus.emit('service.registered', service);\n }\n\n /**\n * 注销 AI 服务\n */\n unregisterService(serviceName: string): boolean {\n const service = this.services.get(serviceName);\n if (!service) {\n return false;\n }\n\n this.services.delete(serviceName);\n\n // 从类型分组中移除\n const typeServices = this.servicesByType.get(service.type);\n if (typeServices) {\n const index = typeServices.findIndex((s) => s.name === serviceName);\n if (index > -1) {\n typeServices.splice(index, 1);\n }\n }\n\n this.logger.log(`Service unregistered: ${serviceName}`);\n this.eventBus.emit('service.unregistered', service);\n return true;\n }\n\n /**\n * 获取服务\n */\n getService(serviceName: string): AiService | undefined {\n return this.services.get(serviceName);\n }\n\n /**\n * 根据类型获取服务列表\n */\n getServicesByType(type: string): AiService[] {\n return this.servicesByType.get(type) || [];\n }\n\n /**\n * 获取所有服务\n */\n getAllServices(): AiService[] {\n return Array.from(this.services.values());\n }\n\n /**\n * 获取服务统计信息\n */\n getServiceStats(): {\n total: number;\n byType: Record;\n healthy: number;\n } {\n const total = this.services.size;\n const byType: Record = {};\n\n for (const [type, services] of this.servicesByType) {\n byType[type] = services.length;\n }\n\n return {\n total,\n byType,\n healthy: 0, // 将在健康检查中更新\n };\n }\n\n /**\n * 启动健康检查\n */\n private async startHealthCheck(): Promise {\n this.healthCheckInterval = setInterval(async () => {\n await this.performHealthCheck();\n }, 30000);\n }\n\n /**\n * 执行健康检查\n */\n private async performHealthCheck(): Promise {\n let healthyCount = 0;\n\n for (const service of this.services.values()) {\n try {\n const isHealthy = await service.isHealthy();\n if (isHealthy) {\n healthyCount++;\n } else {\n this.logger.warn(`Service unhealthy: ${service.name}`);\n this.eventBus.emit('service.unhealthy', service);\n }\n } catch (error) {\n this.logger.error(\n `Health check failed for service: ${service.name}`,\n error,\n );\n this.eventBus.emit('service.error', { service, error });\n }\n }\n\n this.logger.debug(\n `Health check completed: ${healthyCount}/${this.services.size} services healthy`,\n );\n }\n\n /**\n * 查找服务\n */\n findServices(predicate: (service: AiService) => boolean): AiService[] {\n return Array.from(this.services.values()).filter(predicate);\n }\n\n /**\n * 检查服务是否存在\n */\n hasService(serviceName: string): boolean {\n return this.services.has(serviceName);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/safe/analyzers/security.analyzer.ts","messages":[{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkJwtSecurity' has no 'await' expression.","line":151,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":151,"endColumn":33,"suggestions":[{"messageId":"removeAsync","fix":{"range":[3559,3613],"text":"checkJwtSecurity(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkPasswordPolicy' has no 'await' expression.","line":169,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":169,"endColumn":36,"suggestions":[{"messageId":"removeAsync","fix":{"range":[3926,3983],"text":"checkPasswordPolicy(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkSessionSecurity' has no 'await' expression.","line":186,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":186,"endColumn":37,"suggestions":[{"messageId":"removeAsync","fix":{"range":[4282,4340],"text":"checkSessionSecurity(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkMfaSecurity' has no 'await' expression.","line":203,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":203,"endColumn":33,"suggestions":[{"messageId":"removeAsync","fix":{"range":[4642,4696],"text":"checkMfaSecurity(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkDataEncryption' has no 'await' expression.","line":219,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":219,"endColumn":36,"suggestions":[{"messageId":"removeAsync","fix":{"range":[4979,5036],"text":"checkDataEncryption(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkDataAccess' has no 'await' expression.","line":236,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":236,"endColumn":32,"suggestions":[{"messageId":"removeAsync","fix":{"range":[5335,5388],"text":"checkDataAccess(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkDataBackup' has no 'await' expression.","line":253,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":253,"endColumn":32,"suggestions":[{"messageId":"removeAsync","fix":{"range":[5688,5741],"text":"checkDataBackup(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkDataRetention' has no 'await' expression.","line":270,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":270,"endColumn":35,"suggestions":[{"messageId":"removeAsync","fix":{"range":[6030,6086],"text":"checkDataRetention(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkHttpsSecurity' has no 'await' expression.","line":287,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":287,"endColumn":35,"suggestions":[{"messageId":"removeAsync","fix":{"range":[6391,6447],"text":"checkHttpsSecurity(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkCorsConfiguration' has no 'await' expression.","line":304,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":304,"endColumn":39,"suggestions":[{"messageId":"removeAsync","fix":{"range":[6732,6792],"text":"checkCorsConfiguration(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkRateLimiting' has no 'await' expression.","line":321,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":321,"endColumn":34,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7127,7182],"text":"checkRateLimiting(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkFirewallRules' has no 'await' expression.","line":338,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":338,"endColumn":35,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7470,7526],"text":"checkFirewallRules(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkInputValidation' has no 'await' expression.","line":355,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":355,"endColumn":37,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7820,7878],"text":"checkInputValidation(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkSqlInjection' has no 'await' expression.","line":372,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":372,"endColumn":34,"suggestions":[{"messageId":"removeAsync","fix":{"range":[8180,8235],"text":"checkSqlInjection(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkXssProtection' has no 'await' expression.","line":389,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":389,"endColumn":35,"suggestions":[{"messageId":"removeAsync","fix":{"range":[8551,8607],"text":"checkXssProtection(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'checkDependencyVulnerabilities' has no 'await' expression.","line":406,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":406,"endColumn":47,"suggestions":[{"messageId":"removeAsync","fix":{"range":[8899,8967],"text":"checkDependencyVulnerabilities(): SecurityCheckResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":524,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":524,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12229,12232],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12229,12232],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":17,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Injectable, Logger } from '@nestjs/common';\n\n/**\n * Security Analyzer - 安全分析器\n *\n * 职责:\n * - 分析系统安全状态\n * - 识别潜在安全威胁\n * - 评估安全风险等级\n * - 生成安全报告\n */\n@Injectable()\nexport class SecurityAnalyzer {\n private readonly logger = new Logger(SecurityAnalyzer.name);\n\n /**\n * 分析系统安全状态\n */\n async analyzeSystemSecurity(): Promise {\n this.logger.log('Starting system security analysis');\n\n const startTime = Date.now();\n\n try {\n // 执行各项安全检查\n const [authSecurity, dataSecurity, networkSecurity, codeSecurity] =\n await Promise.all([\n this.analyzeAuthSecurity(),\n this.analyzeDataSecurity(),\n this.analyzeNetworkSecurity(),\n this.analyzeCodeSecurity(),\n ]);\n\n const overallRisk = this.calculateOverallRisk([\n authSecurity.riskLevel,\n dataSecurity.riskLevel,\n networkSecurity.riskLevel,\n codeSecurity.riskLevel,\n ]);\n\n return {\n timestamp: Date.now(),\n duration: Date.now() - startTime,\n overallRisk,\n categories: {\n authentication: authSecurity,\n dataProtection: dataSecurity,\n networkSecurity: networkSecurity,\n codeQuality: codeSecurity,\n },\n recommendations: this.generateRecommendations(overallRisk),\n };\n } catch (error) {\n this.logger.error('Security analysis failed', error);\n throw error;\n }\n }\n\n /**\n * 分析认证安全\n */\n private async analyzeAuthSecurity(): Promise {\n // 检查认证机制\n const checks = [\n this.checkJwtSecurity(),\n this.checkPasswordPolicy(),\n this.checkSessionSecurity(),\n this.checkMfaSecurity(),\n ];\n\n const results = await Promise.all(checks);\n const riskLevel = this.calculateCategoryRisk(results);\n\n return {\n category: 'authentication',\n riskLevel,\n checks: results,\n score: this.calculateSecurityScore(results),\n };\n }\n\n /**\n * 分析数据安全\n */\n private async analyzeDataSecurity(): Promise {\n const checks = [\n this.checkDataEncryption(),\n this.checkDataAccess(),\n this.checkDataBackup(),\n this.checkDataRetention(),\n ];\n\n const results = await Promise.all(checks);\n const riskLevel = this.calculateCategoryRisk(results);\n\n return {\n category: 'dataProtection',\n riskLevel,\n checks: results,\n score: this.calculateSecurityScore(results),\n };\n }\n\n /**\n * 分析网络安全\n */\n private async analyzeNetworkSecurity(): Promise {\n const checks = [\n this.checkHttpsSecurity(),\n this.checkCorsConfiguration(),\n this.checkRateLimiting(),\n this.checkFirewallRules(),\n ];\n\n const results = await Promise.all(checks);\n const riskLevel = this.calculateCategoryRisk(results);\n\n return {\n category: 'networkSecurity',\n riskLevel,\n checks: results,\n score: this.calculateSecurityScore(results),\n };\n }\n\n /**\n * 分析代码安全\n */\n private async analyzeCodeSecurity(): Promise {\n const checks = [\n this.checkInputValidation(),\n this.checkSqlInjection(),\n this.checkXssProtection(),\n this.checkDependencyVulnerabilities(),\n ];\n\n const results = await Promise.all(checks);\n const riskLevel = this.calculateCategoryRisk(results);\n\n return {\n category: 'codeQuality',\n riskLevel,\n checks: results,\n score: this.calculateSecurityScore(results),\n };\n }\n\n /**\n * JWT 安全检查\n */\n private async checkJwtSecurity(): Promise {\n // 实现 JWT 安全检查逻辑\n return {\n name: 'JWT Security',\n status: 'pass',\n riskLevel: 'low',\n message: 'JWT configuration is secure',\n details: {\n algorithm: 'RS256',\n expiration: '1h',\n secretRotation: true,\n },\n };\n }\n\n /**\n * 密码策略检查\n */\n private async checkPasswordPolicy(): Promise {\n return {\n name: 'Password Policy',\n status: 'pass',\n riskLevel: 'low',\n message: 'Password policy meets security requirements',\n details: {\n minLength: 8,\n complexity: true,\n expiration: 90,\n },\n };\n }\n\n /**\n * 会话安全检查\n */\n private async checkSessionSecurity(): Promise {\n return {\n name: 'Session Security',\n status: 'pass',\n riskLevel: 'medium',\n message: 'Session configuration needs improvement',\n details: {\n httpOnly: true,\n secure: true,\n sameSite: 'strict',\n },\n };\n }\n\n /**\n * 多因素认证检查\n */\n private async checkMfaSecurity(): Promise {\n return {\n name: 'Multi-Factor Authentication',\n status: 'warning',\n riskLevel: 'medium',\n message: 'MFA is not enabled for all users',\n details: {\n enabled: false,\n coverage: '30%',\n },\n };\n }\n\n /**\n * 数据加密检查\n */\n private async checkDataEncryption(): Promise {\n return {\n name: 'Data Encryption',\n status: 'pass',\n riskLevel: 'low',\n message: 'Data encryption is properly configured',\n details: {\n atRest: true,\n inTransit: true,\n algorithm: 'AES-256',\n },\n };\n }\n\n /**\n * 数据访问检查\n */\n private async checkDataAccess(): Promise {\n return {\n name: 'Data Access Control',\n status: 'pass',\n riskLevel: 'low',\n message: 'Data access controls are properly implemented',\n details: {\n rbac: true,\n audit: true,\n encryption: true,\n },\n };\n }\n\n /**\n * 数据备份检查\n */\n private async checkDataBackup(): Promise {\n return {\n name: 'Data Backup',\n status: 'pass',\n riskLevel: 'low',\n message: 'Data backup strategy is adequate',\n details: {\n frequency: 'daily',\n encryption: true,\n offsite: true,\n },\n };\n }\n\n /**\n * 数据保留检查\n */\n private async checkDataRetention(): Promise {\n return {\n name: 'Data Retention',\n status: 'pass',\n riskLevel: 'low',\n message: 'Data retention policies are compliant',\n details: {\n policy: 'defined',\n automation: true,\n compliance: 'GDPR',\n },\n };\n }\n\n /**\n * HTTPS 安全检查\n */\n private async checkHttpsSecurity(): Promise {\n return {\n name: 'HTTPS Security',\n status: 'pass',\n riskLevel: 'low',\n message: 'HTTPS is properly configured',\n details: {\n enforced: true,\n tlsVersion: '1.3',\n hsts: true,\n },\n };\n }\n\n /**\n * CORS 配置检查\n */\n private async checkCorsConfiguration(): Promise {\n return {\n name: 'CORS Configuration',\n status: 'warning',\n riskLevel: 'medium',\n message: 'CORS configuration may be too permissive',\n details: {\n origins: ['*'],\n credentials: true,\n methods: ['GET', 'POST', 'PUT', 'DELETE'],\n },\n };\n }\n\n /**\n * 速率限制检查\n */\n private async checkRateLimiting(): Promise {\n return {\n name: 'Rate Limiting',\n status: 'pass',\n riskLevel: 'low',\n message: 'Rate limiting is properly configured',\n details: {\n enabled: true,\n limits: '100/min',\n burst: 10,\n },\n };\n }\n\n /**\n * 防火墙规则检查\n */\n private async checkFirewallRules(): Promise {\n return {\n name: 'Firewall Rules',\n status: 'pass',\n riskLevel: 'low',\n message: 'Firewall rules are properly configured',\n details: {\n enabled: true,\n defaultDeny: true,\n logging: true,\n },\n };\n }\n\n /**\n * 输入验证检查\n */\n private async checkInputValidation(): Promise {\n return {\n name: 'Input Validation',\n status: 'pass',\n riskLevel: 'low',\n message: 'Input validation is comprehensive',\n details: {\n sanitization: true,\n validation: true,\n whitelisting: true,\n },\n };\n }\n\n /**\n * SQL 注入检查\n */\n private async checkSqlInjection(): Promise {\n return {\n name: 'SQL Injection Protection',\n status: 'pass',\n riskLevel: 'low',\n message: 'SQL injection protection is effective',\n details: {\n parameterizedQueries: true,\n orm: 'TypeORM',\n escaping: true,\n },\n };\n }\n\n /**\n * XSS 保护检查\n */\n private async checkXssProtection(): Promise {\n return {\n name: 'XSS Protection',\n status: 'pass',\n riskLevel: 'low',\n message: 'XSS protection is properly implemented',\n details: {\n csp: true,\n sanitization: true,\n encoding: true,\n },\n };\n }\n\n /**\n * 依赖漏洞检查\n */\n private async checkDependencyVulnerabilities(): Promise {\n return {\n name: 'Dependency Vulnerabilities',\n status: 'warning',\n riskLevel: 'medium',\n message: 'Some dependencies have known vulnerabilities',\n details: {\n total: 150,\n vulnerable: 3,\n critical: 0,\n high: 1,\n medium: 2,\n },\n };\n }\n\n /**\n * 计算分类风险等级\n */\n private calculateCategoryRisk(results: SecurityCheckResult[]): RiskLevel {\n const riskLevels = results.map((r) => r.riskLevel);\n\n if (riskLevels.includes('critical')) return 'critical';\n if (riskLevels.includes('high')) return 'high';\n if (riskLevels.includes('medium')) return 'medium';\n return 'low';\n }\n\n /**\n * 计算整体风险等级\n */\n private calculateOverallRisk(categoryRisks: RiskLevel[]): RiskLevel {\n const riskWeights = { critical: 4, high: 3, medium: 2, low: 1 };\n const totalWeight = categoryRisks.reduce(\n (sum, risk) => sum + riskWeights[risk],\n 0,\n );\n const avgWeight = totalWeight / categoryRisks.length;\n\n if (avgWeight >= 3.5) return 'critical';\n if (avgWeight >= 2.5) return 'high';\n if (avgWeight >= 1.5) return 'medium';\n return 'low';\n }\n\n /**\n * 计算安全评分\n */\n private calculateSecurityScore(results: SecurityCheckResult[]): number {\n const statusWeights = { pass: 100, warning: 60, fail: 0 };\n const totalScore = results.reduce(\n (sum, result) => sum + statusWeights[result.status],\n 0,\n );\n return Math.round(totalScore / results.length);\n }\n\n /**\n * 生成安全建议\n */\n private generateRecommendations(riskLevel: RiskLevel): string[] {\n const recommendations: Record = {\n critical: [\n 'Immediately address critical security vulnerabilities',\n 'Implement emergency security patches',\n 'Review and strengthen access controls',\n 'Conduct comprehensive security audit',\n ],\n high: [\n 'Address high-priority security issues within 24 hours',\n 'Implement additional security monitoring',\n 'Review security policies and procedures',\n 'Consider security training for development team',\n ],\n medium: [\n 'Address medium-priority security issues within a week',\n 'Implement security best practices',\n 'Regular security assessments',\n 'Update security documentation',\n ],\n low: [\n 'Maintain current security posture',\n 'Continue regular security monitoring',\n 'Keep security tools and policies updated',\n 'Periodic security reviews',\n ],\n };\n\n return recommendations[riskLevel] || recommendations.low;\n }\n}\n\n// 类型定义\nexport interface SecurityAnalysisResult {\n timestamp: number;\n duration: number;\n overallRisk: RiskLevel;\n categories: {\n authentication: SecurityCategoryResult;\n dataProtection: SecurityCategoryResult;\n networkSecurity: SecurityCategoryResult;\n codeQuality: SecurityCategoryResult;\n };\n recommendations: string[];\n}\n\nexport interface SecurityCategoryResult {\n category: string;\n riskLevel: RiskLevel;\n checks: SecurityCheckResult[];\n score: number;\n}\n\nexport interface SecurityCheckResult {\n name: string;\n status: 'pass' | 'warning' | 'fail';\n riskLevel: RiskLevel;\n message: string;\n details: Record;\n}\n\nexport type RiskLevel = 'low' | 'medium' | 'high' | 'critical';\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/safe/detectors/vulnerability.detector.ts","messages":[{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'scanDependencyVulnerabilities' has no 'await' expression.","line":90,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":90,"endColumn":46,"suggestions":[{"messageId":"removeAsync","fix":{"range":[2315,2378],"text":"scanDependencyVulnerabilities(): Vulnerability[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'scanConfigurationVulnerabilities' has no 'await' expression.","line":138,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":138,"endColumn":49,"suggestions":[{"messageId":"removeAsync","fix":{"range":[3685,3751],"text":"scanConfigurationVulnerabilities(): Vulnerability[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'scanNetworkVulnerabilities' has no 'await' expression.","line":166,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":166,"endColumn":43,"suggestions":[{"messageId":"removeAsync","fix":{"range":[4453,4513],"text":"scanNetworkVulnerabilities(): Vulnerability[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'detectSqlInjection' has no 'await' expression.","line":194,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":194,"endColumn":35,"suggestions":[{"messageId":"removeAsync","fix":{"range":[5186,5238],"text":"detectSqlInjection(): Vulnerability[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'detectXssVulnerabilities' has no 'await' expression.","line":202,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":202,"endColumn":41,"suggestions":[{"messageId":"removeAsync","fix":{"range":[5317,5375],"text":"detectXssVulnerabilities(): Vulnerability[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'detectAuthenticationBypass' has no 'await' expression.","line":210,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":210,"endColumn":43,"suggestions":[{"messageId":"removeAsync","fix":{"range":[5451,5511],"text":"detectAuthenticationBypass(): Vulnerability[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'detectPrivilegeEscalation' has no 'await' expression.","line":218,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":218,"endColumn":42,"suggestions":[{"messageId":"removeAsync","fix":{"range":[5586,5645],"text":"detectPrivilegeEscalation(): Vulnerability[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'detectSuspiciousActivity' has no 'await' expression.","line":307,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":307,"endColumn":41,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7603,7654],"text":"detectSuspiciousActivity(): Threat[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'detectAnomalousTraffic' has no 'await' expression.","line":315,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":315,"endColumn":39,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7727,7776],"text":"detectAnomalousTraffic(): Threat[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'detectBruteForceAttacks' has no 'await' expression.","line":323,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":323,"endColumn":40,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7851,7901],"text":"detectBruteForceAttacks(): Threat[]"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'detectMaliciousPayloads' has no 'await' expression.","line":331,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":331,"endColumn":40,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7974,8024],"text":"detectMaliciousPayloads(): Threat[]"},"desc":"Remove 'async'."}]}],"suppressedMessages":[],"errorCount":11,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Injectable, Logger } from '@nestjs/common';\n\n/**\n * Vulnerability Detector - 漏洞检测器\n *\n * 职责:\n * - 扫描系统漏洞\n * - 检测安全威胁\n * - 监控异常行为\n * - 生成威胁报告\n */\n@Injectable()\nexport class VulnerabilityDetector {\n private readonly logger = new Logger(VulnerabilityDetector.name);\n\n /**\n * 执行全面漏洞扫描\n */\n async scanVulnerabilities(): Promise {\n this.logger.log('Starting comprehensive vulnerability scan');\n\n const startTime = Date.now();\n\n try {\n const [\n codeVulnerabilities,\n dependencyVulnerabilities,\n configVulnerabilities,\n networkVulnerabilities,\n ] = await Promise.all([\n this.scanCodeVulnerabilities(),\n this.scanDependencyVulnerabilities(),\n this.scanConfigurationVulnerabilities(),\n this.scanNetworkVulnerabilities(),\n ]);\n\n const allVulnerabilities = [\n ...codeVulnerabilities,\n ...dependencyVulnerabilities,\n ...configVulnerabilities,\n ...networkVulnerabilities,\n ];\n\n return {\n timestamp: Date.now(),\n duration: Date.now() - startTime,\n totalVulnerabilities: allVulnerabilities.length,\n severityBreakdown: this.calculateSeverityBreakdown(allVulnerabilities),\n vulnerabilities: allVulnerabilities,\n recommendations:\n this.generateVulnerabilityRecommendations(allVulnerabilities),\n };\n } catch (error) {\n this.logger.error('Vulnerability scan failed', error);\n throw error;\n }\n }\n\n /**\n * 扫描代码漏洞\n */\n private async scanCodeVulnerabilities(): Promise {\n this.logger.debug('Scanning code vulnerabilities');\n\n // 模拟代码漏洞扫描\n const vulnerabilities: Vulnerability[] = [];\n\n // SQL 注入检测\n const sqlInjectionVulns = await this.detectSqlInjection();\n vulnerabilities.push(...sqlInjectionVulns);\n\n // XSS 检测\n const xssVulns = await this.detectXssVulnerabilities();\n vulnerabilities.push(...xssVulns);\n\n // 认证绕过检测\n const authBypassVulns = await this.detectAuthenticationBypass();\n vulnerabilities.push(...authBypassVulns);\n\n // 权限提升检测\n const privilegeEscalationVulns = await this.detectPrivilegeEscalation();\n vulnerabilities.push(...privilegeEscalationVulns);\n\n return vulnerabilities;\n }\n\n /**\n * 扫描依赖漏洞\n */\n private async scanDependencyVulnerabilities(): Promise {\n this.logger.debug('Scanning dependency vulnerabilities');\n\n // 模拟依赖漏洞扫描结果\n return [\n {\n id: 'CVE-2023-1234',\n type: 'dependency',\n severity: 'high',\n title: 'Remote Code Execution in lodash',\n description:\n 'A prototype pollution vulnerability in lodash allows remote code execution',\n affectedComponent: 'lodash@4.17.20',\n cweId: 'CWE-1321',\n cvssScore: 8.5,\n discoveredAt: Date.now(),\n status: 'open',\n remediation: {\n type: 'update',\n description: 'Update lodash to version 4.17.21 or later',\n effort: 'low',\n },\n },\n {\n id: 'CVE-2023-5678',\n type: 'dependency',\n severity: 'medium',\n title: 'Information Disclosure in express',\n description:\n 'Express middleware may leak sensitive information in error messages',\n affectedComponent: 'express@4.18.0',\n cweId: 'CWE-200',\n cvssScore: 5.3,\n discoveredAt: Date.now(),\n status: 'open',\n remediation: {\n type: 'configuration',\n description:\n 'Configure error handling to prevent information leakage',\n effort: 'medium',\n },\n },\n ];\n }\n\n /**\n * 扫描配置漏洞\n */\n private async scanConfigurationVulnerabilities(): Promise {\n this.logger.debug('Scanning configuration vulnerabilities');\n\n return [\n {\n id: 'CONFIG-001',\n type: 'configuration',\n severity: 'medium',\n title: 'Weak CORS Configuration',\n description:\n 'CORS is configured to allow all origins which may lead to security issues',\n affectedComponent: 'CORS Middleware',\n cweId: 'CWE-346',\n cvssScore: 4.3,\n discoveredAt: Date.now(),\n status: 'open',\n remediation: {\n type: 'configuration',\n description: 'Restrict CORS origins to specific trusted domains',\n effort: 'low',\n },\n },\n ];\n }\n\n /**\n * 扫描网络漏洞\n */\n private async scanNetworkVulnerabilities(): Promise {\n this.logger.debug('Scanning network vulnerabilities');\n\n return [\n {\n id: 'NET-001',\n type: 'network',\n severity: 'low',\n title: 'Missing Security Headers',\n description: 'Some security headers are not configured properly',\n affectedComponent: 'HTTP Headers',\n cweId: 'CWE-693',\n cvssScore: 3.1,\n discoveredAt: Date.now(),\n status: 'open',\n remediation: {\n type: 'configuration',\n description:\n 'Add missing security headers (CSP, HSTS, X-Frame-Options)',\n effort: 'low',\n },\n },\n ];\n }\n\n /**\n * 检测 SQL 注入漏洞\n */\n private async detectSqlInjection(): Promise {\n // 模拟 SQL 注入检测\n return [];\n }\n\n /**\n * 检测 XSS 漏洞\n */\n private async detectXssVulnerabilities(): Promise {\n // 模拟 XSS 检测\n return [];\n }\n\n /**\n * 检测认证绕过漏洞\n */\n private async detectAuthenticationBypass(): Promise {\n // 模拟认证绕过检测\n return [];\n }\n\n /**\n * 检测权限提升漏洞\n */\n private async detectPrivilegeEscalation(): Promise {\n // 模拟权限提升检测\n return [];\n }\n\n /**\n * 计算严重程度分布\n */\n private calculateSeverityBreakdown(\n vulnerabilities: Vulnerability[],\n ): SeverityBreakdown {\n const breakdown = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n };\n\n vulnerabilities.forEach((vuln) => {\n breakdown[vuln.severity]++;\n });\n\n return breakdown;\n }\n\n /**\n * 生成漏洞修复建议\n */\n private generateVulnerabilityRecommendations(\n vulnerabilities: Vulnerability[],\n ): string[] {\n const recommendations: string[] = [];\n\n const criticalCount = vulnerabilities.filter(\n (v) => v.severity === 'critical',\n ).length;\n const highCount = vulnerabilities.filter(\n (v) => v.severity === 'high',\n ).length;\n\n if (criticalCount > 0) {\n recommendations.push(\n `Immediately address ${criticalCount} critical vulnerabilities`,\n );\n }\n\n if (highCount > 0) {\n recommendations.push(\n `Address ${highCount} high-severity vulnerabilities within 24 hours`,\n );\n }\n\n recommendations.push(\n 'Implement automated vulnerability scanning in CI/CD pipeline',\n );\n recommendations.push('Regular security training for development team');\n recommendations.push(\n 'Establish vulnerability disclosure and response process',\n );\n\n return recommendations;\n }\n\n /**\n * 检测实时威胁\n */\n async detectRealTimeThreats(): Promise {\n this.logger.log('Starting real-time threat detection');\n\n const threats = await Promise.all([\n this.detectSuspiciousActivity(),\n this.detectAnomalousTraffic(),\n this.detectBruteForceAttacks(),\n this.detectMaliciousPayloads(),\n ]);\n\n const allThreats = threats.flat();\n\n return {\n timestamp: Date.now(),\n threatsDetected: allThreats.length,\n threats: allThreats,\n riskLevel: this.calculateThreatRiskLevel(allThreats),\n };\n }\n\n /**\n * 检测可疑活动\n */\n private async detectSuspiciousActivity(): Promise {\n // 模拟可疑活动检测\n return [];\n }\n\n /**\n * 检测异常流量\n */\n private async detectAnomalousTraffic(): Promise {\n // 模拟异常流量检测\n return [];\n }\n\n /**\n * 检测暴力破解攻击\n */\n private async detectBruteForceAttacks(): Promise {\n // 模拟暴力破解检测\n return [];\n }\n\n /**\n * 检测恶意载荷\n */\n private async detectMaliciousPayloads(): Promise {\n // 模拟恶意载荷检测\n return [];\n }\n\n /**\n * 计算威胁风险等级\n */\n private calculateThreatRiskLevel(\n threats: Threat[],\n ): 'low' | 'medium' | 'high' | 'critical' {\n if (threats.length === 0) return 'low';\n\n const highSeverityThreats = threats.filter(\n (t) => t.severity === 'high' || t.severity === 'critical',\n );\n\n if (highSeverityThreats.length > 5) return 'critical';\n if (highSeverityThreats.length > 2) return 'high';\n if (threats.length > 10) return 'medium';\n\n return 'low';\n }\n}\n\n// 类型定义\nexport interface VulnerabilityScanResult {\n timestamp: number;\n duration: number;\n totalVulnerabilities: number;\n severityBreakdown: SeverityBreakdown;\n vulnerabilities: Vulnerability[];\n recommendations: string[];\n}\n\nexport interface Vulnerability {\n id: string;\n type: 'code' | 'dependency' | 'configuration' | 'network';\n severity: 'low' | 'medium' | 'high' | 'critical';\n title: string;\n description: string;\n affectedComponent: string;\n cweId?: string;\n cvssScore?: number;\n discoveredAt: number;\n status: 'open' | 'in_progress' | 'resolved' | 'false_positive';\n remediation: {\n type: 'update' | 'patch' | 'configuration' | 'code_change';\n description: string;\n effort: 'low' | 'medium' | 'high';\n };\n}\n\nexport interface SeverityBreakdown {\n critical: number;\n high: number;\n medium: number;\n low: number;\n}\n\nexport interface ThreatDetectionResult {\n timestamp: number;\n threatsDetected: number;\n threats: Threat[];\n riskLevel: 'low' | 'medium' | 'high' | 'critical';\n}\n\nexport interface Threat {\n id: string;\n type:\n | 'suspicious_activity'\n | 'anomalous_traffic'\n | 'brute_force'\n | 'malicious_payload';\n severity: 'low' | 'medium' | 'high' | 'critical';\n source: string;\n description: string;\n detectedAt: number;\n indicators: string[];\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-ai/src/safe/protectors/access.protector.ts","messages":[{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":37,"column":11,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":37,"endColumn":56},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'monitorAccessPatterns' has no 'await' expression.","line":143,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":143,"endColumn":30,"suggestions":[{"messageId":"removeAsync","fix":{"range":[3194,3255],"text":"monitorAccessPatterns(): AccessPatternAnalysis"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":176,"column":32,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":176,"endColumn":35,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4124,4127],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4124,4127],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-return","severity":2,"message":"Unsafe return of a value of type `any`.","line":177,"column":5,"nodeType":"ReturnStatement","messageId":"unsafeReturn","endLine":183,"endColumn":7},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .ip on an `any` value.","line":178,"column":15,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":178,"endColumn":17},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .connection on an `any` value.","line":179,"column":15,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":179,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .socket on an `any` value.","line":180,"column":15,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":180,"endColumn":21},{"ruleId":"@typescript-eslint/no-unsafe-call","severity":2,"message":"Unsafe call of a(n) `any` typed value.","line":181,"column":7,"nodeType":"MemberExpression","messageId":"unsafeCall","endLine":181,"endColumn":48},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .headers on an `any` value.","line":181,"column":15,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":181,"endColumn":22},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access [0] on an `any` value.","line":181,"column":54,"nodeType":"Literal","messageId":"unsafeMemberExpression","endLine":181,"endColumn":55},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":189,"column":52,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":189,"endColumn":55,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4416,4419],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4416,4419],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":197,"column":7,"nodeType":"Property","messageId":"anyAssignment","endLine":197,"endColumn":29},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .method on an `any` value.","line":197,"column":23,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":197,"endColumn":29},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":198,"column":7,"nodeType":"Property","messageId":"anyAssignment","endLine":198,"endColumn":23},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .url on an `any` value.","line":198,"column":20,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":198,"endColumn":23},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":199,"column":7,"nodeType":"Property","messageId":"anyAssignment","endLine":199,"endColumn":47},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .headers on an `any` value.","line":199,"column":26,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":199,"endColumn":33},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":224,"column":57,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":224,"endColumn":60,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5259,5262],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5259,5262],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":237,"column":11,"nodeType":"VariableDeclarator","messageId":"anyAssignment","endLine":237,"endColumn":52},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .headers on an `any` value.","line":237,"column":31,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":237,"endColumn":38},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":238,"column":50,"nodeType":"Identifier","messageId":"unsafeArgument","endLine":238,"endColumn":59},{"ruleId":"@typescript-eslint/no-unsafe-argument","severity":2,"message":"Unsafe argument of type `any` assigned to a parameter of type `string`.","line":243,"column":40,"nodeType":"MemberExpression","messageId":"unsafeArgument","endLine":243,"endColumn":51},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .url on an `any` value.","line":243,"column":48,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":243,"endColumn":51},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":253,"column":57,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":253,"endColumn":60,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5894,5897],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5894,5897],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":263,"column":9,"nodeType":"Property","messageId":"anyAssignment","endLine":263,"endColumn":31},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .method on an `any` value.","line":263,"column":25,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":263,"endColumn":31},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":264,"column":9,"nodeType":"Property","messageId":"anyAssignment","endLine":264,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .url on an `any` value.","line":264,"column":22,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":264,"endColumn":25},{"ruleId":"@typescript-eslint/no-unsafe-assignment","severity":2,"message":"Unsafe assignment of an `any` value.","line":265,"column":9,"nodeType":"Property","messageId":"anyAssignment","endLine":265,"endColumn":49},{"ruleId":"@typescript-eslint/no-unsafe-member-access","severity":2,"message":"Unsafe member access .headers on an `any` value.","line":265,"column":28,"nodeType":"Identifier","messageId":"unsafeMemberExpression","endLine":265,"endColumn":35},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'getUserPermissions' has no 'await' expression.","line":314,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":314,"endColumn":35,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7217,7283],"text":"getUserPermissions(userId: string): UserPermissions"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'getSecurityPolicy' has no 'await' expression.","line":344,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":344,"endColumn":34,"suggestions":[{"messageId":"removeAsync","fix":{"range":[7889,7973],"text":"getSecurityPolicy(\n policyName: string,\n ): SecurityPolicy | null"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'evaluateCondition' has no 'await' expression.","line":388,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":388,"endColumn":34,"suggestions":[{"messageId":"removeAsync","fix":{"range":[8991,9104],"text":"evaluateCondition(\n condition: PolicyCondition,\n context: SecurityContext,\n ): PolicyResult"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'context' is defined but never used.","line":434,"column":5,"nodeType":null,"messageId":"unusedVar","endLine":434,"endColumn":12},{"ruleId":"@typescript-eslint/require-await","severity":2,"message":"Async method 'logSecurityEvent' has no 'await' expression.","line":479,"column":3,"nodeType":"FunctionExpression","messageId":"missingAwait","endLine":479,"endColumn":33,"suggestions":[{"messageId":"removeAsync","fix":{"range":[11195,11262],"text":"logSecurityEvent(eventType: string, data: any): void"},"desc":"Remove 'async'."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":479,"column":59,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":479,"endColumn":62,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[11243,11246],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[11243,11246],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":541,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":541,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12638,12641],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12638,12641],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":37,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import {\n Injectable,\n Logger,\n CanActivate,\n ExecutionContext,\n} from '@nestjs/common';\nimport { Reflector } from '@nestjs/core';\nimport { Observable } from 'rxjs';\n\n/**\n * Access Protector - 访问保护器\n *\n * 职责:\n * - 控制系统访问权限\n * - 实施安全策略\n * - 监控访问行为\n * - 防止未授权访问\n */\n@Injectable()\nexport class AccessProtector implements CanActivate {\n private readonly logger = new Logger(AccessProtector.name);\n private readonly accessAttempts = new Map();\n private readonly blockedIps = new Set();\n private readonly suspiciousActivities = new Map<\n string,\n SuspiciousActivity[]\n >();\n\n constructor(private reflector: Reflector) {}\n\n /**\n * 守卫方法 - 检查访问权限\n */\n canActivate(\n context: ExecutionContext,\n ): boolean | Promise | Observable {\n const request = context.switchToHttp().getRequest();\n const clientIp = this.getClientIp(request);\n\n // 检查 IP 是否被阻止\n if (this.blockedIps.has(clientIp)) {\n this.logger.warn(`Blocked IP attempted access: ${clientIp}`);\n return false;\n }\n\n // 记录访问尝试\n this.recordAccessAttempt(clientIp, request);\n\n // 检查访问频率\n if (this.isAccessRateLimited(clientIp)) {\n this.logger.warn(`Rate limit exceeded for IP: ${clientIp}`);\n return false;\n }\n\n // 检查可疑活动\n if (this.detectSuspiciousActivity(clientIp, request)) {\n this.logger.warn(`Suspicious activity detected from IP: ${clientIp}`);\n this.handleSuspiciousActivity(clientIp, request);\n return false;\n }\n\n return true;\n }\n\n /**\n * 验证用户权限\n */\n async validateUserPermissions(\n userId: string,\n resource: string,\n action: string,\n ): Promise {\n this.logger.debug(\n `Validating permissions for user ${userId}: ${action} on ${resource}`,\n );\n\n try {\n // 获取用户角色和权限\n const userPermissions = await this.getUserPermissions(userId);\n\n // 检查资源访问权限\n const hasPermission = this.checkResourcePermission(\n userPermissions,\n resource,\n action,\n );\n\n if (!hasPermission) {\n this.logger.warn(\n `Permission denied for user ${userId}: ${action} on ${resource}`,\n );\n await this.logSecurityEvent('PERMISSION_DENIED', {\n userId,\n resource,\n action,\n timestamp: Date.now(),\n });\n }\n\n return hasPermission;\n } catch (error) {\n this.logger.error(\n `Error validating permissions for user ${userId}`,\n error,\n );\n return false;\n }\n }\n\n /**\n * 实施安全策略\n */\n async enforceSecurityPolicy(\n policyName: string,\n context: SecurityContext,\n ): Promise {\n this.logger.debug(`Enforcing security policy: ${policyName}`);\n\n const policy = await this.getSecurityPolicy(policyName);\n\n if (!policy) {\n return {\n allowed: false,\n reason: 'Policy not found',\n actions: [],\n };\n }\n\n // 评估策略条件\n const evaluation = await this.evaluatePolicyConditions(policy, context);\n\n if (!evaluation.allowed) {\n // 执行策略动作\n await this.executePolicyActions(policy.denyActions, context);\n }\n\n return evaluation;\n }\n\n /**\n * 监控访问模式\n */\n async monitorAccessPatterns(): Promise {\n this.logger.log('Analyzing access patterns');\n\n const analysis = {\n timestamp: Date.now(),\n totalAccesses: 0,\n uniqueIps: 0,\n suspiciousActivities: 0,\n blockedAttempts: 0,\n topSources: [] as AccessSource[],\n anomalies: [] as AccessAnomaly[],\n };\n\n // 分析访问尝试\n for (const [ip, attempts] of this.accessAttempts.entries()) {\n analysis.totalAccesses += attempts.length;\n\n // 检查异常模式\n const anomalies = this.detectAccessAnomalies(ip, attempts);\n analysis.anomalies.push(...anomalies);\n }\n\n analysis.uniqueIps = this.accessAttempts.size;\n analysis.suspiciousActivities = this.suspiciousActivities.size;\n analysis.blockedAttempts = this.blockedIps.size;\n analysis.topSources = this.getTopAccessSources();\n\n return analysis;\n }\n\n /**\n * 获取客户端 IP\n */\n private getClientIp(request: any): string {\n return (\n request.ip ||\n request.connection?.remoteAddress ||\n request.socket?.remoteAddress ||\n request.headers['x-forwarded-for']?.split(',')[0] ||\n 'unknown'\n );\n }\n\n /**\n * 记录访问尝试\n */\n private recordAccessAttempt(ip: string, request: any): void {\n if (!this.accessAttempts.has(ip)) {\n this.accessAttempts.set(ip, []);\n }\n\n const attempts = this.accessAttempts.get(ip)!;\n attempts.push({\n timestamp: Date.now(),\n method: request.method,\n url: request.url,\n userAgent: request.headers['user-agent'],\n success: true,\n });\n\n // 保持最近 1000 次访问记录\n if (attempts.length > 1000) {\n attempts.splice(0, attempts.length - 1000);\n }\n }\n\n /**\n * 检查访问频率限制\n */\n private isAccessRateLimited(ip: string): boolean {\n const attempts = this.accessAttempts.get(ip) || [];\n const recentAttempts = attempts.filter(\n (attempt) => Date.now() - attempt.timestamp < 60000, // 1分钟内\n );\n\n return recentAttempts.length > 100; // 每分钟最多100次请求\n }\n\n /**\n * 检测可疑活动\n */\n private detectSuspiciousActivity(ip: string, request: any): boolean {\n const attempts = this.accessAttempts.get(ip) || [];\n\n // 检查快速连续请求\n const recentAttempts = attempts.filter(\n (attempt) => Date.now() - attempt.timestamp < 10000, // 10秒内\n );\n\n if (recentAttempts.length > 50) {\n return true;\n }\n\n // 检查异常 User-Agent\n const userAgent = request.headers['user-agent'];\n if (!userAgent || this.isSuspiciousUserAgent(userAgent)) {\n return true;\n }\n\n // 检查恶意路径\n if (this.containsMaliciousPatterns(request.url)) {\n return true;\n }\n\n return false;\n }\n\n /**\n * 处理可疑活动\n */\n private handleSuspiciousActivity(ip: string, request: any): void {\n if (!this.suspiciousActivities.has(ip)) {\n this.suspiciousActivities.set(ip, []);\n }\n\n const activities = this.suspiciousActivities.get(ip)!;\n activities.push({\n timestamp: Date.now(),\n type: 'suspicious_request',\n details: {\n method: request.method,\n url: request.url,\n userAgent: request.headers['user-agent'],\n },\n });\n\n // 如果可疑活动过多,阻止该 IP\n if (activities.length > 10) {\n this.blockedIps.add(ip);\n this.logger.warn(\n `IP ${ip} has been blocked due to excessive suspicious activities`,\n );\n }\n }\n\n /**\n * 检查可疑 User-Agent\n */\n private isSuspiciousUserAgent(userAgent: string): boolean {\n const suspiciousPatterns = [\n /bot/i,\n /crawler/i,\n /spider/i,\n /scanner/i,\n /sqlmap/i,\n /nikto/i,\n ];\n\n return suspiciousPatterns.some((pattern) => pattern.test(userAgent));\n }\n\n /**\n * 检查恶意路径模式\n */\n private containsMaliciousPatterns(url: string): boolean {\n const maliciousPatterns = [\n /\\.\\./, // 路径遍历\n /\\/etc\\/passwd/,\n /\\/proc\\/self/,\n /