diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/index.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/index.js new file mode 100644 index 00000000..be17a02e --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/index.js @@ -0,0 +1,62 @@ +/** + * 转换器模块导出 + * + * 提供统一的转换器导出接口 + */ + +// 主转换器 +const ServiceMethodConverter = require('./service-method-converter'); + +// 语法转换器 +const BasicSyntaxConverter = require('./syntax/basic-syntax.converter'); +const TypeConverter = require('./syntax/type.converter'); +const ExceptionConverter = require('./syntax/exception.converter'); + +// 工具类转换器 +const ConfigConverter = require('./utils/config.converter'); +const FileConverter = require('./utils/file.converter'); +const StringConverter = require('./utils/string.converter'); +const CollectionConverter = require('./utils/collection.converter'); +const JsonConverter = require('./utils/json.converter'); +const ObjectConverter = require('./utils/object.converter'); + +// MyBatis转换器 +const QueryWrapperConverter = require('./mybatis/query-wrapper.converter'); +const MapperConverter = require('./mybatis/mapper.converter'); +const PaginationConverter = require('./mybatis/pagination.converter'); + +// 方法调用转换器 +const GetterSetterConverter = require('./method/getter-setter.converter'); +const MethodCallConverter = require('./method/method-call.converter'); +const StreamApiConverter = require('./method/stream-api.converter'); + +// 后处理器 +const PostProcessor = require('./post-processor'); + +module.exports = { + // 主转换器(推荐使用) + ServiceMethodConverter, + + // 子转换器(按需使用) + BasicSyntaxConverter, + TypeConverter, + ExceptionConverter, + + ConfigConverter, + FileConverter, + StringConverter, + CollectionConverter, + JsonConverter, + ObjectConverter, + + QueryWrapperConverter, + MapperConverter, + PaginationConverter, + + GetterSetterConverter, + MethodCallConverter, + StreamApiConverter, + + PostProcessor +}; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/getter-setter.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/getter-setter.converter.js new file mode 100644 index 00000000..1f7eea9c --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/getter-setter.converter.js @@ -0,0 +1,38 @@ +/** + * Getter/Setter转换器 + * + * Java getter/setter → TypeScript属性访问 + */ +class GetterSetterConverter { + /** + * 转换getter/setter + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. obj.getXxx() → obj.xxx (只转换简单的getter) + // 但保留常见的业务方法如 getList(), getConfig()等 + const commonMethods = ['getList', 'getConfig', 'getPage', 'getTotal', 'getData', 'getSearch', 'getLimit']; + + // 先处理需要保留的方法(不转换) + // 其他的 getXxx() 转换为属性访问 + tsCode = tsCode.replace(/(\w+)\.get(\w+)\(\)/g, (match, obj, prop) => { + const methodName = `get${prop}`; + if (commonMethods.includes(methodName)) { + return match; // 保留不转换 + } + // 转换为属性访问:obj.xxx + return `${obj}.${prop.charAt(0).toLowerCase() + prop.slice(1)}`; + }); + + // 2. obj.setXxx(value) → obj.xxx = value + tsCode = tsCode.replace(/(\w+)\.set(\w+)\(([^)]+)\)/g, (match, obj, prop, value) => { + return `${obj}.${prop.charAt(0).toLowerCase() + prop.slice(1)} = ${value}`; + }); + + return tsCode; + } +} + +module.exports = GetterSetterConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/method-call.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/method-call.converter.js new file mode 100644 index 00000000..cf6b5d97 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/method-call.converter.js @@ -0,0 +1,31 @@ +/** + * 方法调用转换器 + * + * Java方法调用 → TypeScript方法调用 + */ +class MethodCallConverter { + /** + * 转换方法调用 + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. list.add(item) → list.push(item) + tsCode = tsCode.replace(/(\w+)\.add\(/g, '$1.push('); + + // 2. list.size() → list.length + tsCode = tsCode.replace(/(\w+)\.size\(\)/g, '$1.length'); + + // 3. map.put(key, value) → map[key] = value 或 map.set(key, value) + // 这里简化为直接赋值 + tsCode = tsCode.replace(/(\w+)\.put\(([^,]+),\s*([^)]+)\)/g, '$1[$2] = $3'); + + // 4. map.get(key) → map[key] 或 map.get(key) + tsCode = tsCode.replace(/(\w+)\.get\(([^)]+)\)/g, '$1[$2]'); + + return tsCode; + } +} + +module.exports = MethodCallConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/stream-api.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/stream-api.converter.js new file mode 100644 index 00000000..595d2c2d --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/method/stream-api.converter.js @@ -0,0 +1,32 @@ +/** + * Stream API转换器 + * + * Java Stream API → TypeScript数组方法 + */ +class StreamApiConverter { + /** + * 转换Stream API + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. list.stream().filter(x -> x.condition).collect(Collectors.toList()) + // → list.filter(x => x.condition) + tsCode = tsCode.replace(/(\w+)\.stream\(\)\.filter\(([^)]+)\)\.collect\(Collectors\.toList\(\)\)/g, '$1.filter($2)'); + + // 2. list.stream().map(x -> x.transform).collect(Collectors.toList()) + // → list.map(x => x.transform) + tsCode = tsCode.replace(/(\w+)\.stream\(\)\.map\(([^)]+)\)\.collect\(Collectors\.toList\(\)\)/g, '$1.map($2)'); + + // 3. list.stream() → list (简化) + tsCode = tsCode.replace(/(\w+)\.stream\(\)/g, '$1'); + + // 4. Collectors.toList() → (移除,因为TypeScript数组方法默认返回数组) + tsCode = tsCode.replace(/\.collect\(Collectors\.toList\(\)\)/g, ''); + + return tsCode; + } +} + +module.exports = StreamApiConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/mapper.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/mapper.converter.js new file mode 100644 index 00000000..c0b7a24f --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/mapper.converter.js @@ -0,0 +1,60 @@ +/** + * Mapper转换器 + * + * MyBatis Mapper → TypeORM Repository + */ +class MapperConverter { + /** + * 转换Mapper调用 + */ + convert(javaCode, context = {}) { + let tsCode = javaCode; + + // xxxMapper.selectOne() → this.xxxRepository.findOne() + tsCode = tsCode.replace(/(\w+Mapper)\.selectOne\(/g, (match, mapperName) => { + const repoName = mapperName.replace('Mapper', 'Repository'); + const camelRepoName = this.toCamelCase(repoName); + return `this.${camelRepoName}.findOne(`; + }); + + // xxxMapper.selectList() → this.xxxRepository.find() + tsCode = tsCode.replace(/(\w+Mapper)\.selectList\(/g, (match, mapperName) => { + const repoName = mapperName.replace('Mapper', 'Repository'); + const camelRepoName = this.toCamelCase(repoName); + return `this.${camelRepoName}.find(`; + }); + + // xxxMapper.insert() → this.xxxRepository.save() + tsCode = tsCode.replace(/(\w+Mapper)\.insert\(/g, (match, mapperName) => { + const repoName = mapperName.replace('Mapper', 'Repository'); + const camelRepoName = this.toCamelCase(repoName); + return `this.${camelRepoName}.save(`; + }); + + // xxxMapper.update() → this.xxxRepository.save() + tsCode = tsCode.replace(/(\w+Mapper)\.update\(/g, (match, mapperName) => { + const repoName = mapperName.replace('Mapper', 'Repository'); + const camelRepoName = this.toCamelCase(repoName); + return `this.${camelRepoName}.save(`; + }); + + // xxxMapper.delete() → this.xxxRepository.delete() + tsCode = tsCode.replace(/(\w+Mapper)\.delete\(/g, (match, mapperName) => { + const repoName = mapperName.replace('Mapper', 'Repository'); + const camelRepoName = this.toCamelCase(repoName); + return `this.${camelRepoName}.delete(`; + }); + + return tsCode; + } + + /** + * 转换为camelCase + */ + toCamelCase(str) { + return str.charAt(0).toLowerCase() + str.slice(1); + } +} + +module.exports = MapperConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/pagination.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/pagination.converter.js new file mode 100644 index 00000000..ae46f0d7 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/pagination.converter.js @@ -0,0 +1,30 @@ +/** + * 分页转换器 + * + * MyBatis分页 → TypeORM分页 + */ +class PaginationConverter { + /** + * 转换分页 + */ + convert(javaCode) { + let tsCode = javaCode; + + // IPage → TODO: 需要手动处理 + tsCode = tsCode.replace(/IPage<(\w+)>/g, '/* TODO: Paginated<$1> */any'); + + // new Page(page, limit) → TODO + tsCode = tsCode.replace(/new\s+Page<(\w+)>\(([^,]+),\s*([^)]+)\)/g, '/* TODO: { page: $2, limit: $3 } */'); + + // selectPage() → find() with pagination + tsCode = tsCode.replace(/\.selectPage\(/g, '/* TODO: .find() with take/skip */'); + + // PageResult.build() → new PageResult() + tsCode = tsCode.replace(/PageResult\.build\(([^,]+),\s*([^,]+),\s*([^)]+)\)/g, 'new PageResult({ currentPage: $1, perPage: $2, total: $3 })'); + + return tsCode; + } +} + +module.exports = PaginationConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/query-wrapper.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/query-wrapper.converter.js new file mode 100644 index 00000000..ffd2a3b6 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/mybatis/query-wrapper.converter.js @@ -0,0 +1,28 @@ +/** + * QueryWrapper转换器 + * + * MyBatis QueryWrapper → TypeORM QueryBuilder + */ +class QueryWrapperConverter { + /** + * 转换QueryWrapper + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. new QueryWrapper() → 需要转换为TypeORM查询 + // 暂时标记为TODO,因为需要更复杂的上下文 + tsCode = tsCode.replace(/new\s+QueryWrapper<(\w+)>\(\)/g, '/* TODO: TypeORM Query for $1 */{}'); + + // 2. queryWrapper.eq("field", value) → TODO + tsCode = tsCode.replace(/(\w+)\.eq\(([^,]+),\s*([^)]+)\)/g, '/* TODO: .where("$2 = :value", { value: $3 }) */$1'); + + // 3. queryWrapper.like("field", value) → TODO + tsCode = tsCode.replace(/(\w+)\.like\(([^,]+),\s*([^)]+)\)/g, '/* TODO: .where("$2 LIKE :value", { value: `%${$3}%` }) */$1'); + + return tsCode; + } +} + +module.exports = QueryWrapperConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/post-processor.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/post-processor.js new file mode 100644 index 00000000..36252f57 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/post-processor.js @@ -0,0 +1,40 @@ +/** + * 后处理器 + * + * 修复转换后的常见语法错误 + */ +class PostProcessor { + /** + * 后处理清理 + */ + process(tsCode) { + let result = tsCode; + + // 1. 修复 this.fs. 和 this.path. → fs. 和 path. + result = result.replace(/this\.fs\./g, 'fs.'); + result = result.replace(/this\.path\./g, 'path.'); + + // 2. 修复逻辑运算符优先级问题 + // if (!this.config.get('xxx') === "yyy") → if (this.config.get('xxx') !== "yyy") + result = result.replace(/if\s*\(\s*!this\.config\.get\([^)]+\)\s*===\s*([^)]+)\)/g, (match) => { + const configCall = match.match(/this\.config\.get\([^)]+\)/)[0]; + const value = match.match(/===\s*([^)]+)\)/)[1].trim(); + return `if (${configCall} !== ${value})`; + }); + + // 3. 修复 !xxx === "yyy" → xxx !== "yyy" (通用) + result = result.replace(/!\s*([a-zA-Z_$.()[\]]+)\s*===\s*([^;)\n]+)/g, '$1 !== $2'); + + // 4. 修复复杂表达式的 .exists() + // this.config.get('xxx' + yyy).exists() → fs.existsSync(this.config.get('xxx' + yyy)) + result = result.replace(/(this\.config\.get\([^)]+\))\.exists\(\)/g, 'fs.existsSync($1)'); + + // 5. 修复逗号表达式:if (file, "info.json".exists()) + result = result.replace(/if\s*\(\s*(\w+),\s*"([^"]+)"\.exists\(\s*\)\s*\)/g, 'if (fs.existsSync(path.join($1, "$2")))'); + + return result; + } +} + +module.exports = PostProcessor; + 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 index 9ffcb324..f3c9e37b 100644 --- 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 @@ -1,18 +1,60 @@ -const NamingUtils = require('../utils/naming-utils'); - /** - * Service方法体转换器 + * Service方法体转换器(主协调器) * - * 职责:将Java Service方法体转换为TypeScript + * 职责:协调各个子转换器,将Java Service方法体转换为TypeScript * * 核心功能: * 1. 提取Java方法体 - * 2. Java语法 → TypeScript语法转换 - * 3. Java工具类 → NestJS Boot层映射 + * 2. 调用各个专业转换器进行转换 + * 3. 后处理清理 + * 4. 分析需要的imports */ + +// 导入各个转换器 +const BasicSyntaxConverter = require('./syntax/basic-syntax.converter'); +const TypeConverter = require('./syntax/type.converter'); +const ExceptionConverter = require('./syntax/exception.converter'); + +const ConfigConverter = require('./utils/config.converter'); +const FileConverter = require('./utils/file.converter'); +const StringConverter = require('./utils/string.converter'); +const CollectionConverter = require('./utils/collection.converter'); +const JsonConverter = require('./utils/json.converter'); +const ObjectConverter = require('./utils/object.converter'); + +const QueryWrapperConverter = require('./mybatis/query-wrapper.converter'); +const MapperConverter = require('./mybatis/mapper.converter'); +const PaginationConverter = require('./mybatis/pagination.converter'); + +const GetterSetterConverter = require('./method/getter-setter.converter'); +const MethodCallConverter = require('./method/method-call.converter'); +const StreamApiConverter = require('./method/stream-api.converter'); + +const PostProcessor = require('./post-processor'); + class ServiceMethodConverter { constructor() { - this.namingUtils = new NamingUtils(); + // 初始化所有转换器 + this.basicSyntax = new BasicSyntaxConverter(); + this.type = new TypeConverter(); + this.exception = new ExceptionConverter(); + + this.config = new ConfigConverter(); + this.file = new FileConverter(); + this.string = new StringConverter(); + this.collection = new CollectionConverter(); + this.json = new JsonConverter(); + this.object = new ObjectConverter(); + + this.queryWrapper = new QueryWrapperConverter(); + this.mapper = new MapperConverter(); + this.pagination = new PaginationConverter(); + + this.getterSetter = new GetterSetterConverter(); + this.methodCall = new MethodCallConverter(); + this.streamApi = new StreamApiConverter(); + + this.postProcessor = new PostProcessor(); } /** @@ -32,302 +74,55 @@ class ServiceMethodConverter { // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 【阶段1】基础语法转换 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - tsBody = this.convertBasicSyntax(tsBody); + tsBody = this.basicSyntax.convert(tsBody); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 【阶段2】类型转换 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - tsBody = this.convertTypes(tsBody); + tsBody = this.type.convert(tsBody); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - // 【阶段3】工具类映射(Java → NestJS Boot层) + // 【阶段3】工具类转换 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - tsBody = this.convertUtilityClasses(tsBody); + tsBody = this.config.convert(tsBody); + tsBody = this.file.convert(tsBody); + tsBody = this.string.convert(tsBody); + tsBody = this.collection.convert(tsBody); + tsBody = this.json.convert(tsBody); + tsBody = this.object.convert(tsBody); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - // 【阶段4】Mapper/Service调用转换 + // 【阶段4】MyBatis → TypeORM转换 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - tsBody = this.convertDependencyCalls(tsBody, context); + tsBody = this.queryWrapper.convert(tsBody); + tsBody = this.mapper.convert(tsBody, context); + tsBody = this.pagination.convert(tsBody); // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - // 【阶段5】后处理清理 + // 【阶段5】方法调用转换 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - tsBody = this.postProcessCleanup(tsBody); + tsBody = this.streamApi.convert(tsBody); + tsBody = this.methodCall.convert(tsBody); + tsBody = this.getterSetter.convert(tsBody); // 最后转换getter/setter // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - // 【阶段6】添加缩进 + // 【阶段6】异常处理转换 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsBody = this.exception.convert(tsBody); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【阶段7】后处理清理 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsBody = this.postProcessor.process(tsBody); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【阶段8】添加缩进 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ tsBody = tsBody.split('\n').map(line => ' ' + line).join('\n'); return tsBody; } - /** - * 【阶段5】后处理清理 - * 修复转换后的常见语法错误 - */ - postProcessCleanup(tsBody) { - // 1. 修复 this.fs. 和 this.path. → fs. 和 path. - tsBody = tsBody.replace(/this\.fs\./g, 'fs.'); - tsBody = tsBody.replace(/this\.path\./g, 'path.'); - - // 2. 修复逻辑运算符优先级问题 - // if (!this.config.get('xxx') === "yyy") → if (this.config.get('xxx') !== "yyy") - tsBody = tsBody.replace(/if\s*\(\s*!this\.config\.get\([^)]+\)\s*===\s*([^)]+)\)/g, (match) => { - // 提取内容 - const configCall = match.match(/this\.config\.get\([^)]+\)/)[0]; - const value = match.match(/===\s*([^)]+)\)/)[1].trim(); - return `if (${configCall} !== ${value})`; - }); - - // 3. 修复 !xxx === "yyy" → xxx !== "yyy" (通用) - tsBody = tsBody.replace(/!\s*([a-zA-Z_$.()[\]]+)\s*===\s*([^;)\n]+)/g, '$1 !== $2'); - - // 4. 修复复杂表达式的 .exists() - // this.config.get('xxx' + yyy).exists() → fs.existsSync(this.config.get('xxx' + yyy)) - tsBody = tsBody.replace(/(this\.config\.get\([^)]+\))\.exists\(\)/g, 'fs.existsSync($1)'); - - 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.exists() → fs.existsSync(this.config.get('property')) - // 必须在WebAppEnvs.get().property之前处理 - tsBody = tsBody.replace(/WebAppEnvs\.get\(\)\.(\w+)\.exists\(\)/g, (match, prop) => { - return `fs.existsSync(this.config.get('${prop}'))`; - }); - - // 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.exists() → fs.existsSync(this.config.get('property')) - // 必须在GlobalConfig.property之前处理 - tsBody = tsBody.replace(/GlobalConfig\.(\w+)\.exists\(\)/g, (match, prop) => { - return `fs.existsSync(this.config.get('${prop}'))`; - }); - - // 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 - // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - // FileUtils工具类 - tsBody = tsBody.replace(/FileUtils\.cleanDirectory\(([^)]+)\)/g, 'fs.rmSync($1, { recursive: true, force: true })'); - tsBody = tsBody.replace(/FileUtils\.copyFile\(([^,]+),\s*([^)]+)\)/g, 'fs.copyFileSync($1, $2)'); - tsBody = tsBody.replace(/FileUtils\.deleteDirectory\(([^)]+)\)/g, 'fs.rmSync($1, { recursive: true, force: true })'); - tsBody = tsBody.replace(/FileUtils\.readFileToString\(([^)]+)\)/g, 'fs.readFileSync($1, \'utf-8\')'); - tsBody = tsBody.replace(/FileUtils\.writeStringToFile\(([^,]+),\s*([^)]+)\)/g, 'fs.writeFileSync($1, $2, \'utf-8\')'); - - // File API - 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)'); - tsBody = tsBody.replace(/(\w+)\.getPath\(\)/g, '$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() !== \'\')'); - - // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - // 【异常处理】 - // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - // try-catch语句:catch (Exception e) → catch (error) - tsBody = tsBody.replace(/catch\s*\(\s*(?:Exception|RuntimeException|Throwable)\s+(\w+)\s*\)/g, 'catch ($1)'); - - // 异常方法调用:e.getMessage() → e.message - tsBody = tsBody.replace(/(\w+)\.getMessage\(\)/g, '$1.message'); - - // 异常抛出 - 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 * @@ -342,23 +137,15 @@ class ServiceMethodConverter { }; // NestJS异常 - if (convertedBody.includes('BadRequestException')) { - imports.nestjs.add('BadRequestException'); - } - if (convertedBody.includes('UnauthorizedException')) { - imports.nestjs.add('UnauthorizedException'); - } + const nestjsImports = this.exception.analyzeImports(convertedBody); + nestjsImports.forEach(imp => imports.nestjs.add(imp)); // Node.js模块 - if (convertedBody.includes('fs.')) { - imports.nodeModules.add('fs'); - } - if (convertedBody.includes('path.')) { - imports.nodeModules.add('path'); - } + const nodeModules = this.file.analyzeNodeModules(convertedBody); + nodeModules.forEach(mod => imports.nodeModules.add(mod)); // ConfigService - if (convertedBody.includes('this.config.')) { + if (this.config.needsConfigService(convertedBody)) { imports.boot.add('ConfigService'); } @@ -371,4 +158,3 @@ class ServiceMethodConverter { } module.exports = ServiceMethodConverter; - diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/service-method-converter.js.bak b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/service-method-converter.js.bak new file mode 100644 index 00000000..9ffcb324 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/service-method-converter.js.bak @@ -0,0 +1,374 @@ +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 = this.postProcessCleanup(tsBody); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【阶段6】添加缩进 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsBody = tsBody.split('\n').map(line => ' ' + line).join('\n'); + + return tsBody; + } + + /** + * 【阶段5】后处理清理 + * 修复转换后的常见语法错误 + */ + postProcessCleanup(tsBody) { + // 1. 修复 this.fs. 和 this.path. → fs. 和 path. + tsBody = tsBody.replace(/this\.fs\./g, 'fs.'); + tsBody = tsBody.replace(/this\.path\./g, 'path.'); + + // 2. 修复逻辑运算符优先级问题 + // if (!this.config.get('xxx') === "yyy") → if (this.config.get('xxx') !== "yyy") + tsBody = tsBody.replace(/if\s*\(\s*!this\.config\.get\([^)]+\)\s*===\s*([^)]+)\)/g, (match) => { + // 提取内容 + const configCall = match.match(/this\.config\.get\([^)]+\)/)[0]; + const value = match.match(/===\s*([^)]+)\)/)[1].trim(); + return `if (${configCall} !== ${value})`; + }); + + // 3. 修复 !xxx === "yyy" → xxx !== "yyy" (通用) + tsBody = tsBody.replace(/!\s*([a-zA-Z_$.()[\]]+)\s*===\s*([^;)\n]+)/g, '$1 !== $2'); + + // 4. 修复复杂表达式的 .exists() + // this.config.get('xxx' + yyy).exists() → fs.existsSync(this.config.get('xxx' + yyy)) + tsBody = tsBody.replace(/(this\.config\.get\([^)]+\))\.exists\(\)/g, 'fs.existsSync($1)'); + + 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.exists() → fs.existsSync(this.config.get('property')) + // 必须在WebAppEnvs.get().property之前处理 + tsBody = tsBody.replace(/WebAppEnvs\.get\(\)\.(\w+)\.exists\(\)/g, (match, prop) => { + return `fs.existsSync(this.config.get('${prop}'))`; + }); + + // 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.exists() → fs.existsSync(this.config.get('property')) + // 必须在GlobalConfig.property之前处理 + tsBody = tsBody.replace(/GlobalConfig\.(\w+)\.exists\(\)/g, (match, prop) => { + return `fs.existsSync(this.config.get('${prop}'))`; + }); + + // 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 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + // FileUtils工具类 + tsBody = tsBody.replace(/FileUtils\.cleanDirectory\(([^)]+)\)/g, 'fs.rmSync($1, { recursive: true, force: true })'); + tsBody = tsBody.replace(/FileUtils\.copyFile\(([^,]+),\s*([^)]+)\)/g, 'fs.copyFileSync($1, $2)'); + tsBody = tsBody.replace(/FileUtils\.deleteDirectory\(([^)]+)\)/g, 'fs.rmSync($1, { recursive: true, force: true })'); + tsBody = tsBody.replace(/FileUtils\.readFileToString\(([^)]+)\)/g, 'fs.readFileSync($1, \'utf-8\')'); + tsBody = tsBody.replace(/FileUtils\.writeStringToFile\(([^,]+),\s*([^)]+)\)/g, 'fs.writeFileSync($1, $2, \'utf-8\')'); + + // File API + 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)'); + tsBody = tsBody.replace(/(\w+)\.getPath\(\)/g, '$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() !== \'\')'); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【异常处理】 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + // try-catch语句:catch (Exception e) → catch (error) + tsBody = tsBody.replace(/catch\s*\(\s*(?:Exception|RuntimeException|Throwable)\s+(\w+)\s*\)/g, 'catch ($1)'); + + // 异常方法调用:e.getMessage() → e.message + tsBody = tsBody.replace(/(\w+)\.getMessage\(\)/g, '$1.message'); + + // 异常抛出 + 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/converters/syntax/basic-syntax.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/syntax/basic-syntax.converter.js new file mode 100644 index 00000000..01b85cd3 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/syntax/basic-syntax.converter.js @@ -0,0 +1,91 @@ +/** + * 基础语法转换器 + * + * 负责Java基础语法到TypeScript的转换: + * - 变量声明 + * - 循环语句 + * - Lambda表达式 + * - 集合实例化 + */ +class BasicSyntaxConverter { + /** + * 转换基础语法 + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. 变量声明:Type varName = value; → const varName: Type = value; + tsCode = tsCode.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) + tsCode = tsCode.replace(/for\s*\(\s*[\w<>,\s]+\s+(\w+)\s*:\s*([^)]+)\)/g, 'for (const $1 of $2)'); + + // 3. Lambda表达式:item -> expression → item => expression + tsCode = tsCode.replace(/(\w+)\s*->\s*/g, '$1 => '); + tsCode = tsCode.replace(/\(([^)]+)\)\s*->\s*/g, '($1) => '); + + // 4. Java实例化:new ArrayList<>() → [] + tsCode = tsCode.replace(/new\s+ArrayList<[^>]*>\(\)/g, '[]'); + tsCode = tsCode.replace(/new\s+LinkedList<[^>]*>\(\)/g, '[]'); + tsCode = tsCode.replace(/new\s+HashMap<[^>]*>\(\)/g, '{}'); + tsCode = tsCode.replace(/new\s+HashSet<[^>]*>\(\)/g, 'new Set()'); + + return tsCode; + } + + /** + * 映射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; + } +} + +module.exports = BasicSyntaxConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/syntax/exception.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/syntax/exception.converter.js new file mode 100644 index 00000000..d846ed88 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/syntax/exception.converter.js @@ -0,0 +1,49 @@ +/** + * 异常处理转换器 + * + * 负责Java异常到TypeScript/NestJS异常的转换 + */ +class ExceptionConverter { + /** + * 转换异常处理 + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. try-catch语句:catch (Exception e) → catch (e) + tsCode = tsCode.replace(/catch\s*\(\s*(?:Exception|RuntimeException|Throwable|IOException|SQLException)\s+(\w+)\s*\)/g, 'catch ($1)'); + + // 2. 异常方法调用:e.getMessage() → e.message + tsCode = tsCode.replace(/(\w+)\.getMessage\(\)/g, '$1.message'); + tsCode = tsCode.replace(/(\w+)\.printStackTrace\(\)/g, 'console.error($1)'); + + // 3. 异常抛出 + tsCode = tsCode.replace(/throw\s+new\s+CommonException\(/g, 'throw new BadRequestException('); + tsCode = tsCode.replace(/throw\s+new\s+AuthException\(/g, 'throw new UnauthorizedException('); + tsCode = tsCode.replace(/throw\s+new\s+RuntimeException\(/g, 'throw new Error('); + tsCode = tsCode.replace(/throw\s+new\s+Exception\(/g, 'throw new Error('); + tsCode = tsCode.replace(/throw\s+new\s+IOException\(/g, 'throw new Error('); + tsCode = tsCode.replace(/throw\s+new\s+SQLException\(/g, 'throw new Error('); + + return tsCode; + } + + /** + * 分析需要的异常imports + */ + analyzeImports(tsCode) { + const imports = new Set(); + + if (tsCode.includes('BadRequestException')) { + imports.add('BadRequestException'); + } + if (tsCode.includes('UnauthorizedException')) { + imports.add('UnauthorizedException'); + } + + return Array.from(imports); + } +} + +module.exports = ExceptionConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/syntax/type.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/syntax/type.converter.js new file mode 100644 index 00000000..6cdb4f5d --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/syntax/type.converter.js @@ -0,0 +1,31 @@ +/** + * 类型转换器 + * + * 负责Java类型到TypeScript类型的转换 + */ +class TypeConverter { + /** + * 转换类型 + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. 基础类型 + tsCode = tsCode.replace(/\bInteger\b/g, 'number'); + tsCode = tsCode.replace(/\bLong\b/g, 'number'); + tsCode = tsCode.replace(/\bDouble\b/g, 'number'); + tsCode = tsCode.replace(/\bFloat\b/g, 'number'); + + // 2. Java对象类型 + tsCode = tsCode.replace(/\bJSONObject\b/g, 'Record'); + tsCode = tsCode.replace(/\bId\b/g, 'number'); + + // 3. Java类型转换语法:(Type) value → value + tsCode = tsCode.replace(/\(\s*(?:int|long|double|float|String|Integer|Long|Double|Float|number)\s*\)\s*/g, ''); + + return tsCode; + } +} + +module.exports = TypeConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/collection.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/collection.converter.js new file mode 100644 index 00000000..a94a8f97 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/collection.converter.js @@ -0,0 +1,27 @@ +/** + * 集合判空转换器 + * + * Java集合判空方法 → TypeScript数组判空 + */ +class CollectionConverter { + /** + * 转换集合判空 + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. CollectionUtil.isEmpty/isNotEmpty + tsCode = tsCode.replace(/(?:CollectionUtil|CollUtil)\.isEmpty\(([^)]+)\)/g, '(!$1 || $1.length === 0)'); + tsCode = tsCode.replace(/(?:CollectionUtil|CollUtil)\.isNotEmpty\(([^)]+)\)/g, '($1 && $1.length > 0)'); + + // 2. list.isEmpty() → list.length === 0 + // 支持链式调用:obj.getConfig().isEmpty() + tsCode = tsCode.replace(/([a-zA-Z_$][\w$.]*)\.isEmpty\(\)/g, '$1.length === 0'); + tsCode = tsCode.replace(/!([a-zA-Z_$][\w$.]*)\.isEmpty\(\)/g, '$1.length > 0'); + + return tsCode; + } +} + +module.exports = CollectionConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/config.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/config.converter.js new file mode 100644 index 00000000..72758ed9 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/config.converter.js @@ -0,0 +1,53 @@ +/** + * 配置访问转换器 + * + * WebAppEnvs / GlobalConfig → ConfigService + */ +class ConfigConverter { + /** + * 转换配置访问 + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. WebAppEnvs.get().property.exists() → fs.existsSync(this.config.get('property')) + tsCode = tsCode.replace(/WebAppEnvs\.get\(\)\.(\w+)\.exists\(\)/g, (match, prop) => { + return `fs.existsSync(this.config.get('${prop}'))`; + }); + + // 2. WebAppEnvs.get().property → this.config.get('property') + tsCode = tsCode.replace(/WebAppEnvs\.get\(\)\.(\w+)/g, (match, prop) => { + return `this.config.get('${prop}')`; + }); + + // 3. WebAppEnvs.get() → this.config + tsCode = tsCode.replace(/WebAppEnvs\.get\(\)/g, 'this.config'); + + // 4. WebAppEnvs.staticProperty → this.config.get('staticProperty') + tsCode = tsCode.replace(/WebAppEnvs\.(\w+)/g, (match, prop) => { + return `this.config.get('${prop}')`; + }); + + // 5. GlobalConfig.property.exists() → fs.existsSync(this.config.get('property')) + tsCode = tsCode.replace(/GlobalConfig\.(\w+)\.exists\(\)/g, (match, prop) => { + return `fs.existsSync(this.config.get('${prop}'))`; + }); + + // 6. GlobalConfig.property → this.config.get('property') + tsCode = tsCode.replace(/GlobalConfig\.(\w+)/g, (match, prop) => { + return `this.config.get('${prop}')`; + }); + + return tsCode; + } + + /** + * 分析是否需要ConfigService + */ + needsConfigService(tsCode) { + return tsCode.includes('this.config.'); + } +} + +module.exports = ConfigConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/file.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/file.converter.js new file mode 100644 index 00000000..c02a517a --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/file.converter.js @@ -0,0 +1,63 @@ +/** + * 文件操作转换器 + * + * Java File API / FileUtils → Node.js fs/path + */ +class FileConverter { + /** + * 转换文件操作 + */ + convert(javaCode) { + let tsCode = javaCode; + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【FileUtils工具类】 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsCode = tsCode.replace(/FileUtils\.cleanDirectory\(([^)]+)\)/g, 'fs.rmSync($1, { recursive: true, force: true })'); + tsCode = tsCode.replace(/FileUtils\.copyFile\(([^,]+),\s*([^)]+)\)/g, 'fs.copyFileSync($1, $2)'); + tsCode = tsCode.replace(/FileUtils\.deleteDirectory\(([^)]+)\)/g, 'fs.rmSync($1, { recursive: true, force: true })'); + tsCode = tsCode.replace(/FileUtils\.readFileToString\(([^)]+)\)/g, 'fs.readFileSync($1, \'utf-8\')'); + tsCode = tsCode.replace(/FileUtils\.writeStringToFile\(([^,]+),\s*([^)]+)\)/g, 'fs.writeFileSync($1, $2, \'utf-8\')'); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【File API】 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + tsCode = tsCode.replace(/new\s+File\(([^)]+)\)/g, '$1'); + tsCode = tsCode.replace(/(\w+)\.exists\(\)/g, 'fs.existsSync($1)'); + tsCode = tsCode.replace(/(\w+)\.isDirectory\(\)/g, 'fs.lstatSync($1).isDirectory()'); + tsCode = tsCode.replace(/(\w+)\.getName\(\)/g, 'path.basename($1)'); + tsCode = tsCode.replace(/(\w+)\.listFiles\(\)/g, 'fs.readdirSync($1)'); + tsCode = tsCode.replace(/(\w+)\.getPath\(\)/g, '$1'); + tsCode = tsCode.replace(/(\w+)\.getAbsolutePath\(\)/g, 'path.resolve($1)'); + + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // 【Java NIO API】 + // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + // Files.list(Paths.get(x)) → fs.readdirSync(x).map(...) + tsCode = tsCode.replace(/Files\.list\(Paths\.get\(([^)]+)\)\)/g, 'fs.readdirSync($1)'); + + // Paths.get(x) → x + tsCode = tsCode.replace(/Paths\.get\(([^)]+)\)/g, '$1'); + + return tsCode; + } + + /** + * 分析是否需要Node.js模块 + */ + analyzeNodeModules(tsCode) { + const modules = new Set(); + + if (tsCode.includes('fs.')) { + modules.add('fs'); + } + if (tsCode.includes('path.')) { + modules.add('path'); + } + + return Array.from(modules); + } +} + +module.exports = FileConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/json.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/json.converter.js new file mode 100644 index 00000000..faa77913 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/json.converter.js @@ -0,0 +1,27 @@ +/** + * JSON工具类转换器 + * + * JSONUtil / JSON相关 → TypeScript JSON / JsonUtils + */ +class JsonConverter { + /** + * 转换JSON工具类 + */ + convert(javaCode) { + let tsCode = javaCode; + + // JSONUtil.parseObj() → JSON.parse() + tsCode = tsCode.replace(/JSONUtil\.parseObj\(([^)]+)\)/g, 'JSON.parse($1)'); + + // JSONUtil.toBean() → 需要手动处理,暂时保留TODO + tsCode = tsCode.replace(/JSONUtil\.toBean\(([^,]+),\s*([^)]+)\.class\)/g, '/* TODO: JSONUtil.toBean($1, $2) */Object.assign(new $2(), JSON.parse(JSON.stringify($1)))'); + + // JSONObject → Record + tsCode = tsCode.replace(/JSONObject/g, 'Record'); + + return tsCode; + } +} + +module.exports = JsonConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/object.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/object.converter.js new file mode 100644 index 00000000..0986dfe1 --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/object.converter.js @@ -0,0 +1,38 @@ +/** + * 对象工具类转换器 + * + * ObjectUtil / BeanUtils等 → TypeScript对象操作 + */ +class ObjectConverter { + /** + * 转换对象工具类 + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. ObjectUtil.isNotEmpty() → value && ... + tsCode = tsCode.replace(/ObjectUtil\.isNotEmpty\(([^)]+)\)/g, '($1 && Object.keys($1).length > 0)'); + tsCode = tsCode.replace(/ObjectUtil\.isEmpty\(([^)]+)\)/g, '(!$1 || Object.keys($1).length === 0)'); + + // 2. ObjectUtil.defaultIfNull(a, b) → a ?? b + tsCode = tsCode.replace(/ObjectUtil\.defaultIfNull\(([^,]+),\s*([^)]+)\)/g, '$1 ?? $2'); + + // 3. BeanUtils.copyProperties(src, dest) → Object.assign(dest, src) + tsCode = tsCode.replace(/BeanUtils\.copyProperties\(([^,]+),\s*([^)]+)\)/g, 'Object.assign($2, $1)'); + + // 4. System.out.println() → console.log() + tsCode = tsCode.replace(/System\.out\.println\(/g, 'console.log('); + tsCode = tsCode.replace(/System\.err\.println\(/g, 'console.error('); + + // 5. System.currentTimeMillis() → Date.now() + tsCode = tsCode.replace(/System\.currentTimeMillis\(\)/g, 'Date.now()'); + + // 6. Assert.notNull() → if (!x) throw new Error() + tsCode = tsCode.replace(/Assert\.notNull\(([^,]+),\s*([^)]+)\)/g, 'if (!$1) throw new BadRequestException($2)'); + + return tsCode; + } +} + +module.exports = ObjectConverter; + diff --git a/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/string.converter.js b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/string.converter.js new file mode 100644 index 00000000..a9a6a6ff --- /dev/null +++ b/wwjcloud-nest-v1/tools/java-to-nestjs-migration/converters/utils/string.converter.js @@ -0,0 +1,35 @@ +/** + * 字符串方法转换器 + * + * Java String方法 → TypeScript String方法 + */ +class StringConverter { + /** + * 转换字符串方法 + */ + convert(javaCode) { + let tsCode = javaCode; + + // 1. .equals() → === + // 支持方法调用结果:path.basename(child).equals("sql") + tsCode = tsCode.replace(/([a-zA-Z_$][\w$.()]+)\.equals\(([^)]+)\)/g, '$1 === $2'); + + // 2. .equalsIgnoreCase() → .toLowerCase() === xxx.toLowerCase() + tsCode = tsCode.replace(/([a-zA-Z_$][\w$.()]+)\.equalsIgnoreCase\(([^)]+)\)/g, '$1.toLowerCase() === $2.toLowerCase()'); + + // 3. .contains() → .includes() + tsCode = tsCode.replace(/\.contains\(/g, '.includes('); + + // 4. StringUtils.isEmpty/isNotEmpty + tsCode = tsCode.replace(/StringUtils\.isEmpty\(([^)]+)\)/g, '(!$1 || $1.trim() === \'\')'); + tsCode = tsCode.replace(/StringUtils\.isNotEmpty\(([^)]+)\)/g, '($1 && $1.trim() !== \'\')'); + + // 5. String.valueOf() → String() + tsCode = tsCode.replace(/String\.valueOf\(([^)]+)\)/g, 'String($1)'); + + return tsCode; + } +} + +module.exports = StringConverter; + diff --git a/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-boot/src/index.ts b/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-boot/src/index.ts index abe34eb9..5f018e1e 100644 --- a/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-boot/src/index.ts +++ b/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-boot/src/index.ts @@ -39,3 +39,4 @@ export * from "./infra/queue/job-scheduler.service"; export * from "./infra/events/event-listener.service"; export * from "./infra/events/event-bus"; export * from "./infra/common/result"; +export { ConfigService } from "@nestjs/config"; diff --git a/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-core/src/services/admin/home/impl/auth-site-service-impl.service.ts b/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-core/src/services/admin/home/impl/auth-site-service-impl.service.ts index 23c9d9fa..1cdaddaa 100644 --- a/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-core/src/services/admin/home/impl/auth-site-service-impl.service.ts +++ b/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-core/src/services/admin/home/impl/auth-site-service-impl.service.ts @@ -358,14 +358,14 @@ export class AuthSiteServiceImplService { */ async getSiteGroupAppList(...args: any[]): Promise { const siteGroupAppList: string[] = getSiteGroupApps(); - if (CollectionUtils.isEmpty(siteGroupAppList)){ + if (CollectionUtils.isEmpty(siteGroupAppList)){ return List.of(); - } + } const addonList: Addon[] = addonMapper.selectList(new LambdaQueryWrapper() - .eq(Addon::getStatus, AddonStatusEnum.ON.getCode()) - .eq(Addon::getType, AddonActionEnum.APP.getCode()) - .in(Addon::getKey, siteGroupAppList)); + .eq(Addon::getStatus, AddonStatusEnum.ON.getCode()) + .eq(Addon::getType, AddonActionEnum.APP.getCode()) + .in(Addon::getKey, siteGroupAppList)); - return processAddonList(addonList); + return processAddonList(addonList); } }