create-express-esm 1.1.5 → 1.1.8
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/bin/cli.js +93 -39
- package/package.json +6 -2
- package/template/ts/package.json +3 -3
package/bin/cli.js
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { input, select } from '@inquirer/prompts';
|
|
3
|
+
import { input, select, confirm } from '@inquirer/prompts';
|
|
4
4
|
import fs from 'fs-extra';
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
import { execSync } from 'child_process';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
|
|
10
|
-
// ESM에서 __dirname 사용하기 위한 설정
|
|
11
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
11
|
const __dirname = path.dirname(__filename);
|
|
13
12
|
|
|
14
|
-
// 1.2.0 버전 정보 및 메인 로직
|
|
15
13
|
async function run() {
|
|
16
14
|
console.log(chalk.blue.bold('\n🚀 Create Express ESM 시작!\n'));
|
|
17
15
|
|
|
18
16
|
try {
|
|
19
|
-
// 1. 사용자 질문
|
|
17
|
+
// 1. 사용자 질문
|
|
20
18
|
const projectName = await input({
|
|
21
19
|
message: '생성할 프로젝트 이름을 입력하세요:',
|
|
22
20
|
default: 'my-app',
|
|
@@ -30,6 +28,11 @@ async function run() {
|
|
|
30
28
|
],
|
|
31
29
|
});
|
|
32
30
|
|
|
31
|
+
const useTest = await confirm({
|
|
32
|
+
message: 'Vitest 테스트 환경을 추가하시겠습니까?',
|
|
33
|
+
default: true,
|
|
34
|
+
});
|
|
35
|
+
|
|
33
36
|
const targetPath = path.join(process.cwd(), projectName);
|
|
34
37
|
const templatePath = path.join(__dirname, '../template', language);
|
|
35
38
|
|
|
@@ -39,18 +42,11 @@ async function run() {
|
|
|
39
42
|
process.exit(1);
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
// 3. 템플릿 복사
|
|
43
|
-
console.log(chalk.cyan(`\n📂 [${language.toUpperCase()}]
|
|
44
|
-
|
|
45
|
-
if (!fs.existsSync(templatePath)) {
|
|
46
|
-
console.error(chalk.red(`\n❌ 오류: ${language} 템플릿 폴더를 찾을 수 없습니다.`));
|
|
47
|
-
console.log(chalk.gray(`경로 확인: ${templatePath}`));
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
|
|
45
|
+
// 3. 기본 템플릿 복사
|
|
46
|
+
console.log(chalk.cyan(`\n📂 [${language.toUpperCase()}] 템플릿 구성을 시작합니다...`));
|
|
51
47
|
await fs.copy(templatePath, targetPath);
|
|
52
48
|
|
|
53
|
-
// 4. 도트 파일 변환
|
|
49
|
+
// 4. 도트 파일 변환 (_env -> .env 등)
|
|
54
50
|
const renameMap = {
|
|
55
51
|
'gitignore': '.gitignore',
|
|
56
52
|
'_gitignore': '.gitignore',
|
|
@@ -60,46 +56,104 @@ async function run() {
|
|
|
60
56
|
for (const [oldName, newName] of Object.entries(renameMap)) {
|
|
61
57
|
const oldFilePath = path.join(targetPath, oldName);
|
|
62
58
|
const newFilePath = path.join(targetPath, newName);
|
|
63
|
-
|
|
64
59
|
if (await fs.pathExists(oldFilePath)) {
|
|
65
60
|
await fs.move(oldFilePath, newFilePath, { overwrite: true });
|
|
66
61
|
if (newName === '.env') {
|
|
67
|
-
|
|
68
|
-
await fs.copy(newFilePath, exampleEnvPath);
|
|
62
|
+
await fs.copy(newFilePath, path.join(targetPath, '.env.example'));
|
|
69
63
|
}
|
|
70
64
|
}
|
|
71
65
|
}
|
|
72
66
|
|
|
73
|
-
// 5. package.json
|
|
67
|
+
// 5. package.json 동적 수정
|
|
74
68
|
const pkgPath = path.join(targetPath, 'package.json');
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
69
|
+
const pkg = await fs.readJson(pkgPath);
|
|
70
|
+
pkg.name = projectName;
|
|
71
|
+
|
|
72
|
+
// [추가된 부분] TypeScript 환경에서 ESM 에러를 방지하기 위한 tsx 설정
|
|
73
|
+
if (language === 'ts') {
|
|
74
|
+
console.log(chalk.yellow(`⚙️ TypeScript ESM 실행 환경(tsx)을 최적화하는 중...`));
|
|
75
|
+
|
|
76
|
+
// ts-node 대신 tsx를 사용하여 .js 확장자 임포트 문제 해결
|
|
77
|
+
pkg.scripts.dev = "nodemon --exec tsx src/server.ts";
|
|
78
|
+
|
|
79
|
+
// 의존성 교체
|
|
80
|
+
pkg.devDependencies = {
|
|
81
|
+
...pkg.devDependencies,
|
|
82
|
+
"tsx": "^4.7.0"
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// 기존에 ts-node가 있다면 제거 (중복 방지)
|
|
86
|
+
delete pkg.devDependencies['ts-node'];
|
|
79
87
|
}
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
|
|
89
|
+
// Vitest 설정 (이슈 #3 구현 부분)
|
|
90
|
+
if (useTest) {
|
|
91
|
+
console.log(chalk.yellow(`🧪 Vitest 설정 및 샘플 테스트를 생성하는 중...`));
|
|
92
|
+
|
|
93
|
+
pkg.scripts = {
|
|
94
|
+
...pkg.scripts,
|
|
95
|
+
"test": "vitest",
|
|
96
|
+
"test:ui": "vitest --ui",
|
|
97
|
+
"test:run": "vitest run"
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const testDeps = {
|
|
101
|
+
"vitest": "^1.0.0",
|
|
102
|
+
"supertest": "^6.3.3"
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
if (language === 'ts') {
|
|
106
|
+
testDeps["@types/supertest"] = "^2.0.12";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
pkg.devDependencies = {
|
|
110
|
+
...pkg.devDependencies,
|
|
111
|
+
...testDeps
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Vitest 설정 파일 생성
|
|
115
|
+
const configExt = language === 'ts' ? 'ts' : 'js';
|
|
116
|
+
const configContent = `import { defineConfig } from 'vitest/config';
|
|
117
|
+
|
|
118
|
+
export default defineConfig({
|
|
119
|
+
test: {
|
|
120
|
+
globals: true,
|
|
121
|
+
environment: 'node',
|
|
122
|
+
},
|
|
123
|
+
});`;
|
|
124
|
+
await fs.writeFile(path.join(targetPath, `vitest.config.${configExt}`), configContent);
|
|
125
|
+
|
|
126
|
+
// 샘플 테스트 파일 생성
|
|
127
|
+
const testFileExt = language === 'ts' ? 'ts' : 'js';
|
|
128
|
+
const testContent = `import { describe, it, expect } from 'vitest';
|
|
129
|
+
import request from 'supertest';
|
|
130
|
+
import app from './app.js';
|
|
131
|
+
|
|
132
|
+
describe('API Health Check Test', () => {
|
|
133
|
+
it('GET / 요청이 성공해야 한다', async () => {
|
|
134
|
+
const res = await request(app).get('/');
|
|
135
|
+
expect(res.status).toBe(200);
|
|
136
|
+
expect(res.text).toContain('Server is Running');
|
|
137
|
+
});
|
|
138
|
+
});`;
|
|
139
|
+
await fs.writeFile(path.join(targetPath, `src/app.test.${testFileExt}`), testContent);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
143
|
+
console.log(chalk.green(`✅ 모든 구성 완료!`));
|
|
82
144
|
|
|
83
145
|
// 6. 패키지 자동 설치
|
|
84
|
-
console.log(chalk.yellow(`\n📦
|
|
85
|
-
|
|
86
|
-
execSync('npm install', {
|
|
87
|
-
cwd: targetPath,
|
|
88
|
-
stdio: 'inherit'
|
|
89
|
-
});
|
|
146
|
+
console.log(chalk.yellow(`\n📦 의존성 패키지를 설치합니다... (npm install)`));
|
|
147
|
+
execSync('npm install', { cwd: targetPath, stdio: 'inherit' });
|
|
90
148
|
|
|
91
|
-
console.log(chalk.green(`\n✨
|
|
92
|
-
console.log(chalk.white(`\n다음
|
|
149
|
+
console.log(chalk.green(`\n✨ 프로젝트 생성 성공!`));
|
|
150
|
+
console.log(chalk.white(`\n다음 명령어를 입력해 보세요:\n`));
|
|
93
151
|
console.log(chalk.cyan(` cd ${projectName}`));
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
} else {
|
|
97
|
-
console.log(chalk.cyan(` npm run dev`));
|
|
98
|
-
}
|
|
99
|
-
console.log('\n');
|
|
152
|
+
if (useTest) console.log(chalk.cyan(` npm test`));
|
|
153
|
+
console.log(chalk.cyan(` npm run dev\n`));
|
|
100
154
|
|
|
101
155
|
} catch (error) {
|
|
102
|
-
if (error.name === 'ExitPromptError') {
|
|
156
|
+
if (error.name === 'ExitPromptError') { // 오타 수정: ExitPnromptError -> ExitPromptError
|
|
103
157
|
console.log(chalk.yellow('\n\n👋 설치를 중단했습니다.'));
|
|
104
158
|
} else {
|
|
105
159
|
console.error(chalk.red('\n❌ 오류 발생:'), error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-express-esm",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "A modern CLI tool to bootstrap Express.js applications with ES Modules and Layered Architecture.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"author": "munjuin",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@inquirer/prompts": "^8.1.0",
|
|
27
28
|
"chalk": "^5.6.2",
|
|
28
29
|
"commander": "^14.0.2",
|
|
29
30
|
"fs-extra": "^11.3.2",
|
|
@@ -36,5 +37,8 @@
|
|
|
36
37
|
"bugs": {
|
|
37
38
|
"url": "https://github.com/munjuin/create-express-esm/issues"
|
|
38
39
|
},
|
|
39
|
-
"homepage": "https://github.com/munjuin/create-express-esm#readme"
|
|
40
|
+
"homepage": "https://github.com/munjuin/create-express-esm#readme",
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"tsx": "^4.21.0"
|
|
43
|
+
}
|
|
40
44
|
}
|
package/template/ts/package.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
6
|
+
"dev": "nodemon --exec tsx src/server.ts",
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"start": "node dist/server.js"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"express": "^4.18.2",
|