paas-build-package 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/.editorconfig +13 -0
  2. package/.vscode/extensions.json +13 -0
  3. package/.vscode/settings.json +19 -0
  4. package/.vscode/tasks.json +158 -0
  5. package/LICENSE +21 -0
  6. package/README.md +1 -0
  7. package/lerna.json +8 -0
  8. package/package.json +37 -0
  9. package/packages/build/CHANGELOG.md +14 -0
  10. package/packages/build/LICENSE +21 -0
  11. package/packages/build/README.md +1 -0
  12. package/packages/build/build.config.ts +22 -0
  13. package/packages/build/eslint.config.js +8 -0
  14. package/packages/build/package.json +103 -0
  15. package/packages/build/prettier.config.js +3 -0
  16. package/packages/build/src/commitlint/commitlint-config/commitlint-config.ts +37 -0
  17. package/packages/build/src/commitlint/index.ts +1 -0
  18. package/packages/build/src/constants/index.ts +70 -0
  19. package/packages/build/src/eslint/eslint-config/eslint-config.ts +161 -0
  20. package/packages/build/src/eslint/index.ts +1 -0
  21. package/packages/build/src/index.ts +8 -0
  22. package/packages/build/src/prettier/index.ts +1 -0
  23. package/packages/build/src/prettier/prettier-config/prettier-config.ts +48 -0
  24. package/packages/build/src/stylelint/index.ts +1 -0
  25. package/packages/build/src/stylelint/stylelint-config/stylelint-config.ts +39 -0
  26. package/packages/build/src/types/index.d.ts +1 -0
  27. package/packages/build/src/unocss/index.ts +1 -0
  28. package/packages/build/src/unocss/unocss.config.ts +45 -0
  29. package/packages/build/src/util/env-state/env-state.ts +9 -0
  30. package/packages/build/src/util/index.ts +52 -0
  31. package/packages/build/src/util/reg-exp/reg-exp.ts +1 -0
  32. package/packages/build/src/util/watcher/watcher.ts +114 -0
  33. package/packages/build/src/vite/index.ts +13 -0
  34. package/packages/build/src/vite/vite-config/vite-base-config.ts +49 -0
  35. package/packages/build/src/vite/vite-config/vite-config.ts +74 -0
  36. package/packages/build/src/vite/vite-config/vite-dev-config.ts +26 -0
  37. package/packages/build/src/vite/vite-config/vite-pkg-dev-config.ts +123 -0
  38. package/packages/build/src/vite/vite-config/vite-plugin-config.ts +149 -0
  39. package/packages/build/src/vite/vite-config/vite-project-config.ts +82 -0
  40. package/packages/build/src/vite/vite-plugins/imnport-external-plugin.ts +21 -0
  41. package/packages/build/src/vite/vite-plugins/inject-importmap-plugin.ts +133 -0
  42. package/packages/build/tsconfig.json +32 -0
  43. package/packages/cli/CHANGELOG.md +20 -0
  44. package/packages/cli/LICENSE +21 -0
  45. package/packages/cli/README.md +1 -0
  46. package/packages/cli/build.config.ts +22 -0
  47. package/packages/cli/hbs-temp/api-config.ts.hbs +21 -0
  48. package/packages/cli/hbs-temp/apis/{{api}}.service.d.ts.hbs +39 -0
  49. package/packages/cli/hbs-temp/entities.d.ts.hbs +19 -0
  50. package/packages/cli/hbs-temp/index.d.ts.hbs +9 -0
  51. package/packages/cli/package.json +72 -0
  52. package/packages/cli/src/actions/gen-api/api-manage.ts +96 -0
  53. package/packages/cli/src/actions/gen-api/gen-api.ts +211 -0
  54. package/packages/cli/src/actions/gen-api/model-manage.ts +269 -0
  55. package/packages/cli/src/actions/gen-api/special-entities.config.ts +26 -0
  56. package/packages/cli/src/actions/gen-cdn-lib/gen-cdn-lib.ts +149 -0
  57. package/packages/cli/src/actions/index.ts +3 -0
  58. package/packages/cli/src/actions/init-git/init-git.ts +28 -0
  59. package/packages/cli/src/bin.ts +5 -0
  60. package/packages/cli/src/commands/gen-api/gen-api.ts +65 -0
  61. package/packages/cli/src/commands/gen-cdn-lib/gen-cdn-lib.ts +25 -0
  62. package/packages/cli/src/commands/index.ts +22 -0
  63. package/packages/cli/src/commands/init-git/init-git.ts +16 -0
  64. package/packages/cli/src/core/handlebars/constant/index.ts +4 -0
  65. package/packages/cli/src/core/handlebars/handlebars-engine.ts +143 -0
  66. package/packages/cli/src/core/handlebars/helpers/and/and.ts +24 -0
  67. package/packages/cli/src/core/handlebars/helpers/camel-case/camel-case.ts +23 -0
  68. package/packages/cli/src/core/handlebars/helpers/concat/concat.ts +20 -0
  69. package/packages/cli/src/core/handlebars/helpers/eq/eq.ts +27 -0
  70. package/packages/cli/src/core/handlebars/helpers/format-import/format-import.ts +46 -0
  71. package/packages/cli/src/core/handlebars/helpers/format-import-item/format-import-item.ts +67 -0
  72. package/packages/cli/src/core/handlebars/helpers/format-js-type/format-js-type.ts +50 -0
  73. package/packages/cli/src/core/handlebars/helpers/gt/gt.ts +27 -0
  74. package/packages/cli/src/core/handlebars/helpers/gte/gte.ts +27 -0
  75. package/packages/cli/src/core/handlebars/helpers/helper-base.ts +27 -0
  76. package/packages/cli/src/core/handlebars/helpers/includes/includes.ts +25 -0
  77. package/packages/cli/src/core/handlebars/helpers/index.ts +52 -0
  78. package/packages/cli/src/core/handlebars/helpers/json/json.ts +23 -0
  79. package/packages/cli/src/core/handlebars/helpers/lower-case/lower-case.ts +22 -0
  80. package/packages/cli/src/core/handlebars/helpers/lt/lt.ts +27 -0
  81. package/packages/cli/src/core/handlebars/helpers/lte/lte.ts +27 -0
  82. package/packages/cli/src/core/handlebars/helpers/neq/neq.ts +27 -0
  83. package/packages/cli/src/core/handlebars/helpers/not/not.ts +25 -0
  84. package/packages/cli/src/core/handlebars/helpers/not-includes/not-includes.ts +25 -0
  85. package/packages/cli/src/core/handlebars/helpers/or/or.ts +26 -0
  86. package/packages/cli/src/core/handlebars/helpers/pascal-case/pascal-case.ts +23 -0
  87. package/packages/cli/src/core/handlebars/helpers/snake-case/snake-case.ts +23 -0
  88. package/packages/cli/src/core/handlebars/helpers/spinal-case/spinal-case.ts +23 -0
  89. package/packages/cli/src/core/handlebars/helpers/upper-case/upper-case.ts +22 -0
  90. package/packages/cli/src/core/handlebars/index.ts +2 -0
  91. package/packages/cli/src/core/handlebars/utils/helper/helper.ts +67 -0
  92. package/packages/cli/src/core/handlebars/utils/index.ts +23 -0
  93. package/packages/cli/src/core/index.ts +2 -0
  94. package/packages/cli/src/core/interface/index.ts +4 -0
  95. package/packages/cli/src/index.ts +36 -0
  96. package/packages/cli/src/interface/i-command/i-command.ts +23 -0
  97. package/packages/cli/src/interface/i-gen-cdn-lib-options/i-gen-cdn-lib-options.ts +58 -0
  98. package/packages/cli/src/interface/index.ts +2 -0
  99. package/packages/cli/src/types/index.d.ts +1 -0
  100. package/packages/cli/src/utils/index.ts +4 -0
  101. package/packages/cli/src/utils/local-binaries/local-binaries.ts +16 -0
  102. package/packages/cli/tsconfig.json +32 -0
  103. package/pnpm-workspace.yaml +10 -0
  104. package/tsconfig.app.json +18 -0
  105. package/tsconfig.json +11 -0
  106. package/tsconfig.node.json +26 -0
@@ -0,0 +1,9 @@
1
+ {{#each entities as |entity|}}
2
+ import type { {{pascalCase (camelCase entity.entityName) }}Service } from './apis/{{entity.entityName}}.service';
3
+ {{/each}}
4
+
5
+ export interface ApiManage {
6
+ {{#each entities as |entity|}}
7
+ readonly {{camelCase entity.entityName}}: {{pascalCase (camelCase entity.entityName)}}Service;
8
+ {{/each}}
9
+ }
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@gct-paas/cli",
3
+ "version": "0.1.6",
4
+ "type": "module",
5
+ "description": "paas 平台核心包",
6
+ "bin": {
7
+ "gct-paas": "es/bin.mjs"
8
+ },
9
+ "main": "dist/index.cjs",
10
+ "module": "es/index.mjs",
11
+ "types": "es/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./es/index.d.ts",
15
+ "import": "./es/index.mjs",
16
+ "require": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "es",
22
+ "hbs-temp",
23
+ "CHANGELOG.md",
24
+ "README.md"
25
+ ],
26
+ "keywords": [
27
+ "paas",
28
+ "gct"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://git.gct-china.com/paas/frontend/paas-package.git"
33
+ },
34
+ "license": "MIT",
35
+ "author": "gct",
36
+ "scripts": {
37
+ "run": "tsx src/bin.ts gen-cdn-lib --tag=dev --dir=/Users/zhr/workspace/gct/gct-paas-cdn/extras",
38
+ "build": "unbuild",
39
+ "publish:next": "npm run build && npm publish --access public --tag=next --registry=https://registry.npmjs.org/",
40
+ "publish:dev": "npm run build && npm publish --access public --tag=dev --registry=https://registry.npmjs.org/",
41
+ "publish:alpha": "npm run build && npm publish --access public --tag=alpha --registry=https://registry.npmjs.org/",
42
+ "publish:beta": "npm run build && npm publish --access public --tag=beta --registry=https://registry.npmjs.org/",
43
+ "publish:npm": "npm run build && npm publish --access public --registry=https://registry.npmjs.org/"
44
+ },
45
+ "dependencies": {
46
+ "@inquirer/prompts": "^8.2.0",
47
+ "commander": "^14.0.2",
48
+ "consola": "^3.4.2",
49
+ "core-js": "^3.48.0",
50
+ "fast-glob": "^3.3.3",
51
+ "fs-extra": "^11.3.3",
52
+ "got": "^14.6.6",
53
+ "handlebars": "^4.7.8",
54
+ "handlebars-helpers": "^0.10.0",
55
+ "listr2": "^10.2.1",
56
+ "lodash-es": "^4.17.23",
57
+ "ora": "^9.1.0",
58
+ "pacote": "^21.5.0",
59
+ "picocolors": "^1.1.1",
60
+ "rimraf": "^6.1.2",
61
+ "simple-git": "^3.33.0"
62
+ },
63
+ "devDependencies": {
64
+ "@types/fs-extra": "^11.0.4",
65
+ "@types/lodash-es": "^4.17.12",
66
+ "@types/node": "^25.0.10",
67
+ "@types/pacote": "^11.1.8",
68
+ "tsx": "^4.21.0",
69
+ "typescript": "^5.9.3",
70
+ "unbuild": "^3.6.1"
71
+ }
72
+ }
@@ -0,0 +1,96 @@
1
+ import { IObject } from '../../core';
2
+ import { SPECIAL_ENTITIES } from './special-entities.config';
3
+
4
+ /**
5
+ * api 管理
6
+ *
7
+ * @export
8
+ * @class EntityApiManage
9
+ */
10
+ export class EntityApiManage {
11
+ readonly cache = new Map<string, IObject>();
12
+
13
+ constructor(public readonly name: string) {}
14
+
15
+ /**
16
+ * 新增方法
17
+ *
18
+ * @param {string} method 方法名称
19
+ * @param {string} mode 请求方式
20
+ * @param {IObject} cfg 从 swagger 获取的配置
21
+ */
22
+ add(method: string, mode: string, cfg: IObject): void {
23
+ const tag = `${method}:${mode}`;
24
+ this.cache.set(tag, cfg);
25
+ }
26
+ }
27
+
28
+ /**
29
+ * api 清单管理
30
+ *
31
+ * @export
32
+ * @class ApiManage
33
+ */
34
+ export class ApiManage {
35
+ readonly cache = new Map<string, EntityApiManage>();
36
+
37
+ constructor() {
38
+ this.specialTreatment();
39
+ }
40
+
41
+ /**
42
+ * 根据配置文件中的特殊实体映射来处理
43
+ *
44
+ * @protected
45
+ */
46
+ protected specialTreatment() {
47
+ SPECIAL_ENTITIES.forEach(({ canonical, aliases }) => {
48
+ const manage = new EntityApiManage(canonical);
49
+ aliases.forEach(alias => {
50
+ this.cache.set(alias, manage);
51
+ });
52
+ });
53
+ }
54
+
55
+ /**
56
+ * 新增 api
57
+ *
58
+ * @param {string} pathStr 请求路径
59
+ * @param {IObject} cfg swagger 配置
60
+ */
61
+ add(pathStr: string, cfg: IObject) {
62
+ // 根据路径截取归属标识,例:/gct-apaas/api/app-branch/info 提取出 app-branch
63
+ const splits = pathStr.split('/');
64
+ const entityName = splits[3];
65
+ const method = splits.slice(4).join('_');
66
+ const requestPath = splits.slice(4).join('/');
67
+ if (!this.cache.has(entityName)) {
68
+ this.cache.set(entityName, new EntityApiManage(entityName));
69
+ }
70
+ const entity = this.cache.get(entityName)!;
71
+ const modes = Object.keys(cfg);
72
+ modes.forEach(mode => {
73
+ const _cfg = cfg[mode];
74
+ _cfg.requestPath = requestPath;
75
+ entity.add(method, mode, _cfg);
76
+ });
77
+ }
78
+
79
+ /**
80
+ * 结束新增 api 后调用
81
+ *
82
+ */
83
+ done(): void {
84
+ // 清理特殊实体中的别名,保留标准名称
85
+ SPECIAL_ENTITIES.forEach(({ canonical, aliases }) => {
86
+ if (this.cache.has(canonical)) {
87
+ // 删除所有别名,只保留标准名称
88
+ aliases.forEach(alias => {
89
+ if (alias !== canonical) {
90
+ this.cache.delete(alias);
91
+ }
92
+ });
93
+ }
94
+ });
95
+ }
96
+ }
@@ -0,0 +1,211 @@
1
+ import path from 'path';
2
+ import fse from 'fs-extra';
3
+ import * as rm from 'rimraf';
4
+ import glob from 'fast-glob';
5
+ import log from 'consola';
6
+ import got from 'got';
7
+ import { HandlebarsEngine, IObject, MACRO_FOLDER } from '../../core';
8
+ import { ModelManage } from './model-manage';
9
+
10
+ /**
11
+ * 基于 handlebars 模板编写生成 api
12
+ *
13
+ * @export
14
+ * @class GenApiAction
15
+ */
16
+ export class GenApiAction {
17
+ // private baseUrl = 'http://paas.paasdev.gct-paas.com';
18
+
19
+ private engine = new HandlebarsEngine();
20
+
21
+ private modelManage = new ModelManage();
22
+
23
+ private configs: Record<string, string> = {
24
+ platform:
25
+ '/gct-platform/v2/api-docs?group=%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0API',
26
+ apaas: '/gct-apaas/v2/api-docs?group=apaas%E5%B9%B3%E5%8F%B0API',
27
+ ipaas: '/gct-ipaas/v2/api-docs?group=ipaas%E5%B9%B3%E5%8F%B0API',
28
+ rag: '/gct-rag/v2/api-docs?group=%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0API',
29
+ };
30
+
31
+ /**
32
+ * 生成 api
33
+ *
34
+ * @param {string} baseUrl swagger 服务地址
35
+ * @param {string} tag 要发布的 api 标识
36
+ * @param {string} template 模板目录
37
+ * @param {string} output 输出目录
38
+ * @param {boolean} clean 是否清理输出目录后再生成
39
+ */
40
+ async run(
41
+ baseUrl: string,
42
+ tag: string,
43
+ template: string,
44
+ output: string,
45
+ clean: boolean,
46
+ ) {
47
+ try {
48
+ const cwd = process.cwd();
49
+ // 模板绝对路径
50
+ const tempPath = path.resolve(cwd, template);
51
+ // 输出绝对路径
52
+ const outPath = path.resolve(cwd, output);
53
+ // 输出目录目录存在时,根据配置清理
54
+ if (clean === true && fse.existsSync(outPath)) {
55
+ rm.sync(outPath);
56
+ }
57
+ await this.registerMacros(tempPath, this.engine);
58
+ await this.registerTempFiles(tempPath, this.engine);
59
+ await this.write(
60
+ tag,
61
+ path.join(baseUrl, this.configs[tag]),
62
+ outPath,
63
+ this.engine,
64
+ );
65
+ } catch (error) {
66
+ console.error(error);
67
+ }
68
+ }
69
+
70
+ /**
71
+ * 基于模型编译输出文件
72
+ *
73
+ * @protected
74
+ * @param {string} url
75
+ * @param {string} outPath
76
+ * @param {HandlebarsEngine} engine
77
+ * @returns {*} {Promise<void>}
78
+ */
79
+ protected async write(
80
+ tag: string,
81
+ url: string,
82
+ outPath: string,
83
+ engine: HandlebarsEngine,
84
+ ): Promise<void> {
85
+ // 从 swagger 获取配置
86
+ const cfg = await got(url).json<IObject>();
87
+
88
+ const model = this.transformModel(cfg);
89
+
90
+ this.modelManage.init(tag, model);
91
+
92
+ const all: Promise<void>[] = [];
93
+ engine.temps.forEach((template, key) => {
94
+ if (key === '') {
95
+ return;
96
+ }
97
+ const outFilePath = path.join(outPath, key);
98
+ // 解析出模板路径中的所有标识,没有标识表示全局
99
+ const tags = engine.parseContextTags(key);
100
+ if (tags.length === 0) {
101
+ log.info(`生成文件:${outFilePath}`);
102
+ all.push(
103
+ fse.outputFile(
104
+ outFilePath,
105
+ engine.render(template, {
106
+ entities: Array.from(this.modelManage.entities.values()),
107
+ definitions: model.definitions,
108
+ }),
109
+ 'utf-8',
110
+ ),
111
+ );
112
+ } else {
113
+ if (tags.includes('api')) {
114
+ this.modelManage.entities.forEach(model => {
115
+ const filePath = engine.render(outFilePath, model);
116
+ log.info(`生成文件:${filePath}`);
117
+ all.push(
118
+ fse.outputFile(filePath, engine.render(template, model), 'utf-8'),
119
+ );
120
+ });
121
+ }
122
+ }
123
+ });
124
+ await Promise.all(all);
125
+ }
126
+
127
+ /**
128
+ * 注册所有的宏
129
+ *
130
+ * @protected
131
+ * @param {string} tempPath
132
+ * @param {HandlebarsEngine} engine
133
+ * @returns {*} {Promise<void>}
134
+ */
135
+ protected async registerMacros(
136
+ tempPath: string,
137
+ engine: HandlebarsEngine,
138
+ ): Promise<void> {
139
+ const macroFiles = glob.sync(path.join(MACRO_FOLDER, '**/*.hbs'), {
140
+ cwd: tempPath,
141
+ dot: true,
142
+ absolute: true,
143
+ });
144
+ if (macroFiles.length > 0) {
145
+ await Promise.all(
146
+ macroFiles.map(macroFilePath => {
147
+ return new Promise<void>(resolve => {
148
+ fse.readFile(macroFilePath, 'utf-8').then(file => {
149
+ const key = path.relative(tempPath, macroFilePath);
150
+ log.info(`注册宏:${key}`);
151
+ engine.registerMacro(key, file);
152
+ resolve();
153
+ });
154
+ });
155
+ }),
156
+ );
157
+ }
158
+ }
159
+
160
+ /**
161
+ * 注册所有模板文件
162
+ *
163
+ * @protected
164
+ * @param {string} tempPath
165
+ * @param {HandlebarsEngine} engine
166
+ * @returns {*} {Promise<void>}
167
+ */
168
+ protected async registerTempFiles(
169
+ tempPath: string,
170
+ engine: HandlebarsEngine,
171
+ ): Promise<void> {
172
+ const tempFiles = glob.sync('**/*.hbs', {
173
+ cwd: tempPath,
174
+ dot: true,
175
+ absolute: true,
176
+ ignore: [path.join(MACRO_FOLDER, '**/*.hbs')],
177
+ });
178
+ if (tempFiles.length > 0) {
179
+ await Promise.all(
180
+ tempFiles.map(tempFilePath => {
181
+ return new Promise<void>(resolve => {
182
+ fse.readFile(tempFilePath, 'utf-8').then(file => {
183
+ const key = path.relative(tempPath, tempFilePath);
184
+ log.info(`注册模板:${key}`);
185
+ engine.registerTemp(key, file);
186
+ resolve();
187
+ });
188
+ });
189
+ }),
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * 针对加载的配置进行处理
196
+ *
197
+ * @protected
198
+ * @param {IObject} model
199
+ * @returns {*} {IObject}
200
+ */
201
+ protected transformModel(model: IObject): IObject {
202
+ const keys = Object.keys(model.definitions);
203
+ keys.forEach(key => {
204
+ const item = model.definitions[key];
205
+ if (item.properties) {
206
+ item.propertySize = Object.keys(item.properties).length;
207
+ }
208
+ });
209
+ return model;
210
+ }
211
+ }
@@ -0,0 +1,269 @@
1
+ import { IObject } from '../../core';
2
+ import { ApiManage } from './api-manage';
3
+
4
+ /**
5
+ * 实体方法模型
6
+ *
7
+ * @export
8
+ * @interface IMethodModel
9
+ */
10
+ export interface IMethodModel {
11
+ /**
12
+ * 方法名称
13
+ *
14
+ * @type {string}
15
+ */
16
+ name: string;
17
+ /**
18
+ * 请求方式
19
+ *
20
+ * @type {string}
21
+ */
22
+ mode: string;
23
+ /**
24
+ * 方法模型
25
+ *
26
+ * @type {IObject}
27
+ */
28
+ model: IObject;
29
+ /**
30
+ * 请求实体
31
+ *
32
+ * @type {IObject}
33
+ */
34
+ requestEntity?: IObject;
35
+ /**
36
+ * 响应实体
37
+ *
38
+ * @type {IObject}
39
+ */
40
+ responseEntity?: IObject;
41
+ /**
42
+ * 查询参数
43
+ *
44
+ * @type {IObject[]}
45
+ */
46
+ queries: IObject[];
47
+ /**
48
+ * 路径参数, 路径示例:/gct-apaas/api/model-comprehensive/model/{key}/{mode}/{modelCategory}
49
+ *
50
+ * @type {string[]}
51
+ */
52
+ pathParams?: string[];
53
+ }
54
+
55
+ /**
56
+ * 实体模型
57
+ *
58
+ * @export
59
+ * @interface IEntityModel
60
+ */
61
+ export interface IEntityModel {
62
+ /**
63
+ * 实体名称
64
+ *
65
+ * @type {string}
66
+ */
67
+ entityName: string;
68
+ /**
69
+ * 平台标识 apaas, platform
70
+ *
71
+ * @type {string}
72
+ */
73
+ tag: string;
74
+ /**
75
+ * 实体名称(同name)
76
+ *
77
+ * @type {string}
78
+ */
79
+ api: string;
80
+ /**
81
+ * 实体模型
82
+ *
83
+ * @type {IObject}
84
+ */
85
+ model: IObject;
86
+ /**
87
+ * 实体方法模型
88
+ *
89
+ * @type {IMethodModel[]}
90
+ */
91
+ methods: IMethodModel[];
92
+ /**
93
+ * 实体引用实体名称集合
94
+ *
95
+ * @type {string[]}
96
+ */
97
+ entityRefs: string[];
98
+ }
99
+
100
+ /**
101
+ * 模型管理
102
+ *
103
+ * @export
104
+ * @class ModelManage
105
+ */
106
+ export class ModelManage {
107
+ /**
108
+ * 所有实体模型
109
+ *
110
+ * @type {Map<string, IEntityModel>}
111
+ */
112
+ readonly entities = new Map<string, IEntityModel>();
113
+
114
+ /**
115
+ * 所有用到的实体定义
116
+ *
117
+ * @type {Map<string, IObject>}
118
+ */
119
+ readonly definitions = new Map<string, IObject>();
120
+
121
+ /**
122
+ * 目前接口中的基础数据类型
123
+ *
124
+ * @protected
125
+ */
126
+ protected basicDataType = [
127
+ 'any',
128
+ 'number',
129
+ 'string',
130
+ 'null',
131
+ 'boolean',
132
+ 'Void',
133
+ 'object',
134
+ ];
135
+
136
+ init(tag: string, cfg: IObject): void {
137
+ const apiManage = new ApiManage();
138
+ // 从 swagger 配置生成 api 管理类
139
+ const paths = Object.keys(cfg.paths).filter(pathStr => {
140
+ // 过滤 external 开头,但是 /external/api/tenant/info/byPortOrDomain 需要保留
141
+ return (
142
+ !pathStr.startsWith('/external') ||
143
+ pathStr === '/external/api/tenant/info/byPortOrDomain'
144
+ );
145
+ });
146
+ paths.forEach((pathStr: string) => {
147
+ const pathCfg = cfg.paths[pathStr];
148
+ apiManage.add(pathStr, pathCfg);
149
+ });
150
+ apiManage.done();
151
+ // 遍历所有实体
152
+ const entityNames = apiManage.cache.keys();
153
+ for (const entityName of entityNames) {
154
+ const entitySet = new Set<string>();
155
+ const entityManage = apiManage.cache.get(entityName)!;
156
+ const methods: IMethodModel[] = [];
157
+ if (entityManage.cache.size > 0) {
158
+ // 遍历所有方法,tags 拼接规则:方法名-请求方式
159
+ const tags = entityManage.cache.keys();
160
+ for (const tag of tags) {
161
+ // 方法名称、请求方式
162
+ const [methodName, mode] = tag.split(':');
163
+ const config = entityManage.cache.get(tag)!;
164
+ // 请求实体对象
165
+ let requestEntity: IObject | undefined = undefined;
166
+ // 获取 body 参数
167
+ const param = config.parameters.find((param: IObject) => {
168
+ if (param.in === 'body') {
169
+ return param;
170
+ }
171
+ });
172
+ if (param && param.schema) {
173
+ // 后端通用接口特殊处理,名称为 requestBody 的参数,直接定义为 IObject
174
+ if (param.name === 'requestBody') {
175
+ requestEntity = { title: 'IObject' };
176
+ } else if (param.name === 'file') {
177
+ requestEntity = { title: 'UploadFileData' };
178
+ } else {
179
+ const refKey = this.getOriginRef(param.schema);
180
+ // 根据 body 参数获取引用的实体
181
+ requestEntity = cfg.definitions[refKey];
182
+ if (requestEntity && Object.keys(requestEntity).length > 0) {
183
+ this.definitions.set(refKey, requestEntity);
184
+ entitySet.add(refKey);
185
+ }
186
+ }
187
+ }
188
+ // 响应实体对象
189
+ let responseEntity: IObject | undefined = undefined;
190
+ if (config.responses['200'].schema) {
191
+ const refKey = this.getOriginRef(config.responses['200'].schema);
192
+ // 根据 body 参数获取引用的实体
193
+ responseEntity = cfg.definitions[refKey];
194
+ if (responseEntity && Object.keys(responseEntity).length > 0) {
195
+ this.definitions.set(refKey, responseEntity);
196
+ entitySet.add(refKey);
197
+ }
198
+ }
199
+ const queries: IObject[] = config.parameters.filter(
200
+ (param: IObject) => {
201
+ if (param.in === 'query') {
202
+ return param;
203
+ }
204
+ },
205
+ );
206
+ // 2026 年 2 月 3 日 去掉此逻辑,已经支持了 pathParams 的处理,不再需要特殊处理
207
+ // {
208
+ // // 当put方法需要在url中拼接主键时,默认补充query查询参数
209
+ // if (methodName === '{id}') {
210
+ // queries.push({
211
+ // name: 'id',
212
+ // in: 'query',
213
+ // description: '数据主键',
214
+ // required: true,
215
+ // type: 'string',
216
+ // });
217
+ // }
218
+ // }
219
+ // 请求路径 config.requestPath
220
+ const matches = [...config.requestPath.matchAll(/\{([^}]*)\}/g)].map(
221
+ m => m[1],
222
+ );
223
+ methods.push({
224
+ name: methodName !== 'undefined' ? methodName : '',
225
+ mode,
226
+ model: config,
227
+ requestEntity,
228
+ responseEntity,
229
+ queries,
230
+ pathParams: matches,
231
+ });
232
+ }
233
+ this.entities.set(entityName, {
234
+ tag,
235
+ entityName: entityName,
236
+ api: entityName,
237
+ model: cfg.definitions[entityName],
238
+ methods,
239
+ entityRefs: Array.from(entitySet.values()).filter(item => {
240
+ // 过滤掉基础类型的导入
241
+ return (
242
+ this.basicDataType.findIndex(type => {
243
+ return item.indexOf(`«${type}»`) !== -1;
244
+ }) === -1 && !this.basicDataType.includes(item)
245
+ );
246
+ }),
247
+ });
248
+ }
249
+ }
250
+ }
251
+
252
+ /**
253
+ * 获取接口的引用对象
254
+ *
255
+ * @protected
256
+ * @param {IObject} data
257
+ * @returns {*} {string}
258
+ */
259
+ protected getOriginRef(data: IObject): string {
260
+ const { $ref, originalRef, type } = data;
261
+ if (type) return type;
262
+ if (originalRef) return originalRef;
263
+ if ($ref) {
264
+ const _refs_ = $ref.split('/');
265
+ return _refs_[_refs_.length - 1];
266
+ }
267
+ return 'any';
268
+ }
269
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 特殊实体映射配置
3
+ * 用于处理 swagger 中存在的特殊命名或映射规则
4
+ */
5
+ export interface SpecialEntityMapping {
6
+ /** 标准实体名称 */
7
+ canonical: string;
8
+ /** 别名映射列表 */
9
+ aliases: string[];
10
+ }
11
+
12
+ /**
13
+ * 特殊实体配置列表
14
+ * 当后续有类似的特殊处理需求时,直接在此列表中添加新条目即可
15
+ */
16
+ export const SPECIAL_ENTITIES: SpecialEntityMapping[] = [
17
+ {
18
+ canonical: 'med-pro',
19
+ aliases: ['medpro', 'medPro', 'med-pro'],
20
+ },
21
+ // 示例:如果后续有其他特殊映射,按照下面的格式添加
22
+ // {
23
+ // canonical: 'some-entity',
24
+ // aliases: ['someEntity', 'someentity', 'some-entity'],
25
+ // },
26
+ ];