create-aomex 0.0.10 → 0.0.12

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
@@ -4,7 +4,7 @@
4
4
  import path2 from "node:path/posix";
5
5
  import yargsParser from "yargs-parser";
6
6
  import { existsSync } from "node:fs";
7
- import { cp, mkdir, rm } from "node:fs/promises";
7
+ import { cp, mkdir, readdir, rm, stat } from "node:fs/promises";
8
8
  import { Listr } from "listr2";
9
9
  import { styleText } from "node:util";
10
10
  import { execSync, spawn } from "node:child_process";
@@ -62,13 +62,6 @@ spinner.add({
62
62
  process.chdir(path2.resolve(projectName));
63
63
  }
64
64
  });
65
- spinner.add({
66
- title: "git\u521D\u59CB\u5316",
67
- task: async () => {
68
- await runShell("git init");
69
- await sleep();
70
- }
71
- });
72
65
  spinner.add({
73
66
  title: "\u590D\u5236\u6A21\u677F\u6587\u4EF6",
74
67
  task: async () => {
@@ -78,8 +71,19 @@ spinner.add({
78
71
  nodeVersion
79
72
  };
80
73
  await cp(templateDir, targetDir, { recursive: true });
81
- await replaceVariables("package.json", variables);
82
- await replaceVariables("README.md", variables);
74
+ const files = await readdir(targetDir, { recursive: true });
75
+ for (const file of files) {
76
+ const isFile = (await stat(path2.join(targetDir, file))).isFile();
77
+ if (!isFile) continue;
78
+ await replaceVariables(file, variables);
79
+ }
80
+ await sleep();
81
+ }
82
+ });
83
+ spinner.add({
84
+ title: "git\u521D\u59CB\u5316",
85
+ task: async () => {
86
+ await runShell("git init");
83
87
  await sleep();
84
88
  }
85
89
  });
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}\nconst nodeVersion = process.versions.node;\n\nlet packageManager = 'pnpm';\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 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/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 ],\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"]}
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, readdir, rm, stat } 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 = 'pnpm';\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: '复制模板文件',\n task: async () => {\n const variables = {\n projectName,\n packageManager,\n nodeVersion,\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 await replaceVariables(file, variables);\n }\n await sleep();\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: '增加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/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 ],\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,11 +1,11 @@
1
1
  {
2
2
  "name": "create-aomex",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
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 my-aomex && tsx src/index.ts --project=my-aomex",
8
+ "cli": "rm -rf hello-aomex && tsx src/index.ts --project=hello-aomex",
9
9
  "release": "release-it --ci",
10
10
  "build": "tsup",
11
11
  "prepublishOnly": "tsup"
@@ -0,0 +1,3 @@
1
+ volumes/
2
+ node_modules/
3
+ coverage/
package/templates/.env ADDED
@@ -0,0 +1 @@
1
+ DATABASE_URL=mysql://root:abcde@localhost:3306/aomex_db
@@ -0,0 +1 @@
1
+ DATABASE_URL=mysql://USER:PASSWORD@HOST:PORT/DBNAME
@@ -0,0 +1 @@
1
+ DATABASE_URL=mysql://USER:PASSWORD@HOST:PORT/DBNAME
@@ -0,0 +1,10 @@
1
+ FROM node:{{nodeVersion}}
2
+ COPY . /codes
3
+ WORKDIR /codes
4
+ RUN sh scripts/build-in-docker.sh
5
+ RUN mv .env.integration .env
6
+
7
+ ENV TZ=Asia/Shanghai
8
+ ENV PORT=3000
9
+ ENV NODE_ENV=integration
10
+ CMD ["node", "--enable-source-maps", "src/web.js"]
@@ -0,0 +1,10 @@
1
+ FROM node:{{nodeVersion}}
2
+ COPY . /codes
3
+ WORKDIR /codes
4
+ RUN sh scripts/build-in-docker.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,13 @@
1
+ services:
2
+ migration:
3
+ image: {{projectName}}:integration
4
+ command: npx prisma migrate deploy
5
+ api:
6
+ image: {{projectName}}:integration
7
+ restart: always
8
+ ports:
9
+ - 3000:3000
10
+ cron:
11
+ image: {{projectName}}:integration
12
+ container_name: {{projectName}}-cron-integration
13
+ command: npx aomex cron:start
@@ -0,0 +1,13 @@
1
+ services:
2
+ migration:
3
+ image: {{projectName}}:production
4
+ command: npx prisma migrate deploy
5
+ api:
6
+ image: {{projectName}}:production
7
+ restart: always
8
+ ports:
9
+ - 3000:3000
10
+ cron:
11
+ image: {{projectName}}:production
12
+ container_name: {{projectName}}-cron-production
13
+ command: npx aomex cron:start
@@ -0,0 +1,18 @@
1
+ services:
2
+ db:
3
+ image: mysql:8.4
4
+ environment:
5
+ # 修改后需要同步修改.env里的参数
6
+ MYSQL_DATABASE: aomex_db
7
+ MYSQL_ROOT_PASSWORD: abcde
8
+ volumes:
9
+ - ./volumes/mysql:/var/lib/mysql
10
+ ports:
11
+ - 3306:3306
12
+ command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
13
+ redis:
14
+ image: redis:7.4
15
+ volumes:
16
+ - ./volumes/redis:/data
17
+ ports:
18
+ - 6379:6379
@@ -7,8 +7,9 @@
7
7
  "node": "{{nodeVersion}}"
8
8
  },
9
9
  "scripts": {
10
- "start": "prisma generate && prisma db push && node --import tsx/esm --watch src/web.ts",
11
- "build": "tsc && tsc-alias --resolve-full-paths",
10
+ "start": "node scripts/start.mjs",
11
+ "deploy:production": "sh scripts/deploy-production.sh",
12
+ "deploy:integration": "sh scripts/deploy-integration.sh",
12
13
  "prepare": "npx husky",
13
14
  "preinstall": "npx only-allow {{packageManager}}"
14
15
  }
@@ -1,6 +1,6 @@
1
1
  datasource db {
2
- provider = "sqlite"
3
- url = "file:./sqlite.db"
2
+ provider = "mysql"
3
+ url = env("DATABASE_URL")
4
4
  relationMode = "prisma"
5
5
  }
6
6
 
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env sh
2
+
3
+ set -ex
4
+
5
+ corepack enable
6
+ pnpm install
7
+ pnpm prisma generate
8
+ pnpm exec tsc
9
+ pnpm exec tsc-alias --resolve-full-paths
10
+ rm -rf src
11
+ mv build/src .
12
+ pnpm install --prod
13
+ rm -rf node_modules/@types node_modules/*/*.d.ts
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env sh
2
+
3
+ set -ex
4
+
5
+ sudo docker build --tag {{projectName}}:integration --file Dockerfile.integration .
6
+
7
+ cron_container_name={{projectName}}-cron-integration
8
+ container_exist=$(sudo docker ps | { grep $cron_container_name || :; })
9
+ if [ -n "$container_exist" ];
10
+ then
11
+ sudo docker exec it $cron_container_name /bin/sh -c "npx aomex cron:stop"
12
+ fi
13
+
14
+ sudo docker compose --file docker-compose-integration.yml up -d --timeout=1
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env sh
2
+
3
+ set -ex
4
+
5
+ sudo docker build --tag {{projectName}}:production --file Dockerfile.production .
6
+
7
+ cron_container_name={{projectName}}-cron-production
8
+ container_exist=$(sudo docker ps | { grep $cron_container_name || :; })
9
+ if [ -n "$container_exist" ];
10
+ then
11
+ sudo docker exec it $cron_container_name /bin/sh -c "npx aomex cron:stop"
12
+ fi
13
+
14
+ sudo docker compose --file docker-compose-production.yml up -d --timeout=1
@@ -0,0 +1,34 @@
1
+ import { execSync, spawn } from 'node:child_process';
2
+ import process from 'node:process';
3
+
4
+ execSync('docker compose -f docker-compose.yml down', { stdio: 'inherit' });
5
+
6
+ const docker = spawn('docker compose -f docker-compose.yml up', {
7
+ stdio: ['inherit', 'inherit', 'pipe'],
8
+ shell: 'zsh',
9
+ });
10
+
11
+ await new Promise((resolve) => {
12
+ docker.stderr.on('data', (chunk) => {
13
+ process.stderr.write(chunk);
14
+ if (chunk.toString().includes('port: 3306 MySQL Community Server - GPL.')) {
15
+ resolve();
16
+ }
17
+ });
18
+ });
19
+
20
+ const server = spawn(
21
+ 'npx prisma migrate deploy && npx prisma generate && node --import tsx/esm --watch src/web.ts',
22
+ { stdio: 'inherit', shell: 'zsh' },
23
+ );
24
+
25
+ const cron = spawn('npx', ['aomex', 'cron:start'], { stdio: 'inherit', shell: 'zsh' });
26
+
27
+ // 防止被其它逻辑清除监听
28
+ setTimeout(() => {
29
+ process.on('SIGINT', () => {
30
+ cron.kill('SIGINT');
31
+ server.kill('SIGINT');
32
+ docker.kill('SIGINT');
33
+ });
34
+ }, 1000);