create-aomex 0.0.4 → 0.0.6

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 CHANGED
@@ -31,6 +31,7 @@ if (existsSync(targetDir)) {
31
31
  console.error(styleText("red", `\u76EE\u5F55 "${targetDir}" \u5DF2\u5B58\u5728\uFF01`));
32
32
  process.exit(1);
33
33
  }
34
+ var nodeVersion = process.versions.node;
34
35
  var packageManager = "npm";
35
36
  for (const item of ["pnpm", "npm", "yarn"]) {
36
37
  if (argv[item]) {
@@ -71,9 +72,15 @@ spinner.add({
71
72
  spinner.add({
72
73
  title: "\u590D\u5236\u6A21\u677F\u6587\u4EF6",
73
74
  task: async () => {
75
+ const variables = {
76
+ projectName,
77
+ packageManager,
78
+ nodeVersion
79
+ };
74
80
  await cp(templateDir, targetDir, { recursive: true });
75
- await replaceVariables("package.json", { projectName, packageManager });
76
- await replaceVariables("README.md", { projectName, packageManager });
81
+ await replaceVariables("package.json", variables);
82
+ await replaceVariables("README.md", variables);
83
+ await replaceVariables("Dockerfile", variables);
77
84
  await sleep();
78
85
  }
79
86
  });
@@ -83,7 +90,7 @@ spinner.add({
83
90
  return !/\d\.\d/.test(execSync("volta -v", { encoding: "utf8" }));
84
91
  },
85
92
  task: async () => {
86
- await runShell("volta pin node");
93
+ await runShell(`volta pin node@${nodeVersion}`);
87
94
  if (packageManager !== "npm") {
88
95
  await runShell(`volta pin ${packageManager}`);
89
96
  }
@@ -109,17 +116,14 @@ spinner.add({
109
116
  "@aomex/cron",
110
117
  "@aomex/helmet",
111
118
  "@aomex/openapi",
112
- "@prisma/client",
113
- // prisma不会直接导入代码,但是需要在生产环境中生成代码。
114
- // 导致devDependencies被忽略的场景:
115
- // 1. pnpm install --production
116
- // 2. NODE_ENV='production'
117
- "prisma"
119
+ "@aomex/async-trace",
120
+ "@prisma/client"
118
121
  ]
119
122
  },
120
123
  {
121
124
  label: "dev dependencies",
122
125
  pkgs: [
126
+ "prisma",
123
127
  "typescript",
124
128
  "tsx",
125
129
  "tsc-alias",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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"]}
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}\nconst nodeVersion = process.versions.node;\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 const variables = {\n projectName,\n packageManager,\n nodeVersion,\n };\n await cp(templateDir, targetDir, { recursive: true });\n await replaceVariables('package.json', variables);\n await replaceVariables('README.md', variables);\n await replaceVariables('Dockerfile', variables);\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@${nodeVersion}`);\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 '@aomex/async-trace',\n '@prisma/client',\n ],\n },\n {\n label: 'dev dependencies',\n pkgs: [\n 'prisma',\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,6 +1,6 @@
1
1
  {
2
2
  "name": "create-aomex",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "repository": "git@github.com:aomex/create-aomex.git",
5
5
  "author": "geekact <fanwenhua1990@gmail.com>",
6
6
  "license": "MIT",
@@ -36,6 +36,7 @@
36
36
  "yargs-parser": "^21.1.1"
37
37
  },
38
38
  "devDependencies": {
39
+ "@aomex/async-trace": "^1.3.0",
39
40
  "@aomex/commander": "^1.0.5",
40
41
  "@aomex/compress": "^1.0.5",
41
42
  "@aomex/console": "^1.0.5",
@@ -50,7 +51,6 @@
50
51
  "@aomex/router": "^1.0.5",
51
52
  "@aomex/web": "^1.0.5",
52
53
  "@prisma/client": "^5.16.0",
53
- "@types/inquirer": "^9.0.7",
54
54
  "@types/lodash.kebabcase": "^4.1.9",
55
55
  "@types/node": "^20.14.8",
56
56
  "@types/yargs-parser": "^21.0.3",
@@ -0,0 +1,10 @@
1
+ FROM node:{{nodeVersion}}
2
+ COPY . /codes
3
+ WORKDIR /codes
4
+ RUN sh scripts/docker-build.sh
5
+ RUN mv .env.production .env
6
+
7
+ ENV TZ=Asia/Shanghai
8
+ ENV PORT=3000
9
+ ENV NODE_ENV=production
10
+ CMD ["node", "--enable-source-maps", "src/web.js"]
@@ -0,0 +1,18 @@
1
+ services:
2
+ mysql:
3
+ image: mysql:8
4
+ environment:
5
+ # 对应 .env 文件的配置
6
+ MYSQL_DATABASE: demo_db
7
+ MYSQL_ROOT_PASSWORD: 123456
8
+ volumes:
9
+ - ./volumes/mysql:/var/lib/mysql
10
+ ports:
11
+ - 3306:3306
12
+ command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --explicit_defaults_for_timestamp=true
13
+ redis:
14
+ image: redis:7
15
+ volumes:
16
+ - ./volumes/redis:/data
17
+ ports:
18
+ - 6379:6379
@@ -3,10 +3,13 @@
3
3
  "private": true,
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
+ "engines": {
7
+ "node": "{{nodeVersion}}"
8
+ },
6
9
  "scripts": {
7
- "start": "node --import tsx/esm --watch src/web.ts",
10
+ "start": "docker compose -f docker-local.yml up -d && {{packageManager}} install && prisma generate && prisma db push && node --import tsx/esm --watch src/web.ts",
8
11
  "build": "tsc && tsc-alias --resolve-full-paths",
9
- "prepare": "husky",
12
+ "prepare": "npx husky",
10
13
  "preinstall": "npx only-allow {{packageManager}}"
11
14
  }
12
15
  }
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env sh
2
+
3
+ set -ex
4
+
5
+ corepack enable
6
+ pnpm install
7
+ npx prisma generate
8
+ npx tsc && npx tsc-alias --resolve-full-paths
9
+ rm -rf src
10
+ mv build/src .
11
+ pnpm install --prod --ignore-scripts
@@ -2,20 +2,25 @@ import { ConsoleApp } from '@aomex/console';
2
2
  import { commanders } from '@aomex/commander';
3
3
  import { openapi } from '@aomex/openapi';
4
4
  import { cron } from '@aomex/cron';
5
+ import { traceMiddleware } from '@aomex/async-trace';
5
6
 
6
7
  const app = new ConsoleApp({
7
8
  locale: 'zh_CN',
8
9
  mount: [
10
+ cron({
11
+ path: './src/commanders',
12
+ // store: RedisCache,
13
+ }),
14
+ traceMiddleware('生命周期', async (record) => {
15
+ // 根据 record.delta 上报慢日志
16
+ // console.log(record);
17
+ }),
9
18
  openapi({
10
19
  routers: './src/routers',
11
20
  docs: {
12
21
  servers: [{ url: 'http://localhost:3000', description: 'Local' }],
13
22
  },
14
23
  }),
15
- cron({
16
- path: './src/commanders',
17
- // store: RedisCache,
18
- }),
19
24
  commanders('./src/commanders'),
20
25
  ],
21
26
  });
@@ -25,8 +30,8 @@ app.on('error', (err) => {
25
30
  app.log(err);
26
31
  });
27
32
 
28
- await app.run();
29
- process.exit(0);
33
+ const code = await app.run();
34
+ process.exit(code);
30
35
 
31
36
  declare module '@aomex/console' {
32
37
  namespace ConsoleApp {
@@ -34,3 +39,6 @@ declare module '@aomex/console' {
34
39
  interface Props extends T {}
35
40
  }
36
41
  }
42
+ function traceMiddleware(arg0: string, arg1: (record: any) => Promise<void>): any {
43
+ throw new Error('Function not implemented.');
44
+ }
@@ -0,0 +1,7 @@
1
+ import type { Config } from './production';
2
+ import { integration } from './integration';
3
+
4
+ // 本地开发环境,对应随意git分支
5
+ export const development: Config = {
6
+ ...integration,
7
+ };
@@ -0,0 +1,12 @@
1
+ import { production, type Config } from './production';
2
+ import { integration } from './integration';
3
+ import { development } from './development';
4
+
5
+ const configs = {
6
+ production,
7
+ integration,
8
+ development,
9
+ };
10
+
11
+ export const config: Config =
12
+ configs[(process.env['NODE_ENV'] || 'development') as keyof typeof configs];
@@ -0,0 +1,6 @@
1
+ import { production, type Config } from './production';
2
+
3
+ // 线上集成环境,用于功能、交互测试。对应 develop 分支
4
+ export const integration: Config = {
5
+ ...production,
6
+ };
@@ -0,0 +1,4 @@
1
+ // 正式环境。对应 main 分支
2
+ export const production = {};
3
+
4
+ export type Config = typeof production;
@@ -1,9 +1,11 @@
1
1
  import { Service } from '@aomex/core';
2
2
  import { db } from './db';
3
3
  import { Prisma } from '@prisma/client';
4
+ import { traceMethod } from '@aomex/async-trace';
4
5
 
5
6
  export class UserService extends Service {
6
- findAll() {
7
+ @traceMethod('User.findAll')
8
+ async findAll() {
7
9
  return db.user.findMany({
8
10
  orderBy: [
9
11
  {
@@ -13,7 +15,8 @@ export class UserService extends Service {
13
15
  });
14
16
  }
15
17
 
16
- findById(userId: number) {
18
+ @traceMethod((userId) => `User.find(${userId})`)
19
+ async findById(userId: number) {
17
20
  return db.user.findUnique({ where: { id: userId } });
18
21
  }
19
22
 
@@ -6,11 +6,16 @@ import { etag } from '@aomex/etag';
6
6
  import { routers } from '@aomex/router';
7
7
  import { helmet } from '@aomex/helmet';
8
8
  import { responseTime } from '@aomex/response-time';
9
+ import { traceMiddleware } from '@aomex/async-trace';
9
10
 
10
11
  export const app = new WebApp({
11
12
  locale: 'zh_CN',
12
13
  mount: [
13
14
  responseTime,
15
+ traceMiddleware('生命周期', async (record) => {
16
+ // 根据 record.delta 上报慢日志
17
+ // console.log(record);
18
+ }),
14
19
  cors(),
15
20
  compress(),
16
21
  httpLogger(),
@@ -23,6 +23,7 @@
23
23
  "checkJs": false,
24
24
  "declaration": false,
25
25
  "removeComments": true,
26
+ "sourceMap": true,
26
27
  "rootDir": "./",
27
28
  "outDir": "build",
28
29
  "noEmit": false,