@jayfong/x-server 1.10.3 → 1.11.2

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 (73) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/lib/_cjs/cli/api_generator.js +295 -0
  3. package/lib/_cjs/cli/build_util.js +146 -0
  4. package/lib/_cjs/cli/cli.js +190 -0
  5. package/lib/_cjs/cli/deploy_util.js +61 -0
  6. package/lib/_cjs/cli/env_util.js +145 -0
  7. package/lib/_cjs/cli/register.js +8 -0
  8. package/lib/_cjs/cli/template_util.js +77 -0
  9. package/lib/_cjs/cli/templates/handlers.ts +3 -0
  10. package/lib/_cjs/cli/templates/hooks.ts +2 -0
  11. package/lib/_cjs/cli/templates/models.ts +22 -0
  12. package/lib/_cjs/cli/templates/package.json +3 -0
  13. package/lib/_cjs/cli/templates/routes.ts +26 -0
  14. package/lib/_cjs/cli/templates/tasks.ts +2 -0
  15. package/lib/_cjs/core/define_bus.js +28 -0
  16. package/lib/_cjs/core/define_handler.js +43 -0
  17. package/lib/_cjs/core/define_hook.js +10 -0
  18. package/lib/_cjs/core/define_server.js +12 -0
  19. package/lib/_cjs/core/define_task.js +30 -0
  20. package/lib/_cjs/core/handler.js +90 -0
  21. package/lib/_cjs/core/http_error.js +9 -0
  22. package/lib/_cjs/core/http_method.js +12 -0
  23. package/lib/_cjs/core/server.js +145 -0
  24. package/lib/_cjs/core/types.js +18 -0
  25. package/lib/_cjs/index.js +179 -0
  26. package/lib/_cjs/plugins/base.js +3 -0
  27. package/lib/_cjs/plugins/cors.js +44 -0
  28. package/lib/_cjs/plugins/file_parser.js +24 -0
  29. package/lib/_cjs/plugins/ws_parser.js +24 -0
  30. package/lib/_cjs/plugins/xml_parser.js +61 -0
  31. package/lib/_cjs/services/base.js +3 -0
  32. package/lib/_cjs/services/cache.js +231 -0
  33. package/lib/_cjs/services/captcha.js +45 -0
  34. package/lib/_cjs/services/dispose.js +33 -0
  35. package/lib/_cjs/services/jwt.js +59 -0
  36. package/lib/_cjs/services/redis.js +18 -0
  37. package/lib/_cjs/x.js +20 -0
  38. package/lib/cli/api_generator.js +269 -332
  39. package/lib/cli/build_util.d.ts +1 -0
  40. package/lib/cli/build_util.js +108 -130
  41. package/lib/cli/cli.js +161 -181
  42. package/lib/cli/deploy_util.js +37 -41
  43. package/lib/cli/env_util.js +112 -120
  44. package/lib/cli/register.js +5 -7
  45. package/lib/cli/template_util.js +47 -52
  46. package/lib/core/define_bus.js +22 -14
  47. package/lib/core/define_handler.js +31 -36
  48. package/lib/core/define_hook.js +4 -8
  49. package/lib/core/define_server.js +6 -10
  50. package/lib/core/define_task.js +20 -25
  51. package/lib/core/handler.js +78 -74
  52. package/lib/core/http_error.js +2 -8
  53. package/lib/core/http_method.js +7 -10
  54. package/lib/core/server.js +125 -139
  55. package/lib/core/types.js +11 -2
  56. package/lib/index.js +23 -39
  57. package/lib/plugins/base.js +1 -2
  58. package/lib/plugins/cors.js +30 -36
  59. package/lib/plugins/file_parser.d.ts +1 -1
  60. package/lib/plugins/file_parser.js +12 -16
  61. package/lib/plugins/ws_parser.d.ts +1 -1
  62. package/lib/plugins/ws_parser.js +12 -16
  63. package/lib/plugins/xml_parser.d.ts +1 -1
  64. package/lib/plugins/xml_parser.js +47 -43
  65. package/lib/services/base.js +1 -2
  66. package/lib/services/cache.js +213 -190
  67. package/lib/services/captcha.js +32 -33
  68. package/lib/services/dispose.d.ts +1 -1
  69. package/lib/services/dispose.js +22 -23
  70. package/lib/services/jwt.js +45 -48
  71. package/lib/services/redis.js +8 -14
  72. package/lib/x.js +12 -15
  73. package/package.json +6 -4
@@ -1,339 +1,276 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
1
+ import * as parseComment from 'comment-parser';
2
+ import * as ts from 'ts-morph';
3
+ import createDebug from 'debug';
4
+ import fs from 'fs-extra';
5
+ import path from 'node:path';
6
+ import { HandlerMethodToHttpMethod } from "../core/http_method";
7
+ import { ii, pascalCase, snakeCase } from 'vtils';
8
+ export class ApiGenerator {
9
+ constructor() {
10
+ this.debug = createDebug('api');
11
+ this.cwd = process.cwd();
12
+ this.project = void 0;
13
+ }
14
+
15
+ getTypeBySymbol(symbol) {
16
+ return symbol.getTypeAtLocation(symbol.getDeclarations()[0] || symbol.getValueDeclarationOrThrow());
17
+ }
18
+
19
+ getComment(declaration) {
20
+ var _declaration$getLeadi;
21
+
22
+ const text = ((declaration == null ? void 0 : (_declaration$getLeadi = declaration.getLeadingCommentRanges()[0]) == null ? void 0 : _declaration$getLeadi.getText()) || '').trim();
23
+ const comment = parseComment.parse(text)[0];
24
+ const description = (comment == null ? void 0 : comment.description) || '';
25
+ const tags = new Map();
26
+ comment == null ? void 0 : comment.tags.forEach(tag => {
27
+ tags.set(tag.tag, tag.description);
28
+ });
29
+ return {
30
+ existing: !!comment,
31
+ description: description,
32
+ tags: tags
33
+ };
34
+ }
35
+
36
+ getCommentBySymbol(symbol) {
37
+ var _this$getComment;
38
+
39
+ return ((_this$getComment = this.getComment(symbol.getDeclarations()[0])) == null ? void 0 : _this$getComment.description) || '';
40
+ }
41
+
42
+ typeToApiData(type, _symbol) {
43
+ var _type$getSymbol, _type$getSymbol2, _type$getSymbol3;
44
+
45
+ // ws
46
+ if (((_type$getSymbol = type.getSymbol()) == null ? void 0 : _type$getSymbol.getName()) === 'SocketStream') {
47
+ return {
48
+ name: 'ws',
49
+ desc: 'ws',
50
+ required: false,
51
+ type: 'object',
52
+ children: [],
53
+ enum: []
54
+ };
55
+ } // XFile
56
+
57
+
58
+ if (((_type$getSymbol2 = type.getSymbol()) == null ? void 0 : _type$getSymbol2.getName()) === 'MultipartFile') {
59
+ const symbol = _symbol || type.getSymbol();
60
+
61
+ return {
62
+ name: 'file',
63
+ desc: symbol && this.getCommentBySymbol(symbol) || '',
64
+ required: !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional),
65
+ type: 'file',
66
+ children: [],
67
+ enum: []
68
+ };
7
69
  }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.ApiGenerator = void 0;
30
- const parseComment = __importStar(require("comment-parser"));
31
- const ts = __importStar(require("ts-morph"));
32
- const debug_1 = __importDefault(require("debug"));
33
- const fs_extra_1 = __importDefault(require("fs-extra"));
34
- const node_path_1 = __importDefault(require("node:path"));
35
- const http_method_1 = require("../core/http_method");
36
- const vtils_1 = require("vtils");
37
- class ApiGenerator {
38
- constructor() {
39
- this.debug = (0, debug_1.default)('api');
40
- this.cwd = process.cwd();
70
+
71
+ let isRequired = true;
72
+ let isUnion = type.isUnion();
73
+ const unionTypes = isUnion ? type.getUnionTypes().filter(item => !item.isBooleanLiteral() && !item.isNull() && !item.isUndefined()) : [];
74
+ isUnion = !!unionTypes.length;
75
+
76
+ if (isUnion) {
77
+ if (unionTypes.length === 1 && !unionTypes[0].isLiteral()) {
78
+ isUnion = false;
79
+ } // 兼容 prisma 生成的类型用 null 表示可选
80
+
81
+
82
+ isRequired = unionTypes.length === type.getUnionTypes().length; // 必须用 getBaseTypeOfLiteralType 获取枚举字面量的原始类型
83
+
84
+ type = unionTypes[0].getBaseTypeOfLiteralType();
41
85
  }
42
- getTypeBySymbol(symbol) {
43
- return symbol.getTypeAtLocation(symbol.getDeclarations()[0] || symbol.getValueDeclarationOrThrow());
86
+
87
+ const isEnum = type.isEnum();
88
+ const enumData = isEnum ? // @ts-ignore
89
+ type.compilerType.types.reduce((res, item) => {
90
+ res[item.getSymbol().getName()] = item.value;
91
+ return res;
92
+ }, {}) : {};
93
+ const enumKeys = Object.keys(enumData);
94
+ const enumValues = Object.values(enumData);
95
+ const isIntersection = type.isIntersection();
96
+ const intersectionTypes = isIntersection && type.getIntersectionTypes();
97
+ const isArray = type.isArray();
98
+ const isString = isEnum ? typeof enumValues[0] === 'string' : type.isString() || ['Date'].includes(((_type$getSymbol3 = type.getSymbol()) == null ? void 0 : _type$getSymbol3.getName()) || '');
99
+ const isNumber = isEnum ? typeof enumValues[0] === 'number' : type.isNumber();
100
+ const isBoolean = type.isBoolean() || type.isUnion() && type.getUnionTypes().some(item => item.isBooleanLiteral()) && type.getUnionTypes().every(item => item.isBooleanLiteral() || item.isNull() || item.isUndefined());
101
+ const isObject = !isArray && !isString && !isNumber && !isBoolean && type.isObject() || // 将交集类型视为对象
102
+ isIntersection;
103
+
104
+ const symbol = _symbol || type.getSymbol();
105
+
106
+ const apiName = (symbol == null ? void 0 : symbol.getName()) || '__type';
107
+ const apiDesc = [symbol && this.getCommentBySymbol(symbol), isEnum && `枚举:${enumKeys.map((key, index) => `${key}->${enumValues[index]}`).join('; ')}`].filter(Boolean).join('\n');
108
+ const apiEnum = isUnion ? unionTypes.map(t => t.getLiteralValue()) : isEnum ? enumValues : [];
109
+ const apiType = isArray ? 'array' : isString ? 'string' : isNumber ? 'number' : isBoolean ? 'boolean' : 'object';
110
+ const apiRequired = isRequired === false ? false : !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional);
111
+ const apiChildren = isArray ? [this.typeToApiData(type.getArrayElementTypeOrThrow())] : isObject ? ii(() => {
112
+ const context = type._context;
113
+ const compilerFactory = context.compilerFactory;
114
+ const rawChecker = type.compilerType.checker;
115
+ let symbols = [];
116
+
117
+ if (intersectionTypes) {
118
+ // https://github.com/microsoft/TypeScript/issues/38184
119
+ symbols = rawChecker.getAllPossiblePropertiesOfTypes(intersectionTypes.map(item => item.compilerType)) // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
120
+ .map(symbol => compilerFactory.getSymbol(symbol));
121
+ } else {
122
+ // symbols = type.getApparentProperties()
123
+ // https://github.com/microsoft/TypeScript/issues/38184
124
+ symbols = rawChecker.getAllPossiblePropertiesOfTypes([type.compilerType]) // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
125
+ .map(symbol => compilerFactory.getSymbol(symbol));
126
+ }
127
+
128
+ return symbols.map(symbol => {
129
+ return this.typeToApiData(!symbol.compilerSymbol.declarations ? // 对于复杂对象,没有定义的,通过 type 直接获取(在前面通过 getText 预处理得到)
130
+ compilerFactory.getType(symbol.compilerSymbol.type) : this.getTypeBySymbol(symbol), symbol);
131
+ });
132
+ }) : [];
133
+ return {
134
+ name: apiName,
135
+ desc: apiDesc,
136
+ enum: apiEnum,
137
+ type: apiType,
138
+ required: apiRequired,
139
+ children: apiChildren
140
+ };
141
+ }
142
+
143
+ apiDataToJsonSchema(apiData, jsonSchema = {}) {
144
+ jsonSchema.description = apiData.desc;
145
+
146
+ if (apiData.type === 'object') {
147
+ jsonSchema.type = 'object';
148
+ jsonSchema.properties = apiData.children.reduce((res, item) => {
149
+ ;
150
+ res[item.name] = this.apiDataToJsonSchema(item);
151
+ return res;
152
+ }, {});
153
+ jsonSchema.required = apiData.children.filter(item => item.required).map(item => item.name);
154
+ } else if (apiData.type === 'array') {
155
+ jsonSchema.type = 'array';
156
+ jsonSchema.items = apiData.children.map(item => this.apiDataToJsonSchema(item))[0];
157
+ } else {
158
+ jsonSchema.type = apiData.type;
159
+
160
+ if (apiData.enum.length) {
161
+ jsonSchema.enum = apiData.enum;
162
+ }
44
163
  }
45
- getComment(declaration) {
46
- const text = (declaration?.getLeadingCommentRanges()[0]?.getText() || '').trim();
47
- const comment = parseComment.parse(text)[0];
48
- const description = comment?.description || '';
49
- const tags = new Map();
50
- comment?.tags.forEach(tag => {
51
- tags.set(tag.tag, tag.description);
52
- });
53
- return {
54
- existing: !!comment,
55
- description: description,
56
- tags: tags,
57
- };
58
- }
59
- getCommentBySymbol(symbol) {
60
- return this.getComment(symbol.getDeclarations()[0])?.description || '';
164
+
165
+ return jsonSchema;
166
+ }
167
+
168
+ genYApiData(handles) {
169
+ const data = {};
170
+
171
+ for (const handle of handles) {
172
+ data[handle.category] = data[handle.category] || [];
173
+ data[handle.category].push(handle.handlerMethod === 'FILE' ? {
174
+ method: handle.method.toUpperCase(),
175
+ title: handle.name,
176
+ path: handle.path,
177
+ req_body_type: 'form',
178
+ res_body_type: 'json',
179
+ req_body_is_json_schema: false,
180
+ res_body_is_json_schema: true,
181
+ req_params: [],
182
+ req_query: [],
183
+ req_headers: [],
184
+ req_body_form: handle.requestData.children.map(item => ({
185
+ required: item.required ? 1 : 0,
186
+ name: item.name,
187
+ type: item.type === 'file' ? 'file' : 'text'
188
+ })),
189
+ res_body: JSON.stringify(handle.responseDataJsonSchema)
190
+ } : {
191
+ method: handle.method.toUpperCase(),
192
+ title: handle.name,
193
+ path: handle.path,
194
+ req_body_type: 'json',
195
+ res_body_type: 'json',
196
+ req_body_is_json_schema: true,
197
+ res_body_is_json_schema: true,
198
+ req_params: [],
199
+ req_query: [],
200
+ req_headers: [],
201
+ req_body_form: [],
202
+ req_body_other: JSON.stringify(handle.requestDataJsonSchema),
203
+ res_body: JSON.stringify(handle.responseDataJsonSchema)
204
+ });
61
205
  }
62
- typeToApiData(type, _symbol) {
63
- // ws
64
- if (type.getSymbol()?.getName() === 'SocketStream') {
65
- return {
66
- name: 'ws',
67
- desc: 'ws',
68
- required: false,
69
- type: 'object',
70
- children: [],
71
- enum: [],
72
- };
73
- }
74
- // XFile
75
- if (type.getSymbol()?.getName() === 'MultipartFile') {
76
- const symbol = _symbol || type.getSymbol();
77
- return {
78
- name: 'file',
79
- desc: (symbol && this.getCommentBySymbol(symbol)) || '',
80
- required: !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional),
81
- type: 'file',
82
- children: [],
83
- enum: [],
84
- };
85
- }
86
- let isRequired = true;
87
- let isUnion = type.isUnion();
88
- const unionTypes = isUnion
89
- ? type
90
- .getUnionTypes()
91
- .filter(item => !item.isBooleanLiteral() && !item.isNull() && !item.isUndefined())
92
- : [];
93
- isUnion = !!unionTypes.length;
94
- if (isUnion) {
95
- if (unionTypes.length === 1 && !unionTypes[0].isLiteral()) {
96
- isUnion = false;
97
- }
98
- // 兼容 prisma 生成的类型用 null 表示可选
99
- isRequired = unionTypes.length === type.getUnionTypes().length;
100
- // 必须用 getBaseTypeOfLiteralType 获取枚举字面量的原始类型
101
- type = unionTypes[0].getBaseTypeOfLiteralType();
102
- }
103
- const isEnum = type.isEnum();
104
- const enumData = isEnum
105
- ? // @ts-ignore
106
- type.compilerType.types.reduce((res, item) => {
107
- res[item.getSymbol().getName()] = item.value;
108
- return res;
109
- }, {})
110
- : {};
111
- const enumKeys = Object.keys(enumData);
112
- const enumValues = Object.values(enumData);
113
- const isIntersection = type.isIntersection();
114
- const intersectionTypes = isIntersection && type.getIntersectionTypes();
115
- const isArray = type.isArray();
116
- const isString = isEnum
117
- ? typeof enumValues[0] === 'string'
118
- : type.isString() || ['Date'].includes(type.getSymbol()?.getName() || '');
119
- const isNumber = isEnum
120
- ? typeof enumValues[0] === 'number'
121
- : type.isNumber();
122
- const isBoolean = type.isBoolean() ||
123
- (type.isUnion() &&
124
- type.getUnionTypes().some(item => item.isBooleanLiteral()) &&
125
- type
126
- .getUnionTypes()
127
- .every(item => item.isBooleanLiteral() || item.isNull() || item.isUndefined()));
128
- const isObject = (!isArray && !isString && !isNumber && !isBoolean && type.isObject()) ||
129
- // 将交集类型视为对象
130
- isIntersection;
131
- const symbol = _symbol || type.getSymbol();
132
- const apiName = symbol?.getName() || '__type';
133
- const apiDesc = [
134
- symbol && this.getCommentBySymbol(symbol),
135
- isEnum &&
136
- `枚举:${enumKeys
137
- .map((key, index) => `${key}->${enumValues[index]}`)
138
- .join('; ')}`,
139
- ]
140
- .filter(Boolean)
141
- .join('\n');
142
- const apiEnum = isUnion
143
- ? unionTypes.map(t => t.getLiteralValue())
144
- : isEnum
145
- ? enumValues
146
- : [];
147
- const apiType = isArray
148
- ? 'array'
149
- : isString
150
- ? 'string'
151
- : isNumber
152
- ? 'number'
153
- : isBoolean
154
- ? 'boolean'
155
- : 'object';
156
- const apiRequired = isRequired === false
157
- ? false
158
- : !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional);
159
- const apiChildren = isArray
160
- ? [this.typeToApiData(type.getArrayElementTypeOrThrow())]
161
- : isObject
162
- ? (0, vtils_1.ii)(() => {
163
- const context = type._context;
164
- const compilerFactory = context.compilerFactory;
165
- const rawChecker = type.compilerType
166
- .checker;
167
- let symbols = [];
168
- if (intersectionTypes) {
169
- // https://github.com/microsoft/TypeScript/issues/38184
170
- symbols = rawChecker
171
- .getAllPossiblePropertiesOfTypes(intersectionTypes.map(item => item.compilerType))
172
- // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
173
- .map((symbol) => compilerFactory.getSymbol(symbol));
174
- }
175
- else {
176
- // symbols = type.getApparentProperties()
177
- // https://github.com/microsoft/TypeScript/issues/38184
178
- symbols = rawChecker
179
- .getAllPossiblePropertiesOfTypes([type.compilerType])
180
- // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
181
- .map((symbol) => compilerFactory.getSymbol(symbol));
182
- }
183
- return symbols.map(symbol => {
184
- return this.typeToApiData(!symbol.compilerSymbol.declarations
185
- ? // 对于复杂对象,没有定义的,通过 type 直接获取(在前面通过 getText 预处理得到)
186
- compilerFactory.getType(symbol.compilerSymbol.type)
187
- : this.getTypeBySymbol(symbol), symbol);
188
- });
189
- })
190
- : [];
191
- return {
192
- name: apiName,
193
- desc: apiDesc,
194
- enum: apiEnum,
195
- type: apiType,
196
- required: apiRequired,
197
- children: apiChildren,
198
- };
199
- }
200
- apiDataToJsonSchema(apiData, jsonSchema = {}) {
201
- jsonSchema.description = apiData.desc;
202
- if (apiData.type === 'object') {
203
- jsonSchema.type = 'object';
204
- jsonSchema.properties = apiData.children.reduce((res, item) => {
205
- ;
206
- res[item.name] = this.apiDataToJsonSchema(item);
207
- return res;
208
- }, {});
209
- jsonSchema.required = apiData.children
210
- .filter(item => item.required)
211
- .map(item => item.name);
212
- }
213
- else if (apiData.type === 'array') {
214
- jsonSchema.type = 'array';
215
- jsonSchema.items = apiData.children.map(item => this.apiDataToJsonSchema(item))[0];
216
- }
217
- else {
218
- jsonSchema.type = apiData.type;
219
- if (apiData.enum.length) {
220
- jsonSchema.enum = apiData.enum;
221
- }
222
- }
223
- return jsonSchema;
224
- }
225
- genYApiData(handles) {
226
- const data = {};
227
- for (const handle of handles) {
228
- data[handle.category] = data[handle.category] || [];
229
- data[handle.category].push(handle.handlerMethod === 'FILE'
230
- ? {
231
- method: handle.method.toUpperCase(),
232
- title: handle.name,
233
- path: handle.path,
234
- req_body_type: 'form',
235
- res_body_type: 'json',
236
- req_body_is_json_schema: false,
237
- res_body_is_json_schema: true,
238
- req_params: [],
239
- req_query: [],
240
- req_headers: [],
241
- req_body_form: handle.requestData.children.map(item => ({
242
- required: item.required ? 1 : 0,
243
- name: item.name,
244
- type: item.type === 'file' ? 'file' : 'text',
245
- })),
246
- res_body: JSON.stringify(handle.responseDataJsonSchema),
247
- }
248
- : {
249
- method: handle.method.toUpperCase(),
250
- title: handle.name,
251
- path: handle.path,
252
- req_body_type: 'json',
253
- res_body_type: 'json',
254
- req_body_is_json_schema: true,
255
- res_body_is_json_schema: true,
256
- req_params: [],
257
- req_query: [],
258
- req_headers: [],
259
- req_body_form: [],
260
- req_body_other: JSON.stringify(handle.requestDataJsonSchema),
261
- res_body: JSON.stringify(handle.responseDataJsonSchema),
262
- });
263
- }
264
- return Object.keys(data).map(cat => ({
265
- name: cat,
266
- desc: cat,
267
- list: data[cat],
268
- }));
269
- }
270
- async generate() {
271
- this.debug('启动项目...');
272
- this.project = new ts.Project({
273
- tsConfigFilePath: node_path_1.default.join(this.cwd, 'tsconfig.json'),
206
+
207
+ return Object.keys(data).map(cat => ({
208
+ name: cat,
209
+ desc: cat,
210
+ list: data[cat]
211
+ }));
212
+ }
213
+
214
+ async generate() {
215
+ this.debug('启动项目...');
216
+ this.project = new ts.Project({
217
+ tsConfigFilePath: path.join(this.cwd, 'tsconfig.json')
218
+ });
219
+ this.debug('加载文件...');
220
+ const sourceFile = this.project.createSourceFile(path.join(this.cwd, 'src/generated/handlers.ts'), await fs.readFile(path.join(this.cwd, 'node_modules/.x/handlers.ts'), 'utf-8'));
221
+ this.debug('导出处理器...');
222
+ const handlerGroup = sourceFile.getExportSymbols();
223
+ const handles = [];
224
+ this.debug('生成API文档...');
225
+
226
+ for (const handlerList of handlerGroup) {
227
+ const handlerListSourceFile = this.getTypeBySymbol(handlerList).getProperties()[0].getDeclarations()[0].getSourceFile();
228
+ const basePath = `/${snakeCase(handlerListSourceFile.getFilePath().replace('.ts', '').split('/src/handlers/')[1]).replace(/_/g, '/')}/`.replace(/\/{2,}/g, '/');
229
+
230
+ for (const handler of handlerListSourceFile.getVariableStatements().filter(item => item.isExported())) {
231
+ // 重要:这一步必须,先调一遍 getText 获取看到的对象,后续对于复杂定义才不会报错
232
+ handler.getDeclarations().forEach(exp => {
233
+ exp.getType().getText();
274
234
  });
275
- this.debug('加载文件...');
276
- const sourceFile = this.project.createSourceFile(node_path_1.default.join(this.cwd, 'src/generated/handlers.ts'), await fs_extra_1.default.readFile(node_path_1.default.join(this.cwd, 'node_modules/.x/handlers.ts'), 'utf-8'));
277
- this.debug('导出处理器...');
278
- const handlerGroup = sourceFile.getExportSymbols();
279
- const handles = [];
280
- this.debug('生成API文档...');
281
- for (const handlerList of handlerGroup) {
282
- const handlerListSourceFile = this.getTypeBySymbol(handlerList)
283
- .getProperties()[0]
284
- .getDeclarations()[0]
285
- .getSourceFile();
286
- const basePath = `/${(0, vtils_1.snakeCase)(handlerListSourceFile
287
- .getFilePath()
288
- .replace('.ts', '')
289
- .split('/src/handlers/')[1]).replace(/_/g, '/')}/`.replace(/\/{2,}/g, '/');
290
- for (const handler of handlerListSourceFile
291
- .getVariableStatements()
292
- .filter(item => item.isExported())) {
293
- // 重要:这一步必须,先调一遍 getText 获取看到的对象,后续对于复杂定义才不会报错
294
- handler.getDeclarations().forEach(exp => {
295
- exp.getType().getText();
296
- });
297
- const handlerExp = handler.getDeclarations()[0];
298
- const handlerPath = `${basePath}${handlerExp.getName()}`;
299
- this.debug('生成接口: %s ...', handlerPath);
300
- const [requestType, responseType, methodType] = handlerExp
301
- .getType()
302
- .getTypeArguments();
303
- const handlerComment = this.getComment(handlerExp.getParent().getParent());
304
- if (handlerComment.tags.has('private')) {
305
- this.debug('跳过生成接口: %s', `${handlerPath}`);
306
- continue;
307
- }
308
- const handlerCategory = (0, vtils_1.pascalCase)(basePath) || 'ROOT';
309
- const handlerName = handlerComment.description || handlerPath;
310
- const handlerMethod = methodType.getLiteralValueOrThrow();
311
- const serverMethod = http_method_1.HandlerMethodToHttpMethod[handlerMethod];
312
- const requestData = this.typeToApiData(requestType);
313
- const responseData = this.typeToApiData(responseType);
314
- const requestDataJsonSchema = this.apiDataToJsonSchema(requestData);
315
- const responseDataJsonSchema = this.apiDataToJsonSchema(responseData);
316
- handles.push({
317
- category: handlerCategory,
318
- name: handlerName,
319
- path: handlerPath,
320
- handlerMethod: handlerMethod,
321
- method: serverMethod,
322
- requestData: requestData,
323
- responseData: responseData,
324
- requestDataJsonSchema: requestDataJsonSchema,
325
- responseDataJsonSchema: responseDataJsonSchema,
326
- });
327
- }
235
+ const handlerExp = handler.getDeclarations()[0];
236
+ const handlerPath = `${basePath}${handlerExp.getName()}`;
237
+ this.debug('生成接口: %s ...', handlerPath);
238
+ const [requestType, responseType, methodType] = handlerExp.getType().getTypeArguments();
239
+ const handlerComment = this.getComment(handlerExp.getParent().getParent());
240
+
241
+ if (handlerComment.tags.has('private')) {
242
+ this.debug('跳过生成接口: %s', `${handlerPath}`);
243
+ continue;
328
244
  }
329
- this.debug('写入文件...');
330
- await Promise.all([
331
- fs_extra_1.default.outputJSON(node_path_1.default.join(this.cwd, 'temp/api.json'), handles, {
332
- spaces: 2,
333
- }),
334
- fs_extra_1.default.outputJSON(node_path_1.default.join(this.cwd, 'temp/yapi.json'), this.genYApiData(handles), { spaces: 2 }),
335
- ]);
245
+
246
+ const handlerCategory = pascalCase(basePath) || 'ROOT';
247
+ const handlerName = handlerComment.description || handlerPath;
248
+ const handlerMethod = methodType.getLiteralValueOrThrow();
249
+ const serverMethod = HandlerMethodToHttpMethod[handlerMethod];
250
+ const requestData = this.typeToApiData(requestType);
251
+ const responseData = this.typeToApiData(responseType);
252
+ const requestDataJsonSchema = this.apiDataToJsonSchema(requestData);
253
+ const responseDataJsonSchema = this.apiDataToJsonSchema(responseData);
254
+ handles.push({
255
+ category: handlerCategory,
256
+ name: handlerName,
257
+ path: handlerPath,
258
+ handlerMethod: handlerMethod,
259
+ method: serverMethod,
260
+ requestData: requestData,
261
+ responseData: responseData,
262
+ requestDataJsonSchema: requestDataJsonSchema,
263
+ responseDataJsonSchema: responseDataJsonSchema
264
+ });
265
+ }
336
266
  }
337
- }
338
- exports.ApiGenerator = ApiGenerator;
339
- // new ApiGenerator().generate()
267
+
268
+ this.debug('写入文件...');
269
+ await Promise.all([fs.outputJSON(path.join(this.cwd, 'temp/api.json'), handles, {
270
+ spaces: 2
271
+ }), fs.outputJSON(path.join(this.cwd, 'temp/yapi.json'), this.genYApiData(handles), {
272
+ spaces: 2
273
+ })]);
274
+ }
275
+
276
+ } // new ApiGenerator().generate()
@@ -3,6 +3,7 @@ export interface BuildOptions {
3
3
  cwd: string;
4
4
  external?: string[];
5
5
  inlineEnvs?: ParsedEnv[];
6
+ minify?: boolean;
6
7
  }
7
8
  export declare class BuildUtil {
8
9
  static build(options: BuildOptions): Promise<void>;