create-aomex 0.0.28 → 0.0.30

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
@@ -20,8 +20,14 @@ import { setTimeout } from "node:timers/promises";
20
20
  import { terminal } from "@aomex/console";
21
21
  import { input } from "@inquirer/prompts";
22
22
  import { existsSync, readdirSync } from "node:fs";
23
- import kebabCase from "lodash.kebabcase";
23
+ import sanitize from "sanitize-filename";
24
24
  import path from "path";
25
+ var kebabCase = (value) => {
26
+ value = sanitize(value);
27
+ if (!value.length) return "";
28
+ value = value[0].toLowerCase() + value.slice(1);
29
+ return value.replace(/[A-Z]/g, (i) => "-" + i.toLowerCase()).replace(/_/g, "-").replace(/-+/g, "-");
30
+ };
25
31
  var inputProject = async (argv2) => {
26
32
  let projectName2 = argv2["project"];
27
33
  if (projectName2) {
@@ -41,6 +47,7 @@ var inputProject = async (argv2) => {
41
47
  return kebabCase(value);
42
48
  }
43
49
  });
50
+ projectName2 = kebabCase(projectName2);
44
51
  }
45
52
  return projectName2;
46
53
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/input-project.ts","../src/select-package-manager.ts","../src/select-node-version.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport path from 'node:path/posix';\nimport yargsParser from 'yargs-parser';\nimport {\n cp,\n mkdir,\n readdir,\n readFile,\n rename,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport { terminal } from '@aomex/console';\nimport { execSync, spawn } from 'node:child_process';\nimport { setTimeout } from 'node:timers/promises';\nimport { inputProject } from './input-project';\nimport { selectPackageManager } from './select-package-manager';\nimport { selectNodeVersion } from './select-node-version';\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};\n\nconst argv = yargsParser(process.argv.slice(2));\nconst templateDir = path.join(import.meta.dirname, '..', 'templates');\nconst projectName = await inputProject(argv);\nconst { packageManager, packageManagerVersion } = await selectPackageManager(\n argv,\n);\nconst nodeVersion = await selectNodeVersion(argv);\nconst targetDir = path.resolve(projectName);\n\nconst { error } = await terminal.runTasks([\n {\n title: '创建目录',\n task: async () => {\n await mkdir(targetDir, { recursive: true });\n process.chdir(targetDir);\n await setTimeout(500);\n },\n },\n {\n title: '复制模板文件',\n task: async () => {\n const variables = {\n projectName,\n packageManager,\n nodeVersion,\n packageManagerVersion,\n };\n await cp(templateDir, targetDir, { recursive: true });\n const files = await readdir(targetDir, { recursive: true });\n for (const file of files) {\n const isFile = (await stat(path.join(targetDir, file))).isFile();\n if (!isFile) continue;\n const fileAbsolutePath = path.resolve(file);\n let fileContent = await readFile(fileAbsolutePath, 'utf8');\n Object.entries(variables).forEach(([key, value]) => {\n fileContent = fileContent.replaceAll(`{{${key}}}`, value);\n });\n await writeFile(fileAbsolutePath, fileContent);\n }\n // .gitignore这个文件在安装的时候总是被忽略\n await rename(\n path.join(targetDir, 'gitignore'),\n path.join(targetDir, '.gitignore'),\n );\n await setTimeout(500);\n },\n },\n {\n title: 'git初始化',\n skip: async () => {\n return !/\\d\\.\\d/.test(execSync('git -v', { encoding: 'utf8' }));\n },\n task: async () => {\n await runShell('git init');\n await setTimeout(500);\n },\n },\n {\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}@${packageManagerVersion}`);\n }\n },\n },\n {\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/cors',\n '@aomex/etag',\n '@aomex/compress',\n '@aomex/http-logger',\n '@aomex/response-time',\n '@aomex/console',\n '@aomex/cron',\n '@aomex/helmet',\n '@aomex/openapi',\n '@aomex/swagger-ui',\n '@aomex/async-trace',\n '@prisma/client',\n '@aomex/cache',\n '@aomex/cache-redis-adapter',\n 'ioredis',\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.suffix = terminal.style('gray', label);\n await runShell(\n `${packageManager} ${action} ${pkgs.join(' ')} ${\n dev ? devSuffix : ''\n }`,\n );\n }\n task.suffix = '';\n },\n },\n {\n title: '生成prisma客户端',\n task: async () => {\n await runShell('npx prisma generate');\n },\n },\n]);\n\nif (error) process.exit(1);\n\nconsole.log(\n '\\n项目创建成功:' +\n terminal.style(['blue', 'underline'], process.cwd()) +\n '\\n' +\n '启动项目可执行如下指令:' +\n '\\n\\n' +\n terminal.style('green', `cd ${projectName} && ${packageManager} start`) +\n '\\n',\n);\n","import { terminal } from '@aomex/console';\nimport { input } from '@inquirer/prompts';\nimport { existsSync, readdirSync } from 'node:fs';\nimport kebabCase from 'lodash.kebabcase';\nimport path from 'path';\n\nexport const inputProject = async (argv: Record<string, any>) => {\n let projectName: string = argv['project'];\n if (projectName) {\n projectName = kebabCase(projectName);\n const available = isProjectDirAvailable(projectName);\n if (typeof available === 'string') {\n terminal.printError(available);\n process.exit(1);\n }\n } else {\n projectName = await input({\n message: '请输入项目',\n validate(value) {\n return isProjectDirAvailable(value);\n },\n transformer(value) {\n return kebabCase(value);\n },\n });\n }\n\n return projectName;\n};\n\nconst isProjectDirAvailable = (projectName: string): string | true => {\n projectName = projectName.trim();\n if (!projectName.trim()) return '项目名不能为空';\n const targetDir = path.resolve(projectName);\n if (!existsSync(targetDir)) return true;\n if (!readdirSync(targetDir).length) return true;\n return `目录 \"${targetDir}\" 包含其它文件,请手动删除或选择新的项目名`;\n};\n","import { select } from '@inquirer/prompts';\nimport { execSync } from 'node:child_process';\n\nconst packageManagers = <const>['pnpm', 'npm', 'yarn'];\n\nexport const selectPackageManager = async (argv: Record<string, any>) => {\n let packageManager!: (typeof packageManagers)[number];\n for (const item of <const>['pnpm', 'npm', 'yarn']) {\n if (argv[item]) {\n packageManager = item;\n break;\n }\n }\n if (!packageManager) {\n packageManager = await select({\n message: '请选择包管理器',\n default: 'pnpm',\n choices: packageManagers,\n });\n }\n\n const packageManagerVersion =\n execSync(\n packageManager === 'npm'\n ? 'npm -v'\n : `npm view ${packageManager} version`,\n { encoding: 'utf8' },\n ).replaceAll('\\n', '') || '0.0.0';\n\n return { packageManager, packageManagerVersion };\n};\n","import { terminal } from '@aomex/console';\nimport { select } from '@inquirer/prompts';\n\nexport const selectNodeVersion = async (argv: Record<string, any>) => {\n let nodeVersion: string = argv['node'];\n if (!nodeVersion) {\n const nodes = await promise;\n nodeVersion = await select({\n message: '请选择node.js稳定版本',\n choices: nodes.map((item) => {\n return {\n name: `${item.version} ${terminal.style(['gray', 'dim'], item.date)}`,\n value: item.version,\n short: item.version,\n };\n }),\n loop: false,\n });\n }\n\n return nodeVersion.replace(/^v/, '');\n};\n\nconst fetchNodes = async () => {\n const response = await fetch(\n 'https://nodejs.org/download/release/index.json',\n );\n const nodes = (await response.json()) as {\n version: string;\n lts: boolean;\n date: string;\n }[];\n\n return nodes\n .map((item) => {\n return {\n ...item,\n versions: item.version.slice(1).split('.').map(Number) as [\n number,\n number,\n number,\n ],\n };\n })\n .filter((item) => {\n if (!item.lts) return false;\n if (item.versions[0] === 20 && item.versions[1] >= 13) return true;\n if (item.versions[0] >= 22) return true;\n return false;\n });\n};\n\nconst promise = fetchNodes();\n"],"mappings":"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","names":["path","terminal","execSync","argv","projectName","targetDir","argv","packageManager","packageManagerVersion","terminal","select","argv","nodeVersion","path","terminal","execSync"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/input-project.ts","../src/select-package-manager.ts","../src/select-node-version.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport path from 'node:path/posix';\nimport yargsParser from 'yargs-parser';\nimport {\n cp,\n mkdir,\n readdir,\n readFile,\n rename,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport { terminal } from '@aomex/console';\nimport { execSync, spawn } from 'node:child_process';\nimport { setTimeout } from 'node:timers/promises';\nimport { inputProject } from './input-project';\nimport { selectPackageManager } from './select-package-manager';\nimport { selectNodeVersion } from './select-node-version';\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};\n\nconst argv = yargsParser(process.argv.slice(2));\nconst templateDir = path.join(import.meta.dirname, '..', 'templates');\nconst projectName = await inputProject(argv);\nconst { packageManager, packageManagerVersion } = await selectPackageManager(\n argv,\n);\nconst nodeVersion = await selectNodeVersion(argv);\nconst targetDir = path.resolve(projectName);\n\nconst { error } = await terminal.runTasks([\n {\n title: '创建目录',\n task: async () => {\n await mkdir(targetDir, { recursive: true });\n process.chdir(targetDir);\n await setTimeout(500);\n },\n },\n {\n title: '复制模板文件',\n task: async () => {\n const variables = {\n projectName,\n packageManager,\n nodeVersion,\n packageManagerVersion,\n };\n await cp(templateDir, targetDir, { recursive: true });\n const files = await readdir(targetDir, { recursive: true });\n for (const file of files) {\n const isFile = (await stat(path.join(targetDir, file))).isFile();\n if (!isFile) continue;\n const fileAbsolutePath = path.resolve(file);\n let fileContent = await readFile(fileAbsolutePath, 'utf8');\n Object.entries(variables).forEach(([key, value]) => {\n fileContent = fileContent.replaceAll(`{{${key}}}`, value);\n });\n await writeFile(fileAbsolutePath, fileContent);\n }\n // .gitignore这个文件在安装的时候总是被忽略\n await rename(\n path.join(targetDir, 'gitignore'),\n path.join(targetDir, '.gitignore'),\n );\n await setTimeout(500);\n },\n },\n {\n title: 'git初始化',\n skip: async () => {\n return !/\\d\\.\\d/.test(execSync('git -v', { encoding: 'utf8' }));\n },\n task: async () => {\n await runShell('git init');\n await setTimeout(500);\n },\n },\n {\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}@${packageManagerVersion}`);\n }\n },\n },\n {\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/cors',\n '@aomex/etag',\n '@aomex/compress',\n '@aomex/http-logger',\n '@aomex/response-time',\n '@aomex/console',\n '@aomex/cron',\n '@aomex/helmet',\n '@aomex/openapi',\n '@aomex/swagger-ui',\n '@aomex/async-trace',\n '@prisma/client',\n '@aomex/cache',\n '@aomex/cache-redis-adapter',\n 'ioredis',\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.suffix = terminal.style('gray', label);\n await runShell(\n `${packageManager} ${action} ${pkgs.join(' ')} ${\n dev ? devSuffix : ''\n }`,\n );\n }\n task.suffix = '';\n },\n },\n {\n title: '生成prisma客户端',\n task: async () => {\n await runShell('npx prisma generate');\n },\n },\n]);\n\nif (error) process.exit(1);\n\nconsole.log(\n '\\n项目创建成功:' +\n terminal.style(['blue', 'underline'], process.cwd()) +\n '\\n' +\n '启动项目可执行如下指令:' +\n '\\n\\n' +\n terminal.style('green', `cd ${projectName} && ${packageManager} start`) +\n '\\n',\n);\n","import { terminal } from '@aomex/console';\nimport { input } from '@inquirer/prompts';\nimport { existsSync, readdirSync } from 'node:fs';\nimport sanitize from 'sanitize-filename';\nimport path from 'path';\n\nconst kebabCase = (value: string) => {\n value = sanitize(value);\n if (!value.length) return '';\n value = value[0]!.toLowerCase() + value.slice(1);\n return value\n .replace(/[A-Z]/g, (i) => '-' + i.toLowerCase())\n .replace(/_/g, '-')\n .replace(/-+/g, '-');\n};\n\nexport const inputProject = async (argv: Record<string, any>) => {\n let projectName: string = argv['project'];\n if (projectName) {\n projectName = kebabCase(projectName);\n const available = isProjectDirAvailable(projectName);\n if (typeof available === 'string') {\n terminal.printError(available);\n process.exit(1);\n }\n } else {\n projectName = await input({\n message: '请输入项目',\n validate(value) {\n return isProjectDirAvailable(value);\n },\n transformer(value) {\n return kebabCase(value);\n },\n });\n projectName = kebabCase(projectName);\n }\n\n return projectName;\n};\n\nconst isProjectDirAvailable = (projectName: string): string | true => {\n projectName = projectName.trim();\n if (!projectName.trim()) return '项目名不能为空';\n const targetDir = path.resolve(projectName);\n if (!existsSync(targetDir)) return true;\n if (!readdirSync(targetDir).length) return true;\n return `目录 \"${targetDir}\" 包含其它文件,请手动删除或选择新的项目名`;\n};\n","import { select } from '@inquirer/prompts';\nimport { execSync } from 'node:child_process';\n\nconst packageManagers = <const>['pnpm', 'npm', 'yarn'];\n\nexport const selectPackageManager = async (argv: Record<string, any>) => {\n let packageManager!: (typeof packageManagers)[number];\n for (const item of <const>['pnpm', 'npm', 'yarn']) {\n if (argv[item]) {\n packageManager = item;\n break;\n }\n }\n if (!packageManager) {\n packageManager = await select({\n message: '请选择包管理器',\n default: 'pnpm',\n choices: packageManagers,\n });\n }\n\n const packageManagerVersion =\n execSync(\n packageManager === 'npm'\n ? 'npm -v'\n : `npm view ${packageManager} version`,\n { encoding: 'utf8' },\n ).replaceAll('\\n', '') || '0.0.0';\n\n return { packageManager, packageManagerVersion };\n};\n","import { terminal } from '@aomex/console';\nimport { select } from '@inquirer/prompts';\n\nexport const selectNodeVersion = async (argv: Record<string, any>) => {\n let nodeVersion: string = argv['node'];\n if (!nodeVersion) {\n const nodes = await promise;\n nodeVersion = await select({\n message: '请选择node.js稳定版本',\n choices: nodes.map((item) => {\n return {\n name: `${item.version} ${terminal.style(['gray', 'dim'], item.date)}`,\n value: item.version,\n short: item.version,\n };\n }),\n loop: false,\n });\n }\n\n return nodeVersion.replace(/^v/, '');\n};\n\nconst fetchNodes = async () => {\n const response = await fetch(\n 'https://nodejs.org/download/release/index.json',\n );\n const nodes = (await response.json()) as {\n version: string;\n lts: boolean;\n date: string;\n }[];\n\n return nodes\n .map((item) => {\n return {\n ...item,\n versions: item.version.slice(1).split('.').map(Number) as [\n number,\n number,\n number,\n ],\n };\n })\n .filter((item) => {\n if (!item.lts) return false;\n if (item.versions[0] === 20 && item.versions[1] >= 13) return true;\n if (item.versions[0] >= 22) return true;\n return false;\n });\n};\n\nconst promise = fetchNodes();\n"],"mappings":"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","names":["path","terminal","execSync","argv","projectName","targetDir","argv","packageManager","packageManagerVersion","terminal","select","argv","nodeVersion","path","terminal","execSync"]}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "create-aomex",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "repository": "git@github.com:aomex/create-aomex.git",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "scripts": {
8
- "cli": "rm -rf hello-aomex && tsx src/index.ts --project=hello-aomex --pnpm --node v20.16.0",
8
+ "cli": "rm -rf hello-aomex && tsx src/index.ts --project=HelloAomex --pnpm --node v20.16.0",
9
9
  "release": "release-it --ci",
10
10
  "build": "tsup",
11
11
  "prepublishOnly": "tsup"
@@ -33,7 +33,7 @@
33
33
  "@aomex/console": "^3.3.0",
34
34
  "@aomex/core": "^3.3.0",
35
35
  "@inquirer/prompts": "^6.0.1",
36
- "lodash.kebabcase": "^4.1.1",
36
+ "sanitize-filename": "^1.6.3",
37
37
  "yargs-parser": "^21.1.1"
38
38
  },
39
39
  "devDependencies": {
package/templates/.env CHANGED
@@ -1 +1 @@
1
- DATABASE_URL=mysql://root:abcde@localhost:3306/aomex_db
1
+ DATABASE_URL=mysql://root:abcde@localhost:3306/{{projectName}}
@@ -1 +1 @@
1
- DATABASE_URL=mysql://USER:PASSWORD@HOST:PORT/DBNAME
1
+ DATABASE_URL=mysql://USER:PASSWORD@HOST:3306/{{projectName}}
@@ -1 +1 @@
1
- DATABASE_URL=mysql://USER:PASSWORD@HOST:PORT/DBNAME
1
+ DATABASE_URL=mysql://USER:PASSWORD@HOST:3306/{{projectName}}
@@ -1,7 +1,7 @@
1
1
  services:
2
2
  migration:
3
3
  image: {{projectName}}:integration
4
- command: npx prisma migrate deploy
4
+ command: prisma migrate deploy
5
5
  api:
6
6
  image: {{projectName}}:integration
7
7
  restart: always
@@ -10,4 +10,4 @@ services:
10
10
  cron:
11
11
  image: {{projectName}}:integration
12
12
  container_name: {{projectName}}-cron-integration
13
- command: npx aomex cron:start
13
+ command: aomex cron:start
@@ -1,7 +1,7 @@
1
1
  services:
2
2
  migration:
3
3
  image: {{projectName}}:production
4
- command: npx prisma migrate deploy
4
+ command: prisma migrate deploy
5
5
  api:
6
6
  image: {{projectName}}:production
7
7
  restart: always
@@ -10,4 +10,4 @@ services:
10
10
  cron:
11
11
  image: {{projectName}}:production
12
12
  container_name: {{projectName}}-cron-production
13
- command: npx aomex cron:start
13
+ command: aomex cron:start
@@ -3,8 +3,8 @@ services:
3
3
  image: mysql:8.4
4
4
  environment:
5
5
  # 修改后需要同步修改.env里的参数
6
- MYSQL_DATABASE: aomex_db
7
- MYSQL_ROOT_PASSWORD: abcde
6
+ MYSQL_DATABASE: '{{projectName}}'
7
+ MYSQL_ROOT_PASSWORD: 'abcde'
8
8
  volumes:
9
9
  - ./volumes/mysql:/var/lib/mysql
10
10
  ports:
@@ -4,10 +4,12 @@ set -ex
4
4
 
5
5
  corepack enable # package.json => packageManager
6
6
  pnpm install
7
- pnpm prisma generate
7
+ pnpm exec prisma generate
8
8
  pnpm exec tsc
9
9
  pnpm exec tsc-alias --resolve-full-paths
10
10
  rm -rf src
11
11
  mv build/src .
12
12
  pnpm install --prod
13
13
  rm -rf node_modules/@types node_modules/*/*.d.ts
14
+ ln -s $PWD/node_modules/.bin/aomex /usr/local/bin/aomex
15
+ ln -s $PWD/node_modules/.bin/prisma /usr/local/bin/prisma
@@ -3,14 +3,15 @@
3
3
  set -ex
4
4
 
5
5
  env="$1"
6
+ projectName="{{projectName}}"
6
7
 
7
- sudo docker build --tag "{{projectName}}:$env" --file "Dockerfile.$env" .
8
+ sudo docker build --tag "$projectName:$env" --file "Dockerfile.$env" .
8
9
 
9
- cron_container_name="{{projectName}}-cron-$env"
10
+ cron_container_name="$projectName-cron-$env"
10
11
  container_exist=$(sudo docker ps | { grep $cron_container_name || :; })
11
12
  if [ -n "$container_exist" ];
12
13
  then
13
- sudo docker exec it $cron_container_name /bin/sh -c "npx aomex cron:stop"
14
+ sudo docker exec it $cron_container_name /bin/sh -c "aomex cron:stop"
14
15
  fi
15
16
 
16
- sudo docker compose --file "docker-compose-$env.yml" up -d --timeout=1
17
+ sudo docker compose --file "docker-compose-$env.yml" up -d --timeout=1 --remove-orphans
@@ -0,0 +1,8 @@
1
+ import { middleware } from '@aomex/core';
2
+
3
+ let _counter = 0;
4
+
5
+ export const counter = middleware.mixin<{ readonly visitCount: number }>(async (ctx, next) => {
6
+ ctx.visitCount = ++_counter;
7
+ await next();
8
+ });
@@ -0,0 +1,6 @@
1
+ import { middleware, I18n } from '@aomex/core';
2
+
3
+ export const i18nProvider = middleware.web((ctx, next) => {
4
+ // 动态选择i18n语言包
5
+ return I18n.provider(ctx.request.accept.language()[0] || 'zh_CN', next);
6
+ });
@@ -0,0 +1,14 @@
1
+ import { swaggerUI } from '@aomex/swagger-ui';
2
+ import { generateOpenapi } from '@aomex/openapi';
3
+
4
+ // 访问 http://localhost:3000/swagger 可以查看文档
5
+ export const swagger = swaggerUI({
6
+ openapi: () => {
7
+ return generateOpenapi({
8
+ routers: './src/routers',
9
+ docs: {
10
+ servers: [{ url: 'http://localhost:3000', description: 'Local' }],
11
+ },
12
+ });
13
+ },
14
+ });
@@ -0,0 +1,6 @@
1
+ import { traceMiddleware } from '@aomex/async-trace';
2
+
3
+ export const trace = traceMiddleware('生命周期', async (_record) => {
4
+ // 根据 record.delta 上报慢日志
5
+ // console.log(record);
6
+ });
@@ -1,13 +1,13 @@
1
1
  import { rule } from '@aomex/core';
2
2
  import { response, Router } from '@aomex/web';
3
- import { hello } from '@middleware/hello.middleware';
3
+ import { counter } from '@middleware/counter.md';
4
4
  import { i18n } from '../i18n';
5
5
 
6
6
  export const router = new Router();
7
7
 
8
8
  router.get('/', {
9
9
  mount: [
10
- hello,
10
+ counter,
11
11
  response({
12
12
  statusCode: 200,
13
13
  content: rule.string(),
@@ -20,7 +20,7 @@ export class UserService extends Service {
20
20
  return prisma.user.findUnique({ where: { id: userId } });
21
21
  }
22
22
 
23
- async createUser(data: Prisma.UserCreateArgs['data']) {
23
+ async createUser(data: Prisma.userCreateArgs['data']) {
24
24
  await prisma.user.create({
25
25
  data: data,
26
26
  });
@@ -5,38 +5,21 @@ import { httpLogger } from '@aomex/http-logger';
5
5
  import { etag } from '@aomex/etag';
6
6
  import { helmet } from '@aomex/helmet';
7
7
  import { responseTime } from '@aomex/response-time';
8
- import { traceMiddleware } from '@aomex/async-trace';
9
- import { swaggerUI } from '@aomex/swagger-ui';
10
- import { generateOpenapi } from '@aomex/openapi';
11
- import { I18n, middleware } from '@aomex/core';
8
+ import { swagger } from '@middleware/swagger.md';
9
+ import { i18nProvider } from '@middleware/i18n-provider.md';
10
+ import { trace } from '@middleware/trace.md';
12
11
 
13
12
  export const app = new WebApp({
14
13
  language: 'zh_CN',
15
14
  mount: [
16
- middleware.web((ctx, next) => {
17
- // 动态选择i18n语言包
18
- return I18n.provider(ctx.request.accept.language()[0] || 'zh_CN', next);
19
- }),
15
+ i18nProvider,
20
16
  httpLogger(),
21
17
  responseTime,
22
- traceMiddleware('生命周期', async (_record) => {
23
- // 根据 record.delta 上报慢日志
24
- // console.log(record);
25
- }),
18
+ trace,
26
19
  cors(),
27
20
  compress(),
28
21
  etag(),
29
- // 访问 http://localhost:3000/swagger 可以查看文档
30
- swaggerUI({
31
- openapi: () => {
32
- return generateOpenapi({
33
- routers: './src/routers',
34
- docs: {
35
- servers: [{ url: 'http://localhost:3000', description: 'Local' }],
36
- },
37
- });
38
- },
39
- }),
22
+ swagger,
40
23
  helmet(),
41
24
  routers('./src/routers'),
42
25
  ],
@@ -1,8 +0,0 @@
1
- import { middleware } from '@aomex/core';
2
-
3
- let counter = 0;
4
-
5
- export const hello = middleware.web<{ visitCount: number }>(async (ctx, next) => {
6
- ctx.visitCount = ++counter;
7
- await next();
8
- });