create-project-cli-cm 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.
package/test.js ADDED
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Test Suite for create-project-cli
3
+ * Run this to verify all functionality works correctly
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { execSync } = require('child_process');
9
+
10
+ class TestRunner {
11
+ constructor() {
12
+ this.testsPassed = 0;
13
+ this.testsFailed = 0;
14
+ this.testResults = [];
15
+ }
16
+
17
+ /**
18
+ * Run a test and track results
19
+ */
20
+ runTest(name, testFn) {
21
+ try {
22
+ console.log(`\n๐Ÿงช Testing: ${name}...`);
23
+ testFn();
24
+ this.testsPassed++;
25
+ this.testResults.push({ name, status: 'PASS' });
26
+ console.log(`โœ“ ${name} - PASSED`);
27
+ } catch (error) {
28
+ this.testsFailed++;
29
+ this.testResults.push({ name, status: 'FAIL', error: error.message });
30
+ console.error(`โœ— ${name} - FAILED: ${error.message}`);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Clean up test directories
36
+ */
37
+ cleanup() {
38
+ const testDirs = ['test-basic-app', 'test-web-app', 'test-api-app', 'test-cli-app'];
39
+ testDirs.forEach(dir => {
40
+ const dirPath = path.join(process.cwd(), dir);
41
+ if (fs.existsSync(dirPath)) {
42
+ fs.rmSync(dirPath, { recursive: true, force: true });
43
+ }
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Assert that a condition is true
49
+ */
50
+ assert(condition, message) {
51
+ if (!condition) {
52
+ throw new Error(message || 'Assertion failed');
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Test: Basic template creation
58
+ */
59
+ testBasicTemplate() {
60
+ execSync('node index.js test-basic-app --template basic', { stdio: 'ignore' });
61
+
62
+ const projectPath = path.join(process.cwd(), 'test-basic-app');
63
+ this.assert(fs.existsSync(projectPath), 'Project directory should exist');
64
+ this.assert(fs.existsSync(path.join(projectPath, 'src')), 'src directory should exist');
65
+ this.assert(fs.existsSync(path.join(projectPath, 'utils')), 'utils directory should exist');
66
+ this.assert(fs.existsSync(path.join(projectPath, 'package.json')), 'package.json should exist');
67
+ this.assert(fs.existsSync(path.join(projectPath, 'README.md')), 'README.md should exist');
68
+
69
+ // Cleanup
70
+ fs.rmSync(projectPath, { recursive: true, force: true });
71
+ }
72
+
73
+ /**
74
+ * Test: Web template creation
75
+ */
76
+ testWebTemplate() {
77
+ execSync('node index.js test-web-app -t web', { stdio: 'ignore' });
78
+
79
+ const projectPath = path.join(process.cwd(), 'test-web-app');
80
+ this.assert(fs.existsSync(path.join(projectPath, 'src', 'index.html')), 'index.html should exist');
81
+ this.assert(fs.existsSync(path.join(projectPath, 'src', 'css', 'style.css')), 'style.css should exist');
82
+ this.assert(fs.existsSync(path.join(projectPath, 'src', 'js', 'app.js')), 'app.js should exist');
83
+
84
+ // Cleanup
85
+ fs.rmSync(projectPath, { recursive: true, force: true });
86
+ }
87
+
88
+ /**
89
+ * Test: API template creation
90
+ */
91
+ testApiTemplate() {
92
+ execSync('node index.js test-api-app -t api', { stdio: 'ignore' });
93
+
94
+ const projectPath = path.join(process.cwd(), 'test-api-app');
95
+ this.assert(fs.existsSync(path.join(projectPath, 'src', 'server.js')), 'server.js should exist');
96
+ this.assert(fs.existsSync(path.join(projectPath, 'src', 'routes')), 'routes directory should exist');
97
+ this.assert(fs.existsSync(path.join(projectPath, 'src', 'controllers')), 'controllers directory should exist');
98
+ this.assert(fs.existsSync(path.join(projectPath, 'config')), 'config directory should exist');
99
+
100
+ // Cleanup
101
+ fs.rmSync(projectPath, { recursive: true, force: true });
102
+ }
103
+
104
+ /**
105
+ * Test: CLI template creation
106
+ */
107
+ testCliTemplate() {
108
+ execSync('node index.js test-cli-app -t cli', { stdio: 'ignore' });
109
+
110
+ const projectPath = path.join(process.cwd(), 'test-cli-app');
111
+ this.assert(fs.existsSync(path.join(projectPath, 'src', 'cli.js')), 'cli.js should exist');
112
+ this.assert(fs.existsSync(path.join(projectPath, 'commands')), 'commands directory should exist');
113
+
114
+ // Cleanup
115
+ fs.rmSync(projectPath, { recursive: true, force: true });
116
+ }
117
+
118
+ /**
119
+ * Test: Invalid project name handling
120
+ */
121
+ testInvalidProjectName() {
122
+ try {
123
+ execSync('node index.js "test@invalid#name" --template basic', { stdio: 'ignore' });
124
+ throw new Error('Should have failed with invalid project name');
125
+ } catch (error) {
126
+ // Expected to fail
127
+ this.assert(error.status !== 0, 'Should exit with non-zero status for invalid name');
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Test: Duplicate project name handling
133
+ */
134
+ testDuplicateProjectName() {
135
+ execSync('node index.js test-duplicate-app --template basic', { stdio: 'ignore' });
136
+
137
+ try {
138
+ execSync('node index.js test-duplicate-app --template basic', { stdio: 'ignore' });
139
+ throw new Error('Should have failed with duplicate project name');
140
+ } catch (error) {
141
+ // Expected to fail
142
+ this.assert(error.status !== 0, 'Should exit with non-zero status for duplicate name');
143
+ }
144
+
145
+ // Cleanup
146
+ const projectPath = path.join(process.cwd(), 'test-duplicate-app');
147
+ if (fs.existsSync(projectPath)) {
148
+ fs.rmSync(projectPath, { recursive: true, force: true });
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Test: Help command
154
+ */
155
+ testHelpCommand() {
156
+ const output = execSync('node index.js --help').toString();
157
+ this.assert(output.includes('USAGE'), 'Help should contain USAGE section');
158
+ this.assert(output.includes('OPTIONS'), 'Help should contain OPTIONS section');
159
+ this.assert(output.includes('EXAMPLES'), 'Help should contain EXAMPLES section');
160
+ }
161
+
162
+ /**
163
+ * Run all tests
164
+ */
165
+ runAll() {
166
+ console.log('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—');
167
+ console.log('โ•‘ CREATE-PROJECT-CLI - Test Suite โ•‘');
168
+ console.log('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n');
169
+
170
+ // Cleanup before tests
171
+ this.cleanup();
172
+
173
+ // Run tests
174
+ this.runTest('Basic Template Creation', () => this.testBasicTemplate());
175
+ this.runTest('Web Template Creation', () => this.testWebTemplate());
176
+ this.runTest('API Template Creation', () => this.testApiTemplate());
177
+ this.runTest('CLI Template Creation', () => this.testCliTemplate());
178
+ this.runTest('Invalid Project Name Handling', () => this.testInvalidProjectName());
179
+ this.runTest('Duplicate Project Name Handling', () => this.testDuplicateProjectName());
180
+ this.runTest('Help Command', () => this.testHelpCommand());
181
+
182
+ // Final cleanup
183
+ this.cleanup();
184
+
185
+ // Display results
186
+ console.log('\nโ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—');
187
+ console.log('โ•‘ Test Results โ•‘');
188
+ console.log('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n');
189
+
190
+ this.testResults.forEach(result => {
191
+ const status = result.status === 'PASS' ? 'โœ“' : 'โœ—';
192
+ console.log(`${status} ${result.name}: ${result.status}`);
193
+ if (result.error) {
194
+ console.log(` Error: ${result.error}`);
195
+ }
196
+ });
197
+
198
+ console.log(`\n๐Ÿ“Š Summary: ${this.testsPassed} passed, ${this.testsFailed} failed\n`);
199
+
200
+ if (this.testsFailed > 0) {
201
+ process.exit(1);
202
+ }
203
+ }
204
+ }
205
+
206
+ // Run tests
207
+ const runner = new TestRunner();
208
+ runner.runAll();
@@ -0,0 +1,61 @@
1
+ /**
2
+ * ArgumentParser
3
+ * Parses command-line arguments and extracts configuration
4
+ */
5
+
6
+ class ArgumentParser {
7
+ /**
8
+ * Parses command-line arguments into a configuration object
9
+ * @param {Array} args - Command-line arguments
10
+ * @returns {Object} Configuration object
11
+ */
12
+ parse(args) {
13
+ const config = {
14
+ projectName: '',
15
+ template: 'basic',
16
+ gitInit: false,
17
+ author: ''
18
+ };
19
+
20
+ // First non-flag argument is the project name
21
+ config.projectName = args.find(arg => !arg.startsWith('-'));
22
+
23
+ if (!config.projectName) {
24
+ throw new Error('Project name is required. Usage: create-proj <project-name> [options]');
25
+ }
26
+
27
+ // Parse flags
28
+ for (let i = 0; i < args.length; i++) {
29
+ const arg = args[i];
30
+
31
+ switch (arg) {
32
+ case '--template':
33
+ case '-t':
34
+ if (!args[i + 1] || args[i + 1].startsWith('-')) {
35
+ throw new Error('--template flag requires a value');
36
+ }
37
+ config.template = args[i + 1].toLowerCase();
38
+ i++; // Skip next argument as it's the value
39
+ break;
40
+
41
+ case '--git':
42
+ case '-g':
43
+ config.gitInit = true;
44
+ break;
45
+
46
+ case '--author':
47
+ case '-a':
48
+ if (!args[i + 1] || args[i + 1].startsWith('-')) {
49
+ throw new Error('--author flag requires a value');
50
+ }
51
+ config.author = args[i + 1];
52
+ i++; // Skip next argument as it's the value
53
+ break;
54
+ }
55
+ }
56
+
57
+ return config;
58
+ }
59
+ }
60
+
61
+ module.exports = ArgumentParser;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Logger
3
+ * Provides colored console output for better user experience
4
+ */
5
+
6
+ class Logger {
7
+ /**
8
+ * Log informational messages (blue)
9
+ */
10
+ info(message) {
11
+ console.log(`\x1b[36m${message}\x1b[0m`);
12
+ }
13
+
14
+ /**
15
+ * Log success messages (green)
16
+ */
17
+ success(message) {
18
+ console.log(`\x1b[32m${message}\x1b[0m`);
19
+ }
20
+
21
+ /**
22
+ * Log error messages (red)
23
+ */
24
+ error(message) {
25
+ console.error(`\x1b[31m${message}\x1b[0m`);
26
+ }
27
+
28
+ /**
29
+ * Log warning messages (yellow)
30
+ */
31
+ warning(message) {
32
+ console.log(`\x1b[33m${message}\x1b[0m`);
33
+ }
34
+
35
+ /**
36
+ * Log plain messages (no color)
37
+ */
38
+ log(message) {
39
+ console.log(message);
40
+ }
41
+ }
42
+
43
+ module.exports = Logger;