create-react-forge 1.0.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 (90) hide show
  1. package/README.md +109 -0
  2. package/dist/assembler/index.d.ts +100 -0
  3. package/dist/assembler/index.d.ts.map +1 -0
  4. package/dist/assembler/index.js +198 -0
  5. package/dist/assembler/index.js.map +1 -0
  6. package/dist/assembler/merger.d.ts +14 -0
  7. package/dist/assembler/merger.d.ts.map +1 -0
  8. package/dist/assembler/merger.js +58 -0
  9. package/dist/assembler/merger.js.map +1 -0
  10. package/dist/cli/index.d.ts +57 -0
  11. package/dist/cli/index.d.ts.map +1 -0
  12. package/dist/cli/index.js +110 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/cli/parser.d.ts +3 -0
  15. package/dist/cli/parser.d.ts.map +1 -0
  16. package/dist/cli/parser.js +50 -0
  17. package/dist/cli/parser.js.map +1 -0
  18. package/dist/cli/prompts.d.ts +24 -0
  19. package/dist/cli/prompts.d.ts.map +1 -0
  20. package/dist/cli/prompts.js +126 -0
  21. package/dist/cli/prompts.js.map +1 -0
  22. package/dist/config/builder.d.ts +42 -0
  23. package/dist/config/builder.d.ts.map +1 -0
  24. package/dist/config/builder.js +113 -0
  25. package/dist/config/builder.js.map +1 -0
  26. package/dist/config/defaults.d.ts +51 -0
  27. package/dist/config/defaults.d.ts.map +1 -0
  28. package/dist/config/defaults.js +41 -0
  29. package/dist/config/defaults.js.map +1 -0
  30. package/dist/config/schema.d.ts +318 -0
  31. package/dist/config/schema.d.ts.map +1 -0
  32. package/dist/config/schema.js +100 -0
  33. package/dist/config/schema.js.map +1 -0
  34. package/dist/dependencies/resolver.d.ts +43 -0
  35. package/dist/dependencies/resolver.d.ts.map +1 -0
  36. package/dist/dependencies/resolver.js +117 -0
  37. package/dist/dependencies/resolver.js.map +1 -0
  38. package/dist/docs/architecture-generator.d.ts +3 -0
  39. package/dist/docs/architecture-generator.d.ts.map +1 -0
  40. package/dist/docs/architecture-generator.js +73 -0
  41. package/dist/docs/architecture-generator.js.map +1 -0
  42. package/dist/docs/index.d.ts +2 -0
  43. package/dist/docs/index.d.ts.map +1 -0
  44. package/dist/docs/index.js +2 -0
  45. package/dist/docs/index.js.map +1 -0
  46. package/dist/generator/index.d.ts +41 -0
  47. package/dist/generator/index.d.ts.map +1 -0
  48. package/dist/generator/index.js +201 -0
  49. package/dist/generator/index.js.map +1 -0
  50. package/dist/index.d.ts +3 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +7 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/lifecycle/index.d.ts +2 -0
  55. package/dist/lifecycle/index.d.ts.map +1 -0
  56. package/dist/lifecycle/index.js +2 -0
  57. package/dist/lifecycle/index.js.map +1 -0
  58. package/dist/lifecycle/installer.d.ts +2 -0
  59. package/dist/lifecycle/installer.d.ts.map +1 -0
  60. package/dist/lifecycle/installer.js +14 -0
  61. package/dist/lifecycle/installer.js.map +1 -0
  62. package/dist/plugins/index.d.ts +4 -0
  63. package/dist/plugins/index.d.ts.map +1 -0
  64. package/dist/plugins/index.js +4 -0
  65. package/dist/plugins/index.js.map +1 -0
  66. package/dist/plugins/loader.d.ts +5 -0
  67. package/dist/plugins/loader.d.ts.map +1 -0
  68. package/dist/plugins/loader.js +16 -0
  69. package/dist/plugins/loader.js.map +1 -0
  70. package/dist/plugins/manager.d.ts +9 -0
  71. package/dist/plugins/manager.d.ts.map +1 -0
  72. package/dist/plugins/manager.js +41 -0
  73. package/dist/plugins/manager.js.map +1 -0
  74. package/dist/plugins/types.d.ts +17 -0
  75. package/dist/plugins/types.d.ts.map +1 -0
  76. package/dist/plugins/types.js +2 -0
  77. package/dist/plugins/types.js.map +1 -0
  78. package/dist/templates/registry.d.ts +108 -0
  79. package/dist/templates/registry.d.ts.map +1 -0
  80. package/dist/templates/registry.js +238 -0
  81. package/dist/templates/registry.js.map +1 -0
  82. package/dist/templates/utils.d.ts +49 -0
  83. package/dist/templates/utils.d.ts.map +1 -0
  84. package/dist/templates/utils.js +103 -0
  85. package/dist/templates/utils.js.map +1 -0
  86. package/dist/testing/configurer.d.ts +29 -0
  87. package/dist/testing/configurer.d.ts.map +1 -0
  88. package/dist/testing/configurer.js +163 -0
  89. package/dist/testing/configurer.js.map +1 -0
  90. package/package.json +84 -0
package/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # react-scaffold
2
+
3
+ Production-ready React CLI scaffolder with first-class testing support, flexible runtimes (Vite/Next.js), and a composable template system based on [bulletproof-react](https://github.com/alan2207/bulletproof-react) architecture.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Vite & Next.js Support** — Choose your runtime
8
+ - 🧪 **Testing as First-Class Citizen** — Vitest, Jest, React Testing Library, Playwright, Cypress
9
+ - 🎨 **Flexible Styling** — Tailwind CSS, CSS Modules, or plain CSS
10
+ - 📦 **State Management** — Zustand or Redux Toolkit
11
+ - 🔄 **Data Fetching** — TanStack Query with DevTools
12
+ - 📁 **Feature-Based Architecture** — Scalable project structure
13
+ - ⚡ **Zero Config** — Smart defaults, minimal prompts
14
+
15
+ ## Quick Start
16
+
17
+ ```bash
18
+ npx create-react-forge
19
+ ```
20
+
21
+ Or install globally:
22
+
23
+ ```bash
24
+ npm install -g create-react-forge
25
+ create-react-forge
26
+ ```
27
+
28
+ ## What You Get
29
+
30
+ A production-ready React project with:
31
+
32
+ ```
33
+ my-app/
34
+ ├── src/
35
+ │ ├── app/ # App setup (providers, router)
36
+ │ ├── components/ # Shared UI components
37
+ │ ├── features/ # Feature-based modules
38
+ │ ├── hooks/ # Custom hooks
39
+ │ ├── lib/ # Utilities, API client
40
+ │ ├── stores/ # State management
41
+ │ ├── testing/ # Test utilities, mocks
42
+ │ └── types/ # TypeScript types
43
+ ├── tests/ # E2E tests
44
+ └── [config files]
45
+ ```
46
+
47
+ ## Configuration Options
48
+
49
+ | Option | Choices |
50
+ |--------|---------|
51
+ | **Runtime** | Vite, Next.js |
52
+ | **Language** | TypeScript, JavaScript |
53
+ | **Styling** | Tailwind, CSS Modules, CSS |
54
+ | **State** | Zustand, Redux, None |
55
+ | **Data Fetching** | TanStack Query, None |
56
+ | **Unit Testing** | Vitest, Jest |
57
+ | **E2E Testing** | Playwright, Cypress, None |
58
+ | **Package Manager** | npm, yarn, pnpm |
59
+
60
+ ## Architecture
61
+
62
+ This project implements a modular, layered CLI architecture. Generated projects follow the [bulletproof-react](https://github.com/alan2207/bulletproof-react) patterns:
63
+
64
+ - Feature-based folder structure
65
+ - Co-located tests with features
66
+ - Centralized API client
67
+ - Type-safe throughout
68
+
69
+ See [ARCHITECTURE.md](./ARCHITECTURE.md) for detailed design documentation.
70
+
71
+ ## Development
72
+
73
+ ```bash
74
+ # Install dependencies
75
+ npm install
76
+
77
+ # Run CLI in dev mode
78
+ npm run dev
79
+
80
+ # Run tests
81
+ npm run test
82
+ npm run test:watch
83
+
84
+ # Build for production
85
+ npm run build
86
+ ```
87
+
88
+ ## Contributing
89
+
90
+ We welcome contributions! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
91
+
92
+ ### Quick Contribution Steps
93
+
94
+ 1. Fork the repository
95
+ 2. Create a feature branch: `git checkout -b feature/amazing-feature`
96
+ 3. Make your changes
97
+ 4. Run tests: `npm run test`
98
+ 5. Submit a pull request
99
+
100
+ ## Related Projects
101
+
102
+ - [bulletproof-react](https://github.com/alan2207/bulletproof-react) — Architecture reference
103
+ - [Vite](https://vitejs.dev/) — Build tool
104
+ - [Next.js](https://nextjs.org/) — React framework
105
+ - [TanStack Query](https://tanstack.com/query) — Data fetching
106
+
107
+ ## License
108
+
109
+ MIT
@@ -0,0 +1,100 @@
1
+ import type { ProjectConfig } from '../config/schema.js';
2
+ /**
3
+ * Manages assembly of generated project files
4
+ */
5
+ export declare class ProjectAssembler {
6
+ private projectPath;
7
+ private config;
8
+ private fileMap;
9
+ private packageJson;
10
+ constructor(projectPath: string, config: ProjectConfig);
11
+ /**
12
+ * Create base package.json structure
13
+ */
14
+ private createBasePackageJson;
15
+ /**
16
+ * Add a file to the project
17
+ */
18
+ addFile(filePath: string, content: string): void;
19
+ /**
20
+ * Add multiple files from a Map
21
+ */
22
+ addFiles(files: Map<string, string>): void;
23
+ /**
24
+ * Get all registered files
25
+ */
26
+ getFiles(): Map<string, string>;
27
+ /**
28
+ * Add dependencies to package.json
29
+ */
30
+ addDependencies(deps: Record<string, string>): void;
31
+ /**
32
+ * Add dev dependencies to package.json
33
+ */
34
+ addDevDependencies(devDeps: Record<string, string>): void;
35
+ /**
36
+ * Add scripts to package.json
37
+ */
38
+ addScripts(scripts: Record<string, string>): void;
39
+ /**
40
+ * Merge template dependencies and scripts
41
+ */
42
+ mergeTemplateDeps(data: {
43
+ dependencies: Record<string, string>;
44
+ devDependencies: Record<string, string>;
45
+ scripts: Record<string, string>;
46
+ }): void;
47
+ /**
48
+ * Set package.json content
49
+ */
50
+ setPackageJson(pkg: PackageJson): void;
51
+ /**
52
+ * Get package.json
53
+ */
54
+ getPackageJson(): PackageJson;
55
+ /**
56
+ * Sort dependencies alphabetically
57
+ */
58
+ private sortDependencies;
59
+ /**
60
+ * Finalize package.json with sorted dependencies
61
+ */
62
+ private finalizePackageJson;
63
+ /**
64
+ * Create project directory
65
+ */
66
+ createProjectDirectory(): void;
67
+ /**
68
+ * Write a single file to disk
69
+ */
70
+ private writeFile;
71
+ /**
72
+ * Write all files to disk
73
+ */
74
+ writeFiles(): {
75
+ filesWritten: number;
76
+ errors: string[];
77
+ };
78
+ /**
79
+ * Get configuration
80
+ */
81
+ getConfig(): ProjectConfig;
82
+ /**
83
+ * Get project path
84
+ */
85
+ getProjectPath(): string;
86
+ }
87
+ /**
88
+ * Package.json structure
89
+ */
90
+ export interface PackageJson {
91
+ name: string;
92
+ version: string;
93
+ private?: boolean;
94
+ type?: string;
95
+ scripts?: Record<string, string>;
96
+ dependencies?: Record<string, string>;
97
+ devDependencies?: Record<string, string>;
98
+ [key: string]: unknown;
99
+ }
100
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assembler/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAyBzD;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,WAAW,CAAc;gBAErB,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa;IAMtD;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAY7B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAMhD;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAM1C;;OAEG;IACH,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAI/B;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAOnD;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAOzD;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAOjD;;OAEG;IACH,iBAAiB,CAAC,IAAI,EAAE;QACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACjC,GAAG,IAAI;IAMR;;OAEG;IACH,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI;IAItC;;OAEG;IACH,cAAc,IAAI,WAAW;IAI7B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;OAEG;IACH,sBAAsB,IAAI,IAAI;IAM9B;;OAEG;IACH,OAAO,CAAC,SAAS;IAiBjB;;OAEG;IACH,UAAU,IAAI;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IA4BxD;;OAEG;IACH,SAAS,IAAI,aAAa;IAI1B;;OAEG;IACH,cAAc,IAAI,MAAM;CAGzB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
@@ -0,0 +1,198 @@
1
+ import { copyFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { dirname, join } from 'path';
3
+ /**
4
+ * Template variable substitution patterns
5
+ */
6
+ const TEMPLATE_VARIABLES = {
7
+ '{{PROJECT_NAME}}': (config) => config.name,
8
+ '{{PROJECT_DESCRIPTION}}': () => 'A production-ready React application',
9
+ '{{AUTHOR}}': () => '',
10
+ '{{LICENSE}}': () => 'MIT',
11
+ };
12
+ /**
13
+ * Apply template variable substitution to content
14
+ */
15
+ function applyTemplateVariables(content, config) {
16
+ let result = content;
17
+ for (const [pattern, getValue] of Object.entries(TEMPLATE_VARIABLES)) {
18
+ result = result.replaceAll(pattern, getValue(config));
19
+ }
20
+ return result;
21
+ }
22
+ /**
23
+ * Manages assembly of generated project files
24
+ */
25
+ export class ProjectAssembler {
26
+ constructor(projectPath, config) {
27
+ this.fileMap = new Map();
28
+ this.projectPath = projectPath;
29
+ this.config = config;
30
+ this.packageJson = this.createBasePackageJson();
31
+ }
32
+ /**
33
+ * Create base package.json structure
34
+ */
35
+ createBasePackageJson() {
36
+ return {
37
+ name: this.config.name,
38
+ version: '0.1.0',
39
+ private: true,
40
+ type: 'module',
41
+ scripts: {},
42
+ dependencies: {},
43
+ devDependencies: {},
44
+ };
45
+ }
46
+ /**
47
+ * Add a file to the project
48
+ */
49
+ addFile(filePath, content) {
50
+ // Apply template variable substitution
51
+ const processedContent = applyTemplateVariables(content, this.config);
52
+ this.fileMap.set(filePath, processedContent);
53
+ }
54
+ /**
55
+ * Add multiple files from a Map
56
+ */
57
+ addFiles(files) {
58
+ files.forEach((content, path) => {
59
+ this.addFile(path, content);
60
+ });
61
+ }
62
+ /**
63
+ * Get all registered files
64
+ */
65
+ getFiles() {
66
+ return new Map(this.fileMap);
67
+ }
68
+ /**
69
+ * Add dependencies to package.json
70
+ */
71
+ addDependencies(deps) {
72
+ this.packageJson.dependencies = {
73
+ ...this.packageJson.dependencies,
74
+ ...deps,
75
+ };
76
+ }
77
+ /**
78
+ * Add dev dependencies to package.json
79
+ */
80
+ addDevDependencies(devDeps) {
81
+ this.packageJson.devDependencies = {
82
+ ...this.packageJson.devDependencies,
83
+ ...devDeps,
84
+ };
85
+ }
86
+ /**
87
+ * Add scripts to package.json
88
+ */
89
+ addScripts(scripts) {
90
+ this.packageJson.scripts = {
91
+ ...this.packageJson.scripts,
92
+ ...scripts,
93
+ };
94
+ }
95
+ /**
96
+ * Merge template dependencies and scripts
97
+ */
98
+ mergeTemplateDeps(data) {
99
+ this.addDependencies(data.dependencies);
100
+ this.addDevDependencies(data.devDependencies);
101
+ this.addScripts(data.scripts);
102
+ }
103
+ /**
104
+ * Set package.json content
105
+ */
106
+ setPackageJson(pkg) {
107
+ this.packageJson = { ...pkg };
108
+ }
109
+ /**
110
+ * Get package.json
111
+ */
112
+ getPackageJson() {
113
+ return this.packageJson;
114
+ }
115
+ /**
116
+ * Sort dependencies alphabetically
117
+ */
118
+ sortDependencies(deps) {
119
+ return Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));
120
+ }
121
+ /**
122
+ * Finalize package.json with sorted dependencies
123
+ */
124
+ finalizePackageJson() {
125
+ return {
126
+ ...this.packageJson,
127
+ dependencies: this.sortDependencies(this.packageJson.dependencies || {}),
128
+ devDependencies: this.sortDependencies(this.packageJson.devDependencies || {}),
129
+ };
130
+ }
131
+ /**
132
+ * Create project directory
133
+ */
134
+ createProjectDirectory() {
135
+ if (!existsSync(this.projectPath)) {
136
+ mkdirSync(this.projectPath, { recursive: true });
137
+ }
138
+ }
139
+ /**
140
+ * Write a single file to disk
141
+ */
142
+ writeFile(relativePath, content) {
143
+ const fullPath = join(this.projectPath, relativePath);
144
+ const dir = dirname(fullPath);
145
+ if (!existsSync(dir)) {
146
+ mkdirSync(dir, { recursive: true });
147
+ }
148
+ // Handle binary files (marked with __BINARY__:)
149
+ if (content.startsWith('__BINARY__:')) {
150
+ const sourcePath = content.replace('__BINARY__:', '');
151
+ copyFileSync(sourcePath, fullPath);
152
+ }
153
+ else {
154
+ writeFileSync(fullPath, content, 'utf-8');
155
+ }
156
+ }
157
+ /**
158
+ * Write all files to disk
159
+ */
160
+ writeFiles() {
161
+ const errors = [];
162
+ let filesWritten = 0;
163
+ this.createProjectDirectory();
164
+ for (const [filePath, content] of this.fileMap.entries()) {
165
+ try {
166
+ this.writeFile(filePath, content);
167
+ filesWritten++;
168
+ }
169
+ catch (error) {
170
+ errors.push(`Failed to write ${filePath}: ${error}`);
171
+ }
172
+ }
173
+ // Write package.json
174
+ try {
175
+ const pkgPath = join(this.projectPath, 'package.json');
176
+ const finalPkg = this.finalizePackageJson();
177
+ writeFileSync(pkgPath, JSON.stringify(finalPkg, null, 2) + '\n', 'utf-8');
178
+ filesWritten++;
179
+ }
180
+ catch (error) {
181
+ errors.push(`Failed to write package.json: ${error}`);
182
+ }
183
+ return { filesWritten, errors };
184
+ }
185
+ /**
186
+ * Get configuration
187
+ */
188
+ getConfig() {
189
+ return this.config;
190
+ }
191
+ /**
192
+ * Get project path
193
+ */
194
+ getProjectPath() {
195
+ return this.projectPath;
196
+ }
197
+ }
198
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assembler/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Merges configuration objects with smart strategies
3
+ */
4
+ export declare class ConfigMerger {
5
+ /**
6
+ * Deep merge objects with array concatenation
7
+ */
8
+ static merge(...objects: Record<string, unknown>[]): Record<string, unknown>;
9
+ /**
10
+ * Merge package.json files intelligently
11
+ */
12
+ static mergePackageJson(...packages: Record<string, unknown>[]): Record<string, unknown>;
13
+ }
14
+ //# sourceMappingURL=merger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merger.d.ts","sourceRoot":"","sources":["../../src/assembler/merger.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,YAAY;IACvB;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAM5E;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAG,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CA8CzF"}
@@ -0,0 +1,58 @@
1
+ import deepmerge from 'deepmerge';
2
+ /**
3
+ * Merges configuration objects with smart strategies
4
+ */
5
+ export class ConfigMerger {
6
+ /**
7
+ * Deep merge objects with array concatenation
8
+ */
9
+ static merge(...objects) {
10
+ return deepmerge.all(objects, {
11
+ arrayMerge: (target, source) => [...target, ...source],
12
+ });
13
+ }
14
+ /**
15
+ * Merge package.json files intelligently
16
+ */
17
+ static mergePackageJson(...packages) {
18
+ const merged = {};
19
+ for (const pkg of packages) {
20
+ // Regular merge for most fields
21
+ for (const [key, value] of Object.entries(pkg)) {
22
+ if (key === 'scripts') {
23
+ // Merge scripts by combining them
24
+ if (!merged.scripts) {
25
+ merged.scripts = {};
26
+ }
27
+ Object.assign(merged.scripts, value);
28
+ }
29
+ else if (key === 'dependencies' ||
30
+ key === 'devDependencies' ||
31
+ key === 'peerDependencies') {
32
+ // Merge dependencies, later versions win
33
+ if (!merged[key]) {
34
+ merged[key] = {};
35
+ }
36
+ Object.assign(merged[key], value);
37
+ }
38
+ else if (Array.isArray(value)) {
39
+ // Deduplicate arrays
40
+ if (!merged[key]) {
41
+ merged[key] = [];
42
+ }
43
+ merged[key] = Array.from(new Set([...merged[key], ...value]));
44
+ }
45
+ else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
46
+ // Deep merge objects
47
+ merged[key] = this.merge(merged[key], value);
48
+ }
49
+ else {
50
+ // Primitive: later value wins
51
+ merged[key] = value;
52
+ }
53
+ }
54
+ }
55
+ return merged;
56
+ }
57
+ }
58
+ //# sourceMappingURL=merger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merger.js","sourceRoot":"","sources":["../../src/assembler/merger.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAC;AAElC;;GAEG;AACH,MAAM,OAAO,YAAY;IACvB;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,OAAkC;QAChD,OAAO,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE;YAC5B,UAAU,EAAE,CAAC,MAAiB,EAAE,MAAiB,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC;SAC7E,CAA4B,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAG,QAAmC;QAC5D,MAAM,MAAM,GAA4B,EAAE,CAAC;QAE3C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,gCAAgC;YAChC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;oBACtB,kCAAkC;oBAClC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;wBACpB,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;oBACtB,CAAC;oBACD,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,OAAkC,EACzC,KAAgC,CACjC,CAAC;gBACJ,CAAC;qBAAM,IACL,GAAG,KAAK,cAAc;oBACtB,GAAG,KAAK,iBAAiB;oBACzB,GAAG,KAAK,kBAAkB,EAC1B,CAAC;oBACD,yCAAyC;oBACzC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;wBACjB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;oBACnB,CAAC;oBACD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAA4B,EAAE,KAAgC,CAAC,CAAC;gBAC1F,CAAC;qBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAChC,qBAAqB;oBACrB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;wBACjB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;oBACnB,CAAC;oBACD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAI,MAAM,CAAC,GAAG,CAAe,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC/E,CAAC;qBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAChF,qBAAqB;oBACrB,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CACtB,MAAM,CAAC,GAAG,CAA4B,EACtC,KAAgC,CACjC,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,8BAA8B;oBAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,57 @@
1
+ import type { PromptAnswers } from './prompts.js';
2
+ /**
3
+ * Convert prompt answers to ProjectConfig
4
+ */
5
+ export declare function promptAnswersToConfig(answers: PromptAnswers): {
6
+ path: string;
7
+ name: string;
8
+ runtime: "vite" | "nextjs";
9
+ language: "javascript" | "typescript";
10
+ styling: {
11
+ solution: "css" | "tailwind" | "styled-components" | "css-modules";
12
+ };
13
+ stateManagement: "none" | "redux" | "zustand";
14
+ dataFetching: {
15
+ enabled: boolean;
16
+ library: "tanstack-query";
17
+ };
18
+ testing: {
19
+ enabled: boolean;
20
+ unit: {
21
+ enabled: boolean;
22
+ runner: "vitest" | "jest";
23
+ };
24
+ component: {
25
+ enabled: boolean;
26
+ library: "testing-library";
27
+ };
28
+ e2e: {
29
+ enabled: boolean;
30
+ runner: "none" | "playwright" | "cypress";
31
+ };
32
+ };
33
+ linting: {
34
+ prettier: boolean;
35
+ };
36
+ packageManager: "npm" | "yarn" | "pnpm";
37
+ git: {
38
+ init: boolean;
39
+ initialCommit: boolean;
40
+ };
41
+ plugins: {
42
+ name: string;
43
+ config?: unknown;
44
+ }[];
45
+ };
46
+ /**
47
+ * Validate user input
48
+ */
49
+ export declare function validateProjectName(name: string): {
50
+ valid: boolean;
51
+ error?: string;
52
+ };
53
+ /**
54
+ * Main CLI entry point
55
+ */
56
+ export declare function main(): Promise<void>;
57
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+B3D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAQpF;AAuBD;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA2C1C"}
@@ -0,0 +1,110 @@
1
+ import chalk from 'chalk';
2
+ import { resolve } from 'path';
3
+ import { ConfigBuilder } from '../config/builder.js';
4
+ import { generateProject } from '../generator/index.js';
5
+ import { promptForProjectDetails } from './prompts.js';
6
+ /**
7
+ * Convert prompt answers to ProjectConfig
8
+ */
9
+ export function promptAnswersToConfig(answers) {
10
+ const builder = new ConfigBuilder();
11
+ // Resolve project path to absolute path
12
+ const projectPath = resolve(process.cwd(), answers.projectPath);
13
+ builder
14
+ .setName(answers.projectName)
15
+ .setPath(projectPath)
16
+ .setRuntime(answers.runtime)
17
+ .setLanguage(answers.language)
18
+ .setStyling(answers.styling)
19
+ .setStateManagement(answers.stateManagement)
20
+ .setPackageManager(answers.packageManager)
21
+ .setGitInit(answers.git)
22
+ .setDataFetchingEnabled(answers.dataFetching);
23
+ if (answers.testing !== 'none') {
24
+ builder
25
+ .setTestingEnabled(true)
26
+ .setUnitTestRunner(answers.unitRunner)
27
+ .setE2ETestRunner(answers.e2eRunner);
28
+ }
29
+ else {
30
+ builder.setTestingEnabled(false);
31
+ }
32
+ if (!answers.git) {
33
+ builder.setGitInit(false);
34
+ }
35
+ return builder.build();
36
+ }
37
+ /**
38
+ * Validate user input
39
+ */
40
+ export function validateProjectName(name) {
41
+ if (!name) {
42
+ return { valid: false, error: 'Project name is required' };
43
+ }
44
+ if (!/^[a-z0-9-]+$/.test(name)) {
45
+ return { valid: false, error: 'Project name must be lowercase alphanumeric with hyphens' };
46
+ }
47
+ return { valid: true };
48
+ }
49
+ /**
50
+ * Display project summary
51
+ */
52
+ function displayProjectSummary(config) {
53
+ console.log(chalk.cyan('\n📋 Project Configuration:\n'));
54
+ console.log(chalk.gray(' Name: ') + chalk.white(config.name));
55
+ console.log(chalk.gray(' Path: ') + chalk.white(config.path));
56
+ console.log(chalk.gray(' Runtime: ') + chalk.white(config.runtime));
57
+ console.log(chalk.gray(' Language: ') + chalk.white(config.language));
58
+ console.log(chalk.gray(' Styling: ') + chalk.white(config.styling.solution));
59
+ console.log(chalk.gray(' State: ') + chalk.white(config.stateManagement || 'none'));
60
+ console.log(chalk.gray(' Data Fetching: ') + chalk.white(config.dataFetching.enabled ? 'TanStack Query' : 'none'));
61
+ console.log(chalk.gray(' Testing: ') + chalk.white(config.testing.enabled ? `${config.testing.unit?.runner}` : 'disabled'));
62
+ if (config.testing.enabled && config.testing.e2e?.enabled) {
63
+ console.log(chalk.gray(' E2E Testing: ') + chalk.white(config.testing.e2e.runner));
64
+ }
65
+ console.log(chalk.gray(' Package Manager: ') + chalk.white(config.packageManager));
66
+ console.log(chalk.gray(' Git: ') + chalk.white(config.git.init ? 'yes' : 'no'));
67
+ console.log();
68
+ }
69
+ /**
70
+ * Main CLI entry point
71
+ */
72
+ export async function main() {
73
+ console.log(chalk.cyan.bold('\n ⚛️ react-setup\n'));
74
+ console.log(chalk.gray(' Production-ready React scaffolder with first-class testing\n'));
75
+ try {
76
+ // Get user input
77
+ const answers = await promptForProjectDetails();
78
+ // Convert to config
79
+ const config = promptAnswersToConfig(answers);
80
+ // Validate
81
+ const validation = new ConfigBuilder(config).validate();
82
+ if (!validation.success) {
83
+ console.error(chalk.red('\n❌ Configuration validation failed:'));
84
+ validation.errors?.forEach((error) => console.error(chalk.red(` • ${error}`)));
85
+ process.exit(1);
86
+ }
87
+ // Display summary
88
+ displayProjectSummary(config);
89
+ // Generate project
90
+ console.log(chalk.cyan('🚀 Creating project...\n'));
91
+ const result = await generateProject(config);
92
+ if (!result.success) {
93
+ console.error(chalk.red('\n❌ Project generation failed:'));
94
+ result.errors.forEach((error) => console.error(chalk.red(` • ${error}`)));
95
+ process.exit(1);
96
+ }
97
+ if (result.warnings.length > 0) {
98
+ console.log(chalk.yellow('\n⚠️ Warnings:'));
99
+ result.warnings.forEach((warning) => console.log(chalk.yellow(` • ${warning}`)));
100
+ }
101
+ }
102
+ catch (error) {
103
+ if (error instanceof Error && error.message === 'User force closed the prompt') {
104
+ console.log(chalk.yellow('\n✋ Setup cancelled\n'));
105
+ process.exit(0);
106
+ }
107
+ throw error;
108
+ }
109
+ }
110
+ //# sourceMappingURL=index.js.map