create-aomex 0.0.1 → 0.0.3
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.d.ts +1 -2
- package/dist/index.js +89 -96
- package/dist/index.js.map +1 -1
- package/package.json +17 -15
- 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.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { }
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
CHANGED
|
@@ -1,64 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
import inquirer from "inquirer";
|
|
3
|
-
var packageManagers = ["pnpm", "npm", "yarn"];
|
|
4
|
-
var inputPackageManager = async (argv2) => {
|
|
5
|
-
for (const expected of packageManagers) {
|
|
6
|
-
if (argv2[expected]) return expected;
|
|
7
|
-
}
|
|
8
|
-
const { manager } = await inquirer.prompt({
|
|
9
|
-
name: "manager",
|
|
10
|
-
message: "\u9009\u62E9\u5305\u7BA1\u7406\u5DE5\u5177",
|
|
11
|
-
type: "list",
|
|
12
|
-
choices: packageManagers,
|
|
13
|
-
default: "pnpm",
|
|
14
|
-
askAnswered: true
|
|
15
|
-
});
|
|
16
|
-
return manager;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// src/input-project-name.ts
|
|
20
|
-
import inquirer2 from "inquirer";
|
|
21
|
-
import kebabCase from "lodash.kebabcase";
|
|
22
|
-
import { existsSync } from "node:fs";
|
|
23
|
-
import path from "node:path";
|
|
24
|
-
var inputProjectName = async (argv2) => {
|
|
25
|
-
if (typeof argv2["name"] === "string") return argv2["name"];
|
|
26
|
-
const result = await inquirer2.prompt({
|
|
27
|
-
name: "projectName",
|
|
28
|
-
type: "input",
|
|
29
|
-
message: "\u9879\u76EE\u540D\u79F0",
|
|
30
|
-
suffix: ":"
|
|
31
|
-
});
|
|
32
|
-
const projectName2 = kebabCase(result.projectName);
|
|
33
|
-
const absolutePath = path.posix.resolve(projectName2);
|
|
34
|
-
if (existsSync(absolutePath) && argv2["force"] !== true) {
|
|
35
|
-
const { goon } = await inquirer2.prompt({
|
|
36
|
-
name: "goon",
|
|
37
|
-
type: "confirm",
|
|
38
|
-
message: `\u76EE\u5F55 "${absolutePath}" \u5DF2\u7ECF\u5B58\u5728\uFF0C\u662F\u5426\u8986\u76D6\uFF1F`,
|
|
39
|
-
suffix: ":"
|
|
40
|
-
});
|
|
41
|
-
if (!goon) {
|
|
42
|
-
process.exit(0);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return projectName2;
|
|
46
|
-
};
|
|
1
|
+
#!/usr/bin/env node
|
|
47
2
|
|
|
48
3
|
// src/index.ts
|
|
49
|
-
import
|
|
4
|
+
import path2 from "node:path/posix";
|
|
50
5
|
import yargsParser from "yargs-parser";
|
|
51
|
-
import { existsSync
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
52
7
|
import { cp, mkdir, rm } from "node:fs/promises";
|
|
53
8
|
import { Listr } from "listr2";
|
|
54
|
-
import {
|
|
55
|
-
import
|
|
9
|
+
import { styleText } from "node:util";
|
|
10
|
+
import { execSync, spawn } from "node:child_process";
|
|
56
11
|
|
|
57
12
|
// src/replace-variables.ts
|
|
58
13
|
import { readFile, writeFile } from "node:fs/promises";
|
|
59
|
-
import
|
|
14
|
+
import path from "node:path";
|
|
60
15
|
var replaceVariables = async (filename, variables) => {
|
|
61
|
-
const packageJSONFile =
|
|
16
|
+
const packageJSONFile = path.resolve(filename);
|
|
62
17
|
let packageContent = await readFile(packageJSONFile, "utf8");
|
|
63
18
|
Object.entries(variables).forEach(([key, value]) => {
|
|
64
19
|
packageContent = packageContent.replaceAll(`{{${key}}}`, value);
|
|
@@ -67,28 +22,49 @@ var replaceVariables = async (filename, variables) => {
|
|
|
67
22
|
};
|
|
68
23
|
|
|
69
24
|
// src/index.ts
|
|
25
|
+
import kebabCase from "lodash.kebabcase";
|
|
70
26
|
var argv = yargsParser(process.argv.slice(2));
|
|
71
|
-
var
|
|
72
|
-
var
|
|
73
|
-
var
|
|
74
|
-
|
|
75
|
-
|
|
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
|
+
};
|
|
76
52
|
var sleep = () => new Promise((resolve) => setTimeout(resolve, 500));
|
|
77
53
|
var spinner = new Listr([]);
|
|
78
54
|
spinner.add({
|
|
79
55
|
title: "\u521B\u5EFA\u76EE\u5F55",
|
|
80
56
|
task: async () => {
|
|
81
|
-
if (
|
|
57
|
+
if (existsSync(targetDir)) {
|
|
82
58
|
await rm(targetDir, { recursive: true, force: true });
|
|
83
59
|
}
|
|
84
60
|
await mkdir(targetDir, { recursive: true });
|
|
85
|
-
process.chdir(
|
|
61
|
+
process.chdir(path2.resolve(projectName));
|
|
86
62
|
}
|
|
87
63
|
});
|
|
88
64
|
spinner.add({
|
|
89
65
|
title: "git\u521D\u59CB\u5316",
|
|
90
66
|
task: async () => {
|
|
91
|
-
await
|
|
67
|
+
await runShell("git init");
|
|
92
68
|
await sleep();
|
|
93
69
|
}
|
|
94
70
|
});
|
|
@@ -104,12 +80,12 @@ spinner.add({
|
|
|
104
80
|
spinner.add({
|
|
105
81
|
title: "\u589E\u52A0volta\u914D\u7F6E",
|
|
106
82
|
skip: async () => {
|
|
107
|
-
return !/\d\.\d/.test((
|
|
83
|
+
return !/\d\.\d/.test(execSync("volta -v", { encoding: "utf8" }));
|
|
108
84
|
},
|
|
109
85
|
task: async () => {
|
|
110
|
-
await
|
|
86
|
+
await runShell("volta pin node");
|
|
111
87
|
if (packageManager !== "npm") {
|
|
112
|
-
await
|
|
88
|
+
await runShell(`volta pin ${packageManager}`);
|
|
113
89
|
}
|
|
114
90
|
}
|
|
115
91
|
});
|
|
@@ -117,53 +93,70 @@ spinner.add({
|
|
|
117
93
|
title: "\u5B89\u88C5\u63D2\u4EF6",
|
|
118
94
|
task: async (_, task) => {
|
|
119
95
|
const packages = [
|
|
120
|
-
{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
+
}
|
|
144
138
|
];
|
|
145
139
|
const action = packageManager === "npm" ? "install" : "add";
|
|
146
140
|
const devSuffix = packageManager === "npm" ? "--save-dev" : "-D";
|
|
147
141
|
for (let i = 0; i < packages.length; ++i) {
|
|
148
|
-
const {
|
|
149
|
-
task.title = "\u5B89\u88C5\u63D2\u4EF6 " + styleText("gray",
|
|
150
|
-
await
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
});
|
|
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
|
+
);
|
|
154
147
|
}
|
|
155
148
|
task.title = "\u5B89\u88C5\u63D2\u4EF6";
|
|
156
149
|
}
|
|
157
150
|
});
|
|
158
151
|
spinner.add({
|
|
159
|
-
title: "\u751F\u6210prisma
|
|
152
|
+
title: "\u751F\u6210prisma\u5BA2\u6237\u7AEF",
|
|
160
153
|
task: async () => {
|
|
161
|
-
await
|
|
154
|
+
await runShell("npx prisma generate");
|
|
162
155
|
await sleep();
|
|
163
156
|
}
|
|
164
157
|
});
|
|
165
158
|
await spinner.run();
|
|
166
159
|
console.log(
|
|
167
|
-
"\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"
|
|
168
161
|
);
|
|
169
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.3",
|
|
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"
|
|
@@ -37,17 +37,19 @@
|
|
|
37
37
|
"yargs-parser": "^21.1.1"
|
|
38
38
|
},
|
|
39
39
|
"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/
|
|
40
|
+
"@aomex/commander": "^1.0.5",
|
|
41
|
+
"@aomex/compress": "^1.0.5",
|
|
42
|
+
"@aomex/console": "^1.0.5",
|
|
43
|
+
"@aomex/core": "^1.0.5",
|
|
44
|
+
"@aomex/cors": "^1.0.5",
|
|
45
|
+
"@aomex/cron": "^1.3.0",
|
|
46
|
+
"@aomex/etag": "^1.0.5",
|
|
47
|
+
"@aomex/helmet": "^1.0.5",
|
|
48
|
+
"@aomex/http-logger": "^1.0.5",
|
|
49
|
+
"@aomex/openapi": "^1.0.5",
|
|
50
|
+
"@aomex/response-time": "^1.3.0",
|
|
51
|
+
"@aomex/router": "^1.0.5",
|
|
52
|
+
"@aomex/web": "^1.0.5",
|
|
51
53
|
"@prisma/client": "^5.16.0",
|
|
52
54
|
"@types/inquirer": "^9.0.7",
|
|
53
55
|
"@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;
|