@jayfong/x-server 1.11.0 → 1.11.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 (72) hide show
  1. package/CHANGELOG.md +7 -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.js +108 -130
  40. package/lib/cli/cli.js +161 -187
  41. package/lib/cli/deploy_util.js +37 -41
  42. package/lib/cli/env_util.js +112 -120
  43. package/lib/cli/register.js +5 -7
  44. package/lib/cli/template_util.js +47 -52
  45. package/lib/core/define_bus.js +22 -14
  46. package/lib/core/define_handler.js +31 -36
  47. package/lib/core/define_hook.js +4 -8
  48. package/lib/core/define_server.js +6 -10
  49. package/lib/core/define_task.js +20 -25
  50. package/lib/core/handler.js +78 -74
  51. package/lib/core/http_error.js +2 -8
  52. package/lib/core/http_method.js +7 -10
  53. package/lib/core/server.js +125 -139
  54. package/lib/core/types.js +11 -2
  55. package/lib/index.js +23 -39
  56. package/lib/plugins/base.js +1 -2
  57. package/lib/plugins/cors.js +30 -36
  58. package/lib/plugins/file_parser.d.ts +1 -1
  59. package/lib/plugins/file_parser.js +12 -16
  60. package/lib/plugins/ws_parser.d.ts +1 -1
  61. package/lib/plugins/ws_parser.js +12 -16
  62. package/lib/plugins/xml_parser.d.ts +1 -1
  63. package/lib/plugins/xml_parser.js +47 -43
  64. package/lib/services/base.js +1 -2
  65. package/lib/services/cache.js +213 -190
  66. package/lib/services/captcha.js +32 -33
  67. package/lib/services/dispose.d.ts +1 -1
  68. package/lib/services/dispose.js +22 -23
  69. package/lib/services/jwt.js +45 -48
  70. package/lib/services/redis.js +8 -14
  71. package/lib/x.js +12 -15
  72. package/package.json +4 -3
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.11.1](https://github.com/jfWorks/x-server/compare/v1.11.0...v1.11.1) (2022-04-20)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * module ([cdbc01b](https://github.com/jfWorks/x-server/commit/cdbc01b7e252283fa868c5519dd7f22263853aa9))
11
+
5
12
  ## [1.11.0](https://github.com/jfWorks/x-server/compare/v1.10.3...v1.11.0) (2022-04-20)
6
13
 
7
14
 
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
6
+
7
+ exports.__esModule = true;
8
+ exports.ApiGenerator = void 0;
9
+
10
+ var parseComment = _interopRequireWildcard(require("comment-parser"));
11
+
12
+ var ts = _interopRequireWildcard(require("ts-morph"));
13
+
14
+ var _debug = _interopRequireDefault(require("debug"));
15
+
16
+ var _fsExtra = _interopRequireDefault(require("fs-extra"));
17
+
18
+ var _nodePath = _interopRequireDefault(require("node:path"));
19
+
20
+ var _http_method = require("../core/http_method");
21
+
22
+ var _vtils = require("vtils");
23
+
24
+ class ApiGenerator {
25
+ constructor() {
26
+ this.debug = (0, _debug.default)('api');
27
+ this.cwd = process.cwd();
28
+ this.project = void 0;
29
+ }
30
+
31
+ getTypeBySymbol(symbol) {
32
+ return symbol.getTypeAtLocation(symbol.getDeclarations()[0] || symbol.getValueDeclarationOrThrow());
33
+ }
34
+
35
+ getComment(declaration) {
36
+ var _declaration$getLeadi;
37
+
38
+ const text = ((declaration == null ? void 0 : (_declaration$getLeadi = declaration.getLeadingCommentRanges()[0]) == null ? void 0 : _declaration$getLeadi.getText()) || '').trim();
39
+ const comment = parseComment.parse(text)[0];
40
+ const description = (comment == null ? void 0 : comment.description) || '';
41
+ const tags = new Map();
42
+ comment == null ? void 0 : comment.tags.forEach(tag => {
43
+ tags.set(tag.tag, tag.description);
44
+ });
45
+ return {
46
+ existing: !!comment,
47
+ description: description,
48
+ tags: tags
49
+ };
50
+ }
51
+
52
+ getCommentBySymbol(symbol) {
53
+ var _this$getComment;
54
+
55
+ return ((_this$getComment = this.getComment(symbol.getDeclarations()[0])) == null ? void 0 : _this$getComment.description) || '';
56
+ }
57
+
58
+ typeToApiData(type, _symbol) {
59
+ var _type$getSymbol, _type$getSymbol2, _type$getSymbol3;
60
+
61
+ // ws
62
+ if (((_type$getSymbol = type.getSymbol()) == null ? void 0 : _type$getSymbol.getName()) === 'SocketStream') {
63
+ return {
64
+ name: 'ws',
65
+ desc: 'ws',
66
+ required: false,
67
+ type: 'object',
68
+ children: [],
69
+ enum: []
70
+ };
71
+ } // XFile
72
+
73
+
74
+ if (((_type$getSymbol2 = type.getSymbol()) == null ? void 0 : _type$getSymbol2.getName()) === 'MultipartFile') {
75
+ const symbol = _symbol || type.getSymbol();
76
+
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
+
87
+ let isRequired = true;
88
+ let isUnion = type.isUnion();
89
+ const unionTypes = isUnion ? type.getUnionTypes().filter(item => !item.isBooleanLiteral() && !item.isNull() && !item.isUndefined()) : [];
90
+ isUnion = !!unionTypes.length;
91
+
92
+ if (isUnion) {
93
+ if (unionTypes.length === 1 && !unionTypes[0].isLiteral()) {
94
+ isUnion = false;
95
+ } // 兼容 prisma 生成的类型用 null 表示可选
96
+
97
+
98
+ isRequired = unionTypes.length === type.getUnionTypes().length; // 必须用 getBaseTypeOfLiteralType 获取枚举字面量的原始类型
99
+
100
+ type = unionTypes[0].getBaseTypeOfLiteralType();
101
+ }
102
+
103
+ const isEnum = type.isEnum();
104
+ const enumData = isEnum ? // @ts-ignore
105
+ type.compilerType.types.reduce((res, item) => {
106
+ res[item.getSymbol().getName()] = item.value;
107
+ return res;
108
+ }, {}) : {};
109
+ const enumKeys = Object.keys(enumData);
110
+ const enumValues = Object.values(enumData);
111
+ const isIntersection = type.isIntersection();
112
+ const intersectionTypes = isIntersection && type.getIntersectionTypes();
113
+ const isArray = type.isArray();
114
+ const isString = isEnum ? typeof enumValues[0] === 'string' : type.isString() || ['Date'].includes(((_type$getSymbol3 = type.getSymbol()) == null ? void 0 : _type$getSymbol3.getName()) || '');
115
+ const isNumber = isEnum ? typeof enumValues[0] === 'number' : type.isNumber();
116
+ const isBoolean = type.isBoolean() || type.isUnion() && type.getUnionTypes().some(item => item.isBooleanLiteral()) && type.getUnionTypes().every(item => item.isBooleanLiteral() || item.isNull() || item.isUndefined());
117
+ const isObject = !isArray && !isString && !isNumber && !isBoolean && type.isObject() || // 将交集类型视为对象
118
+ isIntersection;
119
+
120
+ const symbol = _symbol || type.getSymbol();
121
+
122
+ const apiName = (symbol == null ? void 0 : symbol.getName()) || '__type';
123
+ const apiDesc = [symbol && this.getCommentBySymbol(symbol), isEnum && `枚举:${enumKeys.map((key, index) => `${key}->${enumValues[index]}`).join('; ')}`].filter(Boolean).join('\n');
124
+ const apiEnum = isUnion ? unionTypes.map(t => t.getLiteralValue()) : isEnum ? enumValues : [];
125
+ const apiType = isArray ? 'array' : isString ? 'string' : isNumber ? 'number' : isBoolean ? 'boolean' : 'object';
126
+ const apiRequired = isRequired === false ? false : !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional);
127
+ const apiChildren = isArray ? [this.typeToApiData(type.getArrayElementTypeOrThrow())] : isObject ? (0, _vtils.ii)(() => {
128
+ const context = type._context;
129
+ const compilerFactory = context.compilerFactory;
130
+ const rawChecker = type.compilerType.checker;
131
+ let symbols = [];
132
+
133
+ if (intersectionTypes) {
134
+ // https://github.com/microsoft/TypeScript/issues/38184
135
+ 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
136
+ .map(symbol => compilerFactory.getSymbol(symbol));
137
+ } else {
138
+ // symbols = type.getApparentProperties()
139
+ // https://github.com/microsoft/TypeScript/issues/38184
140
+ symbols = rawChecker.getAllPossiblePropertiesOfTypes([type.compilerType]) // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
141
+ .map(symbol => compilerFactory.getSymbol(symbol));
142
+ }
143
+
144
+ return symbols.map(symbol => {
145
+ return this.typeToApiData(!symbol.compilerSymbol.declarations ? // 对于复杂对象,没有定义的,通过 type 直接获取(在前面通过 getText 预处理得到)
146
+ compilerFactory.getType(symbol.compilerSymbol.type) : this.getTypeBySymbol(symbol), symbol);
147
+ });
148
+ }) : [];
149
+ return {
150
+ name: apiName,
151
+ desc: apiDesc,
152
+ enum: apiEnum,
153
+ type: apiType,
154
+ required: apiRequired,
155
+ children: apiChildren
156
+ };
157
+ }
158
+
159
+ apiDataToJsonSchema(apiData, jsonSchema = {}) {
160
+ jsonSchema.description = apiData.desc;
161
+
162
+ if (apiData.type === 'object') {
163
+ jsonSchema.type = 'object';
164
+ jsonSchema.properties = apiData.children.reduce((res, item) => {
165
+ ;
166
+ res[item.name] = this.apiDataToJsonSchema(item);
167
+ return res;
168
+ }, {});
169
+ jsonSchema.required = apiData.children.filter(item => item.required).map(item => item.name);
170
+ } else if (apiData.type === 'array') {
171
+ jsonSchema.type = 'array';
172
+ jsonSchema.items = apiData.children.map(item => this.apiDataToJsonSchema(item))[0];
173
+ } else {
174
+ jsonSchema.type = apiData.type;
175
+
176
+ if (apiData.enum.length) {
177
+ jsonSchema.enum = apiData.enum;
178
+ }
179
+ }
180
+
181
+ return jsonSchema;
182
+ }
183
+
184
+ genYApiData(handles) {
185
+ const data = {};
186
+
187
+ for (const handle of handles) {
188
+ data[handle.category] = data[handle.category] || [];
189
+ data[handle.category].push(handle.handlerMethod === 'FILE' ? {
190
+ method: handle.method.toUpperCase(),
191
+ title: handle.name,
192
+ path: handle.path,
193
+ req_body_type: 'form',
194
+ res_body_type: 'json',
195
+ req_body_is_json_schema: false,
196
+ res_body_is_json_schema: true,
197
+ req_params: [],
198
+ req_query: [],
199
+ req_headers: [],
200
+ req_body_form: handle.requestData.children.map(item => ({
201
+ required: item.required ? 1 : 0,
202
+ name: item.name,
203
+ type: item.type === 'file' ? 'file' : 'text'
204
+ })),
205
+ res_body: JSON.stringify(handle.responseDataJsonSchema)
206
+ } : {
207
+ method: handle.method.toUpperCase(),
208
+ title: handle.name,
209
+ path: handle.path,
210
+ req_body_type: 'json',
211
+ res_body_type: 'json',
212
+ req_body_is_json_schema: true,
213
+ res_body_is_json_schema: true,
214
+ req_params: [],
215
+ req_query: [],
216
+ req_headers: [],
217
+ req_body_form: [],
218
+ req_body_other: JSON.stringify(handle.requestDataJsonSchema),
219
+ res_body: JSON.stringify(handle.responseDataJsonSchema)
220
+ });
221
+ }
222
+
223
+ return Object.keys(data).map(cat => ({
224
+ name: cat,
225
+ desc: cat,
226
+ list: data[cat]
227
+ }));
228
+ }
229
+
230
+ async generate() {
231
+ this.debug('启动项目...');
232
+ this.project = new ts.Project({
233
+ tsConfigFilePath: _nodePath.default.join(this.cwd, 'tsconfig.json')
234
+ });
235
+ this.debug('加载文件...');
236
+ const sourceFile = this.project.createSourceFile(_nodePath.default.join(this.cwd, 'src/generated/handlers.ts'), await _fsExtra.default.readFile(_nodePath.default.join(this.cwd, 'node_modules/.x/handlers.ts'), 'utf-8'));
237
+ this.debug('导出处理器...');
238
+ const handlerGroup = sourceFile.getExportSymbols();
239
+ const handles = [];
240
+ this.debug('生成API文档...');
241
+
242
+ for (const handlerList of handlerGroup) {
243
+ const handlerListSourceFile = this.getTypeBySymbol(handlerList).getProperties()[0].getDeclarations()[0].getSourceFile();
244
+ const basePath = `/${(0, _vtils.snakeCase)(handlerListSourceFile.getFilePath().replace('.ts', '').split('/src/handlers/')[1]).replace(/_/g, '/')}/`.replace(/\/{2,}/g, '/');
245
+
246
+ for (const handler of handlerListSourceFile.getVariableStatements().filter(item => item.isExported())) {
247
+ // 重要:这一步必须,先调一遍 getText 获取看到的对象,后续对于复杂定义才不会报错
248
+ handler.getDeclarations().forEach(exp => {
249
+ exp.getType().getText();
250
+ });
251
+ const handlerExp = handler.getDeclarations()[0];
252
+ const handlerPath = `${basePath}${handlerExp.getName()}`;
253
+ this.debug('生成接口: %s ...', handlerPath);
254
+ const [requestType, responseType, methodType] = handlerExp.getType().getTypeArguments();
255
+ const handlerComment = this.getComment(handlerExp.getParent().getParent());
256
+
257
+ if (handlerComment.tags.has('private')) {
258
+ this.debug('跳过生成接口: %s', `${handlerPath}`);
259
+ continue;
260
+ }
261
+
262
+ const handlerCategory = (0, _vtils.pascalCase)(basePath) || 'ROOT';
263
+ const handlerName = handlerComment.description || handlerPath;
264
+ const handlerMethod = methodType.getLiteralValueOrThrow();
265
+ const serverMethod = _http_method.HandlerMethodToHttpMethod[handlerMethod];
266
+ const requestData = this.typeToApiData(requestType);
267
+ const responseData = this.typeToApiData(responseType);
268
+ const requestDataJsonSchema = this.apiDataToJsonSchema(requestData);
269
+ const responseDataJsonSchema = this.apiDataToJsonSchema(responseData);
270
+ handles.push({
271
+ category: handlerCategory,
272
+ name: handlerName,
273
+ path: handlerPath,
274
+ handlerMethod: handlerMethod,
275
+ method: serverMethod,
276
+ requestData: requestData,
277
+ responseData: responseData,
278
+ requestDataJsonSchema: requestDataJsonSchema,
279
+ responseDataJsonSchema: responseDataJsonSchema
280
+ });
281
+ }
282
+ }
283
+
284
+ this.debug('写入文件...');
285
+ await Promise.all([_fsExtra.default.outputJSON(_nodePath.default.join(this.cwd, 'temp/api.json'), handles, {
286
+ spaces: 2
287
+ }), _fsExtra.default.outputJSON(_nodePath.default.join(this.cwd, 'temp/yapi.json'), this.genYApiData(handles), {
288
+ spaces: 2
289
+ })]);
290
+ }
291
+
292
+ } // new ApiGenerator().generate()
293
+
294
+
295
+ exports.ApiGenerator = ApiGenerator;
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
6
+
7
+ exports.__esModule = true;
8
+ exports.BuildUtil = void 0;
9
+
10
+ var esbuild = _interopRequireWildcard(require("esbuild"));
11
+
12
+ var _compressing = _interopRequireDefault(require("compressing"));
13
+
14
+ var _execa = _interopRequireDefault(require("execa"));
15
+
16
+ var _fsExtra = _interopRequireDefault(require("fs-extra"));
17
+
18
+ var _nodePath = _interopRequireDefault(require("node:path"));
19
+
20
+ var _vtils = require("vtils");
21
+
22
+ class BuildUtil {
23
+ static async build(options) {
24
+ var _options$minify, _options$inlineEnvs;
25
+
26
+ const mainFile = _nodePath.default.join(options.cwd, 'src/main.ts');
27
+
28
+ const pkgFile = _nodePath.default.join(options.cwd, 'package.json');
29
+
30
+ const pkgContent = await _fsExtra.default.readJson(pkgFile);
31
+
32
+ const distDir = _nodePath.default.join(options.cwd, 'dist');
33
+
34
+ const tempDir = _nodePath.default.join(options.cwd, 'temp');
35
+
36
+ const distMainFile = _nodePath.default.join(distDir, 'main.js');
37
+
38
+ const distPkgFile = _nodePath.default.join(distDir, 'package.json');
39
+
40
+ const distPm2File = _nodePath.default.join(distDir, 'pm2.config.js');
41
+
42
+ const distBundleFile = _nodePath.default.join(tempDir, `app.${pkgContent.version}.tgz`);
43
+
44
+ await _fsExtra.default.ensureDir(distDir);
45
+ await _fsExtra.default.ensureDir(tempDir); // 处理 external
46
+
47
+ const external = (0, _vtils.uniq)(options.external || []);
48
+ const externalWithVersions = await Promise.all(external.map(async item => {
49
+ const itemPkgFile = require.resolve(`${item}/package.json`);
50
+
51
+ const itemPkgContent = await _fsExtra.default.readJson(itemPkgFile);
52
+ return {
53
+ name: item,
54
+ version: itemPkgContent.version
55
+ };
56
+ })); // 构建
57
+
58
+ await _fsExtra.default.emptyDir(distDir);
59
+ await esbuild.build({
60
+ entryPoints: [mainFile],
61
+ bundle: true,
62
+ outfile: distMainFile,
63
+ platform: 'node',
64
+ target: `node${process.version.slice(1)}`,
65
+ external: external,
66
+ minify: (_options$minify = options.minify) != null ? _options$minify : true,
67
+ format: 'cjs',
68
+ sourcemap: false,
69
+ treeShaking: true,
70
+ banner: {
71
+ js: `${`;${(_options$inlineEnvs = options.inlineEnvs) == null ? void 0 : _options$inlineEnvs.map(env => `process.env[${JSON.stringify(env.key)}]=${JSON.stringify(env.value)}`).join(';')}` || ''};`
72
+ },
73
+ plugins: [{
74
+ name: 'extract-assets',
75
+
76
+ setup(build) {
77
+ build.onLoad({
78
+ filter: /\/svg-captcha\/lib\/option-manager\.js$/
79
+ }, async args => {
80
+ let js = await _fsExtra.default.readFile(args.path, 'utf-8');
81
+ js = js.replace('../fonts/Comismsh.ttf', './assets/svg-captcha/fonts/Comismsh.ttf');
82
+ await _fsExtra.default.copy(_nodePath.default.dirname(require.resolve('svg-captcha/fonts/LICENSE.md')), _nodePath.default.join(distDir, 'assets/svg-captcha/fonts'));
83
+ return {
84
+ contents: js,
85
+ loader: 'js'
86
+ };
87
+ });
88
+ build.onLoad({
89
+ filter: /\/bull\/lib\/commands\/index\.js$/
90
+ }, async args => {
91
+ let js = await _fsExtra.default.readFile(args.path, 'utf-8');
92
+ js = js.replace('loadScripts(__dirname)', 'loadScripts("./assets/bull/commands")');
93
+ await _fsExtra.default.copy(_nodePath.default.dirname(require.resolve('bull/lib/commands/index.js')), _nodePath.default.join(distDir, 'assets/bull/commands'));
94
+ return {
95
+ contents: js,
96
+ loader: 'js'
97
+ };
98
+ });
99
+ }
100
+
101
+ }]
102
+ }); // 兼容 prisma
103
+
104
+ const prismaSchemaFile = _nodePath.default.join(options.cwd, 'src/db/schema.prisma');
105
+
106
+ if (await _fsExtra.default.pathExists(prismaSchemaFile)) {
107
+ const distPrismaSchemaFile = _nodePath.default.join(distDir, 'schema.prisma');
108
+
109
+ await _fsExtra.default.copyFile(prismaSchemaFile, distPrismaSchemaFile);
110
+ await _fsExtra.default.copyFile(require.resolve('@prisma/engines/libquery_engine-rhel-openssl-1.0.x.so.node'), _nodePath.default.join(distDir, 'libquery_engine-rhel-openssl-1.0.x.so.node'));
111
+ } // 写入 pkg
112
+
113
+
114
+ const deps = externalWithVersions.reduce((res, item) => {
115
+ res[item.name] = item.version;
116
+ return res;
117
+ }, {});
118
+ const distPkgContent = {
119
+ name: pkgContent.name,
120
+ version: pkgContent.version,
121
+ dependencies: deps
122
+ };
123
+ await _fsExtra.default.writeJSON(distPkgFile, distPkgContent); // 写入 pm2 配置
124
+
125
+ await _fsExtra.default.writeFile(distPm2File, (0, _vtils.dedent)`
126
+ module.exports = {
127
+ apps: [
128
+ {
129
+ name: ${JSON.stringify(pkgContent.name)},
130
+ script: './main.js',
131
+ },
132
+ ],
133
+ }
134
+ `); // 安装 external 依赖
135
+
136
+ await (0, _execa.default)('tyn', {
137
+ cwd: distDir,
138
+ stdio: 'inherit'
139
+ }); // 打包为 tgz
140
+
141
+ await _compressing.default.tgz.compressDir(distDir, distBundleFile);
142
+ }
143
+
144
+ }
145
+
146
+ exports.BuildUtil = BuildUtil;
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5
+
6
+ var _chokidar = _interopRequireDefault(require("chokidar"));
7
+
8
+ var _execa = _interopRequireDefault(require("execa"));
9
+
10
+ var _yargs = _interopRequireDefault(require("yargs"));
11
+
12
+ var _api_generator = require("./api_generator");
13
+
14
+ var _build_util = require("./build_util");
15
+
16
+ var _vtils = require("vtils");
17
+
18
+ var _deploy_util = require("./deploy_util");
19
+
20
+ var _env_util = require("./env_util");
21
+
22
+ var _vscodeGenerateIndexStandalone = require("vscode-generate-index-standalone");
23
+
24
+ var _template_util = require("./template_util");
25
+
26
+ _yargs.default.command('dev', '开始开发', _ => _.positional('index', {
27
+ alias: 'i',
28
+ describe: '额外需要生成的索引文件',
29
+ type: 'string',
30
+ array: true
31
+ }).positional('npc', {
32
+ describe: 'npc 地址及密钥,格式:地址@密钥',
33
+ type: 'string'
34
+ }), async argv => {
35
+ process.env.NODE_ENV = 'development';
36
+ let lastRun;
37
+
38
+ const run = () => {
39
+ lastRun = (0, _execa.default)('node', ['-r', require.resolve("./register"), 'src/main.ts'], {
40
+ cwd: process.cwd(),
41
+ stdio: 'inherit'
42
+ });
43
+ };
44
+
45
+ if (argv.npc) {
46
+ const [server, vkey] = argv.npc.split('@');
47
+ (0, _execa.default)('docker', ['run', '--rm', 'ffdfgdfg/npc:v0.26.9', `-server=${server}`, `-vkey=${vkey}`, '-type=tcp'], {
48
+ cwd: process.cwd(),
49
+ stdio: 'inherit'
50
+ });
51
+ }
52
+
53
+ await _template_util.TemplateUtil.initHelperPackage(process.cwd());
54
+
55
+ const watcher = _chokidar.default.watch(['src', '.env'], {
56
+ cwd: process.cwd()
57
+ });
58
+
59
+ watcher.on('all', (0, _vtils.debounce)(async () => {
60
+ await _env_util.EnvUtil.importFile({
61
+ cwd: process.cwd(),
62
+ file: '.env'
63
+ });
64
+
65
+ _env_util.EnvUtil.outputTypes({
66
+ cwd: process.cwd(),
67
+ file: '.env',
68
+ outFile: 'env.d.ts'
69
+ });
70
+
71
+ (0, _vscodeGenerateIndexStandalone.generateManyIndex)({
72
+ cwd: process.cwd(),
73
+ patterns: ['src/**/index.ts', 'node_modules/.x/*.ts', ...(argv.index || [])],
74
+ replaceFile: true,
75
+ onSuccess: filePath => {
76
+ console.log(`✔️ 索引文件已更新: ${filePath}`);
77
+ }
78
+ });
79
+
80
+ if (lastRun) {
81
+ console.log('==== 重启服务中 ====');
82
+ lastRun.kill();
83
+ setTimeout(run, 0);
84
+ } else {
85
+ console.log('==== 启动服务中 ====');
86
+ run();
87
+ }
88
+ }, 6));
89
+ }).command('build', '构建', _ => _.positional('external', {
90
+ alias: 'e',
91
+ describe: '不应该被打的包',
92
+ type: 'string',
93
+ array: true
94
+ }).positional('minify', {
95
+ alias: 'm',
96
+ describe: '是否压缩',
97
+ type: 'boolean',
98
+ default: true
99
+ }), async argv => {
100
+ process.env.NODE_ENV = 'production';
101
+ const envs = await _env_util.EnvUtil.parseFile({
102
+ cwd: process.cwd(),
103
+ file: '.env'
104
+ });
105
+ envs.unshift({
106
+ key: 'NODE_ENV',
107
+ value: 'production',
108
+ comment: ''
109
+ });
110
+ await _template_util.TemplateUtil.initHelperPackage(process.cwd());
111
+ await (0, _vscodeGenerateIndexStandalone.generateManyIndex)({
112
+ cwd: process.cwd(),
113
+ patterns: ['src/.x/*.ts'],
114
+ replaceFile: true,
115
+ onSuccess: filePath => {
116
+ console.log(`✔️ 索引文件已更新: ${filePath}`);
117
+ }
118
+ });
119
+ await _build_util.BuildUtil.build({
120
+ cwd: process.cwd(),
121
+ external: argv.external,
122
+ inlineEnvs: envs,
123
+ minify: argv.minify
124
+ });
125
+ console.log('构建成功');
126
+ }).command('api', '生成 API', async () => {
127
+ await new _api_generator.ApiGenerator().generate();
128
+ }).command('prisma', 'prisma 代理,主要为了注入环境变量', _ => _.positional('production', {
129
+ alias: 'p',
130
+ describe: '是否生产模式',
131
+ type: 'boolean',
132
+ default: false
133
+ }), async argv => {
134
+ process.env.NODE_ENV = argv.production ? 'production' : 'development'; // https://www.prisma.io/docs/reference/api-reference/environment-variables-reference#prisma_cli_binary_targets
135
+ // https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#binarytargets-options
136
+
137
+ process.env.PRISMA_CLI_BINARY_TARGETS = 'darwin,rhel-openssl-1.0.x';
138
+ await _env_util.EnvUtil.importFile({
139
+ cwd: process.cwd(),
140
+ file: '.env'
141
+ });
142
+ process.env.DATABASE_URL = process.env.DATABASE_ACTION_URL || process.env.DATABASE_URL;
143
+ await (0, _execa.default)('tnpx', ['prisma', ...argv._.slice(1), '--schema', 'src/db/schema.prisma'], {
144
+ cwd: process.cwd(),
145
+ stdio: 'inherit'
146
+ });
147
+
148
+ if (!argv.production) {
149
+ await _template_util.TemplateUtil.initModels(process.cwd());
150
+ }
151
+ }).command('run [script]', '执行脚本', _ => _.positional('script', {
152
+ describe: '脚本',
153
+ type: 'string'
154
+ }).positional('production', {
155
+ alias: 'p',
156
+ describe: '是否生产模式',
157
+ type: 'boolean',
158
+ default: false
159
+ }), async argv => {
160
+ process.env.NODE_ENV = argv.production ? 'production' : 'development';
161
+ await _env_util.EnvUtil.importFile({
162
+ cwd: process.cwd(),
163
+ file: '.env'
164
+ });
165
+ process.env.DATABASE_URL = process.env.DATABASE_ACTION_URL || process.env.DATABASE_URL;
166
+
167
+ if (!argv.script) {
168
+ await (0, _execa.default)('tnpx', ['select-run'], {
169
+ cwd: process.cwd(),
170
+ stdio: 'inherit'
171
+ });
172
+ } else {
173
+ await (0, _execa.default)('node', ['-r', require.resolve("./register"), argv.script], {
174
+ cwd: process.cwd(),
175
+ stdio: 'inherit'
176
+ });
177
+ }
178
+ }).command('deploy', '部署', async () => {
179
+ await _env_util.EnvUtil.importFile({
180
+ cwd: process.cwd(),
181
+ file: '.env.deploy'
182
+ });
183
+ await _deploy_util.DeployUtil.deploy({
184
+ cwd: process.cwd(),
185
+ host: process.env.HOST,
186
+ user: process.env.USER,
187
+ key: process.env.KEY,
188
+ dir: process.env.DIR
189
+ });
190
+ }).parse();