create-aomex 0.0.2 → 0.0.4
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.
- package/dist/index.js +88 -97
- package/dist/index.js.map +1 -1
- package/package.json +17 -16
- package/templates/.env +1 -1
- package/templates/prisma/schema.prisma +0 -9
- package/templates/src/cli.ts +28 -2
- package/templates/src/commanders/hello.cmd.ts +19 -6
- package/templates/src/commanders/schedule.cmd.ts +43 -0
- package/templates/src/routers/index.router.ts +9 -0
- package/templates/src/routers/user.router.ts +33 -6
- package/templates/src/services/index.ts +1 -1
- package/templates/src/services/user.service.ts +17 -1
- package/templates/src/web.ts +35 -4
- package/templates/tsconfig.json +3 -2
- package/templates/src/middleware/console.chain.ts +0 -9
- package/templates/src/middleware/openapi.md.ts +0 -13
- package/templates/src/middleware/web.chain.ts +0 -17
package/dist/index.js
CHANGED
|
@@ -1,66 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// src/input-package-manager.ts
|
|
4
|
-
import inquirer from "inquirer";
|
|
5
|
-
var packageManagers = ["pnpm", "npm", "yarn"];
|
|
6
|
-
var inputPackageManager = async (argv2) => {
|
|
7
|
-
for (const expected of packageManagers) {
|
|
8
|
-
if (argv2[expected]) return expected;
|
|
9
|
-
}
|
|
10
|
-
const { manager } = await inquirer.prompt({
|
|
11
|
-
name: "manager",
|
|
12
|
-
message: "\u9009\u62E9\u5305\u7BA1\u7406\u5DE5\u5177",
|
|
13
|
-
type: "list",
|
|
14
|
-
choices: packageManagers,
|
|
15
|
-
default: "pnpm",
|
|
16
|
-
askAnswered: true
|
|
17
|
-
});
|
|
18
|
-
return manager;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// src/input-project-name.ts
|
|
22
|
-
import inquirer2 from "inquirer";
|
|
23
|
-
import kebabCase from "lodash.kebabcase";
|
|
24
|
-
import { existsSync } from "node:fs";
|
|
25
|
-
import path from "node:path";
|
|
26
|
-
var inputProjectName = async (argv2) => {
|
|
27
|
-
if (typeof argv2["name"] === "string") return argv2["name"];
|
|
28
|
-
const result = await inquirer2.prompt({
|
|
29
|
-
name: "projectName",
|
|
30
|
-
type: "input",
|
|
31
|
-
message: "\u9879\u76EE\u540D\u79F0",
|
|
32
|
-
suffix: ":"
|
|
33
|
-
});
|
|
34
|
-
const projectName2 = kebabCase(result.projectName);
|
|
35
|
-
const absolutePath = path.posix.resolve(projectName2);
|
|
36
|
-
if (existsSync(absolutePath) && argv2["force"] !== true) {
|
|
37
|
-
const { goon } = await inquirer2.prompt({
|
|
38
|
-
name: "goon",
|
|
39
|
-
type: "confirm",
|
|
40
|
-
message: `\u76EE\u5F55 "${absolutePath}" \u5DF2\u7ECF\u5B58\u5728\uFF0C\u662F\u5426\u8986\u76D6\uFF1F`,
|
|
41
|
-
suffix: ":"
|
|
42
|
-
});
|
|
43
|
-
if (!goon) {
|
|
44
|
-
process.exit(0);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return projectName2;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
3
|
// src/index.ts
|
|
51
|
-
import
|
|
4
|
+
import path2 from "node:path/posix";
|
|
52
5
|
import yargsParser from "yargs-parser";
|
|
53
|
-
import { existsSync
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
54
7
|
import { cp, mkdir, rm } from "node:fs/promises";
|
|
55
8
|
import { Listr } from "listr2";
|
|
56
|
-
import {
|
|
57
|
-
import
|
|
9
|
+
import { styleText } from "node:util";
|
|
10
|
+
import { execSync, spawn } from "node:child_process";
|
|
58
11
|
|
|
59
12
|
// src/replace-variables.ts
|
|
60
13
|
import { readFile, writeFile } from "node:fs/promises";
|
|
61
|
-
import
|
|
14
|
+
import path from "node:path";
|
|
62
15
|
var replaceVariables = async (filename, variables) => {
|
|
63
|
-
const packageJSONFile =
|
|
16
|
+
const packageJSONFile = path.resolve(filename);
|
|
64
17
|
let packageContent = await readFile(packageJSONFile, "utf8");
|
|
65
18
|
Object.entries(variables).forEach(([key, value]) => {
|
|
66
19
|
packageContent = packageContent.replaceAll(`{{${key}}}`, value);
|
|
@@ -69,28 +22,49 @@ var replaceVariables = async (filename, variables) => {
|
|
|
69
22
|
};
|
|
70
23
|
|
|
71
24
|
// src/index.ts
|
|
25
|
+
import kebabCase from "lodash.kebabcase";
|
|
72
26
|
var argv = yargsParser(process.argv.slice(2));
|
|
73
|
-
var
|
|
74
|
-
var
|
|
75
|
-
var
|
|
76
|
-
|
|
77
|
-
|
|
27
|
+
var templateDir = path2.join(import.meta.dirname, "..", "templates");
|
|
28
|
+
var projectName = kebabCase(argv["project"] || "my-aomex-project");
|
|
29
|
+
var targetDir = path2.resolve(projectName);
|
|
30
|
+
if (existsSync(targetDir)) {
|
|
31
|
+
console.error(styleText("red", `\u76EE\u5F55 "${targetDir}" \u5DF2\u5B58\u5728\uFF01`));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
var packageManager = "npm";
|
|
35
|
+
for (const item of ["pnpm", "npm", "yarn"]) {
|
|
36
|
+
if (argv[item]) {
|
|
37
|
+
packageManager = item;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
var runShell = async (command) => {
|
|
42
|
+
await new Promise((resolve, reject) => {
|
|
43
|
+
const stream = spawn(command, {
|
|
44
|
+
cwd: process.cwd(),
|
|
45
|
+
env: process.env,
|
|
46
|
+
shell: true
|
|
47
|
+
});
|
|
48
|
+
stream.on("close", resolve);
|
|
49
|
+
stream.on("error", reject);
|
|
50
|
+
});
|
|
51
|
+
};
|
|
78
52
|
var sleep = () => new Promise((resolve) => setTimeout(resolve, 500));
|
|
79
53
|
var spinner = new Listr([]);
|
|
80
54
|
spinner.add({
|
|
81
55
|
title: "\u521B\u5EFA\u76EE\u5F55",
|
|
82
56
|
task: async () => {
|
|
83
|
-
if (
|
|
57
|
+
if (existsSync(targetDir)) {
|
|
84
58
|
await rm(targetDir, { recursive: true, force: true });
|
|
85
59
|
}
|
|
86
60
|
await mkdir(targetDir, { recursive: true });
|
|
87
|
-
process.chdir(
|
|
61
|
+
process.chdir(path2.resolve(projectName));
|
|
88
62
|
}
|
|
89
63
|
});
|
|
90
64
|
spinner.add({
|
|
91
65
|
title: "git\u521D\u59CB\u5316",
|
|
92
66
|
task: async () => {
|
|
93
|
-
await
|
|
67
|
+
await runShell("git init");
|
|
94
68
|
await sleep();
|
|
95
69
|
}
|
|
96
70
|
});
|
|
@@ -106,12 +80,12 @@ spinner.add({
|
|
|
106
80
|
spinner.add({
|
|
107
81
|
title: "\u589E\u52A0volta\u914D\u7F6E",
|
|
108
82
|
skip: async () => {
|
|
109
|
-
return !/\d\.\d/.test((
|
|
83
|
+
return !/\d\.\d/.test(execSync("volta -v", { encoding: "utf8" }));
|
|
110
84
|
},
|
|
111
85
|
task: async () => {
|
|
112
|
-
await
|
|
86
|
+
await runShell("volta pin node");
|
|
113
87
|
if (packageManager !== "npm") {
|
|
114
|
-
await
|
|
88
|
+
await runShell(`volta pin ${packageManager}`);
|
|
115
89
|
}
|
|
116
90
|
}
|
|
117
91
|
});
|
|
@@ -119,53 +93,70 @@ spinner.add({
|
|
|
119
93
|
title: "\u5B89\u88C5\u63D2\u4EF6",
|
|
120
94
|
task: async (_, task) => {
|
|
121
95
|
const packages = [
|
|
122
|
-
{
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
96
|
+
{
|
|
97
|
+
label: "dependencies",
|
|
98
|
+
pkgs: [
|
|
99
|
+
"@aomex/core",
|
|
100
|
+
"@aomex/web",
|
|
101
|
+
"@aomex/router",
|
|
102
|
+
"@aomex/cors",
|
|
103
|
+
"@aomex/etag",
|
|
104
|
+
"@aomex/compress",
|
|
105
|
+
"@aomex/http-logger",
|
|
106
|
+
"@aomex/response-time",
|
|
107
|
+
"@aomex/console",
|
|
108
|
+
"@aomex/commander",
|
|
109
|
+
"@aomex/cron",
|
|
110
|
+
"@aomex/helmet",
|
|
111
|
+
"@aomex/openapi",
|
|
112
|
+
"@prisma/client",
|
|
113
|
+
// prisma不会直接导入代码,但是需要在生产环境中生成代码。
|
|
114
|
+
// 导致devDependencies被忽略的场景:
|
|
115
|
+
// 1. pnpm install --production
|
|
116
|
+
// 2. NODE_ENV='production'
|
|
117
|
+
"prisma"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
label: "dev dependencies",
|
|
122
|
+
pkgs: [
|
|
123
|
+
"typescript",
|
|
124
|
+
"tsx",
|
|
125
|
+
"tsc-alias",
|
|
126
|
+
"@types/node",
|
|
127
|
+
"husky",
|
|
128
|
+
"prettier",
|
|
129
|
+
"@commitlint/cli",
|
|
130
|
+
"@commitlint/config-conventional",
|
|
131
|
+
"eslint",
|
|
132
|
+
"@typescript-eslint/eslint-plugin",
|
|
133
|
+
"@typescript-eslint/parser",
|
|
134
|
+
"eslint-plugin-check-file"
|
|
135
|
+
],
|
|
136
|
+
dev: true
|
|
137
|
+
}
|
|
146
138
|
];
|
|
147
139
|
const action = packageManager === "npm" ? "install" : "add";
|
|
148
140
|
const devSuffix = packageManager === "npm" ? "--save-dev" : "-D";
|
|
149
141
|
for (let i = 0; i < packages.length; ++i) {
|
|
150
|
-
const {
|
|
151
|
-
task.title = "\u5B89\u88C5\u63D2\u4EF6 " + styleText("gray",
|
|
152
|
-
await
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
142
|
+
const { pkgs, dev, label } = packages[i];
|
|
143
|
+
task.title = "\u5B89\u88C5\u63D2\u4EF6 " + styleText("gray", label);
|
|
144
|
+
await runShell(
|
|
145
|
+
`${packageManager} ${action} ${pkgs.join(" ")} ${dev ? devSuffix : ""}`
|
|
146
|
+
);
|
|
156
147
|
}
|
|
157
148
|
task.title = "\u5B89\u88C5\u63D2\u4EF6";
|
|
158
149
|
}
|
|
159
150
|
});
|
|
160
151
|
spinner.add({
|
|
161
|
-
title: "\u751F\u6210prisma
|
|
152
|
+
title: "\u751F\u6210prisma\u5BA2\u6237\u7AEF",
|
|
162
153
|
task: async () => {
|
|
163
|
-
await
|
|
154
|
+
await runShell("npx prisma generate");
|
|
164
155
|
await sleep();
|
|
165
156
|
}
|
|
166
157
|
});
|
|
167
158
|
await spinner.run();
|
|
168
159
|
console.log(
|
|
169
|
-
"\n\u9879\u76EE\u521B\u5EFA\u6210\u529F\uFF1A" + styleText(["blue", "underline"], process.cwd()) + "\n"
|
|
160
|
+
"\n\u9879\u76EE\u521B\u5EFA\u6210\u529F\uFF1A" + styleText(["blue", "underline"], process.cwd()) + "\n\u542F\u52A8\u9879\u76EE\u53EF\u6267\u884C\u5982\u4E0B\u6307\u4EE4\uFF1A\n\n" + styleText("green", `cd ${projectName} && ${packageManager} start`) + "\n"
|
|
170
161
|
);
|
|
171
162
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/replace-variables.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport path from 'node:path/posix';\nimport yargsParser from 'yargs-parser';\nimport { existsSync } from 'node:fs';\nimport { cp, mkdir, rm } from 'node:fs/promises';\nimport { Listr } from 'listr2';\nimport { styleText } from 'node:util';\nimport { execSync, spawn } from 'node:child_process';\nimport { replaceVariables } from './replace-variables';\nimport kebabCase from 'lodash.kebabcase';\n\nconst argv = yargsParser(process.argv.slice(2));\nconst templateDir = path.join(import.meta.dirname, '..', 'templates');\n\nconst projectName = kebabCase(argv['project'] || 'my-aomex-project');\nconst targetDir = path.resolve(projectName);\nif (existsSync(targetDir)) {\n console.error(styleText('red', `目录 \"${targetDir}\" 已存在!`));\n process.exit(1);\n}\n\nlet packageManager = 'npm';\nfor (const item of <const>['pnpm', 'npm', 'yarn']) {\n if (argv[item]) {\n packageManager = item;\n break;\n }\n}\n\nconst runShell = async (command: string) => {\n await new Promise((resolve, reject) => {\n const stream = spawn(command, {\n cwd: process.cwd(),\n env: process.env,\n shell: true,\n });\n stream.on('close', resolve);\n stream.on('error', reject);\n });\n};\nconst sleep = () => new Promise((resolve) => setTimeout(resolve, 500));\n\nconst spinner = new Listr([]);\n\nspinner.add({\n title: '创建目录',\n task: async () => {\n if (existsSync(targetDir)) {\n await rm(targetDir, { recursive: true, force: true });\n }\n await mkdir(targetDir, { recursive: true });\n process.chdir(path.resolve(projectName));\n },\n});\n\nspinner.add({\n title: 'git初始化',\n task: async () => {\n await runShell('git init');\n await sleep();\n },\n});\n\nspinner.add({\n title: '复制模板文件',\n task: async () => {\n await cp(templateDir, targetDir, { recursive: true });\n await replaceVariables('package.json', { projectName, packageManager });\n await replaceVariables('README.md', { projectName, packageManager });\n await sleep();\n },\n});\n\nspinner.add({\n title: '增加volta配置',\n skip: async () => {\n return !/\\d\\.\\d/.test(execSync('volta -v', { encoding: 'utf8' }));\n },\n task: async () => {\n await runShell('volta pin node');\n if (packageManager !== 'npm') {\n await runShell(`volta pin ${packageManager}`);\n }\n },\n});\n\nspinner.add({\n title: '安装插件',\n task: async (_, task) => {\n const packages: { label: string; pkgs: string[]; dev?: boolean }[] = [\n {\n label: 'dependencies',\n pkgs: [\n '@aomex/core',\n '@aomex/web',\n '@aomex/router',\n '@aomex/cors',\n '@aomex/etag',\n '@aomex/compress',\n '@aomex/http-logger',\n '@aomex/response-time',\n '@aomex/console',\n '@aomex/commander',\n '@aomex/cron',\n '@aomex/helmet',\n '@aomex/openapi',\n '@prisma/client',\n // prisma不会直接导入代码,但是需要在生产环境中生成代码。\n // 导致devDependencies被忽略的场景:\n // 1. pnpm install --production\n // 2. NODE_ENV='production'\n 'prisma',\n ],\n },\n {\n label: 'dev dependencies',\n pkgs: [\n 'typescript',\n 'tsx',\n 'tsc-alias',\n '@types/node',\n 'husky',\n 'prettier',\n '@commitlint/cli',\n '@commitlint/config-conventional',\n 'eslint',\n '@typescript-eslint/eslint-plugin',\n '@typescript-eslint/parser',\n 'eslint-plugin-check-file',\n ],\n dev: true,\n },\n ];\n const action = packageManager === 'npm' ? 'install' : 'add';\n const devSuffix = packageManager === 'npm' ? '--save-dev' : '-D';\n\n for (let i = 0; i < packages.length; ++i) {\n const { pkgs, dev, label } = packages[i]!;\n task.title = '安装插件 ' + styleText('gray', label);\n await runShell(\n `${packageManager} ${action} ${pkgs.join(' ')} ${dev ? devSuffix : ''}`,\n );\n }\n task.title = '安装插件';\n },\n});\n\nspinner.add({\n title: '生成prisma客户端',\n task: async () => {\n await runShell('npx prisma generate');\n await sleep();\n },\n});\n\nawait spinner.run();\n\nconsole.log(\n '\\n项目创建成功:' +\n styleText(['blue', 'underline'], process.cwd()) +\n '\\n' +\n '启动项目可执行如下指令:' +\n '\\n\\n' +\n styleText('green', `cd ${projectName} && ${packageManager} start`) +\n '\\n',\n);\n","import { readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nexport const replaceVariables = async (\n filename: string,\n variables: Record<string, string>,\n) => {\n const packageJSONFile = path.resolve(filename);\n let packageContent = await readFile(packageJSONFile, 'utf8');\n Object.entries(variables).forEach(([key, value]) => {\n packageContent = packageContent.replaceAll(`{{${key}}}`, value);\n });\n await writeFile(packageJSONFile, packageContent);\n};\n"],"mappings":"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","names":["path","path"]}
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-aomex",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"repository": "git@github.com:aomex/create-aomex.git",
|
|
5
5
|
"author": "geekact <fanwenhua1990@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"cli": "tsx src/index.ts",
|
|
9
|
+
"cli": "tsx src/index.ts --project=abc --pnpm",
|
|
10
10
|
"release": "release-it --ci",
|
|
11
11
|
"build": "tsup",
|
|
12
|
-
"prepublishOnly": "
|
|
12
|
+
"prepublishOnly": "tsup"
|
|
13
13
|
},
|
|
14
14
|
"volta": {
|
|
15
15
|
"node": "20.15.0",
|
|
16
16
|
"pnpm": "9.4.0"
|
|
17
17
|
},
|
|
18
18
|
"engines": {
|
|
19
|
-
"node": ">=20"
|
|
19
|
+
"node": ">=20.13.0"
|
|
20
20
|
},
|
|
21
21
|
"publishConfig": {
|
|
22
22
|
"access": "public"
|
|
@@ -31,23 +31,24 @@
|
|
|
31
31
|
"bin": "dist/index.js",
|
|
32
32
|
"packageManager": "pnpm@9.4.0",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"inquirer": "^9.2.23",
|
|
35
34
|
"listr2": "^8.2.3",
|
|
36
35
|
"lodash.kebabcase": "^4.1.1",
|
|
37
36
|
"yargs-parser": "^21.1.1"
|
|
38
37
|
},
|
|
39
38
|
"devDependencies": {
|
|
40
|
-
"@aomex/commander": "^1.0.
|
|
41
|
-
"@aomex/compress": "^1.0.
|
|
42
|
-
"@aomex/console": "^1.0.
|
|
43
|
-
"@aomex/core": "^1.0.
|
|
44
|
-
"@aomex/cors": "^1.0.
|
|
45
|
-
"@aomex/
|
|
46
|
-
"@aomex/
|
|
47
|
-
"@aomex/
|
|
48
|
-
"@aomex/
|
|
49
|
-
"@aomex/
|
|
50
|
-
"@aomex/
|
|
39
|
+
"@aomex/commander": "^1.0.5",
|
|
40
|
+
"@aomex/compress": "^1.0.5",
|
|
41
|
+
"@aomex/console": "^1.0.5",
|
|
42
|
+
"@aomex/core": "^1.0.5",
|
|
43
|
+
"@aomex/cors": "^1.0.5",
|
|
44
|
+
"@aomex/cron": "^1.3.0",
|
|
45
|
+
"@aomex/etag": "^1.0.5",
|
|
46
|
+
"@aomex/helmet": "^1.0.5",
|
|
47
|
+
"@aomex/http-logger": "^1.0.5",
|
|
48
|
+
"@aomex/openapi": "^1.0.5",
|
|
49
|
+
"@aomex/response-time": "^1.3.0",
|
|
50
|
+
"@aomex/router": "^1.0.5",
|
|
51
|
+
"@aomex/web": "^1.0.5",
|
|
51
52
|
"@prisma/client": "^5.16.0",
|
|
52
53
|
"@types/inquirer": "^9.0.7",
|
|
53
54
|
"@types/lodash.kebabcase": "^4.1.9",
|
package/templates/.env
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
DATABASE_URL="mysql://
|
|
1
|
+
DATABASE_URL="mysql://root:123456@localhost:3306/demo_db"
|
|
@@ -15,12 +15,3 @@ model User {
|
|
|
15
15
|
created_at DateTime @default(now()) @db.DateTime(0)
|
|
16
16
|
updated_at DateTime @default(now()) @updatedAt @db.DateTime(0)
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
model Post {
|
|
20
|
-
id Int @id @default(autoincrement())
|
|
21
|
-
user_id Int
|
|
22
|
-
title String
|
|
23
|
-
content String @db.Text()
|
|
24
|
-
created_at DateTime @default(now()) @db.DateTime(0)
|
|
25
|
-
updated_at DateTime @default(now()) @updatedAt @db.DateTime(0)
|
|
26
|
-
}
|
package/templates/src/cli.ts
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
import { ConsoleApp } from '@aomex/console';
|
|
2
|
-
import {
|
|
2
|
+
import { commanders } from '@aomex/commander';
|
|
3
|
+
import { openapi } from '@aomex/openapi';
|
|
4
|
+
import { cron } from '@aomex/cron';
|
|
3
5
|
|
|
4
6
|
const app = new ConsoleApp({
|
|
5
7
|
locale: 'zh_CN',
|
|
6
|
-
mount:
|
|
8
|
+
mount: [
|
|
9
|
+
openapi({
|
|
10
|
+
routers: './src/routers',
|
|
11
|
+
docs: {
|
|
12
|
+
servers: [{ url: 'http://localhost:3000', description: 'Local' }],
|
|
13
|
+
},
|
|
14
|
+
}),
|
|
15
|
+
cron({
|
|
16
|
+
path: './src/commanders',
|
|
17
|
+
// store: RedisCache,
|
|
18
|
+
}),
|
|
19
|
+
commanders('./src/commanders'),
|
|
20
|
+
],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
app.on('error', (err) => {
|
|
24
|
+
// 上报错误日志
|
|
25
|
+
app.log(err);
|
|
7
26
|
});
|
|
8
27
|
|
|
9
28
|
await app.run();
|
|
10
29
|
process.exit(0);
|
|
30
|
+
|
|
31
|
+
declare module '@aomex/console' {
|
|
32
|
+
namespace ConsoleApp {
|
|
33
|
+
type T = ConsoleApp.Infer<typeof app>;
|
|
34
|
+
interface Props extends T {}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
import { Commander } from '@aomex/commander';
|
|
2
|
-
import {
|
|
2
|
+
import { options } from '@aomex/console';
|
|
3
|
+
import { rule } from '@aomex/core';
|
|
3
4
|
|
|
4
|
-
export const commander = new Commander(
|
|
5
|
-
mount: commanderChain,
|
|
6
|
-
});
|
|
5
|
+
export const commander = new Commander();
|
|
7
6
|
|
|
7
|
+
// npx aomex hello
|
|
8
|
+
// npx aomex hello --user World
|
|
9
|
+
// npx aomex hello -u aomex.js
|
|
8
10
|
commander.create('hello', {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
mount: [
|
|
12
|
+
options(
|
|
13
|
+
{
|
|
14
|
+
user: rule.string().default('World'),
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
user: ['u'],
|
|
18
|
+
},
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
action: async (ctx) => {
|
|
22
|
+
const { user } = ctx.options;
|
|
23
|
+
console.log(`Hello ${user}`);
|
|
11
24
|
},
|
|
12
25
|
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Commander } from '@aomex/commander';
|
|
2
|
+
import { options } from '@aomex/console';
|
|
3
|
+
import { rule } from '@aomex/core';
|
|
4
|
+
import { schedule } from '@aomex/cron';
|
|
5
|
+
|
|
6
|
+
export const commander = new Commander();
|
|
7
|
+
|
|
8
|
+
// npx aomex cron:start
|
|
9
|
+
commander.create('schedule', {
|
|
10
|
+
mount: [
|
|
11
|
+
schedule({
|
|
12
|
+
second: '*/5',
|
|
13
|
+
}),
|
|
14
|
+
schedule({
|
|
15
|
+
second: '*/8',
|
|
16
|
+
args: ['--user', 'aomex.js'],
|
|
17
|
+
}),
|
|
18
|
+
options({
|
|
19
|
+
user: rule.string().default('World'),
|
|
20
|
+
}),
|
|
21
|
+
],
|
|
22
|
+
action: async (ctx) => {
|
|
23
|
+
const { user } = ctx.options;
|
|
24
|
+
console.log(`Hello ${user}`);
|
|
25
|
+
await new Promise((resolve) => {
|
|
26
|
+
setTimeout(resolve, 2_000);
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
commander.create('long:schedule', {
|
|
32
|
+
mount: [
|
|
33
|
+
schedule({
|
|
34
|
+
second: '*/10',
|
|
35
|
+
overlap: true,
|
|
36
|
+
}),
|
|
37
|
+
],
|
|
38
|
+
action: async () => {
|
|
39
|
+
await new Promise((resolve) => {
|
|
40
|
+
setTimeout(resolve, 15_000);
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -1,18 +1,45 @@
|
|
|
1
1
|
import { Router } from '@aomex/router';
|
|
2
|
-
import {
|
|
2
|
+
import { services } from '../services';
|
|
3
|
+
import { body, params } from '@aomex/web';
|
|
4
|
+
import { rule } from '@aomex/core';
|
|
3
5
|
|
|
4
6
|
export const router = new Router({
|
|
5
|
-
|
|
7
|
+
prefix: '/users',
|
|
6
8
|
});
|
|
7
9
|
|
|
8
10
|
router.get('/', {
|
|
9
|
-
async
|
|
10
|
-
|
|
11
|
+
action: async (ctx) => {
|
|
12
|
+
const users = await services.user.findAll();
|
|
13
|
+
ctx.send(200, users);
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
router.get('/:id', {
|
|
18
|
+
mount: [
|
|
19
|
+
params({
|
|
20
|
+
id: rule.int().min(1),
|
|
21
|
+
}),
|
|
22
|
+
],
|
|
23
|
+
action: async (ctx) => {
|
|
24
|
+
const { id } = ctx.params;
|
|
25
|
+
const user = await services.user.findById(id);
|
|
26
|
+
if (!user) {
|
|
27
|
+
ctx.throw(404, 'user not found');
|
|
28
|
+
}
|
|
29
|
+
ctx.send(user);
|
|
11
30
|
},
|
|
12
31
|
});
|
|
13
32
|
|
|
14
33
|
router.post('/', {
|
|
15
|
-
|
|
16
|
-
|
|
34
|
+
mount: [
|
|
35
|
+
body({
|
|
36
|
+
name: rule.string(),
|
|
37
|
+
age: rule.number(),
|
|
38
|
+
}),
|
|
39
|
+
],
|
|
40
|
+
action: async (ctx) => {
|
|
41
|
+
const { name, age } = ctx.body;
|
|
42
|
+
await services.user.createUser(name, age);
|
|
43
|
+
ctx.send(201);
|
|
17
44
|
},
|
|
18
45
|
});
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import { Service } from '@aomex/core';
|
|
2
2
|
import { db } from './db';
|
|
3
|
+
import { Prisma } from '@prisma/client';
|
|
3
4
|
|
|
4
5
|
export class UserService extends Service {
|
|
5
6
|
findAll() {
|
|
6
|
-
return db.user.
|
|
7
|
+
return db.user.findMany({
|
|
8
|
+
orderBy: [
|
|
9
|
+
{
|
|
10
|
+
id: Prisma.SortOrder.desc,
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
});
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
findById(userId: number) {
|
|
10
17
|
return db.user.findUnique({ where: { id: userId } });
|
|
11
18
|
}
|
|
19
|
+
|
|
20
|
+
async createUser(name: string, age: number) {
|
|
21
|
+
await db.user.create({
|
|
22
|
+
data: {
|
|
23
|
+
name,
|
|
24
|
+
age,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
12
28
|
}
|
package/templates/src/web.ts
CHANGED
|
@@ -1,11 +1,42 @@
|
|
|
1
1
|
import { WebApp } from '@aomex/web';
|
|
2
|
-
import {
|
|
2
|
+
import { cors } from '@aomex/cors';
|
|
3
|
+
import { compress } from '@aomex/compress';
|
|
4
|
+
import { httpLogger } from '@aomex/http-logger';
|
|
5
|
+
import { etag } from '@aomex/etag';
|
|
6
|
+
import { routers } from '@aomex/router';
|
|
7
|
+
import { helmet } from '@aomex/helmet';
|
|
8
|
+
import { responseTime } from '@aomex/response-time';
|
|
3
9
|
|
|
4
10
|
export const app = new WebApp({
|
|
5
11
|
locale: 'zh_CN',
|
|
6
|
-
mount:
|
|
12
|
+
mount: [
|
|
13
|
+
responseTime,
|
|
14
|
+
cors(),
|
|
15
|
+
compress(),
|
|
16
|
+
httpLogger(),
|
|
17
|
+
etag(),
|
|
18
|
+
helmet(),
|
|
19
|
+
routers('./src/routers'),
|
|
20
|
+
],
|
|
7
21
|
});
|
|
8
22
|
|
|
9
|
-
app.
|
|
10
|
-
|
|
23
|
+
app.on('error', (err, ctx) => {
|
|
24
|
+
// 上报错误日志
|
|
25
|
+
app.log(err, ctx);
|
|
26
|
+
ctx.response.body = {
|
|
27
|
+
status: ctx.response.statusCode,
|
|
28
|
+
message: ctx.response.body,
|
|
29
|
+
};
|
|
11
30
|
});
|
|
31
|
+
|
|
32
|
+
const port = process.env['PORT'] || 3000;
|
|
33
|
+
app.listen(port, () => {
|
|
34
|
+
console.log(`服务已启动,点击 http://localhost:${port} 访问`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
declare module '@aomex/web' {
|
|
38
|
+
namespace WebApp {
|
|
39
|
+
type T = WebApp.Infer<typeof app>;
|
|
40
|
+
interface Props extends T {}
|
|
41
|
+
}
|
|
42
|
+
}
|
package/templates/tsconfig.json
CHANGED
|
@@ -22,9 +22,10 @@
|
|
|
22
22
|
"allowJs": false,
|
|
23
23
|
"checkJs": false,
|
|
24
24
|
"declaration": false,
|
|
25
|
-
"removeComments":
|
|
25
|
+
"removeComments": true,
|
|
26
26
|
"rootDir": "./",
|
|
27
|
-
"
|
|
27
|
+
"outDir": "build",
|
|
28
|
+
"noEmit": false,
|
|
28
29
|
"importHelpers": false,
|
|
29
30
|
"downlevelIteration": true,
|
|
30
31
|
"noImplicitAny": true,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { mdchain } from '@aomex/core';
|
|
2
|
-
import { openapiGenerator } from './openapi.md';
|
|
3
|
-
import { commanders } from '@aomex/commander';
|
|
4
|
-
|
|
5
|
-
export const appChain = mdchain.console
|
|
6
|
-
.mount(openapiGenerator)
|
|
7
|
-
.mount(commanders('./src/commanders'));
|
|
8
|
-
|
|
9
|
-
export const commanderChain = appChain.mount(null);
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { mdchain } from '@aomex/core';
|
|
2
|
-
import { cors } from '@aomex/cors';
|
|
3
|
-
import { compress } from '@aomex/compress';
|
|
4
|
-
import { routers } from '@aomex/router';
|
|
5
|
-
import { httpLogger } from '@aomex/http-logger';
|
|
6
|
-
import { helmet } from '@aomex/helmet';
|
|
7
|
-
import { etag } from '@aomex/etag';
|
|
8
|
-
|
|
9
|
-
export const appChain = mdchain.web
|
|
10
|
-
.mount(cors())
|
|
11
|
-
.mount(compress())
|
|
12
|
-
.mount(httpLogger())
|
|
13
|
-
.mount(etag())
|
|
14
|
-
.mount(helmet())
|
|
15
|
-
.mount(routers('./src/routers'));
|
|
16
|
-
|
|
17
|
-
export const routerChain = appChain;
|