diff --git a/bin/service-code-generation/config/index.js b/bin/service-code-generation/config/index.js index 5a2cb86..b23e161 100644 --- a/bin/service-code-generation/config/index.js +++ b/bin/service-code-generation/config/index.js @@ -1,6 +1,6 @@ module.exports = { // 需要被监听的api地址路径 - apiListPath: "F:\\desktop\\vue-class-api-tsx\\src\\core\\config\\configure.config.ts", + apiListPath: "/Users/bmy/source/TsxVueClassApi/src/core/config/configure.config.ts", // 生成的service层代码存放路径 - outPutServicePath: "F:\\desktop\\vue-class-api-tsx\\src\\core\\service" + outPutServicePath: "/Users/bmy/source/TsxVueClassApi/src/core/service" } \ No newline at end of file diff --git a/bin/service-code-generation/index.js b/bin/service-code-generation/index.js index 455097d..2ca2dbe 100644 --- a/bin/service-code-generation/index.js +++ b/bin/service-code-generation/index.js @@ -8,22 +8,26 @@ let ServerMap = new Map(); // 'Order' => Map(1) { 'test' => 'test' } // } let main = async () => { + // 读取配置文件中,注释 start 和 end 中间的 对象代码 let readApi = new readApiList(config.apiListPath) let res = await readApi.getFileList() - + + console.log("getFileList: ", res) + + // 处理读取到的 字符串数组,将多个key方法进行分类归入不同的class文件中 + // 比如 Car_carList 和 Car_addCar,应该同属 Car.service.ts,而 + // carList 和 addCar 则为文件中class的方法 res.forEach(v => { // [ 'Car', 'IndexTest' ] let key = v.split(":")[0].split("_") if (!ServerMap.get(key[0])) { - ServerMap.set(key[0], new Map()) - } + ServerMap.set(key[0], new Map()) + } ServerMap.get(key[0]).set(key[1],key[1]) }); - // 根据接口对象的配置文件,自动生成service文件和代码 - ServerMap.forEach((value,key) => { - file.createdService(key,value) - }) + // 根据上面的输出结果,自动生成service文件和代码 + ServerMap.forEach((value,key) => file.createdService(key,value)) } main() diff --git a/bin/service-code-generation/utils/File.js b/bin/service-code-generation/utils/File.js index e22004c..870b193 100644 --- a/bin/service-code-generation/utils/File.js +++ b/bin/service-code-generation/utils/File.js @@ -4,8 +4,10 @@ const config = require("../config"); class File { createdService(ServiceName, ServiceMethods) { - let fullPath = `${config.outPutServicePath}\\${ServiceName}.service.ts` - if (!existsSync(fullPath)) { + console.log("ServiceName: ", ServiceName); + console.log("ServiceMethods: ", ServiceMethods); + let fullPath = `${config.outPutServicePath}/${ServiceName}.service.ts` + // if (!existsSync(fullPath)) { let mArray = Array.from(ServiceMethods, ([name, value]) => ({ name, value })); writeFileSync(fullPath, this.stripIndent` // @ts-nocheck @@ -29,7 +31,7 @@ class File { } } `) - } + // } } diff --git a/bin/service-code-generation/utils/ReadApiList.js b/bin/service-code-generation/utils/ReadApiList.js index d1815e6..9119704 100644 --- a/bin/service-code-generation/utils/ReadApiList.js +++ b/bin/service-code-generation/utils/ReadApiList.js @@ -1,59 +1,55 @@ const { createReadStream } = require('fs') class ReadApiList { - apiListPath = ""; - lineLength = 0; textArr = []; - lineBuffer = Buffer.alloc(4096); - text = ""; + status = false; + lineBuffer = []; + lineLength = 0; + stream = null constructor(path) { - this.apiListPath = path + this.stream = createReadStream(path); } getFileList() { - this.text = createReadStream(this.apiListPath) - return new Promise((s, e) => { - this.textArr = []; - let status = false - this.text.on('data', (data) => { - for (var i = 0; i < data.length; i++) { - if (data[i] == 10 || data[i] == 13) { - if (data[i] == 10) { - try { - var line = this.lineBuffer.slice(0, this.lineLength); - if (line.length != 0) { - let str = line.toString('utf8') - .replace(/^\s+|\s+$/g, '') - .replace(/\'/g, "") - .replace(/,/g, "") + return new Promise((resolve, reject) => { + this.stream.on('data', (data) => { + for (let i = 0; i < data.length; i++) { + const byte = data[i]; + if (byte === 10 || byte === 13) { // 处理 \n 和 \r + if (this.lineLength > 0) { + const line = Buffer.from(this.lineBuffer.slice(0, this.lineLength)).toString('utf8'); + const cleanedLine = line.trim().replace(/'|,/g, ''); - if (str.includes("start -")) { - status = true - continue; - } - if (str.includes("end -")) { - status = false - break; - } + if (cleanedLine.includes("start -")) { + this.status = true; + } else if (cleanedLine.includes("end -")) { + this.status = false; - if (status) { - // console.log("str: ", str.split(":")) - this.textArr.push(str); - } - } - } finally { - this.lineLength = 0; + // 去除被注释的key代码 + } else if (this.status && !cleanedLine.includes("//")) { + this.textArr.push(cleanedLine); } } + this.lineLength = 0; // 重置行缓冲区 } else { - this.lineBuffer[this.lineLength] = data[i]; + if (this.lineLength >= this.lineBuffer.length) { + this.lineBuffer.push(byte); + } else { + this.lineBuffer[this.lineLength] = byte; + } this.lineLength++; } } + }); - s(this.textArr) - }) + this.stream.on('end', () => { + resolve(this.textArr); + }); + + this.stream.on('error', (err) => { + reject(err); + }); }) } } diff --git a/bin/test/generator.js b/bin/test/generator.js index e69de29..4986372 100644 --- a/bin/test/generator.js +++ b/bin/test/generator.js @@ -0,0 +1,45 @@ +const fs = require('fs'); +const path = require('path'); +const chokidar = require('chokidar'); +const { parse } = require('@babel/parser'); +const { codeFrameColumns } = require('@babel/code-frame'); + +// 配置常量 +const AUTO_START = '/* auto-generated-start */'; +const AUTO_END = '/* auto-generated-end */'; +const INDENT = ' '; // 缩进2空格 + +// 配置文件路径 +// const CONFIG_PATH = path.join(__dirname, '../config/dynamic-config.js'); +const CONFIG_PATH = "/Users/bmy/source/TsxVueClassApi/src/core/config/configure.config.ts"; +const TARGET_PATH = path.join(__dirname, 'templates/TargetClass.ts'); + +function generateClassMethods(keys) { + // 读取目标文件 + let targetContent; + try { + targetContent = fs.readFileSync(TARGET_PATH, 'utf8'); + } catch { + targetContent = `${AUTO_START}\n${AUTO_END}`; + } + + // 生成新方法代码 + const newMethods = keys.map(key => + `${INDENT}public ${key}() {\n${INDENT} // Auto-generated\n${INDENT}}` + ).join('\n\n'); + + // 替换标记区域 + const newContent = targetContent.replace( + new RegExp(`${AUTO_START}([\\s\\S]*?)${AUTO_END}`), + `${AUTO_START}\n${newMethods}\n${INDENT}${AUTO_END}` + ); + + // 格式校验 + try { + parse(newContent, { plugins: ['typescript'] }); + fs.writeFileSync(TARGET_PATH, newContent); + } catch (err) { + console.error('⚠️ 生成代码语法错误:'); + console.log(codeFrameColumns(newContent, err.loc, { highlightCode: true })); + } +} \ No newline at end of file diff --git a/package.json b/package.json index 169490b..e7256c3 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,10 @@ "tinit": "bin/tinit" }, "dependencies": { + "@babel/code-frame": "^7.26.2", "ant-design-vue": "^1.6.5", "axios": "^0.20.0", + "chokidar": "^4.0.3", "core-js": "^3.6.5", "isarray": "^2.0.5", "vue": "^2.6.11", diff --git a/src/core/config/configure.config.ts b/src/core/config/configure.config.ts index 26ae1da..ae48965 100644 --- a/src/core/config/configure.config.ts +++ b/src/core/config/configure.config.ts @@ -24,14 +24,23 @@ export class ConfigureConfig { DevUrl: 'http://127.0.0.1:8080', ProdUrl: 'http://127.0.0.1:9090/api', ApiList: { - // start - 注释内的key都将被Node.js监听并diff取出实时编辑后的差异项,然后程序决定是否增删请求中间层xx文件中的xx方法代码【不要删除】 - UserList: '/UserList', + // start - 下面 注释内的各个对象key 将被Nodejs实时监听,获取你key改动(增删改)后,将同步 + // start - 自动生成接口请求中间层的文件和文件内部的代码。 + // start - 注意 下面 被注释的key 将不会生成文件或代码 + + // UserList: '/UserList', // User_IndexTest: '/test', - // Car_carList: '/test', + Car_carList: '/test', // Car_addCar: '/test', - // Index_reg: '/reg', - // Order_test: '/test', - // end - 注释内的key都将被Node.js监听并diff取出实时编辑后的差异项,然后程序决定是否增删请求中间层xx文件中的xx方法代码【不要删除】 + + Index_reg: '/reg', + Index_login: '/login', + + Order_test: '/test', + + // end - 上面 注释内的各个对象key 将被Nodejs实时监听,获取你key改动(增删改)后,将同步 + // end - 自动生成接口请求中间层的文件和文件内部的代码。 + // end - 注意 上面 被注释的key 将不会生成文件或代码 } }; diff --git a/src/core/service/Car.service.ts b/src/core/service/Car.service.ts new file mode 100644 index 0000000..17b0ef9 --- /dev/null +++ b/src/core/service/Car.service.ts @@ -0,0 +1,17 @@ +// @ts-nocheck +import { GET, Mapper, POST, PUT, DELETE } from "@ann/Http.annotation"; +import { property, defaultValue, deserialize } from "@ann/JsonToClass"; + +// 建议用工具json-class-desktop生成这个类 类型 +export class ResponseType { + @property("id") + user_id!: number; +} + +export class CarService { + + @GET() + @Mapper(ResponseType) + public async carList (params: object): Promise {} + +} \ No newline at end of file diff --git a/src/core/service/Index.service.ts b/src/core/service/Index.service.ts new file mode 100644 index 0000000..88daee6 --- /dev/null +++ b/src/core/service/Index.service.ts @@ -0,0 +1,21 @@ +// @ts-nocheck +import { GET, Mapper, POST, PUT, DELETE } from "@ann/Http.annotation"; +import { property, defaultValue, deserialize } from "@ann/JsonToClass"; + +// 建议用工具json-class-desktop生成这个类 类型 +export class ResponseType { + @property("id") + user_id!: number; +} + +export class IndexService { + + @GET() + @Mapper(ResponseType) + public async reg (params: object): Promise {} + + @GET() + @Mapper(ResponseType) + public async login (params: object): Promise {} + +} \ No newline at end of file diff --git a/src/core/service/Order.service.ts b/src/core/service/Order.service.ts new file mode 100644 index 0000000..6aace68 --- /dev/null +++ b/src/core/service/Order.service.ts @@ -0,0 +1,17 @@ +// @ts-nocheck +import { GET, Mapper, POST, PUT, DELETE } from "@ann/Http.annotation"; +import { property, defaultValue, deserialize } from "@ann/JsonToClass"; + +// 建议用工具json-class-desktop生成这个类 类型 +export class ResponseType { + @property("id") + user_id!: number; +} + +export class OrderService { + + @GET() + @Mapper(ResponseType) + public async test (params: object): Promise {} + +} \ No newline at end of file