@daawoonkim/create-arch-app 0.1.0

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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +267 -0
  3. package/TESTING.md +224 -0
  4. package/bin/cli.js +4 -0
  5. package/create-arch-app_mvp_faa8b53b.plan.md +454 -0
  6. package/dist/commands/create.d.ts +2 -0
  7. package/dist/commands/create.d.ts.map +1 -0
  8. package/dist/commands/create.js +63 -0
  9. package/dist/commands/create.js.map +1 -0
  10. package/dist/generators/index.d.ts +3 -0
  11. package/dist/generators/index.d.ts.map +1 -0
  12. package/dist/generators/index.js +221 -0
  13. package/dist/generators/index.js.map +1 -0
  14. package/dist/generators/nextjs.d.ts +3 -0
  15. package/dist/generators/nextjs.d.ts.map +1 -0
  16. package/dist/generators/nextjs.js +253 -0
  17. package/dist/generators/nextjs.js.map +1 -0
  18. package/dist/generators/react.d.ts +3 -0
  19. package/dist/generators/react.d.ts.map +1 -0
  20. package/dist/generators/react.js +210 -0
  21. package/dist/generators/react.js.map +1 -0
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +14 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/prompts/projectSetup.d.ts +3 -0
  27. package/dist/prompts/projectSetup.d.ts.map +1 -0
  28. package/dist/prompts/projectSetup.js +110 -0
  29. package/dist/prompts/projectSetup.js.map +1 -0
  30. package/dist/types.d.ts +22 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +2 -0
  33. package/dist/types.js.map +1 -0
  34. package/dist/utils/dependencies.d.ts +5 -0
  35. package/dist/utils/dependencies.d.ts.map +1 -0
  36. package/dist/utils/dependencies.js +90 -0
  37. package/dist/utils/dependencies.js.map +1 -0
  38. package/dist/utils/fileSystem.d.ts +5 -0
  39. package/dist/utils/fileSystem.d.ts.map +1 -0
  40. package/dist/utils/fileSystem.js +23 -0
  41. package/dist/utils/fileSystem.js.map +1 -0
  42. package/package.json +51 -0
@@ -0,0 +1,221 @@
1
+ import path from 'path';
2
+ import { ensureDir, writeJson, createFile } from '../utils/fileSystem.js';
3
+ import { getDependencies, getDevDependencies, getScripts } from '../utils/dependencies.js';
4
+ import { generateReactProject } from './react.js';
5
+ import { generateNextJsProject } from './nextjs.js';
6
+ export async function generateProject(config, projectPath) {
7
+ // 프로젝트 디렉토리 생성
8
+ await ensureDir(projectPath);
9
+ // package.json 생성
10
+ const packageJson = {
11
+ name: config.projectName,
12
+ version: '0.1.0',
13
+ private: true,
14
+ scripts: getScripts(config),
15
+ dependencies: getDependencies(config),
16
+ devDependencies: getDevDependencies(config),
17
+ };
18
+ await writeJson(path.join(projectPath, 'package.json'), packageJson);
19
+ // tsconfig.json 생성
20
+ await generateTsConfig(config, projectPath);
21
+ // .gitignore 생성
22
+ await generateGitIgnore(projectPath);
23
+ // README.md 생성
24
+ await generateReadme(config, projectPath);
25
+ // 프레임워크별 프로젝트 생성
26
+ if (config.framework === 'react') {
27
+ await generateReactProject(config, projectPath);
28
+ }
29
+ else if (config.framework === 'nextjs') {
30
+ await generateNextJsProject(config, projectPath);
31
+ }
32
+ // Tailwind 설정
33
+ if (config.styling === 'tailwind') {
34
+ await generateTailwindConfig(config, projectPath);
35
+ }
36
+ }
37
+ async function generateTsConfig(config, projectPath) {
38
+ let tsConfig;
39
+ if (config.framework === 'react') {
40
+ tsConfig = {
41
+ compilerOptions: {
42
+ target: 'ES2020',
43
+ useDefineForClassFields: true,
44
+ lib: ['ES2020', 'DOM', 'DOM.Iterable'],
45
+ module: 'ESNext',
46
+ skipLibCheck: true,
47
+ moduleResolution: 'bundler',
48
+ allowImportingTsExtensions: true,
49
+ resolveJsonModule: true,
50
+ isolatedModules: true,
51
+ noEmit: true,
52
+ jsx: 'react-jsx',
53
+ strict: true,
54
+ noUnusedLocals: true,
55
+ noUnusedParameters: true,
56
+ noFallthroughCasesInSwitch: true,
57
+ },
58
+ include: ['src'],
59
+ references: [{ path: './tsconfig.node.json' }],
60
+ };
61
+ await writeJson(path.join(projectPath, 'tsconfig.json'), tsConfig);
62
+ // tsconfig.node.json for Vite
63
+ const tsConfigNode = {
64
+ compilerOptions: {
65
+ composite: true,
66
+ skipLibCheck: true,
67
+ module: 'ESNext',
68
+ moduleResolution: 'bundler',
69
+ allowSyntheticDefaultImports: true,
70
+ },
71
+ include: ['vite.config.ts'],
72
+ };
73
+ await writeJson(path.join(projectPath, 'tsconfig.node.json'), tsConfigNode);
74
+ }
75
+ else if (config.framework === 'nextjs') {
76
+ tsConfig = {
77
+ compilerOptions: {
78
+ lib: ['dom', 'dom.iterable', 'esnext'],
79
+ allowJs: true,
80
+ skipLibCheck: true,
81
+ strict: true,
82
+ noEmit: true,
83
+ esModuleInterop: true,
84
+ module: 'esnext',
85
+ moduleResolution: 'bundler',
86
+ resolveJsonModule: true,
87
+ isolatedModules: true,
88
+ jsx: 'preserve',
89
+ incremental: true,
90
+ plugins: [
91
+ {
92
+ name: 'next',
93
+ },
94
+ ],
95
+ paths: {
96
+ '@/*': ['./*'],
97
+ },
98
+ },
99
+ include: ['next-env.d.ts', '**/*.ts', '**/*.tsx', '.next/types/**/*.ts'],
100
+ exclude: ['node_modules'],
101
+ };
102
+ await writeJson(path.join(projectPath, 'tsconfig.json'), tsConfig);
103
+ }
104
+ }
105
+ async function generateGitIgnore(projectPath) {
106
+ const content = `# dependencies
107
+ node_modules/
108
+ .pnp
109
+ .pnp.js
110
+
111
+ # testing
112
+ coverage/
113
+
114
+ # production
115
+ build/
116
+ dist/
117
+ .next/
118
+ out/
119
+
120
+ # misc
121
+ .DS_Store
122
+ *.pem
123
+ .env
124
+ .env*.local
125
+
126
+ # debug
127
+ npm-debug.log*
128
+ yarn-debug.log*
129
+ yarn-error.log*
130
+
131
+ # typescript
132
+ *.tsbuildinfo
133
+ next-env.d.ts
134
+ `;
135
+ await createFile(path.join(projectPath, '.gitignore'), content);
136
+ }
137
+ async function generateReadme(config, projectPath) {
138
+ const content = `# ${config.projectName}
139
+
140
+ 이 프로젝트는 **create-arch-app**으로 생성되었습니다.
141
+
142
+ ## 기술 스택
143
+
144
+ - **프레임워크**: ${config.framework === 'react' ? 'React with Vite' : 'Next.js'}
145
+ ${config.framework === 'nextjs' ? `- **라우터**: ${config.router === 'app' ? 'App Router' : 'Pages Router'}\n` : ''}
146
+ - **아키텍처**: ${config.architecture}
147
+ - **언어**: TypeScript
148
+ - **스타일링**: ${config.styling === 'tailwind' ? 'Tailwind CSS' : 'CSS Modules'}
149
+ - **상태관리**: ${config.stateManagement}
150
+ ${config.formLibrary !== 'none' ? `- **폼**: ${config.formLibrary}\n` : ''}
151
+ ${config.testing ? '- **테스팅**: Vitest + Testing Library\n' : ''}
152
+
153
+ ## 시작하기
154
+
155
+ \`\`\`bash
156
+ # 의존성 설치
157
+ npm install
158
+
159
+ # 개발 서버 시작
160
+ npm run dev
161
+
162
+ # 프로덕션 빌드
163
+ npm run build
164
+ ${config.testing ? '\n# 테스트 실행\nnpm test' : ''}
165
+ \`\`\`
166
+
167
+ ## 아키텍처 구조
168
+
169
+ ### ${config.architecture.toUpperCase()}
170
+
171
+ ${getArchitectureDescription(config.architecture)}
172
+ `;
173
+ await createFile(path.join(projectPath, 'README.md'), content);
174
+ }
175
+ function getArchitectureDescription(architecture) {
176
+ switch (architecture) {
177
+ case 'ddd':
178
+ return '이 프로젝트는 Domain-Driven Design 패턴을 따릅니다.\n- `domain/`: 비즈니스 엔티티와 로직\n- `application/`: 유스케이스\n- `infrastructure/`: 외부 서비스 통합\n- `presentation/`: UI 컴포넌트';
179
+ case 'clean':
180
+ return '이 프로젝트는 Clean Architecture 패턴을 따릅니다.\n- `core/`: 비즈니스 로직\n- `features/`: 기능별 모듈\n- `shared/`: 공통 컴포넌트';
181
+ case 'atomic':
182
+ return '이 프로젝트는 Atomic Design 패턴을 따릅니다.\n- `atoms/`: 기본 UI 컴포넌트\n- `molecules/`: atoms 조합\n- `organisms/`: molecules 조합\n- `templates/`: 페이지 레이아웃\n- `pages/`: 실제 페이지';
183
+ case 'default':
184
+ return '이 프로젝트는 기본 구조를 사용합니다.\n- `components/`: UI 컴포넌트\n- `hooks/`: 커스텀 훅\n- `utils/`: 유틸리티 함수';
185
+ default:
186
+ return '';
187
+ }
188
+ }
189
+ async function generateTailwindConfig(config, projectPath) {
190
+ let contentPaths;
191
+ if (config.framework === 'react') {
192
+ contentPaths = ['./index.html', './src/**/*.{js,ts,jsx,tsx}'];
193
+ }
194
+ else {
195
+ if (config.router === 'app') {
196
+ contentPaths = ['./app/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'];
197
+ }
198
+ else {
199
+ contentPaths = ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'];
200
+ }
201
+ }
202
+ const tailwindConfig = `/** @type {import('tailwindcss').Config} */
203
+ module.exports = {
204
+ content: ${JSON.stringify(contentPaths, null, 2)},
205
+ theme: {
206
+ extend: {},
207
+ },
208
+ plugins: [],
209
+ }
210
+ `;
211
+ await createFile(path.join(projectPath, 'tailwind.config.js'), tailwindConfig);
212
+ const postcssConfig = `module.exports = {
213
+ plugins: {
214
+ tailwindcss: {},
215
+ autoprefixer: {},
216
+ },
217
+ }
218
+ `;
219
+ await createFile(path.join(projectPath, 'postcss.config.js'), postcssConfig);
220
+ }
221
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { ProjectConfig } from '../types.js';
2
+ export declare function generateNextJsProject(config: ProjectConfig, projectPath: string): Promise<void>;
3
+ //# sourceMappingURL=nextjs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../src/generators/nextjs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAef"}
@@ -0,0 +1,253 @@
1
+ import path from 'path';
2
+ import { ensureDir, createFile } from '../utils/fileSystem.js';
3
+ export async function generateNextJsProject(config, projectPath) {
4
+ // next.config.js 생성
5
+ await generateNextConfig(projectPath);
6
+ if (config.router === 'app') {
7
+ await generateAppRouter(config, projectPath);
8
+ }
9
+ else {
10
+ await generatePagesRouter(config, projectPath);
11
+ }
12
+ // 아키텍처별 폴더 구조 생성
13
+ await generateArchitectureStructure(config, projectPath);
14
+ // 공통 설정 파일
15
+ await generateCommonFiles(config, projectPath);
16
+ }
17
+ async function generateNextConfig(projectPath) {
18
+ const content = `/** @type {import('next').NextConfig} */
19
+ const nextConfig = {
20
+ reactStrictMode: true,
21
+ }
22
+
23
+ module.exports = nextConfig
24
+ `;
25
+ await createFile(path.join(projectPath, 'next.config.js'), content);
26
+ }
27
+ async function generateAppRouter(config, projectPath) {
28
+ const appPath = path.join(projectPath, 'app');
29
+ await ensureDir(appPath);
30
+ // layout.tsx
31
+ const layoutContent = `import type { Metadata } from 'next'
32
+ ${config.styling === 'tailwind' ? "import './globals.css'\n" : ''}
33
+ export const metadata: Metadata = {
34
+ title: '${config.projectName}',
35
+ description: 'Created with create-arch-app',
36
+ }
37
+
38
+ export default function RootLayout({
39
+ children,
40
+ }: {
41
+ children: React.ReactNode
42
+ }) {
43
+ return (
44
+ <html lang="ko">
45
+ <body>{children}</body>
46
+ </html>
47
+ )
48
+ }
49
+ `;
50
+ await createFile(path.join(appPath, 'layout.tsx'), layoutContent);
51
+ // page.tsx
52
+ const pageContent = `export default function Home() {
53
+ return (
54
+ <main className="min-h-screen flex items-center justify-center bg-gray-100">
55
+ <div className="text-center">
56
+ <h1 className="text-4xl font-bold text-gray-900 mb-4">
57
+ ${config.projectName}
58
+ </h1>
59
+ <p className="text-lg text-gray-600 mb-8">
60
+ Created with create-arch-app
61
+ </p>
62
+ <div className="space-y-2 text-sm text-gray-500">
63
+ <p>Framework: Next.js (App Router)</p>
64
+ <p>Architecture: ${config.architecture}</p>
65
+ <p>Styling: ${config.styling}</p>
66
+ </div>
67
+ </div>
68
+ </main>
69
+ )
70
+ }
71
+ `;
72
+ await createFile(path.join(appPath, 'page.tsx'), pageContent);
73
+ // globals.css
74
+ if (config.styling === 'tailwind') {
75
+ const cssContent = `@tailwind base;
76
+ @tailwind components;
77
+ @tailwind utilities;
78
+ `;
79
+ await createFile(path.join(appPath, 'globals.css'), cssContent);
80
+ }
81
+ else {
82
+ const cssContent = `* {
83
+ margin: 0;
84
+ padding: 0;
85
+ box-sizing: border-box;
86
+ }
87
+
88
+ body {
89
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
90
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
91
+ sans-serif;
92
+ }
93
+ `;
94
+ await createFile(path.join(appPath, 'globals.css'), cssContent);
95
+ }
96
+ }
97
+ async function generatePagesRouter(config, projectPath) {
98
+ const pagesPath = path.join(projectPath, 'pages');
99
+ const stylesPath = path.join(projectPath, 'styles');
100
+ await ensureDir(pagesPath);
101
+ await ensureDir(stylesPath);
102
+ // _app.tsx
103
+ const appContent = `import type { AppProps } from 'next/app'
104
+ import '../styles/globals.css'
105
+
106
+ export default function App({ Component, pageProps }: AppProps) {
107
+ return <Component {...pageProps} />
108
+ }
109
+ `;
110
+ await createFile(path.join(pagesPath, '_app.tsx'), appContent);
111
+ // _document.tsx
112
+ const documentContent = `import { Html, Head, Main, NextScript } from 'next/document'
113
+
114
+ export default function Document() {
115
+ return (
116
+ <Html lang="ko">
117
+ <Head />
118
+ <body>
119
+ <Main />
120
+ <NextScript />
121
+ </body>
122
+ </Html>
123
+ )
124
+ }
125
+ `;
126
+ await createFile(path.join(pagesPath, '_document.tsx'), documentContent);
127
+ // index.tsx
128
+ const indexContent = `export default function Home() {
129
+ return (
130
+ <main className="min-h-screen flex items-center justify-center bg-gray-100">
131
+ <div className="text-center">
132
+ <h1 className="text-4xl font-bold text-gray-900 mb-4">
133
+ ${config.projectName}
134
+ </h1>
135
+ <p className="text-lg text-gray-600 mb-8">
136
+ Created with create-arch-app
137
+ </p>
138
+ <div className="space-y-2 text-sm text-gray-500">
139
+ <p>Framework: Next.js (Pages Router)</p>
140
+ <p>Architecture: ${config.architecture}</p>
141
+ <p>Styling: ${config.styling}</p>
142
+ </div>
143
+ </div>
144
+ </main>
145
+ )
146
+ }
147
+ `;
148
+ await createFile(path.join(pagesPath, 'index.tsx'), indexContent);
149
+ // globals.css
150
+ if (config.styling === 'tailwind') {
151
+ const cssContent = `@tailwind base;
152
+ @tailwind components;
153
+ @tailwind utilities;
154
+ `;
155
+ await createFile(path.join(stylesPath, 'globals.css'), cssContent);
156
+ }
157
+ else {
158
+ const cssContent = `* {
159
+ margin: 0;
160
+ padding: 0;
161
+ box-sizing: border-box;
162
+ }
163
+
164
+ body {
165
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
166
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
167
+ sans-serif;
168
+ }
169
+ `;
170
+ await createFile(path.join(stylesPath, 'globals.css'), cssContent);
171
+ }
172
+ }
173
+ async function generateArchitectureStructure(config, projectPath) {
174
+ switch (config.architecture) {
175
+ case 'ddd':
176
+ await ensureDir(path.join(projectPath, 'domain/entities'));
177
+ await ensureDir(path.join(projectPath, 'domain/repositories'));
178
+ await ensureDir(path.join(projectPath, 'domain/services'));
179
+ await ensureDir(path.join(projectPath, 'application/usecases'));
180
+ await ensureDir(path.join(projectPath, 'application/ports'));
181
+ await ensureDir(path.join(projectPath, 'infrastructure/api'));
182
+ await ensureDir(path.join(projectPath, 'infrastructure/persistence'));
183
+ await ensureDir(path.join(projectPath, 'presentation/components'));
184
+ await createFile(path.join(projectPath, 'domain/entities/README.md'), '# Domain Entities\n\n비즈니스 엔티티를 정의합니다.');
185
+ await createFile(path.join(projectPath, 'application/usecases/README.md'), '# Use Cases\n\n애플리케이션 유스케이스를 구현합니다.');
186
+ break;
187
+ case 'clean':
188
+ await ensureDir(path.join(projectPath, 'core/entities'));
189
+ await ensureDir(path.join(projectPath, 'core/usecases'));
190
+ await ensureDir(path.join(projectPath, 'core/interfaces'));
191
+ await ensureDir(path.join(projectPath, 'features/example/domain'));
192
+ await ensureDir(path.join(projectPath, 'features/example/data'));
193
+ await ensureDir(path.join(projectPath, 'features/example/presentation'));
194
+ await ensureDir(path.join(projectPath, 'shared/components'));
195
+ await ensureDir(path.join(projectPath, 'shared/utils'));
196
+ await createFile(path.join(projectPath, 'core/entities/README.md'), '# Core Entities\n\n핵심 비즈니스 엔티티를 정의합니다.');
197
+ break;
198
+ case 'atomic':
199
+ await ensureDir(path.join(projectPath, 'components/atoms'));
200
+ await ensureDir(path.join(projectPath, 'components/molecules'));
201
+ await ensureDir(path.join(projectPath, 'components/organisms'));
202
+ await ensureDir(path.join(projectPath, 'components/templates'));
203
+ await ensureDir(path.join(projectPath, 'hooks'));
204
+ await ensureDir(path.join(projectPath, 'utils'));
205
+ // Example Button component
206
+ await createFile(path.join(projectPath, 'components/atoms/Button.tsx'), `interface ButtonProps {
207
+ children: React.ReactNode;
208
+ onClick?: () => void;
209
+ variant?: 'primary' | 'secondary';
210
+ }
211
+
212
+ export const Button: React.FC<ButtonProps> = ({
213
+ children,
214
+ onClick,
215
+ variant = 'primary',
216
+ }) => {
217
+ const baseStyles = 'px-4 py-2 rounded font-medium transition-colors';
218
+ const variantStyles = variant === 'primary'
219
+ ? 'bg-blue-500 hover:bg-blue-600 text-white'
220
+ : 'bg-gray-200 hover:bg-gray-300 text-gray-800';
221
+
222
+ return (
223
+ <button
224
+ onClick={onClick}
225
+ className={\`\${baseStyles} \${variantStyles}\`}
226
+ >
227
+ {children}
228
+ </button>
229
+ );
230
+ };
231
+ `);
232
+ await createFile(path.join(projectPath, 'components/atoms/README.md'), '# Atoms\n\n가장 작은 UI 컴포넌트 단위입니다.');
233
+ break;
234
+ case 'default':
235
+ default:
236
+ await ensureDir(path.join(projectPath, 'components'));
237
+ await ensureDir(path.join(projectPath, 'hooks'));
238
+ await ensureDir(path.join(projectPath, 'utils'));
239
+ await ensureDir(path.join(projectPath, 'types'));
240
+ await createFile(path.join(projectPath, 'components/README.md'), '# Components\n\nReact 컴포넌트를 작성합니다.');
241
+ break;
242
+ }
243
+ }
244
+ async function generateCommonFiles(config, projectPath) {
245
+ // public 디렉토리
246
+ await ensureDir(path.join(projectPath, 'public'));
247
+ // .eslintrc.json
248
+ const eslintContent = {
249
+ extends: 'next/core-web-vitals',
250
+ };
251
+ await createFile(path.join(projectPath, '.eslintrc.json'), JSON.stringify(eslintContent, null, 2));
252
+ }
253
+ //# sourceMappingURL=nextjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../../src/generators/nextjs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { ProjectConfig } from '../types.js';
2
+ export declare function generateReactProject(config: ProjectConfig, projectPath: string): Promise<void>;
3
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/generators/react.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAsBf"}