Skip to content

Commit 9a7efad

Browse files
committed
feat(codegen): 添加 JavaScript 和 TypeScript SDK 代码生成器
- 新增 JavaScriptSdkEntityApiGenerator、JavaScriptSdkEntityGenerator 和 JavaScriptSdkEnumGenerator - 新增 TypeScriptSdkEntityApiGenerator、TypeScriptSdkEntityGenerator 和 TypeScriptSdkEnumGenerator - 实现了实体类、枚举类和 API 类的代码生成 -支持 JavaScript 和 TypeScript 两种语言
1 parent 5b2b0aa commit 9a7efad

File tree

6 files changed

+725
-0
lines changed

6 files changed

+725
-0
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import tech.wetech.flexmodel.codegen.AbstractGenerator
2+
import tech.wetech.flexmodel.codegen.GenerationContext
3+
import tech.wetech.flexmodel.codegen.ModelClass
4+
5+
import java.nio.file.Path
6+
7+
class JavaScriptSdkEntityApiGenerator extends AbstractGenerator {
8+
9+
@Override
10+
String getTargetFile(GenerationContext context, String targetDirectory) {
11+
ModelClass modelClass = context.modelClass
12+
return Path.of(targetDirectory, modelClass.shortClassName + 'Api.js').toString()
13+
}
14+
15+
@Override
16+
void writeModel(PrintWriter out, GenerationContext context) {
17+
def modelClass = context.modelClass
18+
def className = modelClass.shortClassName
19+
def variableName = className.toLowerCase()
20+
21+
// 导入语句
22+
out.println "import { ${className} } from './${className}.js';"
23+
out.println "import { PageResult } from '../api/PageResult.js';"
24+
out.println ""
25+
26+
// 文档注释
27+
out.println "/**"
28+
out.println " * ${className} API - 直接访问${className}实体"
29+
out.println " */"
30+
out.println ""
31+
32+
// 类定义
33+
out.println "export class ${className}Api {"
34+
out.println " constructor(apiClient, datasourceName, modelName) {"
35+
out.println " this.apiClient = apiClient;"
36+
out.println " this.datasourceName = datasourceName;"
37+
out.println " this.modelName = modelName;"
38+
out.println " }"
39+
out.println ""
40+
41+
// 辅助方法
42+
out.println " encode(str) {"
43+
out.println " return str.replace(/\\//g, '%2F');"
44+
out.println " }"
45+
out.println ""
46+
47+
// 分页查询方法
48+
out.println " /**"
49+
out.println " * 获取所有${className}记录(分页)"
50+
out.println " */"
51+
out.println " async list${className}s(options = {}) {"
52+
out.println " const {"
53+
out.println " current = null,"
54+
out.println " pageSize = null,"
55+
out.println " filter = null,"
56+
out.println " nestedQuery = null,"
57+
out.println " sort = null"
58+
out.println " } = options;"
59+
out.println ""
60+
out.println " const path = `/api/f/datasources/\${this.encode(this.datasourceName)}/models/\${this.encode(this.modelName)}/records`;"
61+
out.println " const params = {};"
62+
out.println " "
63+
out.println " if (current !== null) params.current = current;"
64+
out.println " if (pageSize !== null) params.pageSize = pageSize;"
65+
out.println " if (filter !== null) params.filter = filter;"
66+
out.println " if (nestedQuery !== null) params.nestedQuery = nestedQuery;"
67+
out.println " if (sort !== null) params.sort = sort;"
68+
out.println ""
69+
out.println " const data = await this.apiClient.get(path, params);"
70+
out.println " const ${variableName}s = data.list.map(item => ${className}.fromJSON(item));"
71+
out.println " return new PageResult(data.total, ${variableName}s);"
72+
out.println " }"
73+
out.println ""
74+
75+
// 直接返回列表方法
76+
out.println " /**"
77+
out.println " * 获取所有${className}记录(直接返回列表)"
78+
out.println " * 这是您想要的方法:const ${variableName}s = await ${variableName}Api.list${className}sAsList();"
79+
out.println " */"
80+
out.println " async list${className}sAsList(options = {}) {"
81+
out.println " const pageResult = await this.list${className}s(options);"
82+
out.println " return pageResult.getList();"
83+
out.println " }"
84+
out.println ""
85+
86+
// 简单查询方法
87+
out.println " /**"
88+
out.println " * 获取所有${className}记录(最简单的调用)"
89+
out.println " */"
90+
out.println " async list${className}sSimple() {"
91+
out.println " return await this.list${className}sAsList();"
92+
out.println " }"
93+
out.println ""
94+
95+
// 获取单个记录方法
96+
out.println " /**"
97+
out.println " * 根据ID获取${className}记录"
98+
out.println " */"
99+
out.println " async get${className}(id, options = {}) {"
100+
out.println " const { nestedQuery = null } = options;"
101+
out.println " const path = `/api/f/datasources/\${this.encode(this.datasourceName)}/models/\${this.encode(this.modelName)}/records/\${this.encode(id)}`;"
102+
out.println " const params = {};"
103+
out.println " "
104+
out.println " if (nestedQuery !== null) params.nestedQuery = nestedQuery;"
105+
out.println ""
106+
out.println " const data = await this.apiClient.get(path, params);"
107+
out.println " return ${className}.fromJSON(data);"
108+
out.println " }"
109+
out.println ""
110+
111+
// 创建记录方法
112+
out.println " /**"
113+
out.println " * 创建新的${className}记录"
114+
out.println " */"
115+
out.println " async create${className}(${variableName}) {"
116+
out.println " const path = `/api/f/datasources/\${this.encode(this.datasourceName)}/models/\${this.encode(this.modelName)}/records`;"
117+
out.println " const data = await this.apiClient.post(path, ${variableName}.toJSON());"
118+
out.println " return ${className}.fromJSON(data);"
119+
out.println " }"
120+
out.println ""
121+
122+
// 更新记录方法
123+
out.println " /**"
124+
out.println " * 更新${className}记录"
125+
out.println " */"
126+
out.println " async update${className}(id, ${variableName}) {"
127+
out.println " const path = `/api/f/datasources/\${this.encode(this.datasourceName)}/models/\${this.encode(this.modelName)}/records/\${this.encode(id)}`;"
128+
out.println " const data = await this.apiClient.put(path, ${variableName}.toJSON());"
129+
out.println " return ${className}.fromJSON(data);"
130+
out.println " }"
131+
out.println ""
132+
133+
// 部分更新记录方法
134+
out.println " /**"
135+
out.println " * 部分更新${className}记录"
136+
out.println " */"
137+
out.println " async patch${className}(id, ${variableName}) {"
138+
out.println " const path = `/api/f/datasources/\${this.encode(this.datasourceName)}/models/\${this.encode(this.modelName)}/records/\${this.encode(id)}`;"
139+
out.println " const data = await this.apiClient.patch(path, ${variableName}.toJSON());"
140+
out.println " return ${className}.fromJSON(data);"
141+
out.println " }"
142+
out.println ""
143+
144+
// 删除记录方法
145+
out.println " /**"
146+
out.println " * 删除${className}记录"
147+
out.println " */"
148+
out.println " async delete${className}(id) {"
149+
out.println " const path = `/api/f/datasources/\${this.encode(this.datasourceName)}/models/\${this.encode(this.modelName)}/records/\${this.encode(id)}`;"
150+
out.println " await this.apiClient.delete(path);"
151+
out.println " }"
152+
out.println "}"
153+
}
154+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import tech.wetech.flexmodel.codegen.AbstractGenerator
2+
import tech.wetech.flexmodel.codegen.GenerationContext
3+
import tech.wetech.flexmodel.codegen.ModelClass
4+
5+
import java.nio.file.Path
6+
7+
class JavaScriptSdkEntityGenerator extends AbstractGenerator {
8+
9+
@Override
10+
String getTargetFile(GenerationContext context, String targetDirectory) {
11+
ModelClass modelClass = context.modelClass
12+
return Path.of(targetDirectory, modelClass.shortClassName + '.js').toString()
13+
}
14+
15+
@Override
16+
void writeModel(PrintWriter out, GenerationContext context) {
17+
def modelClass = context.modelClass
18+
def className = modelClass.shortClassName
19+
20+
// 文档注释
21+
out.println "/**"
22+
out.println " * ${className}实体类"
23+
out.println " */"
24+
out.println ""
25+
26+
// 类定义
27+
out.println "export class ${className} {"
28+
out.println " constructor(data = {}) {"
29+
30+
// 字段初始化
31+
modelClass.allFields.each { field ->
32+
def fieldName = field.variableName
33+
out.println " this.${fieldName} = data.${fieldName} || null;"
34+
}
35+
out.println " }"
36+
out.println ""
37+
38+
// Getter方法
39+
modelClass.allFields.each { field ->
40+
def fieldName = field.variableName
41+
def capitalizedName = fieldName.capitalize()
42+
out.println " get${capitalizedName}() {"
43+
out.println " return this.${fieldName};"
44+
out.println " }"
45+
out.println ""
46+
}
47+
48+
// Setter方法
49+
modelClass.allFields.each { field ->
50+
def fieldName = field.variableName
51+
def capitalizedName = fieldName.capitalize()
52+
out.println " set${capitalizedName}(${fieldName}) {"
53+
out.println " this.${fieldName} = ${fieldName};"
54+
out.println " }"
55+
out.println ""
56+
}
57+
58+
// 转换为JSON方法
59+
out.println " /**"
60+
out.println " * 转换为JSON对象"
61+
out.println " */"
62+
out.println " toJSON() {"
63+
out.println " return {"
64+
modelClass.allFields.eachWithIndex { field, index ->
65+
def fieldName = field.variableName
66+
if (index < modelClass.allFields.size() - 1) {
67+
out.println " ${fieldName}: this.${fieldName},"
68+
} else {
69+
out.println " ${fieldName}: this.${fieldName}"
70+
}
71+
}
72+
out.println " };"
73+
out.println " }"
74+
out.println ""
75+
76+
// 从JSON创建实例的静态方法
77+
out.println " /**"
78+
out.println " * 从JSON对象创建${className}实例"
79+
out.println " */"
80+
out.println " static fromJSON(data) {"
81+
out.println " return new ${className}(data);"
82+
out.println " }"
83+
out.println "}"
84+
}
85+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import groovy.util.logging.Log
2+
import tech.wetech.flexmodel.codegen.AbstractGenerator
3+
import tech.wetech.flexmodel.codegen.GenerationContext
4+
5+
import java.nio.file.Path
6+
7+
/**
8+
* JavaScript SDK枚举生成器
9+
* @author cjbi
10+
*/
11+
@Log
12+
class JavaScriptSdkEnumGenerator extends AbstractGenerator {
13+
14+
@Override
15+
String getTargetFile(GenerationContext context, String targetDirectory) {
16+
return Path.of(targetDirectory, context.enumClass.getShortClassName() + ".js").toString()
17+
}
18+
19+
@Override
20+
void writeEnum(PrintWriter out, GenerationContext context) {
21+
def enumClass = context.enumClass;
22+
def className = enumClass.shortClassName
23+
def elements = enumClass.elements
24+
25+
// 文档注释
26+
out.println "/**"
27+
if (enumClass.comment) {
28+
out.println " * ${enumClass.comment}"
29+
}
30+
out.println " * Generated by Flexmodel Generator"
31+
out.println " */"
32+
out.println ""
33+
34+
// 类定义
35+
out.println "export class ${className} {"
36+
out.println " constructor(value) {"
37+
out.println " this.value = value;"
38+
out.println " }"
39+
out.println ""
40+
41+
// 枚举值定义
42+
elements.each { element ->
43+
out.println " static ${element} = new ${className}('${element}');"
44+
}
45+
out.println ""
46+
47+
// 所有枚举值的数组
48+
out.println " static values() {"
49+
out.println " return ["
50+
elements.eachWithIndex { element, index ->
51+
if (index < elements.size() - 1) {
52+
out.println " ${className}.${element},"
53+
} else {
54+
out.println " ${className}.${element}"
55+
}
56+
}
57+
out.println " ];"
58+
out.println " }"
59+
out.println ""
60+
61+
// 从字符串创建实例的静态方法
62+
out.println " static fromString(value) {"
63+
out.println " const enumValue = ${className}.values().find(item => item.value === value);"
64+
out.println " if (!enumValue) {"
65+
out.println " throw new Error(`Invalid ${className} value: \${value}`);"
66+
out.println " }"
67+
out.println " return enumValue;"
68+
out.println " }"
69+
out.println ""
70+
71+
// toString方法
72+
out.println " toString() {"
73+
out.println " return this.value;"
74+
out.println " }"
75+
out.println ""
76+
77+
// valueOf方法
78+
out.println " valueOf() {"
79+
out.println " return this.value;"
80+
out.println " }"
81+
out.println ""
82+
83+
// equals方法
84+
out.println " equals(other) {"
85+
out.println " return other instanceof ${className} && this.value === other.value;"
86+
out.println " }"
87+
out.println "}"
88+
}
89+
}

0 commit comments

Comments
 (0)