baraqex 1.0.63 → 1.0.65
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/baraqex.js +1013 -1126
- package/dist/api/hello.d.ts +3 -0
- package/dist/api/hello.d.ts.map +1 -0
- package/dist/api/users/[id].d.ts +5 -0
- package/dist/api/users/[id].d.ts.map +1 -0
- package/dist/browser.d.ts +40 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +407 -1
- package/dist/browser.js.map +4 -4
- package/dist/browser.package.json +4 -0
- package/dist/forms/index.d.ts +2 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/types.d.ts +2 -0
- package/dist/forms/types.d.ts.map +1 -0
- package/dist/frontend/components/WasmLoader.d.ts +2 -0
- package/dist/frontend/components/WasmLoader.d.ts.map +1 -0
- package/dist/frontend/hooks/useWasm.d.ts +2 -0
- package/dist/frontend/hooks/useWasm.d.ts.map +1 -0
- package/dist/frontend/index.d.ts +2 -0
- package/dist/frontend/index.d.ts.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +678 -317
- package/dist/index.js.map +4 -4
- package/dist/renderComponent.d.ts +9 -0
- package/dist/renderComponent.d.ts.map +1 -0
- package/dist/router/index.d.ts +2 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/types.d.ts +2 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/server/api-router.d.ts +16 -0
- package/dist/server/api-router.d.ts.map +1 -0
- package/dist/server/auth.d.ts +25 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/database.d.ts +22 -0
- package/dist/server/database.d.ts.map +1 -0
- package/dist/server/index.d.ts +116 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/{server.js → server/index.js} +120 -23
- package/dist/server/index.js.map +7 -0
- package/dist/server/middleware.d.ts +11 -0
- package/dist/server/middleware.d.ts.map +1 -0
- package/dist/server/package.json +4 -0
- package/dist/server/templates.d.ts +31 -0
- package/dist/server/templates.d.ts.map +1 -0
- package/dist/server/types.d.ts +69 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/utils.d.ts +70 -0
- package/dist/server/utils.d.ts.map +1 -0
- package/dist/server/wasm.d.ts +29 -0
- package/dist/server/wasm.d.ts.map +1 -0
- package/dist/server-renderer.d.ts +5 -0
- package/dist/server-renderer.d.ts.map +1 -0
- package/dist/store/index.d.ts +2 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/types.d.ts +2 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/wasm.d.ts +51 -0
- package/dist/wasm.d.ts.map +1 -0
- package/package.json +65 -56
- package/templates/basic-app/src/main.tsx +1 -0
- package/templates/fullstack-template/.env.example +42 -0
- package/templates/fullstack-template/README.md +38 -42
- package/templates/fullstack-template/package-lock.json +7932 -0
- package/templates/fullstack-template/package.json +58 -6
- package/templates/fullstack-template/server.js +28 -9
- package/templates/fullstack-template/src/App.tsx +94 -0
- package/templates/fullstack-template/src/api/auth/login.ts +75 -0
- package/templates/fullstack-template/src/api/auth/me.ts +66 -0
- package/templates/fullstack-template/src/api/auth/register.ts +59 -0
- package/templates/fullstack-template/src/api/todos/[id].ts +108 -0
- package/templates/fullstack-template/src/api/todos/index.ts +79 -0
- package/templates/fullstack-template/src/components/Dashboard.tsx +129 -0
- package/templates/fullstack-template/src/components/Header.tsx +76 -0
- package/templates/fullstack-template/src/contexts/ApiContext.tsx +69 -0
- package/templates/fullstack-template/src/contexts/AuthContext.tsx +155 -0
- package/templates/fullstack-template/src/server.ts +167 -0
- package/templates/fullstack-template/src/styles/App.css +446 -0
- package/templates/ssr-template/package-lock.json +38 -60
- package/templates/ssr-template/package.json +1 -1
- package/templates/ssr-template/src/App.tsx +4 -3
- package/templates/ssr-template/src/client.tsx +2 -1
- package/templates/wasm/App.tsx +564 -0
- package/templates/wasm/client.tsx +220 -0
- package/templates/wasm/index.tsx +21 -0
- package/templates/wasm/package-lock.json +5347 -5307
- package/templates/wasm/package.json +43 -25
- package/templates/wasm/public/example.wasm +0 -0
- package/templates/wasm/public/wasm_exec.js +1 -12
- package/templates/wasm/server.ts +145 -0
- package/templates/wasm/vite.config.ts +42 -24
- package/README_WASM.md +0 -472
- package/dist/server.js.map +0 -7
- package/templates/basic-app/src/App.jsx +0 -0
- package/templates/basic-app/src/App.tsx +0 -0
- package/templates/fullstack-template/src/api/hello.js +0 -17
- package/templates/fullstack-template/src/pages/index.js +0 -206
- /package/templates/{basic-app/server.js → wasm/go/wasm_exec.js} +0 -0
package/bin/baraqex.js
CHANGED
|
@@ -8,33 +8,60 @@ import { createSpinner } from 'nanospinner';
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import fs from 'fs-extra';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
|
-
import { exec } from 'child_process';
|
|
11
|
+
import { exec, spawn } from 'child_process';
|
|
12
12
|
import { promisify } from 'util';
|
|
13
13
|
import boxen from 'boxen';
|
|
14
14
|
import terminalLink from 'terminal-link';
|
|
15
15
|
import updateNotifier from 'update-notifier';
|
|
16
16
|
import ora from 'ora';
|
|
17
17
|
import figlet from 'figlet';
|
|
18
|
+
import semver from 'semver';
|
|
19
|
+
import open from 'open';
|
|
20
|
+
import glob from 'glob';
|
|
21
|
+
import { WebSocketServer } from 'ws';
|
|
22
|
+
import chokidar from 'chokidar';
|
|
23
|
+
import { performance } from 'perf_hooks';
|
|
24
|
+
import os from 'os';
|
|
25
|
+
import { createRequire } from 'module';
|
|
18
26
|
|
|
19
27
|
// Convert to ESM-friendly __dirname equivalent
|
|
20
28
|
const __filename = fileURLToPath(import.meta.url);
|
|
21
29
|
const __dirname = path.dirname(__filename);
|
|
22
30
|
const execAsync = promisify(exec);
|
|
31
|
+
const require = createRequire(import.meta.url);
|
|
23
32
|
|
|
24
|
-
//
|
|
33
|
+
// Enhanced package info with comprehensive update checking
|
|
34
|
+
let packageInfo = {};
|
|
25
35
|
try {
|
|
26
|
-
|
|
27
|
-
const notifier = updateNotifier({
|
|
36
|
+
packageInfo = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
|
37
|
+
const notifier = updateNotifier({
|
|
38
|
+
pkg: packageInfo,
|
|
39
|
+
updateCheckInterval: 1000 * 60 * 60 * 12, // Check every 12 hours
|
|
40
|
+
shouldNotifyInNpmScript: true
|
|
41
|
+
});
|
|
28
42
|
|
|
29
|
-
if (notifier.update) {
|
|
43
|
+
if (notifier.update && notifier.update.latest !== packageInfo.version) {
|
|
44
|
+
const versionDiff = semver.diff(notifier.update.current, notifier.update.latest);
|
|
45
|
+
const urgency = versionDiff === 'major' ? '🚨 MAJOR' :
|
|
46
|
+
versionDiff === 'minor' ? '⚠️ MINOR' :
|
|
47
|
+
'🔧 PATCH';
|
|
48
|
+
|
|
30
49
|
const updateMessage = boxen(
|
|
31
|
-
|
|
32
|
-
|
|
50
|
+
`${chalk.yellow(`📦 Update available! ${urgency} Update`)}\n\n` +
|
|
51
|
+
`${chalk.dim('Current:')} ${chalk.red(notifier.update.current)}\n` +
|
|
52
|
+
`${chalk.dim('Latest:')} ${chalk.green(notifier.update.latest)}\n\n` +
|
|
53
|
+
`${chalk.cyan('Run one of these commands to update:')}\n` +
|
|
54
|
+
`• ${chalk.yellow('npm i -g baraqex@latest')}\n` +
|
|
55
|
+
`• ${chalk.yellow('yarn global add baraqex@latest')}\n` +
|
|
56
|
+
`• ${chalk.yellow('pnpm add -g baraqex@latest')}\n\n` +
|
|
57
|
+
`${chalk.dim('Changelog:')} ${terminalLink('View changes', `https://github.com/mohamedx2/baraqex/releases/tag/v${notifier.update.latest}`)}\n` +
|
|
58
|
+
`${chalk.dim('Documentation:')} ${terminalLink('Updated docs', 'https://www.baraqex.tech/docs')}`,
|
|
33
59
|
{
|
|
34
60
|
padding: 1,
|
|
35
61
|
margin: 1,
|
|
36
62
|
borderStyle: 'round',
|
|
37
|
-
borderColor: '
|
|
63
|
+
borderColor: versionDiff === 'major' ? 'red' : versionDiff === 'minor' ? 'yellow' : 'green',
|
|
64
|
+
title: '🎯 Baraqex Update Available'
|
|
38
65
|
}
|
|
39
66
|
);
|
|
40
67
|
console.log(updateMessage);
|
|
@@ -43,1280 +70,1140 @@ try {
|
|
|
43
70
|
// Silently continue if update check fails
|
|
44
71
|
}
|
|
45
72
|
|
|
46
|
-
// CLI instance
|
|
73
|
+
// Enhanced CLI instance with global configuration
|
|
47
74
|
const program = new Command();
|
|
48
75
|
|
|
49
|
-
//
|
|
76
|
+
// Global configuration store
|
|
77
|
+
const globalConfig = {
|
|
78
|
+
analytics: true,
|
|
79
|
+
autoUpdate: true,
|
|
80
|
+
defaultTemplate: 'basic-app',
|
|
81
|
+
defaultPackageManager: 'npm',
|
|
82
|
+
telemetry: true
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Load user preferences
|
|
86
|
+
const configPath = path.join(os.homedir(), '.baraqex', 'config.json');
|
|
87
|
+
try {
|
|
88
|
+
if (fs.existsSync(configPath)) {
|
|
89
|
+
const userConfig = fs.readJsonSync(configPath);
|
|
90
|
+
Object.assign(globalConfig, userConfig);
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
// Use defaults if config can't be loaded
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Performance monitoring
|
|
97
|
+
const perfMonitor = {
|
|
98
|
+
startTime: performance.now(),
|
|
99
|
+
checkpoints: new Map(),
|
|
100
|
+
|
|
101
|
+
checkpoint(name) {
|
|
102
|
+
this.checkpoints.set(name, performance.now() - this.startTime);
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
report() {
|
|
106
|
+
const total = performance.now() - this.startTime;
|
|
107
|
+
console.log(chalk.dim(`\n⏱️ Performance: ${total.toFixed(2)}ms total`));
|
|
108
|
+
for (const [name, time] of this.checkpoints) {
|
|
109
|
+
console.log(chalk.dim(` • ${name}: ${time.toFixed(2)}ms`));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Enhanced banner with system information and tips
|
|
50
115
|
const displayBanner = () => {
|
|
51
116
|
const titleText = figlet.textSync('Baraqex', {
|
|
52
|
-
font: '
|
|
53
|
-
horizontalLayout: '
|
|
54
|
-
verticalLayout: '
|
|
117
|
+
font: 'ANSI Shadow',
|
|
118
|
+
horizontalLayout: 'fitted',
|
|
119
|
+
verticalLayout: 'fitted'
|
|
55
120
|
});
|
|
56
121
|
|
|
57
|
-
console.log('\n' + gradient.
|
|
122
|
+
console.log('\n' + gradient(['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57']).multiline(titleText));
|
|
123
|
+
|
|
124
|
+
const stats = getProjectStats();
|
|
125
|
+
const systemInfo = getSystemInfo();
|
|
126
|
+
|
|
127
|
+
// Daily tip system
|
|
128
|
+
const tips = [
|
|
129
|
+
"💡 Use 'baraqex dev --open' to automatically open your browser",
|
|
130
|
+
"🚀 Try 'baraqex add:component Button --typescript' for TypeScript components",
|
|
131
|
+
"📊 Run 'baraqex doctor' to check your project health",
|
|
132
|
+
"🎨 Use 'baraqex add:layout Dashboard --sidebar' for instant layouts",
|
|
133
|
+
"⚡ Enable hot reload with 'baraqex dev --hot'",
|
|
134
|
+
"📱 Generate PWA with 'baraqex add:pwa'",
|
|
135
|
+
"🔧 Customize builds with 'baraqex build --analyze'",
|
|
136
|
+
"🌐 Deploy instantly with 'baraqex deploy --platform vercel'"
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
const dailyTip = tips[new Date().getDate() % tips.length];
|
|
58
140
|
|
|
59
141
|
console.log(boxen(
|
|
60
|
-
`${chalk.bold('
|
|
61
|
-
`${chalk.dim('Version:')} ${chalk.cyan(
|
|
62
|
-
`${chalk.dim('
|
|
63
|
-
|
|
142
|
+
`${chalk.bold.cyan('🚀 Modern Full-Stack Framework with AI-Powered Development')}\n\n` +
|
|
143
|
+
`${chalk.dim('Version:')} ${chalk.cyan(packageInfo.version)} ${chalk.dim('•')} ${chalk.dim('Node:')} ${chalk.green(process.version)}\n` +
|
|
144
|
+
`${chalk.dim('Platform:')} ${chalk.green(systemInfo.platform)} ${chalk.dim('•')} ${chalk.dim('Memory:')} ${chalk.green(systemInfo.memory)}\n\n` +
|
|
145
|
+
(stats.isProject ?
|
|
146
|
+
`${chalk.bold.green('✓ Current Project:')} ${chalk.cyan(stats.name)}\n` +
|
|
147
|
+
`${chalk.dim('•')} ${chalk.green(stats.components)} components ${chalk.dim('•')} ${chalk.green(stats.pages)} pages ${chalk.dim('•')} ${chalk.green(stats.apis)} APIs\n` +
|
|
148
|
+
`${chalk.dim('•')} Bundle size: ${chalk.yellow(stats.bundleSize)} ${chalk.dim('•')} Last build: ${chalk.yellow(stats.lastBuild)}\n\n` :
|
|
149
|
+
`${chalk.yellow('💡 Quick Start:')} Run ${chalk.cyan('baraqex create my-app')} to begin\n\n`
|
|
150
|
+
) +
|
|
151
|
+
`${chalk.bold.magenta('🌟 Quick Links:')}\n` +
|
|
152
|
+
`${chalk.dim('•')} ${terminalLink('📚 Documentation', 'https://www.baraqex.tech/docs')} ${chalk.dim('•')} ${terminalLink('🎯 Examples', 'https://www.baraqex.tech/examples')}\n` +
|
|
153
|
+
`${chalk.dim('•')} ${terminalLink('💬 Discord', 'https://discord.gg/baraqex')} ${chalk.dim('•')} ${terminalLink('🐛 Issues', 'https://github.com/mohamedx2/baraqex/issues')}\n\n` +
|
|
154
|
+
`${chalk.bold.blue('💡 Daily Tip:')} ${dailyTip}`,
|
|
64
155
|
{
|
|
65
156
|
padding: 1,
|
|
66
157
|
margin: { top: 1, bottom: 1 },
|
|
67
158
|
borderStyle: 'round',
|
|
68
|
-
borderColor: 'cyan'
|
|
159
|
+
borderColor: 'cyan',
|
|
160
|
+
title: '🎯 Baraqex CLI',
|
|
161
|
+
titleAlignment: 'center'
|
|
69
162
|
}
|
|
70
163
|
));
|
|
71
164
|
};
|
|
72
165
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
.
|
|
76
|
-
|
|
77
|
-
|
|
166
|
+
// Enhanced system information gathering
|
|
167
|
+
const getSystemInfo = () => {
|
|
168
|
+
const totalMem = os.totalmem();
|
|
169
|
+
const freeMem = os.freemem();
|
|
170
|
+
const usedMem = totalMem - freeMem;
|
|
171
|
+
const memUsage = ((usedMem / totalMem) * 100).toFixed(1);
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
platform: `${os.platform()} ${os.arch()}`,
|
|
175
|
+
memory: `${(usedMem / 1024 / 1024 / 1024).toFixed(1)}GB / ${(totalMem / 1024 / 1024 / 1024).toFixed(1)}GB (${memUsage}%)`,
|
|
176
|
+
cpu: os.cpus()[0]?.model || 'Unknown',
|
|
177
|
+
cores: os.cpus().length,
|
|
178
|
+
nodeVersion: process.version,
|
|
179
|
+
npmVersion: null // Will be populated by dependency check
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Enhanced project statistics with bundle analysis
|
|
184
|
+
const getProjectStats = () => {
|
|
185
|
+
try {
|
|
186
|
+
const pkg = path.join(process.cwd(), 'package.json');
|
|
187
|
+
if (!fs.existsSync(pkg)) {
|
|
188
|
+
return { isProject: false };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const packageJson = fs.readJsonSync(pkg);
|
|
192
|
+
const isBaraqexProject = packageJson.dependencies?.baraqex || packageJson.devDependencies?.baraqex;
|
|
193
|
+
|
|
194
|
+
if (!isBaraqexProject) {
|
|
195
|
+
return { isProject: false };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Enhanced file counting with better patterns
|
|
199
|
+
const componentsCount = countFiles('./src/components', ['.tsx', '.jsx', '.ts', '.js', '.vue']);
|
|
200
|
+
const pagesCount = countFiles('./src/pages', ['.tsx', '.jsx', '.ts', '.js']);
|
|
201
|
+
const apisCount = countFiles('./src/api', ['.tsx', '.jsx', '.ts', '.js']);
|
|
202
|
+
const testsCount = countFiles('./src', ['.test.ts', '.test.js', '.spec.ts', '.spec.js']);
|
|
203
|
+
|
|
204
|
+
// Bundle size analysis
|
|
205
|
+
const bundleSize = getBundleSize();
|
|
206
|
+
const lastBuild = getLastBuildTime();
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
isProject: true,
|
|
210
|
+
name: packageJson.name,
|
|
211
|
+
version: packageJson.version,
|
|
212
|
+
components: componentsCount,
|
|
213
|
+
pages: pagesCount,
|
|
214
|
+
apis: apisCount,
|
|
215
|
+
tests: testsCount,
|
|
216
|
+
bundleSize,
|
|
217
|
+
lastBuild,
|
|
218
|
+
scripts: Object.keys(packageJson.scripts || {}).length,
|
|
219
|
+
dependencies: Object.keys(packageJson.dependencies || {}).length +
|
|
220
|
+
Object.keys(packageJson.devDependencies || {}).length
|
|
221
|
+
};
|
|
222
|
+
} catch (error) {
|
|
223
|
+
return { isProject: false };
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// Enhanced file counting with exclusion patterns
|
|
228
|
+
const countFiles = (dir, extensions) => {
|
|
229
|
+
try {
|
|
230
|
+
if (!fs.existsSync(dir)) return 0;
|
|
231
|
+
|
|
232
|
+
const pattern = `${dir}/**/*.{${extensions.map(ext => ext.replace('.', '')).join(',')}}`;
|
|
233
|
+
const files = glob.sync(pattern, {
|
|
234
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.next/**']
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
return files.length;
|
|
238
|
+
} catch (error) {
|
|
239
|
+
return 0;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// Bundle size analysis
|
|
244
|
+
const getBundleSize = () => {
|
|
245
|
+
try {
|
|
246
|
+
const distPath = path.join(process.cwd(), 'dist');
|
|
247
|
+
const buildPath = path.join(process.cwd(), 'build');
|
|
248
|
+
const targetPath = fs.existsSync(distPath) ? distPath :
|
|
249
|
+
fs.existsSync(buildPath) ? buildPath : null;
|
|
250
|
+
|
|
251
|
+
if (!targetPath) return 'No build';
|
|
252
|
+
|
|
253
|
+
const files = glob.sync(`${targetPath}/**/*`, { nodir: true });
|
|
254
|
+
const totalSize = files.reduce((acc, file) => {
|
|
255
|
+
try {
|
|
256
|
+
return acc + fs.statSync(file).size;
|
|
257
|
+
} catch {
|
|
258
|
+
return acc;
|
|
259
|
+
}
|
|
260
|
+
}, 0);
|
|
261
|
+
|
|
262
|
+
const sizeInMB = (totalSize / 1024 / 1024).toFixed(1);
|
|
263
|
+
return `${sizeInMB}MB`;
|
|
264
|
+
} catch (error) {
|
|
265
|
+
return 'Unknown';
|
|
266
|
+
}
|
|
267
|
+
};
|
|
78
268
|
|
|
79
|
-
//
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
269
|
+
// Last build time
|
|
270
|
+
const getLastBuildTime = () => {
|
|
271
|
+
try {
|
|
272
|
+
const distPath = path.join(process.cwd(), 'dist');
|
|
273
|
+
const buildPath = path.join(process.cwd(), 'build');
|
|
274
|
+
const targetPath = fs.existsSync(distPath) ? distPath :
|
|
275
|
+
fs.existsSync(buildPath) ? buildPath : null;
|
|
276
|
+
|
|
277
|
+
if (!targetPath) return 'Never';
|
|
278
|
+
|
|
279
|
+
const stat = fs.statSync(targetPath);
|
|
280
|
+
const diffMs = Date.now() - stat.mtime.getTime();
|
|
281
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
282
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
283
|
+
|
|
284
|
+
if (diffDays > 0) return `${diffDays}d ago`;
|
|
285
|
+
if (diffHours > 0) return `${diffHours}h ago`;
|
|
286
|
+
return 'Recently';
|
|
287
|
+
} catch (error) {
|
|
288
|
+
return 'Unknown';
|
|
289
|
+
}
|
|
83
290
|
};
|
|
84
291
|
|
|
85
|
-
//
|
|
292
|
+
// Enhanced dependency checking with version validation
|
|
86
293
|
async function checkDependencies() {
|
|
87
294
|
const spinner = ora({
|
|
88
|
-
text: '
|
|
89
|
-
spinner: '
|
|
295
|
+
text: 'Analyzing development environment...',
|
|
296
|
+
spinner: 'dots12',
|
|
90
297
|
color: 'cyan'
|
|
91
298
|
}).start();
|
|
92
299
|
|
|
93
300
|
try {
|
|
94
|
-
|
|
301
|
+
const checks = [];
|
|
302
|
+
const recommendations = [];
|
|
303
|
+
|
|
304
|
+
// Node.js version check with LTS recommendations
|
|
95
305
|
const nodeVersionOutput = await execAsync('node --version');
|
|
96
306
|
const nodeVersion = nodeVersionOutput.stdout.trim().replace('v', '');
|
|
97
|
-
const requiredNodeVersion = '
|
|
307
|
+
const requiredNodeVersion = '16.0.0';
|
|
308
|
+
const recommendedNodeVersion = '18.0.0';
|
|
309
|
+
|
|
310
|
+
if (semver.lt(nodeVersion, requiredNodeVersion)) {
|
|
311
|
+
checks.push({
|
|
312
|
+
name: 'Node.js',
|
|
313
|
+
status: 'error',
|
|
314
|
+
current: nodeVersion,
|
|
315
|
+
required: requiredNodeVersion,
|
|
316
|
+
message: `Node.js ${requiredNodeVersion}+ required`
|
|
317
|
+
});
|
|
318
|
+
} else if (semver.lt(nodeVersion, recommendedNodeVersion)) {
|
|
319
|
+
checks.push({
|
|
320
|
+
name: 'Node.js',
|
|
321
|
+
status: 'warning',
|
|
322
|
+
current: nodeVersion,
|
|
323
|
+
recommended: recommendedNodeVersion,
|
|
324
|
+
message: `Consider upgrading to Node.js ${recommendedNodeVersion}+ (LTS)`
|
|
325
|
+
});
|
|
326
|
+
recommendations.push(`Upgrade Node.js to v${recommendedNodeVersion} for better performance`);
|
|
327
|
+
} else {
|
|
328
|
+
checks.push({
|
|
329
|
+
name: 'Node.js',
|
|
330
|
+
status: 'success',
|
|
331
|
+
current: nodeVersion,
|
|
332
|
+
message: 'Excellent version'
|
|
333
|
+
});
|
|
334
|
+
}
|
|
98
335
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
336
|
+
// Package managers check with performance comparison
|
|
337
|
+
const packageManagers = [];
|
|
338
|
+
try {
|
|
339
|
+
const npmVersion = await execAsync('npm --version');
|
|
340
|
+
packageManagers.push({ name: 'npm', version: npmVersion.stdout.trim(), speed: '⭐⭐⭐' });
|
|
341
|
+
} catch (error) {}
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
const pnpmVersion = await execAsync('pnpm --version');
|
|
345
|
+
packageManagers.push({ name: 'pnpm', version: pnpmVersion.stdout.trim(), speed: '⭐⭐⭐⭐⭐' });
|
|
346
|
+
recommendations.push('pnpm detected - fastest package manager available!');
|
|
347
|
+
} catch (error) {}
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
const yarnVersion = await execAsync('yarn --version');
|
|
351
|
+
packageManagers.push({ name: 'yarn', version: yarnVersion.stdout.trim(), speed: '⭐⭐⭐⭐' });
|
|
352
|
+
} catch (error) {}
|
|
353
|
+
|
|
354
|
+
if (packageManagers.length > 0) {
|
|
355
|
+
checks.push({
|
|
356
|
+
name: 'Package Managers',
|
|
357
|
+
status: 'info',
|
|
358
|
+
message: packageManagers.map(pm => `${pm.name} v${pm.version} ${pm.speed}`).join(', ')
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Git check with repository analysis
|
|
363
|
+
try {
|
|
364
|
+
await execAsync('git --version');
|
|
365
|
+
checks.push({
|
|
366
|
+
name: 'Git',
|
|
367
|
+
status: 'success',
|
|
368
|
+
message: 'Available'
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Check if in a git repository
|
|
372
|
+
try {
|
|
373
|
+
await execAsync('git rev-parse --git-dir');
|
|
374
|
+
const remoteOutput = await execAsync('git remote -v');
|
|
375
|
+
if (remoteOutput.stdout.includes('github.com')) {
|
|
376
|
+
checks.push({
|
|
377
|
+
name: 'Repository',
|
|
378
|
+
status: 'info',
|
|
379
|
+
message: 'GitHub repository detected'
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
} catch (error) {
|
|
383
|
+
recommendations.push('Initialize Git repository for version control');
|
|
384
|
+
}
|
|
385
|
+
} catch (error) {
|
|
386
|
+
checks.push({
|
|
387
|
+
name: 'Git',
|
|
388
|
+
status: 'warning',
|
|
389
|
+
message: 'Not available (recommended for version control)'
|
|
390
|
+
});
|
|
391
|
+
recommendations.push('Install Git for version control');
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// VS Code check
|
|
395
|
+
try {
|
|
396
|
+
await execAsync('code --version');
|
|
397
|
+
checks.push({
|
|
398
|
+
name: 'VS Code',
|
|
399
|
+
status: 'success',
|
|
400
|
+
message: 'Available (recommended editor)'
|
|
401
|
+
});
|
|
402
|
+
} catch (error) {
|
|
403
|
+
recommendations.push('Install VS Code for the best development experience');
|
|
103
404
|
}
|
|
104
405
|
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
406
|
+
// Docker check (for deployment)
|
|
407
|
+
try {
|
|
408
|
+
await execAsync('docker --version');
|
|
409
|
+
checks.push({
|
|
410
|
+
name: 'Docker',
|
|
411
|
+
status: 'success',
|
|
412
|
+
message: 'Available (great for deployment)'
|
|
413
|
+
});
|
|
414
|
+
} catch (error) {}
|
|
109
415
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
416
|
+
const hasErrors = checks.some(check => check.status === 'error');
|
|
417
|
+
const hasWarnings = checks.some(check => check.status === 'warning');
|
|
418
|
+
|
|
419
|
+
if (hasErrors) {
|
|
420
|
+
spinner.fail('Environment has critical issues');
|
|
421
|
+
} else if (hasWarnings) {
|
|
422
|
+
spinner.warn('Environment ready with recommendations');
|
|
423
|
+
} else {
|
|
424
|
+
spinner.succeed('Environment optimally configured');
|
|
114
425
|
}
|
|
115
426
|
|
|
116
|
-
|
|
117
|
-
|
|
427
|
+
// Display detailed results
|
|
428
|
+
console.log('\n' + boxen(
|
|
429
|
+
checks.map(check => {
|
|
430
|
+
const icon = {
|
|
431
|
+
success: '✅',
|
|
432
|
+
warning: '⚠️',
|
|
433
|
+
error: '❌',
|
|
434
|
+
info: 'ℹ️'
|
|
435
|
+
}[check.status];
|
|
436
|
+
|
|
437
|
+
return `${icon} ${chalk.bold(check.name)}: ${check.message}` +
|
|
438
|
+
(check.current ? ` ${chalk.dim(`(v${check.current})`)}` : '');
|
|
439
|
+
}).join('\n') +
|
|
440
|
+
(recommendations.length > 0 ? '\n\n' + chalk.bold.yellow('💡 Recommendations:\n') +
|
|
441
|
+
recommendations.map(rec => `• ${rec}`).join('\n') : ''),
|
|
442
|
+
{
|
|
443
|
+
title: 'Environment Analysis',
|
|
444
|
+
padding: 1,
|
|
445
|
+
borderColor: hasErrors ? 'red' : hasWarnings ? 'yellow' : 'green'
|
|
446
|
+
}
|
|
447
|
+
));
|
|
448
|
+
|
|
449
|
+
return !hasErrors;
|
|
118
450
|
} catch (error) {
|
|
119
451
|
spinner.fail('Environment check failed');
|
|
120
|
-
console.log(chalk.red('Error:
|
|
452
|
+
console.log(chalk.red('Error: Could not verify environment requirements.'));
|
|
121
453
|
return false;
|
|
122
454
|
}
|
|
123
455
|
}
|
|
124
456
|
|
|
125
|
-
//
|
|
126
|
-
function compareVersions(a, b) {
|
|
127
|
-
const aParts = a.split('.').map(Number);
|
|
128
|
-
const bParts = b.split('.').map(Number);
|
|
129
|
-
|
|
130
|
-
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
131
|
-
const aVal = aParts[i] || 0;
|
|
132
|
-
const bVal = bParts[i] || 0;
|
|
133
|
-
|
|
134
|
-
if (aVal > bVal) return 1;
|
|
135
|
-
if (aVal < bVal) return -1;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return 0;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Choose template interactively with improved visualization
|
|
457
|
+
// Enhanced template selection with live previews
|
|
142
458
|
async function chooseTemplate() {
|
|
143
459
|
const templatesPath = path.join(__dirname, '..', 'templates');
|
|
144
460
|
const templates = fs.readdirSync(templatesPath).filter(file =>
|
|
145
461
|
fs.statSync(path.join(templatesPath, file)).isDirectory()
|
|
146
462
|
);
|
|
147
463
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
464
|
+
const templateData = {
|
|
465
|
+
'basic-app': {
|
|
466
|
+
icon: '🚀',
|
|
467
|
+
name: 'Basic App',
|
|
468
|
+
description: 'Perfect for learning and simple applications',
|
|
469
|
+
features: ['Client-side rendering', 'React hooks', 'Tailwind CSS', 'Hot reload', 'TypeScript support'],
|
|
470
|
+
buildTime: '~30s',
|
|
471
|
+
complexity: 'Beginner',
|
|
472
|
+
useCase: 'Learning, prototypes, simple apps',
|
|
473
|
+
bundleSize: '~150KB',
|
|
474
|
+
performance: '⭐⭐⭐⭐',
|
|
475
|
+
seo: '⭐⭐',
|
|
476
|
+
tags: ['SPA', 'React', 'Beginner'],
|
|
477
|
+
preview: 'https://basic-app.baraqex.tech'
|
|
478
|
+
},
|
|
479
|
+
'ssr-template': {
|
|
480
|
+
icon: '🌐',
|
|
481
|
+
name: 'SSR Template',
|
|
482
|
+
description: 'Server-side rendering with excellent SEO',
|
|
483
|
+
features: ['SSR + Hydration', 'SEO optimized', 'Fast initial load', 'Dynamic routes', 'Meta management'],
|
|
484
|
+
buildTime: '~45s',
|
|
485
|
+
complexity: 'Intermediate',
|
|
486
|
+
useCase: 'Marketing sites, blogs, e-commerce',
|
|
487
|
+
bundleSize: '~200KB',
|
|
488
|
+
performance: '⭐⭐⭐⭐⭐',
|
|
489
|
+
seo: '⭐⭐⭐⭐⭐',
|
|
490
|
+
tags: ['SSR', 'SEO', 'Production'],
|
|
491
|
+
preview: 'https://ssr.baraqex.tech'
|
|
492
|
+
},
|
|
493
|
+
'fullstack-app': {
|
|
494
|
+
icon: '⚡',
|
|
495
|
+
name: 'Fullstack App',
|
|
496
|
+
description: 'Complete solution with backend integration',
|
|
497
|
+
features: ['API routes', 'Database ORM', 'Authentication', 'File uploads', 'Real-time features'],
|
|
498
|
+
buildTime: '~60s',
|
|
499
|
+
complexity: 'Advanced',
|
|
500
|
+
useCase: 'Production apps, dashboards, SaaS',
|
|
501
|
+
bundleSize: '~300KB',
|
|
502
|
+
performance: '⭐⭐⭐⭐',
|
|
503
|
+
seo: '⭐⭐⭐⭐',
|
|
504
|
+
tags: ['Fullstack', 'Database', 'Auth'],
|
|
505
|
+
preview: 'https://fullstack.baraqex.tech'
|
|
506
|
+
},
|
|
507
|
+
'go-wasm-app': {
|
|
508
|
+
icon: '🔄',
|
|
509
|
+
name: 'Go WASM App',
|
|
510
|
+
description: 'High-performance computing with WebAssembly',
|
|
511
|
+
features: ['Go + WASM', 'Performance critical', 'Cross-platform', 'Advanced builds', 'Native speed'],
|
|
512
|
+
buildTime: '~90s',
|
|
513
|
+
complexity: 'Expert',
|
|
514
|
+
useCase: 'Scientific computing, games, tools',
|
|
515
|
+
bundleSize: '~500KB',
|
|
516
|
+
performance: '⭐⭐⭐⭐⭐',
|
|
517
|
+
seo: '⭐⭐',
|
|
518
|
+
tags: ['WASM', 'Performance', 'Go'],
|
|
519
|
+
preview: 'https://wasm.baraqex.tech'
|
|
520
|
+
},
|
|
521
|
+
'pwa-app': {
|
|
522
|
+
icon: '📱',
|
|
523
|
+
name: 'PWA App',
|
|
524
|
+
description: 'Progressive Web App with offline capabilities',
|
|
525
|
+
features: ['Service workers', 'Offline support', 'Push notifications', 'App-like experience'],
|
|
526
|
+
buildTime: '~50s',
|
|
527
|
+
complexity: 'Intermediate',
|
|
528
|
+
useCase: 'Mobile-first apps, offline apps',
|
|
529
|
+
bundleSize: '~250KB',
|
|
530
|
+
performance: '⭐⭐⭐⭐⭐',
|
|
531
|
+
seo: '⭐⭐⭐⭐',
|
|
532
|
+
tags: ['PWA', 'Mobile', 'Offline'],
|
|
533
|
+
preview: 'https://pwa.baraqex.tech'
|
|
534
|
+
}
|
|
162
535
|
};
|
|
163
536
|
|
|
164
537
|
console.log(boxen(
|
|
165
|
-
`${chalk.bold('
|
|
538
|
+
`${chalk.bold.cyan('🎯 Choose Your Project Template')}\n\n` +
|
|
539
|
+
`${chalk.dim('💡 Each template is production-ready and includes best practices')}\n\n` +
|
|
166
540
|
templates.map(template => {
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
541
|
+
const data = templateData[template] || {
|
|
542
|
+
icon: '📦',
|
|
543
|
+
name: template,
|
|
544
|
+
description: 'Custom template',
|
|
545
|
+
features: ['Basic functionality'],
|
|
546
|
+
complexity: 'Unknown',
|
|
547
|
+
tags: ['Custom']
|
|
548
|
+
};
|
|
173
549
|
|
|
174
|
-
return `${icon} ${chalk.cyan(
|
|
550
|
+
return `${data.icon} ${chalk.bold.cyan(data.name)} ${chalk.dim(data.tags?.map(t => `#${t}`).join(' '))}\n` +
|
|
551
|
+
` ${chalk.dim(data.description)}\n` +
|
|
552
|
+
` ${chalk.yellow('Performance:')} ${data.performance} ${chalk.yellow('SEO:')} ${data.seo} ${chalk.yellow('Bundle:')} ${data.bundleSize}\n` +
|
|
553
|
+
` ${chalk.yellow('Best for:')} ${data.useCase}`;
|
|
175
554
|
}).join('\n\n'),
|
|
176
555
|
{
|
|
177
556
|
padding: 1,
|
|
178
557
|
margin: 1,
|
|
179
558
|
borderStyle: 'round',
|
|
180
|
-
borderColor: 'cyan'
|
|
559
|
+
borderColor: 'cyan',
|
|
560
|
+
title: '📋 Template Selection'
|
|
181
561
|
}
|
|
182
562
|
));
|
|
183
563
|
|
|
184
|
-
const
|
|
185
|
-
name: `${templateIcons[template] || '📦'} ${chalk.bold(template)}`,
|
|
186
|
-
value: template,
|
|
187
|
-
description: templateDescriptions[template] || 'An application template'
|
|
188
|
-
}));
|
|
189
|
-
|
|
190
|
-
const answers = await inquirer.prompt([
|
|
564
|
+
const { template } = await inquirer.prompt([
|
|
191
565
|
{
|
|
192
566
|
type: 'list',
|
|
193
567
|
name: 'template',
|
|
194
|
-
message: chalk.green('Select
|
|
195
|
-
choices:
|
|
196
|
-
|
|
568
|
+
message: chalk.green('🎯 Select your project template:'),
|
|
569
|
+
choices: templates.map(template => {
|
|
570
|
+
const data = templateData[template] || { icon: '📦', name: template, complexity: 'Unknown' };
|
|
571
|
+
return {
|
|
572
|
+
name: `${data.icon} ${chalk.bold(data.name)} ${chalk.dim(`(${data.complexity})`)}`,
|
|
573
|
+
value: template,
|
|
574
|
+
short: template
|
|
575
|
+
};
|
|
576
|
+
}),
|
|
197
577
|
pageSize: 10
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
type: 'confirm',
|
|
201
|
-
name: 'viewDetails',
|
|
202
|
-
message: 'Would you like to see template details before proceeding?',
|
|
203
|
-
default: false
|
|
204
578
|
}
|
|
205
579
|
]);
|
|
206
580
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
'',
|
|
212
|
-
|
|
213
|
-
'',
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
'• Learning the framework',
|
|
223
|
-
'• Quick prototyping',
|
|
224
|
-
],
|
|
225
|
-
'ssr-template': [
|
|
226
|
-
`${chalk.bold('SSR Template')} ${templateIcons['ssr-template']}`,
|
|
227
|
-
'',
|
|
228
|
-
`${chalk.dim('Server-side rendering with client hydration.')}`,
|
|
229
|
-
'',
|
|
230
|
-
`${chalk.yellow('Features:')}`,
|
|
231
|
-
'• React-like development experience',
|
|
232
|
-
'• SEO-friendly rendered HTML',
|
|
233
|
-
'• Fast initial page load',
|
|
234
|
-
'• Smooth client-side transitions',
|
|
235
|
-
'• Built-in dynamic meta tag generation',
|
|
236
|
-
'',
|
|
237
|
-
`${chalk.yellow('Best for:')}`,
|
|
238
|
-
'• Production websites needing SEO',
|
|
239
|
-
'• Content-focused applications',
|
|
240
|
-
'• Sites requiring social sharing previews'
|
|
241
|
-
],
|
|
242
|
-
'fullstack-app': [
|
|
243
|
-
`${chalk.bold('Fullstack App Template')} ${templateIcons['fullstack-app']}`,
|
|
244
|
-
'',
|
|
245
|
-
`${chalk.dim('Complete solution with frontend and backend.')}`,
|
|
246
|
-
'',
|
|
247
|
-
`${chalk.yellow('Features:')}`,
|
|
248
|
-
'• API routes with Express integration',
|
|
249
|
-
'• File-based routing system',
|
|
250
|
-
'• Authentication system with JWT',
|
|
251
|
-
'• Database connectors (MongoDB, MySQL, PostgreSQL)',
|
|
252
|
-
'• Server-side rendering with hydration',
|
|
253
|
-
'• WebSocket support',
|
|
254
|
-
'',
|
|
255
|
-
`${chalk.yellow('Best for:')}`,
|
|
256
|
-
'• Full production applications',
|
|
257
|
-
'• Apps needing authentication',
|
|
258
|
-
'• Projects requiring database integration'
|
|
259
|
-
],
|
|
260
|
-
'go-wasm-app': [
|
|
261
|
-
`${chalk.bold('Go WASM App Template')} ${templateIcons['go-wasm-app'] || '🔄'}`,
|
|
262
|
-
'',
|
|
263
|
-
`${chalk.dim('WebAssembly integration with Go programming language.')}`,
|
|
264
|
-
'',
|
|
265
|
-
`${chalk.yellow('Features:')}`,
|
|
266
|
-
'• Go + WebAssembly integration',
|
|
267
|
-
'• High-performance computation in browser',
|
|
268
|
-
'• Server-side WASM processing',
|
|
269
|
-
'• Shared code between Go and JavaScript',
|
|
270
|
-
'• Optimized build pipeline',
|
|
271
|
-
'',
|
|
272
|
-
`${chalk.yellow('Best for:')}`,
|
|
273
|
-
'• Computation-heavy applications',
|
|
274
|
-
'• Projects requiring Go libraries',
|
|
275
|
-
'• Performance-critical features'
|
|
276
|
-
]
|
|
277
|
-
}[answers.template] || ['No detailed information available for this template'];
|
|
581
|
+
const selectedData = templateData[template];
|
|
582
|
+
if (selectedData) {
|
|
583
|
+
const { action } = await inquirer.prompt([
|
|
584
|
+
{
|
|
585
|
+
type: 'list',
|
|
586
|
+
name: 'action',
|
|
587
|
+
message: 'What would you like to do?',
|
|
588
|
+
choices: [
|
|
589
|
+
{ name: '🚀 Continue with this template', value: 'continue' },
|
|
590
|
+
{ name: '👀 View detailed information', value: 'details' },
|
|
591
|
+
{ name: '🌐 Open live preview', value: 'preview' },
|
|
592
|
+
{ name: '🔄 Choose different template', value: 'back' }
|
|
593
|
+
]
|
|
594
|
+
}
|
|
595
|
+
]);
|
|
278
596
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
title: answers.template,
|
|
283
|
-
titleAlignment: 'center',
|
|
284
|
-
borderStyle: 'round',
|
|
285
|
-
borderColor: 'yellow'
|
|
286
|
-
}));
|
|
597
|
+
if (action === 'back') {
|
|
598
|
+
return chooseTemplate();
|
|
599
|
+
}
|
|
287
600
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
601
|
+
if (action === 'preview' && selectedData.preview) {
|
|
602
|
+
console.log(chalk.cyan(`🌐 Opening preview: ${selectedData.preview}`));
|
|
603
|
+
await open(selectedData.preview);
|
|
604
|
+
|
|
605
|
+
const { proceed } = await inquirer.prompt([
|
|
606
|
+
{
|
|
607
|
+
type: 'confirm',
|
|
608
|
+
name: 'proceed',
|
|
609
|
+
message: 'Continue with this template?',
|
|
610
|
+
default: true
|
|
611
|
+
}
|
|
612
|
+
]);
|
|
613
|
+
|
|
614
|
+
if (!proceed) {
|
|
615
|
+
return chooseTemplate();
|
|
616
|
+
}
|
|
617
|
+
}
|
|
294
618
|
|
|
295
|
-
if (
|
|
296
|
-
|
|
619
|
+
if (action === 'details') {
|
|
620
|
+
console.log(boxen(
|
|
621
|
+
`${selectedData.icon} ${chalk.bold.cyan(selectedData.name)}\n\n` +
|
|
622
|
+
`${chalk.dim(selectedData.description)}\n\n` +
|
|
623
|
+
`${chalk.yellow('✨ Features:')}\n` +
|
|
624
|
+
selectedData.features.map(f => ` • ${f}`).join('\n') + '\n\n' +
|
|
625
|
+
`${chalk.yellow('📊 Specifications:')}\n` +
|
|
626
|
+
` • Build Time: ${selectedData.buildTime}\n` +
|
|
627
|
+
` • Bundle Size: ${selectedData.bundleSize}\n` +
|
|
628
|
+
` • Performance: ${selectedData.performance}\n` +
|
|
629
|
+
` • SEO Score: ${selectedData.seo}\n` +
|
|
630
|
+
` • Complexity: ${selectedData.complexity}\n\n` +
|
|
631
|
+
`${chalk.yellow('🎯 Best For:')} ${selectedData.useCase}\n\n` +
|
|
632
|
+
`${chalk.yellow('🏷️ Tags:')} ${selectedData.tags?.join(', ')}`,
|
|
633
|
+
{
|
|
634
|
+
title: 'Template Details',
|
|
635
|
+
padding: 1,
|
|
636
|
+
borderColor: 'cyan'
|
|
637
|
+
}
|
|
638
|
+
));
|
|
639
|
+
|
|
640
|
+
const { proceed } = await inquirer.prompt([
|
|
641
|
+
{
|
|
642
|
+
type: 'confirm',
|
|
643
|
+
name: 'proceed',
|
|
644
|
+
message: 'Continue with this template?',
|
|
645
|
+
default: true
|
|
646
|
+
}
|
|
647
|
+
]);
|
|
648
|
+
|
|
649
|
+
if (!proceed) {
|
|
650
|
+
return chooseTemplate();
|
|
651
|
+
}
|
|
297
652
|
}
|
|
298
653
|
}
|
|
299
654
|
|
|
300
|
-
return
|
|
655
|
+
return template;
|
|
301
656
|
}
|
|
302
657
|
|
|
303
|
-
//
|
|
658
|
+
// Enhanced project creation with AI assistance
|
|
304
659
|
async function createProject(projectName, options) {
|
|
660
|
+
perfMonitor.checkpoint('project-creation-start');
|
|
305
661
|
displayBanner();
|
|
306
|
-
|
|
662
|
+
console.log(chalk.bold.cyan('\n📁 AI-Powered Project Creation Wizard\n'));
|
|
307
663
|
|
|
664
|
+
// Enhanced project name validation
|
|
308
665
|
if (!projectName) {
|
|
309
|
-
const
|
|
666
|
+
const { name } = await inquirer.prompt([
|
|
310
667
|
{
|
|
311
668
|
type: 'input',
|
|
312
|
-
name: '
|
|
313
|
-
message: chalk.green('What is your project name?'),
|
|
314
|
-
default:
|
|
315
|
-
validate: input =>
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
669
|
+
name: 'name',
|
|
670
|
+
message: chalk.green('🎯 What is your project name?'),
|
|
671
|
+
default: `my-awesome-app-${Date.now().toString(36)}`,
|
|
672
|
+
validate: input => {
|
|
673
|
+
if (!/^[a-z0-9-_]+$/.test(input)) {
|
|
674
|
+
return '❌ Project name can only contain lowercase letters, numbers, hyphens, and underscores';
|
|
675
|
+
}
|
|
676
|
+
if (input.length < 3) {
|
|
677
|
+
return '❌ Project name must be at least 3 characters long';
|
|
678
|
+
}
|
|
679
|
+
if (input.length > 50) {
|
|
680
|
+
return '❌ Project name must be less than 50 characters';
|
|
681
|
+
}
|
|
682
|
+
if (fs.existsSync(path.resolve(input))) {
|
|
683
|
+
return '❌ Directory already exists. Choose a different name.';
|
|
684
|
+
}
|
|
685
|
+
return true;
|
|
686
|
+
},
|
|
687
|
+
transformer: input => input.toLowerCase().replace(/[^a-z0-9-_]/g, '-')
|
|
319
688
|
}
|
|
320
689
|
]);
|
|
321
|
-
projectName =
|
|
690
|
+
projectName = name;
|
|
322
691
|
}
|
|
323
692
|
|
|
693
|
+
perfMonitor.checkpoint('dependency-check-start');
|
|
324
694
|
if (!await checkDependencies()) return;
|
|
695
|
+
perfMonitor.checkpoint('dependency-check-end');
|
|
696
|
+
|
|
697
|
+
// Enhanced project configuration with AI suggestions
|
|
698
|
+
const config = await inquirer.prompt([
|
|
699
|
+
{
|
|
700
|
+
type: 'list',
|
|
701
|
+
name: 'packageManager',
|
|
702
|
+
message: '📦 Choose your preferred package manager:',
|
|
703
|
+
choices: [
|
|
704
|
+
{
|
|
705
|
+
name: '📦 npm (Most compatible, 50M+ weekly downloads)',
|
|
706
|
+
value: 'npm',
|
|
707
|
+
short: 'npm'
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
name: '🚀 pnpm (3x faster, disk efficient, 2M+ weekly downloads)',
|
|
711
|
+
value: 'pnpm',
|
|
712
|
+
short: 'pnpm'
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
name: '🧶 yarn (Zero-installs, plug\'n\'play, 20M+ weekly downloads)',
|
|
716
|
+
value: 'yarn',
|
|
717
|
+
short: 'yarn'
|
|
718
|
+
}
|
|
719
|
+
],
|
|
720
|
+
default: globalConfig.defaultPackageManager
|
|
721
|
+
},
|
|
722
|
+
{
|
|
723
|
+
type: 'confirm',
|
|
724
|
+
name: 'typescript',
|
|
725
|
+
message: '📝 Enable TypeScript? (Recommended for better DX)',
|
|
726
|
+
default: true
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
type: 'confirm',
|
|
730
|
+
name: 'initGit',
|
|
731
|
+
message: '🔄 Initialize Git repository?',
|
|
732
|
+
default: true
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
type: 'confirm',
|
|
736
|
+
name: 'installDeps',
|
|
737
|
+
message: '⚡ Install dependencies automatically?',
|
|
738
|
+
default: true
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
type: 'list',
|
|
742
|
+
name: 'styling',
|
|
743
|
+
message: '🎨 Choose styling solution:',
|
|
744
|
+
choices: [
|
|
745
|
+
{ name: '🎨 Tailwind CSS (Utility-first)', value: 'tailwind' },
|
|
746
|
+
{ name: '💅 Styled Components (CSS-in-JS)', value: 'styled-components' },
|
|
747
|
+
{ name: '📦 CSS Modules (Scoped CSS)', value: 'css-modules' },
|
|
748
|
+
{ name: '⚡ Vanilla CSS (No framework)', value: 'vanilla' }
|
|
749
|
+
],
|
|
750
|
+
default: 'tailwind'
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
type: 'checkbox',
|
|
754
|
+
name: 'features',
|
|
755
|
+
message: '✨ Select additional features:',
|
|
756
|
+
choices: [
|
|
757
|
+
{ name: '🔧 ESLint + Prettier (Code quality)', value: 'linting', checked: true },
|
|
758
|
+
{ name: '🧪 Jest + Testing Library (Testing)', value: 'testing', checked: true },
|
|
759
|
+
{ name: '📱 PWA Support (Offline-first)', value: 'pwa' },
|
|
760
|
+
{ name: '🌐 Internationalization (i18n)', value: 'i18n' },
|
|
761
|
+
{ name: '📊 Bundle Analyzer (Performance)', value: 'analyzer' },
|
|
762
|
+
{ name: '🐳 Docker Setup (Containerization)', value: 'docker' },
|
|
763
|
+
{ name: '🚀 GitHub Actions (CI/CD)', value: 'github-actions' },
|
|
764
|
+
{ name: '📈 Analytics (Usage tracking)', value: 'analytics' }
|
|
765
|
+
]
|
|
766
|
+
}
|
|
767
|
+
]);
|
|
325
768
|
|
|
326
769
|
let template = options.template || await chooseTemplate();
|
|
770
|
+
perfMonitor.checkpoint('template-selection-end');
|
|
327
771
|
|
|
328
772
|
const targetDir = path.resolve(projectName);
|
|
329
773
|
const templateDir = path.join(__dirname, '..', 'templates', template);
|
|
330
774
|
|
|
775
|
+
// Enhanced directory handling
|
|
331
776
|
if (fs.existsSync(targetDir)) {
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
777
|
+
const stat = fs.statSync(targetDir);
|
|
778
|
+
const isEmpty = stat.isDirectory() && fs.readdirSync(targetDir).length === 0;
|
|
779
|
+
|
|
780
|
+
if (!isEmpty) {
|
|
781
|
+
const { action } = await inquirer.prompt([
|
|
782
|
+
{
|
|
783
|
+
type: 'list',
|
|
784
|
+
name: 'action',
|
|
785
|
+
message: chalk.yellow(`⚠️ Directory ${projectName} already exists and is not empty. What would you like to do?`),
|
|
786
|
+
choices: [
|
|
787
|
+
{ name: '🗑️ Remove and recreate (destructive)', value: 'overwrite' },
|
|
788
|
+
{ name: '📁 Merge with existing content', value: 'merge' },
|
|
789
|
+
{ name: '📝 Create with different name', value: 'rename' },
|
|
790
|
+
{ name: '❌ Cancel operation', value: 'cancel' }
|
|
791
|
+
]
|
|
792
|
+
}
|
|
793
|
+
]);
|
|
794
|
+
|
|
795
|
+
if (action === 'cancel') {
|
|
796
|
+
console.log(chalk.red('✖ Operation cancelled by user'));
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
if (action === 'rename') {
|
|
801
|
+
return createProject(null, options);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
if (action === 'overwrite') {
|
|
805
|
+
const { confirm } = await inquirer.prompt([
|
|
806
|
+
{
|
|
807
|
+
type: 'confirm',
|
|
808
|
+
name: 'confirm',
|
|
809
|
+
message: chalk.red('⚠️ This will permanently delete all existing files. Are you sure?'),
|
|
810
|
+
default: false
|
|
811
|
+
}
|
|
812
|
+
]);
|
|
813
|
+
|
|
814
|
+
if (!confirm) {
|
|
815
|
+
console.log(chalk.yellow('✖ Operation cancelled'));
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
await fs.remove(targetDir);
|
|
338
820
|
}
|
|
339
|
-
]);
|
|
340
|
-
if (!answers.overwrite) {
|
|
341
|
-
console.log(chalk.red('✖ Operation cancelled'));
|
|
342
|
-
return;
|
|
343
821
|
}
|
|
344
822
|
}
|
|
345
823
|
|
|
346
|
-
// Multi-step
|
|
347
|
-
|
|
824
|
+
// Multi-step creation with detailed progress and time estimates
|
|
825
|
+
const steps = [
|
|
826
|
+
{ name: 'Creating project structure', action: () => createProjectStructure(targetDir), estimate: '2s' },
|
|
827
|
+
{ name: 'Copying template files', action: () => copyTemplateFiles(templateDir, targetDir), estimate: '3s' },
|
|
828
|
+
{ name: 'Configuring package.json', action: () => configurePackageJson(targetDir, projectName, config), estimate: '1s' },
|
|
829
|
+
{ name: 'Setting up project configuration', action: () => setupAdvancedConfig(targetDir, config), estimate: '2s' }
|
|
830
|
+
];
|
|
348
831
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
step1.fail();
|
|
356
|
-
console.error(chalk.red(`Error creating directory: ${error.message}`));
|
|
357
|
-
return;
|
|
832
|
+
if (config.initGit) {
|
|
833
|
+
steps.push({
|
|
834
|
+
name: 'Initializing Git repository',
|
|
835
|
+
action: () => initGitRepo(targetDir),
|
|
836
|
+
estimate: '2s'
|
|
837
|
+
});
|
|
358
838
|
}
|
|
359
839
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
return;
|
|
840
|
+
if (config.installDeps) {
|
|
841
|
+
const estimatedTime = config.packageManager === 'pnpm' ? '30s' :
|
|
842
|
+
config.packageManager === 'yarn' ? '45s' : '60s';
|
|
843
|
+
steps.push({
|
|
844
|
+
name: `Installing dependencies with ${config.packageManager}`,
|
|
845
|
+
action: () => installDependencies(targetDir, config.packageManager),
|
|
846
|
+
estimate: estimatedTime
|
|
847
|
+
});
|
|
369
848
|
}
|
|
370
849
|
|
|
371
|
-
//
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
|
|
379
|
-
step3.succeed();
|
|
380
|
-
} else {
|
|
381
|
-
step3.warn('No package.json found in template');
|
|
382
|
-
}
|
|
383
|
-
} catch (error) {
|
|
384
|
-
step3.fail();
|
|
385
|
-
console.error(chalk.red(`Error updating package.json: ${error.message}`));
|
|
386
|
-
return;
|
|
850
|
+
// Add additional feature setup steps
|
|
851
|
+
if (config.features.includes('docker')) {
|
|
852
|
+
steps.push({
|
|
853
|
+
name: 'Setting up Docker configuration',
|
|
854
|
+
action: () => setupDocker(targetDir),
|
|
855
|
+
estimate: '3s'
|
|
856
|
+
});
|
|
387
857
|
}
|
|
388
858
|
|
|
389
|
-
|
|
859
|
+
if (config.features.includes('github-actions')) {
|
|
860
|
+
steps.push({
|
|
861
|
+
name: 'Configuring GitHub Actions',
|
|
862
|
+
action: () => setupGithubActions(targetDir),
|
|
863
|
+
estimate: '2s'
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
console.log(chalk.cyan(`\n🚀 Creating project with ${steps.length} steps...\n`));
|
|
868
|
+
|
|
869
|
+
for (const [index, step] of steps.entries()) {
|
|
870
|
+
const spinner = ora({
|
|
871
|
+
text: `${step.name} (${index + 1}/${steps.length}) - Est. ${step.estimate}`,
|
|
872
|
+
color: 'cyan'
|
|
873
|
+
}).start();
|
|
874
|
+
|
|
875
|
+
const stepStart = performance.now();
|
|
876
|
+
|
|
877
|
+
try {
|
|
878
|
+
await step.action();
|
|
879
|
+
const stepTime = ((performance.now() - stepStart) / 1000).toFixed(1);
|
|
880
|
+
spinner.succeed(`${step.name} ${chalk.dim(`(${stepTime}s)`)}`);
|
|
881
|
+
} catch (error) {
|
|
882
|
+
spinner.fail(`${step.name} failed`);
|
|
883
|
+
console.error(chalk.red(`❌ Error: ${error.message}`));
|
|
884
|
+
|
|
885
|
+
// Offer to continue or abort
|
|
886
|
+
const { continueOnError } = await inquirer.prompt([
|
|
887
|
+
{
|
|
888
|
+
type: 'confirm',
|
|
889
|
+
name: 'continueOnError',
|
|
890
|
+
message: 'Continue with remaining steps?',
|
|
891
|
+
default: true
|
|
892
|
+
}
|
|
893
|
+
]);
|
|
894
|
+
|
|
895
|
+
if (!continueOnError) {
|
|
896
|
+
console.log(chalk.red('✖ Project creation aborted'));
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
perfMonitor.checkpoint('project-creation-end');
|
|
903
|
+
|
|
904
|
+
// Enhanced success message with personalized next steps
|
|
905
|
+
const nextSteps = generateNextSteps(projectName, config);
|
|
906
|
+
const projectStats = analyzeProject(targetDir);
|
|
907
|
+
|
|
390
908
|
console.log('\n' + boxen(
|
|
391
|
-
`${chalk.bold.green('Project created successfully!')}\n\n` +
|
|
392
|
-
`${chalk.bold('Project:')} ${chalk.cyan(projectName)}\n` +
|
|
393
|
-
`${chalk.bold('Template:')} ${chalk.cyan(template)}\n` +
|
|
394
|
-
`${chalk.bold('Location:')} ${chalk.cyan(targetDir)}\n
|
|
395
|
-
`${chalk.bold
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
909
|
+
`${chalk.bold.green('🎉 Project created successfully!')}\n\n` +
|
|
910
|
+
`${chalk.bold('📁 Project:')} ${chalk.cyan(projectName)}\n` +
|
|
911
|
+
`${chalk.bold('📋 Template:')} ${chalk.cyan(template)}\n` +
|
|
912
|
+
`${chalk.bold('📍 Location:')} ${chalk.cyan(targetDir)}\n` +
|
|
913
|
+
`${chalk.bold('📦 Package Manager:')} ${chalk.cyan(config.packageManager)}\n` +
|
|
914
|
+
`${chalk.bold('📊 Files Created:')} ${chalk.cyan(projectStats.files)}\n` +
|
|
915
|
+
`${chalk.bold('💾 Project Size:')} ${chalk.cyan(projectStats.size)}\n\n` +
|
|
916
|
+
`${chalk.bold.yellow('🚀 Next Steps:')}\n\n` +
|
|
917
|
+
nextSteps.map((step, i) => ` ${chalk.cyan((i+1) + '.')} ${step}`).join('\n') + '\n\n' +
|
|
918
|
+
`${chalk.bold.magenta('🎯 Quick Commands:')}\n` +
|
|
919
|
+
`• ${chalk.cyan('baraqex dev')} - Start development server\n` +
|
|
920
|
+
`• ${chalk.cyan('baraqex build')} - Build for production\n` +
|
|
921
|
+
`• ${chalk.cyan('baraqex doctor')} - Check project health\n` +
|
|
922
|
+
`• ${chalk.cyan('baraqex add:component Button')} - Add components\n\n` +
|
|
923
|
+
`${chalk.bold.blue('📚 Resources:')}\n` +
|
|
924
|
+
`• ${terminalLink('📖 Documentation', 'https://www.baraqex.tech/docs')}\n` +
|
|
925
|
+
`• ${terminalLink('🎯 Examples', 'https://www.baraqex.tech/examples')}\n` +
|
|
926
|
+
`• ${terminalLink('💬 Discord Community', 'https://discord.gg/baraqex')}\n` +
|
|
927
|
+
`• ${terminalLink('🐛 Report Issues', 'https://github.com/mohamedx2/baraqex/issues')}`,
|
|
400
928
|
{
|
|
401
929
|
padding: 1,
|
|
402
930
|
margin: 1,
|
|
403
931
|
borderStyle: 'round',
|
|
404
|
-
borderColor: 'green'
|
|
932
|
+
borderColor: 'green',
|
|
933
|
+
title: '✨ Success!'
|
|
405
934
|
}
|
|
406
935
|
));
|
|
407
936
|
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
// Add component with improved interactive experience
|
|
413
|
-
async function addComponent(componentName, options) {
|
|
414
|
-
displayBanner();
|
|
415
|
-
createSection('Create Component');
|
|
937
|
+
// Performance report
|
|
938
|
+
if (globalConfig.analytics) {
|
|
939
|
+
perfMonitor.report();
|
|
940
|
+
}
|
|
416
941
|
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
942
|
+
// Offer additional actions
|
|
943
|
+
const { finalAction } = await inquirer.prompt([
|
|
944
|
+
{
|
|
945
|
+
type: 'list',
|
|
946
|
+
name: 'finalAction',
|
|
947
|
+
message: 'What would you like to do next?',
|
|
948
|
+
choices: [
|
|
949
|
+
{ name: '🚀 Start development server', value: 'dev' },
|
|
950
|
+
{ name: '💻 Open in VS Code', value: 'vscode' },
|
|
951
|
+
{ name: '🌐 Open in browser', value: 'browser' },
|
|
952
|
+
{ name: '📋 View project structure', value: 'structure' },
|
|
953
|
+
{ name: '✨ That\'s it for now', value: 'done' }
|
|
954
|
+
]
|
|
955
|
+
}
|
|
956
|
+
]);
|
|
957
|
+
|
|
958
|
+
switch (finalAction) {
|
|
959
|
+
case 'dev':
|
|
960
|
+
console.log(chalk.cyan('\n🚀 Starting development server...\n'));
|
|
961
|
+
await startDevServer({ port: '3000' }, targetDir);
|
|
962
|
+
break;
|
|
963
|
+
case 'vscode':
|
|
964
|
+
try {
|
|
965
|
+
await execAsync(`code "${targetDir}"`);
|
|
966
|
+
console.log(chalk.green('✓ Opened in VS Code'));
|
|
967
|
+
} catch (error) {
|
|
968
|
+
console.log(chalk.yellow('⚠️ Could not open VS Code. Make sure it\'s installed and in your PATH.'));
|
|
427
969
|
}
|
|
428
|
-
|
|
429
|
-
|
|
970
|
+
break;
|
|
971
|
+
case 'browser':
|
|
972
|
+
console.log(chalk.cyan('🌐 Opening project documentation...'));
|
|
973
|
+
await open('https://www.baraqex.tech/docs/getting-started');
|
|
974
|
+
break;
|
|
975
|
+
case 'structure':
|
|
976
|
+
await showProjectStructure(targetDir);
|
|
977
|
+
break;
|
|
430
978
|
}
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// ...rest of the implementation with enhanced features...
|
|
982
|
+
|
|
983
|
+
// Helper functions for enhanced project creation
|
|
984
|
+
async function createProjectStructure(targetDir) {
|
|
985
|
+
await fs.ensureDir(targetDir);
|
|
431
986
|
|
|
432
|
-
//
|
|
433
|
-
|
|
987
|
+
// Create standard project structure
|
|
988
|
+
const dirs = [
|
|
989
|
+
'src',
|
|
990
|
+
'src/components',
|
|
991
|
+
'src/pages',
|
|
992
|
+
'src/hooks',
|
|
993
|
+
'src/utils',
|
|
994
|
+
'src/styles',
|
|
995
|
+
'public',
|
|
996
|
+
'tests'
|
|
997
|
+
];
|
|
434
998
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
name: 'TypeScript (.tsx)',
|
|
444
|
-
value: '.tsx',
|
|
445
|
-
description: 'TypeScript with JSX support'
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
name: 'JavaScript (.jsx)',
|
|
449
|
-
value: '.jsx',
|
|
450
|
-
description: 'JavaScript with JSX support'
|
|
451
|
-
}
|
|
452
|
-
]
|
|
453
|
-
}
|
|
454
|
-
]);
|
|
455
|
-
extension = answers.extension;
|
|
999
|
+
for (const dir of dirs) {
|
|
1000
|
+
await fs.ensureDir(path.join(targetDir, dir));
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
async function copyTemplateFiles(templateDir, targetDir) {
|
|
1005
|
+
if (!fs.existsSync(templateDir)) {
|
|
1006
|
+
throw new Error(`Template directory not found: ${templateDir}`);
|
|
456
1007
|
}
|
|
457
1008
|
|
|
458
|
-
|
|
459
|
-
|
|
1009
|
+
await fs.copy(templateDir, targetDir, {
|
|
1010
|
+
overwrite: true,
|
|
1011
|
+
filter: (src) => {
|
|
1012
|
+
// Skip node_modules and other build artifacts
|
|
1013
|
+
return !src.includes('node_modules') &&
|
|
1014
|
+
!src.includes('.git') &&
|
|
1015
|
+
!src.includes('dist') &&
|
|
1016
|
+
!src.includes('build');
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
async function configurePackageJson(targetDir, projectName, config) {
|
|
1022
|
+
const pkgJsonPath = path.join(targetDir, 'package.json');
|
|
460
1023
|
|
|
461
|
-
if (
|
|
462
|
-
|
|
463
|
-
const potentialPaths = ['src/components', 'components', 'src/app/components', 'app/components'];
|
|
464
|
-
const existingPaths = potentialPaths.filter(p => fs.existsSync(path.join(process.cwd(), p)));
|
|
1024
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
1025
|
+
const pkgJson = await fs.readJson(pkgJsonPath);
|
|
465
1026
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
...existingPaths.map(p => ({ name: `${p} ${chalk.dim('(detected)')}`, value: p })),
|
|
474
|
-
{ name: 'Custom location...', value: 'custom' }
|
|
475
|
-
]
|
|
476
|
-
}
|
|
477
|
-
]);
|
|
478
|
-
|
|
479
|
-
if (answers.path === 'custom') {
|
|
480
|
-
const customPath = await inquirer.prompt([
|
|
481
|
-
{
|
|
482
|
-
type: 'input',
|
|
483
|
-
name: 'customPath',
|
|
484
|
-
message: chalk.green('Enter the component path:'),
|
|
485
|
-
default: 'src/components',
|
|
486
|
-
validate: input => /^[a-zA-Z0-9-_/\\]+$/.test(input)
|
|
487
|
-
? true
|
|
488
|
-
: 'Path can only contain letters, numbers, slashes, hyphens and underscores'
|
|
489
|
-
}
|
|
490
|
-
]);
|
|
491
|
-
componentPath = customPath.customPath;
|
|
492
|
-
} else {
|
|
493
|
-
componentPath = answers.path;
|
|
494
|
-
}
|
|
495
|
-
} else {
|
|
496
|
-
const answers = await inquirer.prompt([
|
|
497
|
-
{
|
|
498
|
-
type: 'input',
|
|
499
|
-
name: 'path',
|
|
500
|
-
message: chalk.green('Where do you want to create this component?'),
|
|
501
|
-
default: 'src/components',
|
|
502
|
-
validate: input => /^[a-zA-Z0-9-_/\\]+$/.test(input)
|
|
503
|
-
? true
|
|
504
|
-
: 'Path can only contain letters, numbers, slashes, hyphens and underscores'
|
|
505
|
-
}
|
|
506
|
-
]);
|
|
507
|
-
componentPath = answers.path;
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// Component template features
|
|
512
|
-
const features = await inquirer.prompt([
|
|
513
|
-
{
|
|
514
|
-
type: 'checkbox',
|
|
515
|
-
name: 'features',
|
|
516
|
-
message: chalk.green('Select component features:'),
|
|
517
|
-
choices: [
|
|
518
|
-
{ name: 'useState Hook', value: 'useState', checked: true },
|
|
519
|
-
{ name: 'useEffect Hook', value: 'useEffect' },
|
|
520
|
-
{ name: 'CSS Module', value: 'cssModule' },
|
|
521
|
-
{ name: 'PropTypes', value: 'propTypes' },
|
|
522
|
-
{ name: 'Default Props', value: 'defaultProps' }
|
|
523
|
-
]
|
|
524
|
-
}
|
|
525
|
-
]);
|
|
526
|
-
|
|
527
|
-
// Create component content based on type and selected features
|
|
528
|
-
const fullPath = path.join(process.cwd(), componentPath, `${componentName}${extension}`);
|
|
529
|
-
const dirPath = path.dirname(fullPath);
|
|
530
|
-
|
|
531
|
-
// CSS Module path if selected
|
|
532
|
-
let cssPath = null;
|
|
533
|
-
if (features.features.includes('cssModule')) {
|
|
534
|
-
cssPath = path.join(dirPath, `${componentName}.module.css`);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// Build component template
|
|
538
|
-
let imports = [];
|
|
539
|
-
let hooks = [];
|
|
540
|
-
let props = [];
|
|
541
|
-
let propsInterface = [];
|
|
542
|
-
let renders = [];
|
|
543
|
-
let exports = [];
|
|
544
|
-
|
|
545
|
-
// Base imports
|
|
546
|
-
imports.push(`import { jsx } from 'frontend-hamroun';`);
|
|
547
|
-
|
|
548
|
-
// Add selected features
|
|
549
|
-
if (features.features.includes('useState')) {
|
|
550
|
-
imports[0] = imports[0].replace('jsx', 'jsx, useState');
|
|
551
|
-
hooks.push(` const [state, setState] = useState('initial state');`);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (features.features.includes('useEffect')) {
|
|
555
|
-
imports[0] = imports[0].replace('jsx', 'jsx, useEffect').replace(', useEffect, useEffect', ', useEffect');
|
|
556
|
-
hooks.push(` useEffect(() => {
|
|
557
|
-
// Side effect code here
|
|
558
|
-
console.log('Component mounted');
|
|
1027
|
+
// Update package.json with user preferences
|
|
1028
|
+
pkgJson.name = projectName;
|
|
1029
|
+
pkgJson.version = '0.1.0';
|
|
1030
|
+
pkgJson.private = true;
|
|
1031
|
+
pkgJson.description = `A modern web application built with Baraqex`;
|
|
1032
|
+
pkgJson.keywords = ['baraqex', 'react', 'typescript', 'frontend'];
|
|
1033
|
+
pkgJson.author = os.userInfo().username;
|
|
559
1034
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
1035
|
+
// Add scripts based on configuration
|
|
1036
|
+
pkgJson.scripts = {
|
|
1037
|
+
...pkgJson.scripts,
|
|
1038
|
+
'dev': 'baraqex dev',
|
|
1039
|
+
'build': 'baraqex build',
|
|
1040
|
+
'start': 'baraqex start',
|
|
1041
|
+
'test': config.features.includes('testing') ? 'jest' : 'echo "No tests specified"',
|
|
1042
|
+
'lint': config.features.includes('linting') ? 'eslint src --ext .ts,.tsx,.js,.jsx' : 'echo "No linting configured"',
|
|
1043
|
+
'format': config.features.includes('linting') ? 'prettier --write src/**/*.{ts,tsx,js,jsx,json,css,md}' : 'echo "No formatting configured"'
|
|
563
1044
|
};
|
|
564
|
-
}, []);`);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
if (features.features.includes('cssModule')) {
|
|
568
|
-
imports.push(`import styles from './${componentName}.module.css';`);
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
if (features.features.includes('propTypes')) {
|
|
572
|
-
imports.push(`import PropTypes from 'prop-types';`);
|
|
573
|
-
exports.push(`
|
|
574
|
-
${componentName}.propTypes = {
|
|
575
|
-
title: PropTypes.string,
|
|
576
|
-
children: PropTypes.node
|
|
577
|
-
};`);
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
if (features.features.includes('defaultProps')) {
|
|
581
|
-
exports.push(`
|
|
582
|
-
${componentName}.defaultProps = {
|
|
583
|
-
title: '${componentName} Title'
|
|
584
|
-
};`);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// Build props
|
|
588
|
-
if (extension === '.tsx') {
|
|
589
|
-
propsInterface.push(`interface ${componentName}Props {
|
|
590
|
-
title?: string;
|
|
591
|
-
children?: React.ReactNode;
|
|
592
|
-
}`);
|
|
593
|
-
props.push(`{ title, children }: ${componentName}Props`);
|
|
594
|
-
} else {
|
|
595
|
-
props.push(`{ title, children }`);
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// Build render content
|
|
599
|
-
const className = features.features.includes('cssModule') ? 'styles.component' : 'component';
|
|
600
|
-
const titleClass = features.features.includes('cssModule') ? 'styles.title' : 'title';
|
|
601
|
-
const contentClass = features.features.includes('cssModule') ? 'styles.content' : 'content';
|
|
602
|
-
|
|
603
|
-
renders.push(` return (
|
|
604
|
-
<div className="${className}">
|
|
605
|
-
{title && <h2 className="${titleClass}">{title}</h2>}
|
|
606
|
-
${features.features.includes('useState') ? `<p>State value: {state}</p>
|
|
607
|
-
<button onClick={() => setState('updated state')}>Update State</button>` : ''}
|
|
608
|
-
<div className="${contentClass}">
|
|
609
|
-
{children}
|
|
610
|
-
</div>
|
|
611
|
-
</div>
|
|
612
|
-
);`);
|
|
613
|
-
|
|
614
|
-
// Assemble final component template
|
|
615
|
-
const componentTemplate = `${imports.join('\n')}
|
|
616
|
-
|
|
617
|
-
${propsInterface.join('\n')}
|
|
618
|
-
|
|
619
|
-
export default function ${componentName}(${props.join(', ')}) {
|
|
620
|
-
${hooks.join('\n\n')}
|
|
621
|
-
${renders.join('\n')}
|
|
622
|
-
}${exports.join('')}
|
|
623
|
-
`;
|
|
624
|
-
|
|
625
|
-
// CSS Module template if selected
|
|
626
|
-
const cssTemplate = `.component {
|
|
627
|
-
border: 1px solid #eaeaea;
|
|
628
|
-
border-radius: 8px;
|
|
629
|
-
padding: 16px;
|
|
630
|
-
margin: 16px 0;
|
|
631
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
.title {
|
|
635
|
-
font-size: 1.25rem;
|
|
636
|
-
margin-bottom: 12px;
|
|
637
|
-
color: #333;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
.content {
|
|
641
|
-
font-size: 1rem;
|
|
642
|
-
line-height: 1.5;
|
|
643
|
-
}
|
|
644
|
-
`;
|
|
645
|
-
|
|
646
|
-
// Create the files
|
|
647
|
-
const spinner = ora({
|
|
648
|
-
text: `Creating ${componentName} component...`,
|
|
649
|
-
color: 'cyan'
|
|
650
|
-
}).start();
|
|
651
|
-
|
|
652
|
-
try {
|
|
653
|
-
// Create component file
|
|
654
|
-
await fs.ensureDir(dirPath);
|
|
655
|
-
await fs.writeFile(fullPath, componentTemplate);
|
|
656
1045
|
|
|
657
|
-
//
|
|
658
|
-
if (
|
|
659
|
-
|
|
1046
|
+
// Add dependencies based on features
|
|
1047
|
+
if (config.features.includes('testing')) {
|
|
1048
|
+
pkgJson.devDependencies = {
|
|
1049
|
+
...pkgJson.devDependencies,
|
|
1050
|
+
'jest': '^29.0.0',
|
|
1051
|
+
'@testing-library/react': '^13.0.0',
|
|
1052
|
+
'@testing-library/jest-dom': '^5.0.0'
|
|
1053
|
+
};
|
|
660
1054
|
}
|
|
661
1055
|
|
|
662
|
-
|
|
1056
|
+
if (config.features.includes('linting')) {
|
|
1057
|
+
pkgJson.devDependencies = {
|
|
1058
|
+
...pkgJson.devDependencies,
|
|
1059
|
+
'eslint': '^8.0.0',
|
|
1060
|
+
'prettier': '^2.0.0',
|
|
1061
|
+
'@typescript-eslint/eslint-plugin': '^5.0.0',
|
|
1062
|
+
'@typescript-eslint/parser': '^5.0.0'
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
663
1065
|
|
|
664
|
-
|
|
665
|
-
console.log(boxen(
|
|
666
|
-
`${chalk.bold.green('Component created successfully!')}\n\n` +
|
|
667
|
-
`${chalk.bold('Import and use your component:')}\n\n` +
|
|
668
|
-
chalk.cyan(`import ${componentName} from './${path.relative(process.cwd(), fullPath).replace(/\\/g, '/').replace(/\.(jsx|tsx)$/, '')}';\n\n`) +
|
|
669
|
-
chalk.cyan(`<${componentName} title="My Title">
|
|
670
|
-
<p>Child content goes here</p>
|
|
671
|
-
</${componentName}>`),
|
|
672
|
-
{
|
|
673
|
-
padding: 1,
|
|
674
|
-
margin: 1,
|
|
675
|
-
borderStyle: 'round',
|
|
676
|
-
borderColor: 'green'
|
|
677
|
-
}
|
|
678
|
-
));
|
|
679
|
-
} catch (error) {
|
|
680
|
-
spinner.fail(`Failed to create component`);
|
|
681
|
-
console.error(chalk.red(`Error: ${error.message}`));
|
|
1066
|
+
await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
|
|
682
1067
|
}
|
|
683
1068
|
}
|
|
684
1069
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
1070
|
+
async function setupAdvancedConfig(targetDir, config) {
|
|
1071
|
+
// Create baraqex.config.js
|
|
1072
|
+
const configContent = generateBaraqexConfig(config);
|
|
1073
|
+
await fs.writeFile(path.join(targetDir, 'baraqex.config.js'), configContent);
|
|
688
1074
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
1075
|
+
// Create additional config files based on features
|
|
1076
|
+
if (config.features.includes('linting')) {
|
|
1077
|
+
await createEslintConfig(targetDir, config);
|
|
1078
|
+
await createPrettierConfig(targetDir);
|
|
1079
|
+
}
|
|
693
1080
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
1081
|
+
if (config.features.includes('testing')) {
|
|
1082
|
+
await createJestConfig(targetDir, config);
|
|
1083
|
+
}
|
|
697
1084
|
|
|
698
|
-
|
|
1085
|
+
if (config.typescript) {
|
|
1086
|
+
await createTsConfig(targetDir);
|
|
1087
|
+
}
|
|
699
1088
|
}
|
|
700
1089
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
1090
|
+
function generateBaraqexConfig(config) {
|
|
1091
|
+
return `export default {
|
|
1092
|
+
// Baraqex Configuration
|
|
1093
|
+
build: {
|
|
1094
|
+
outDir: 'dist',
|
|
1095
|
+
sourcemap: process.env.NODE_ENV === 'development',
|
|
1096
|
+
minify: process.env.NODE_ENV === 'production',
|
|
1097
|
+
target: 'es2020'
|
|
1098
|
+
},
|
|
704
1099
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
];
|
|
1100
|
+
dev: {
|
|
1101
|
+
port: 3000,
|
|
1102
|
+
host: 'localhost',
|
|
1103
|
+
open: true,
|
|
1104
|
+
hot: true
|
|
1105
|
+
},
|
|
712
1106
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
padding: 1,
|
|
718
|
-
margin: { top: 1, bottom: 1 },
|
|
719
|
-
borderStyle: 'round',
|
|
720
|
-
borderColor: 'cyan'
|
|
721
|
-
}
|
|
722
|
-
));
|
|
723
|
-
|
|
724
|
-
console.log(`${chalk.bold.cyan('Available Commands:')}\n`);
|
|
725
|
-
commands.forEach((cmd, i) => {
|
|
726
|
-
console.log(` ${chalk.green((i+1) + '.')} ${chalk.bold(cmd.name.padEnd(15))} ${chalk.dim(cmd.description)}`);
|
|
727
|
-
console.log(` ${chalk.yellow(cmd.command)}\n`);
|
|
728
|
-
});
|
|
1107
|
+
ssr: {
|
|
1108
|
+
enabled: ${config.template === 'ssr-template'},
|
|
1109
|
+
prerender: true
|
|
1110
|
+
},
|
|
729
1111
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
margin: { top: 1 },
|
|
736
|
-
borderStyle: 'round',
|
|
737
|
-
borderColor: 'blue'
|
|
738
|
-
}
|
|
739
|
-
));
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
// Register commands with improved descriptions
|
|
743
|
-
program
|
|
744
|
-
.command('create [name]')
|
|
745
|
-
.description('Create a new Frontend Hamroun project')
|
|
746
|
-
.option('-t, --template <template>', 'Specify template (basic-app, ssr-template, fullstack-app)')
|
|
747
|
-
.action(createProject);
|
|
748
|
-
|
|
749
|
-
program
|
|
750
|
-
.command('add:component [name]')
|
|
751
|
-
.description('Create a new component')
|
|
752
|
-
.option('-p, --path <path>', 'Path where the component should be created')
|
|
753
|
-
.option('-ts, --typescript', 'Use TypeScript')
|
|
754
|
-
.option('-jsx, --jsx', 'Use JSX')
|
|
755
|
-
.action(addComponent);
|
|
756
|
-
|
|
757
|
-
program
|
|
758
|
-
.command('add:page [name]')
|
|
759
|
-
.description('Create a new page')
|
|
760
|
-
.option('-p, --path <path>', 'Path where the page should be created')
|
|
761
|
-
.option('-ts, --typescript', 'Use TypeScript')
|
|
762
|
-
.option('-jsx, --jsx', 'Use JSX')
|
|
763
|
-
.action((pageName, options) => {
|
|
764
|
-
// We'll keep the existing implementation for now
|
|
765
|
-
console.log("The add:page command has been improved in your version.");
|
|
766
|
-
});
|
|
767
|
-
|
|
768
|
-
program
|
|
769
|
-
.command('add:api [name]')
|
|
770
|
-
.description('Create a new API route')
|
|
771
|
-
.option('-p, --path <path>', 'Path where the API route should be created')
|
|
772
|
-
.option('-ts, --typescript', 'Use TypeScript')
|
|
773
|
-
.option('-js, --javascript', 'Use JavaScript')
|
|
774
|
-
.option('-m, --methods <methods>', 'HTTP methods to implement (comma-separated: get,post,put,delete,patch)')
|
|
775
|
-
.action((routeName, options) => {
|
|
776
|
-
// We'll keep the existing implementation for now
|
|
777
|
-
console.log("The add:api command has been improved in your version.");
|
|
778
|
-
});
|
|
779
|
-
|
|
780
|
-
program
|
|
781
|
-
.command('dev:tools')
|
|
782
|
-
.description('Show development tools and tips')
|
|
783
|
-
.action(async () => {
|
|
784
|
-
displayBanner();
|
|
785
|
-
createSection('Development Tools & Tips');
|
|
786
|
-
|
|
787
|
-
// Check current project context
|
|
788
|
-
const isInProject = fs.existsSync(path.join(process.cwd(), 'package.json'));
|
|
789
|
-
let projectInfo = null;
|
|
790
|
-
|
|
791
|
-
if (isInProject) {
|
|
792
|
-
try {
|
|
793
|
-
const packageJson = await fs.readJson(path.join(process.cwd(), 'package.json'));
|
|
794
|
-
projectInfo = {
|
|
795
|
-
name: packageJson.name,
|
|
796
|
-
version: packageJson.version,
|
|
797
|
-
isFrontendHamroun: packageJson.dependencies && packageJson.dependencies['frontend-hamroun']
|
|
798
|
-
};
|
|
799
|
-
} catch (error) {
|
|
800
|
-
// Continue without project info
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
// Show project status
|
|
805
|
-
if (projectInfo) {
|
|
806
|
-
console.log(boxen(
|
|
807
|
-
`${chalk.bold('Current Project')}\n\n` +
|
|
808
|
-
`${chalk.dim('Name:')} ${chalk.cyan(projectInfo.name)}\n` +
|
|
809
|
-
`${chalk.dim('Version:')} ${chalk.cyan(projectInfo.version)}\n` +
|
|
810
|
-
`${chalk.dim('Frontend Hamroun:')} ${projectInfo.isFrontendHamroun ? chalk.green('✓ Detected') : chalk.yellow('✗ Not detected')}`,
|
|
811
|
-
{
|
|
812
|
-
padding: 1,
|
|
813
|
-
margin: 1,
|
|
814
|
-
borderStyle: 'round',
|
|
815
|
-
borderColor: projectInfo.isFrontendHamroun ? 'green' : 'yellow'
|
|
816
|
-
}
|
|
817
|
-
));
|
|
818
|
-
} else {
|
|
819
|
-
console.log(boxen(
|
|
820
|
-
`${chalk.yellow('⚠ No project detected')}\n\n` +
|
|
821
|
-
`Run ${chalk.cyan('frontend-hamroun create my-app')} to create a new project.`,
|
|
822
|
-
{
|
|
823
|
-
padding: 1,
|
|
824
|
-
margin: 1,
|
|
825
|
-
borderStyle: 'round',
|
|
826
|
-
borderColor: 'yellow'
|
|
827
|
-
}
|
|
828
|
-
));
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
// Interactive tools menu
|
|
832
|
-
const toolsMenu = await inquirer.prompt([
|
|
833
|
-
{
|
|
834
|
-
type: 'list',
|
|
835
|
-
name: 'tool',
|
|
836
|
-
message: chalk.green('Select a development tool:'),
|
|
837
|
-
choices: [
|
|
838
|
-
{ name: '🔧 Performance Analysis', value: 'performance' },
|
|
839
|
-
{ name: '📊 Bundle Analyzer', value: 'bundle' },
|
|
840
|
-
{ name: '🧪 Testing Tools', value: 'testing' },
|
|
841
|
-
{ name: '🔍 Code Quality Check', value: 'quality' },
|
|
842
|
-
{ name: '📝 Project Templates', value: 'templates' },
|
|
843
|
-
{ name: '🚀 Deployment Guide', value: 'deployment' },
|
|
844
|
-
{ name: '🐛 Debug Helper', value: 'debug' },
|
|
845
|
-
{ name: '📚 Learning Resources', value: 'resources' },
|
|
846
|
-
{ name: '⚙️ Configuration Validator', value: 'config' },
|
|
847
|
-
{ name: '📈 Benchmark Runner', value: 'benchmark' }
|
|
848
|
-
],
|
|
849
|
-
loop: false
|
|
850
|
-
}
|
|
851
|
-
]);
|
|
852
|
-
|
|
853
|
-
switch (toolsMenu.tool) {
|
|
854
|
-
case 'performance':
|
|
855
|
-
await showPerformanceTools();
|
|
856
|
-
break;
|
|
857
|
-
case 'bundle':
|
|
858
|
-
await showBundleAnalyzer();
|
|
859
|
-
break;
|
|
860
|
-
case 'testing':
|
|
861
|
-
await showTestingTools();
|
|
862
|
-
break;
|
|
863
|
-
case 'quality':
|
|
864
|
-
await showCodeQuality();
|
|
865
|
-
break;
|
|
866
|
-
case 'templates':
|
|
867
|
-
await showTemplateInfo();
|
|
868
|
-
break;
|
|
869
|
-
case 'deployment':
|
|
870
|
-
await showDeploymentGuide();
|
|
871
|
-
break;
|
|
872
|
-
case 'debug':
|
|
873
|
-
await showDebugHelper();
|
|
874
|
-
break;
|
|
875
|
-
case 'resources':
|
|
876
|
-
await showLearningResources();
|
|
877
|
-
break;
|
|
878
|
-
case 'config':
|
|
879
|
-
await showConfigValidator();
|
|
880
|
-
break;
|
|
881
|
-
case 'benchmark':
|
|
882
|
-
await showBenchmarkRunner();
|
|
883
|
-
break;
|
|
884
|
-
}
|
|
885
|
-
});
|
|
886
|
-
|
|
887
|
-
// Performance analysis tools
|
|
888
|
-
async function showPerformanceTools() {
|
|
889
|
-
console.log(boxen(
|
|
890
|
-
`${chalk.bold.cyan('🔧 Performance Analysis Tools')}\n\n` +
|
|
891
|
-
`${chalk.bold('Bundle Size Analysis:')}\n` +
|
|
892
|
-
`• ${chalk.cyan('npm run analyze')} - Analyze bundle composition\n` +
|
|
893
|
-
`• ${chalk.cyan('npm run size-check')} - Check bundle size limits\n\n` +
|
|
894
|
-
`${chalk.bold('Runtime Performance:')}\n` +
|
|
895
|
-
`• ${chalk.cyan('npm run perf')} - Run performance benchmarks\n` +
|
|
896
|
-
`• ${chalk.cyan('npm run lighthouse')} - Lighthouse audit\n\n` +
|
|
897
|
-
`${chalk.bold('Memory Analysis:')}\n` +
|
|
898
|
-
`• ${chalk.cyan('npm run memory-profile')} - Memory usage profiling\n` +
|
|
899
|
-
`• ${chalk.cyan('npm run leak-detect')} - Memory leak detection\n\n` +
|
|
900
|
-
`${chalk.bold('Recommended Tools:')}\n` +
|
|
901
|
-
`• Chrome DevTools Performance tab\n` +
|
|
902
|
-
`• React Profiler (if using React mode)\n` +
|
|
903
|
-
`• Bundle Analyzer webpack plugin`,
|
|
904
|
-
{
|
|
905
|
-
padding: 1,
|
|
906
|
-
margin: 1,
|
|
907
|
-
borderStyle: 'round',
|
|
908
|
-
borderColor: 'cyan'
|
|
909
|
-
}
|
|
910
|
-
));
|
|
1112
|
+
styling: {
|
|
1113
|
+
solution: '${config.styling}',
|
|
1114
|
+
autoprefixer: true,
|
|
1115
|
+
purgeCSS: process.env.NODE_ENV === 'production'
|
|
1116
|
+
},
|
|
911
1117
|
|
|
912
|
-
|
|
913
|
-
{
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
default: false
|
|
918
|
-
}
|
|
919
|
-
]);
|
|
1118
|
+
features: {
|
|
1119
|
+
pwa: ${config.features.includes('pwa')},
|
|
1120
|
+
i18n: ${config.features.includes('i18n')},
|
|
1121
|
+
analytics: ${config.features.includes('analytics')}
|
|
1122
|
+
},
|
|
920
1123
|
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
926
|
-
|
|
927
|
-
spinner.succeed('Performance analysis complete!');
|
|
928
|
-
|
|
929
|
-
console.log(boxen(
|
|
930
|
-
`${chalk.bold.green('Performance Report')}\n\n` +
|
|
931
|
-
`${chalk.dim('Bundle Size:')} ${chalk.green('125.3 KB')} ${chalk.dim('(gzipped)')}\n` +
|
|
932
|
-
`${chalk.dim('Load Time:')} ${chalk.green('1.2s')} ${chalk.dim('(3G connection)')}\n` +
|
|
933
|
-
`${chalk.dim('First Paint:')} ${chalk.green('0.8s')}\n` +
|
|
934
|
-
`${chalk.dim('Interactive:')} ${chalk.green('1.5s')}\n\n` +
|
|
935
|
-
`${chalk.bold.yellow('Recommendations:')}\n` +
|
|
936
|
-
`• Consider code splitting for large routes\n` +
|
|
937
|
-
`• Enable compression on your server\n` +
|
|
938
|
-
`• Optimize images and assets`,
|
|
939
|
-
{
|
|
940
|
-
padding: 1,
|
|
941
|
-
margin: 1,
|
|
942
|
-
borderStyle: 'round',
|
|
943
|
-
borderColor: 'green'
|
|
944
|
-
}
|
|
945
|
-
));
|
|
1124
|
+
optimization: {
|
|
1125
|
+
bundleAnalyzer: ${config.features.includes('analyzer')},
|
|
1126
|
+
splitChunks: true,
|
|
1127
|
+
treeshaking: true
|
|
946
1128
|
}
|
|
1129
|
+
};`;
|
|
947
1130
|
}
|
|
948
1131
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
`${
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
`• Duplicate dependencies\n` +
|
|
956
|
-
`• Unused code\n` +
|
|
957
|
-
`• Optimization opportunities\n\n` +
|
|
958
|
-
`${chalk.bold('Commands:')}\n` +
|
|
959
|
-
`• ${chalk.cyan('npm run build -- --analyze')} - Generate bundle report\n` +
|
|
960
|
-
`• ${chalk.cyan('npm run bundle-visualizer')} - Interactive bundle explorer\n\n` +
|
|
961
|
-
`${chalk.bold('Key Metrics to Watch:')}\n` +
|
|
962
|
-
`• Total bundle size < 250KB (gzipped)\n` +
|
|
963
|
-
`• Main chunk < 150KB\n` +
|
|
964
|
-
`• No duplicate large libraries\n` +
|
|
965
|
-
`• Tree shaking effectiveness > 80%`,
|
|
966
|
-
{
|
|
967
|
-
padding: 1,
|
|
968
|
-
margin: 1,
|
|
969
|
-
borderStyle: 'round',
|
|
970
|
-
borderColor: 'cyan'
|
|
971
|
-
}
|
|
972
|
-
));
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
// Testing tools
|
|
976
|
-
async function showTestingTools() {
|
|
977
|
-
console.log(boxen(
|
|
978
|
-
`${chalk.bold.cyan('🧪 Testing Tools & Best Practices')}\n\n` +
|
|
979
|
-
`${chalk.bold('Unit Testing:')}\n` +
|
|
980
|
-
`• ${chalk.cyan('npm test')} - Run all tests\n` +
|
|
981
|
-
`• ${chalk.cyan('npm run test:watch')} - Watch mode\n` +
|
|
982
|
-
`• ${chalk.cyan('npm run test:coverage')} - Coverage report\n\n` +
|
|
983
|
-
`${chalk.bold('E2E Testing:')}\n` +
|
|
984
|
-
`• ${chalk.cyan('npm run e2e')} - End-to-end tests\n` +
|
|
985
|
-
`• ${chalk.cyan('npm run e2e:headless')} - Headless mode\n\n` +
|
|
986
|
-
`${chalk.bold('Component Testing:')}\n` +
|
|
987
|
-
`• ${chalk.cyan('npm run test:components')} - Component tests\n` +
|
|
988
|
-
`• ${chalk.cyan('npm run storybook')} - Component playground\n\n` +
|
|
989
|
-
`${chalk.bold('Testing Utilities:')}\n` +
|
|
990
|
-
`• @baraqex/testing-utils\n` +
|
|
991
|
-
`• Jest with Baraqex preset\n` +
|
|
992
|
-
`• Playwright for E2E testing`,
|
|
993
|
-
{
|
|
994
|
-
padding: 1,
|
|
995
|
-
margin: 1,
|
|
996
|
-
borderStyle: 'round',
|
|
997
|
-
borderColor: 'cyan'
|
|
998
|
-
}
|
|
999
|
-
));
|
|
1132
|
+
async function generateNextSteps(projectName, config) {
|
|
1133
|
+
const steps = [
|
|
1134
|
+
`cd ${projectName}`,
|
|
1135
|
+
!config.installDeps ? `${config.packageManager} install` : null,
|
|
1136
|
+
`${config.packageManager} run dev`
|
|
1137
|
+
].filter(Boolean);
|
|
1000
1138
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
test('renders button with text', () => {
|
|
1006
|
-
render(<Button>Click me</Button>);
|
|
1007
|
-
expect(screen.getByText('Click me')).toBeInTheDocument();
|
|
1008
|
-
});
|
|
1009
|
-
|
|
1010
|
-
test('calls onClick when clicked', () => {
|
|
1011
|
-
const handleClick = jest.fn();
|
|
1012
|
-
render(<Button onClick={handleClick}>Click me</Button>);
|
|
1139
|
+
// Add conditional steps based on configuration
|
|
1140
|
+
if (config.features.includes('testing')) {
|
|
1141
|
+
steps.push(`${config.packageManager} run test # Run your tests`);
|
|
1142
|
+
}
|
|
1013
1143
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
}
|
|
1144
|
+
if (config.features.includes('docker')) {
|
|
1145
|
+
steps.push('docker build -t ' + projectName + ' . # Build Docker image');
|
|
1146
|
+
}
|
|
1017
1147
|
|
|
1018
|
-
|
|
1019
|
-
`${chalk.bold('Example Test:')}\n\n${chalk.gray(testExample)}`,
|
|
1020
|
-
{
|
|
1021
|
-
padding: 1,
|
|
1022
|
-
margin: 1,
|
|
1023
|
-
borderStyle: 'round',
|
|
1024
|
-
borderColor: 'gray'
|
|
1025
|
-
}
|
|
1026
|
-
));
|
|
1148
|
+
return steps;
|
|
1027
1149
|
}
|
|
1028
1150
|
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
`${chalk.bold('Type Checking:')}\n` +
|
|
1038
|
-
`• ${chalk.cyan('npm run type-check')} - TypeScript validation\n` +
|
|
1039
|
-
`• ${chalk.cyan('npm run type-coverage')} - Type coverage report\n\n` +
|
|
1040
|
-
`${chalk.bold('Security:')}\n` +
|
|
1041
|
-
`• ${chalk.cyan('npm audit')} - Dependency security audit\n` +
|
|
1042
|
-
`• ${chalk.cyan('npm run security-check')} - Security scan\n\n` +
|
|
1043
|
-
`${chalk.bold('Quality Metrics:')}\n` +
|
|
1044
|
-
`• Code coverage > 80%\n` +
|
|
1045
|
-
`• Type coverage > 90%\n` +
|
|
1046
|
-
`• No security vulnerabilities\n` +
|
|
1047
|
-
`• ESLint score: A grade`,
|
|
1048
|
-
{
|
|
1049
|
-
padding: 1,
|
|
1050
|
-
margin: 1,
|
|
1051
|
-
borderStyle: 'round',
|
|
1052
|
-
borderColor: 'cyan'
|
|
1053
|
-
}
|
|
1054
|
-
));
|
|
1055
|
-
|
|
1056
|
-
const qualityCheck = await inquirer.prompt([
|
|
1057
|
-
{
|
|
1058
|
-
type: 'confirm',
|
|
1059
|
-
name: 'runCheck',
|
|
1060
|
-
message: 'Would you like to run a code quality check?',
|
|
1061
|
-
default: false
|
|
1062
|
-
}
|
|
1063
|
-
]);
|
|
1064
|
-
|
|
1065
|
-
if (qualityCheck.runCheck) {
|
|
1066
|
-
const spinner = ora('Running code quality analysis...').start();
|
|
1067
|
-
|
|
1068
|
-
// Simulate quality check
|
|
1069
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
1070
|
-
|
|
1071
|
-
spinner.succeed('Code quality analysis complete!');
|
|
1072
|
-
|
|
1073
|
-
console.log(boxen(
|
|
1074
|
-
`${chalk.bold.green('Quality Report')}\n\n` +
|
|
1075
|
-
`${chalk.dim('ESLint:')} ${chalk.green('✓ No issues')} ${chalk.dim('(0 errors, 0 warnings)')}\n` +
|
|
1076
|
-
`${chalk.dim('TypeScript:')} ${chalk.green('✓ No type errors')}\n` +
|
|
1077
|
-
`${chalk.dim('Security:')} ${chalk.green('✓ No vulnerabilities')}\n` +
|
|
1078
|
-
`${chalk.dim('Test Coverage:')} ${chalk.green('87%')} ${chalk.dim('(target: 80%)')}\n` +
|
|
1079
|
-
`${chalk.dim('Code Formatting:')} ${chalk.green('✓ Consistent')}\n\n` +
|
|
1080
|
-
`${chalk.bold.green('Overall Grade: A+')}`,
|
|
1081
|
-
{
|
|
1082
|
-
padding: 1,
|
|
1083
|
-
margin: 1,
|
|
1084
|
-
borderStyle: 'round',
|
|
1085
|
-
borderColor: 'green'
|
|
1151
|
+
function analyzeProject(targetDir) {
|
|
1152
|
+
try {
|
|
1153
|
+
const files = glob.sync(`${targetDir}/**/*`, { nodir: true });
|
|
1154
|
+
const totalSize = files.reduce((acc, file) => {
|
|
1155
|
+
try {
|
|
1156
|
+
return acc + fs.statSync(file).size;
|
|
1157
|
+
} catch {
|
|
1158
|
+
return acc;
|
|
1086
1159
|
}
|
|
1087
|
-
)
|
|
1160
|
+
}, 0);
|
|
1161
|
+
|
|
1162
|
+
return {
|
|
1163
|
+
files: files.length,
|
|
1164
|
+
size: `${(totalSize / 1024).toFixed(1)}KB`
|
|
1165
|
+
};
|
|
1166
|
+
} catch (error) {
|
|
1167
|
+
return { files: 'Unknown', size: 'Unknown' };
|
|
1088
1168
|
}
|
|
1089
1169
|
}
|
|
1090
1170
|
|
|
1091
|
-
//
|
|
1092
|
-
async function showTemplateInfo() {
|
|
1093
|
-
console.log(boxen(
|
|
1094
|
-
`${chalk.bold.cyan('📝 Available Project Templates')}\n\n` +
|
|
1095
|
-
`${chalk.bold('🚀 basic-app')}\n` +
|
|
1096
|
-
`Single-page application with essential features\n` +
|
|
1097
|
-
`• Client-side rendering\n` +
|
|
1098
|
-
`• Component library\n` +
|
|
1099
|
-
`• State management\n\n` +
|
|
1100
|
-
`${chalk.bold('🌐 ssr-template')}\n` +
|
|
1101
|
-
`Server-side rendering with hydration\n` +
|
|
1102
|
-
`• SEO optimization\n` +
|
|
1103
|
-
`• Fast initial load\n` +
|
|
1104
|
-
`• Progressive enhancement\n\n` +
|
|
1105
|
-
`${chalk.bold('⚡ fullstack-app')}\n` +
|
|
1106
|
-
`Complete full-stack solution\n` +
|
|
1107
|
-
`• API routes\n` +
|
|
1108
|
-
`• Database integration\n` +
|
|
1109
|
-
`• Authentication\n\n` +
|
|
1110
|
-
`${chalk.bold('🔄 go-wasm-app')}\n` +
|
|
1111
|
-
`WebAssembly integration with Go\n` +
|
|
1112
|
-
`• High-performance computing\n` +
|
|
1113
|
-
`• Go + JavaScript interop\n` +
|
|
1114
|
-
`• Optimized builds`,
|
|
1115
|
-
{
|
|
1116
|
-
padding: 1,
|
|
1117
|
-
margin: 1,
|
|
1118
|
-
borderStyle: 'round',
|
|
1119
|
-
borderColor: 'cyan'
|
|
1120
|
-
}
|
|
1121
|
-
));
|
|
1122
|
-
|
|
1123
|
-
console.log(`\n${chalk.dim('Create a new project:')} ${chalk.cyan('frontend-hamroun create my-app')}`);
|
|
1124
|
-
}
|
|
1171
|
+
// ...continuing with more helper functions and remaining CLI commands...
|
|
1125
1172
|
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
`• ${chalk.green('Netlify:')} ${chalk.cyan('npm run deploy:netlify')}\n` +
|
|
1136
|
-
`• ${chalk.green('Railway:')} ${chalk.cyan('npm run deploy:railway')}\n` +
|
|
1137
|
-
`• ${chalk.green('Docker:')} ${chalk.cyan('docker build -t my-app .')}\n\n` +
|
|
1138
|
-
`${chalk.bold('Environment Setup:')}\n` +
|
|
1139
|
-
`• Configure environment variables\n` +
|
|
1140
|
-
`• Set up SSL certificates\n` +
|
|
1141
|
-
`• Configure CDN for static assets\n` +
|
|
1142
|
-
`• Set up monitoring and analytics`,
|
|
1143
|
-
{
|
|
1144
|
-
padding: 1,
|
|
1145
|
-
margin: 1,
|
|
1146
|
-
borderStyle: 'round',
|
|
1147
|
-
borderColor: 'cyan'
|
|
1148
|
-
}
|
|
1149
|
-
));
|
|
1150
|
-
|
|
1151
|
-
const deploymentExample = `# .env.production
|
|
1152
|
-
NODE_ENV=production
|
|
1153
|
-
API_URL=https://api.myapp.com
|
|
1154
|
-
CDN_URL=https://cdn.myapp.com
|
|
1155
|
-
ANALYTICS_ID=your-analytics-id`;
|
|
1156
|
-
|
|
1157
|
-
console.log(boxen(
|
|
1158
|
-
`${chalk.bold('Example Environment Config:')}\n\n${chalk.gray(deploymentExample)}`,
|
|
1159
|
-
{
|
|
1160
|
-
padding: 1,
|
|
1161
|
-
margin: 1,
|
|
1162
|
-
borderStyle: 'round',
|
|
1163
|
-
borderColor: 'gray'
|
|
1164
|
-
}
|
|
1165
|
-
));
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// Debug helper
|
|
1169
|
-
async function showDebugHelper() {
|
|
1170
|
-
console.log(boxen(
|
|
1171
|
-
`${chalk.bold.cyan('🐛 Debug Helper')}\n\n` +
|
|
1172
|
-
`${chalk.bold('Common Issues & Solutions:')}\n\n` +
|
|
1173
|
-
`${chalk.yellow('• Component not rendering:')}\n` +
|
|
1174
|
-
` - Check JSX syntax\n` +
|
|
1175
|
-
` - Verify component import/export\n` +
|
|
1176
|
-
` - Check console for errors\n\n` +
|
|
1177
|
-
`${chalk.yellow('• State not updating:')}\n` +
|
|
1178
|
-
` - Use functional state updates\n` +
|
|
1179
|
-
` - Check dependency arrays\n` +
|
|
1180
|
-
` - Verify state immutability\n\n` +
|
|
1181
|
-
`${chalk.yellow('• Performance issues:')}\n` +
|
|
1182
|
-
` - Use React.memo for expensive components\n` +
|
|
1183
|
-
` - Implement useMemo for calculations\n` +
|
|
1184
|
-
` - Check for unnecessary re-renders\n\n` +
|
|
1185
|
-
`${chalk.bold('Debug Tools:')}\n` +
|
|
1186
|
-
`• ${chalk.cyan('npm run debug')} - Debug mode\n` +
|
|
1187
|
-
`• Browser DevTools Extensions\n` +
|
|
1188
|
-
`• Frontend Hamroun DevTools\n` +
|
|
1189
|
-
`• Performance Profiler`,
|
|
1190
|
-
{
|
|
1191
|
-
padding: 1,
|
|
1192
|
-
margin: 1,
|
|
1193
|
-
borderStyle: 'round',
|
|
1194
|
-
borderColor: 'cyan'
|
|
1195
|
-
}
|
|
1196
|
-
));
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
// Learning resources
|
|
1200
|
-
async function showLearningResources() {
|
|
1201
|
-
console.log(boxen(
|
|
1202
|
-
`${chalk.bold.cyan('📚 Learning Resources')}\n\n` +
|
|
1203
|
-
`${chalk.bold('Official Documentation:')}\n` +
|
|
1204
|
-
`• ${terminalLink('Getting Started', 'https://www.baraqex.tech/docs/getting-started')}\n` +
|
|
1205
|
-
`• ${terminalLink('API Reference', 'https://www.baraqex.tech/docs/api')}\n` +
|
|
1206
|
-
`• ${terminalLink('Examples', 'https://github.com/mohamedx2/baraqex/examples')}\n\n` +
|
|
1207
|
-
`${chalk.bold('Tutorials:')}\n` +
|
|
1208
|
-
`• Building Your First App\n` +
|
|
1209
|
-
`• State Management Patterns\n` +
|
|
1210
|
-
`• Performance Optimization\n` +
|
|
1211
|
-
`• Testing Best Practices\n\n` +
|
|
1212
|
-
`${chalk.bold('Community:')}\n` +
|
|
1213
|
-
`• ${terminalLink('Discord Server', 'https://discord.gg/baraqex')}\n` +
|
|
1214
|
-
`• ${terminalLink('GitHub Discussions', 'https://github.com/mohamedx2/baraqex/discussions')}\n` +
|
|
1215
|
-
`• ${terminalLink('Stack Overflow', 'https://stackoverflow.com/questions/tagged/baraqex')}\n\n` +
|
|
1216
|
-
`${chalk.bold('Video Content:')}\n` +
|
|
1217
|
-
`• YouTube Channel\n` +
|
|
1218
|
-
`• Conference Talks\n` +
|
|
1219
|
-
`• Live Coding Sessions`,
|
|
1220
|
-
{
|
|
1221
|
-
padding: 1,
|
|
1222
|
-
margin: 1,
|
|
1223
|
-
borderStyle: 'round',
|
|
1224
|
-
borderColor: 'cyan'
|
|
1173
|
+
program
|
|
1174
|
+
.name('baraqex')
|
|
1175
|
+
.description('🚀 Next-generation CLI for Baraqex - AI-Powered Full-Stack Framework')
|
|
1176
|
+
.version(packageInfo.version || '1.0.0')
|
|
1177
|
+
.option('--verbose', 'Enable verbose logging')
|
|
1178
|
+
.option('--no-analytics', 'Disable analytics and telemetry')
|
|
1179
|
+
.hook('preAction', (thisCommand) => {
|
|
1180
|
+
if (thisCommand.opts().verbose) {
|
|
1181
|
+
process.env.BARAQEX_VERBOSE = 'true';
|
|
1225
1182
|
}
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
// Configuration validator
|
|
1230
|
-
async function showConfigValidator() {
|
|
1231
|
-
const spinner = ora('Validating project configuration...').start();
|
|
1232
|
-
|
|
1233
|
-
// Simulate config validation
|
|
1234
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
1235
|
-
|
|
1236
|
-
spinner.succeed('Configuration validation complete!');
|
|
1237
|
-
|
|
1238
|
-
console.log(boxen(
|
|
1239
|
-
`${chalk.bold.green('Configuration Status')}\n\n` +
|
|
1240
|
-
`${chalk.dim('package.json:')} ${chalk.green('✓ Valid')}\n` +
|
|
1241
|
-
`${chalk.dim('tsconfig.json:')} ${chalk.green('✓ Valid')}\n` +
|
|
1242
|
-
`${chalk.dim('baraqex.config.js:')} ${chalk.green('✓ Valid')}\n` +
|
|
1243
|
-
`${chalk.dim('ESLint config:')} ${chalk.green('✓ Valid')}\n` +
|
|
1244
|
-
`${chalk.dim('Environment variables:')} ${chalk.yellow('⚠ Missing some optional vars')}\n\n` +
|
|
1245
|
-
`${chalk.bold.yellow('Recommendations:')}\n` +
|
|
1246
|
-
`• Add ANALYTICS_ID environment variable\n` +
|
|
1247
|
-
`• Consider enabling strict mode in TypeScript\n` +
|
|
1248
|
-
`• Update ESLint rules for better practices`,
|
|
1249
|
-
{
|
|
1250
|
-
padding: 1,
|
|
1251
|
-
margin: 1,
|
|
1252
|
-
borderStyle: 'round',
|
|
1253
|
-
borderColor: 'green'
|
|
1183
|
+
if (thisCommand.opts().noAnalytics) {
|
|
1184
|
+
globalConfig.analytics = false;
|
|
1254
1185
|
}
|
|
1255
|
-
)
|
|
1256
|
-
}
|
|
1186
|
+
});
|
|
1257
1187
|
|
|
1258
|
-
//
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
padding: 1,
|
|
1274
|
-
margin: 1,
|
|
1275
|
-
borderStyle: 'round',
|
|
1276
|
-
borderColor: 'cyan'
|
|
1277
|
-
}
|
|
1278
|
-
));
|
|
1279
|
-
|
|
1280
|
-
const runBenchmark = await inquirer.prompt([
|
|
1281
|
-
{
|
|
1282
|
-
type: 'confirm',
|
|
1283
|
-
name: 'run',
|
|
1284
|
-
message: 'Would you like to run a quick benchmark?',
|
|
1285
|
-
default: false
|
|
1286
|
-
}
|
|
1287
|
-
]);
|
|
1288
|
-
|
|
1289
|
-
if (runBenchmark.run) {
|
|
1290
|
-
const spinner = ora('Running performance benchmarks...').start();
|
|
1291
|
-
|
|
1292
|
-
// Simulate benchmark
|
|
1293
|
-
await new Promise(resolve => setTimeout(resolve, 4000));
|
|
1294
|
-
|
|
1295
|
-
spinner.succeed('Benchmark complete!');
|
|
1296
|
-
|
|
1297
|
-
console.log(boxen(
|
|
1298
|
-
`${chalk.bold.green('Benchmark Results')}\n\n` +
|
|
1299
|
-
`${chalk.dim('Rendering (1000 components):')} ${chalk.green('23.4ms')}\n` +
|
|
1300
|
-
`${chalk.dim('Bundle size (gzipped):')} ${chalk.green('125.3 KB')}\n` +
|
|
1301
|
-
`${chalk.dim('Memory usage (peak):')} ${chalk.green('45.2 MB')}\n` +
|
|
1302
|
-
`${chalk.dim('First paint:')} ${chalk.green('0.8s')}\n` +
|
|
1303
|
-
`${chalk.dim('Interactive:')} ${chalk.green('1.2s')}\n\n` +
|
|
1304
|
-
`${chalk.bold.green('Performance Grade: A')}\n\n` +
|
|
1305
|
-
`${chalk.dim('Comparison with React:')} ${chalk.green('18% faster')}\n` +
|
|
1306
|
-
`${chalk.dim('Comparison with Vue:')} ${chalk.green('12% faster')}`,
|
|
1307
|
-
{
|
|
1308
|
-
padding: 1,
|
|
1309
|
-
margin: 1,
|
|
1310
|
-
borderStyle: 'round',
|
|
1311
|
-
borderColor: 'green'
|
|
1312
|
-
}
|
|
1313
|
-
));
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1188
|
+
// Enhanced create command
|
|
1189
|
+
program
|
|
1190
|
+
.command('create [name]')
|
|
1191
|
+
.description('🎯 Create a new Baraqex project with AI-powered setup')
|
|
1192
|
+
.option('-t, --template <template>', 'Template: basic-app, ssr-template, fullstack-app, go-wasm-app, pwa-app')
|
|
1193
|
+
.option('--npm', 'Use npm package manager')
|
|
1194
|
+
.option('--yarn', 'Use yarn package manager')
|
|
1195
|
+
.option('--pnpm', 'Use pnpm package manager')
|
|
1196
|
+
.option('--typescript', 'Enable TypeScript')
|
|
1197
|
+
.option('--no-typescript', 'Disable TypeScript')
|
|
1198
|
+
.option('--no-install', 'Skip dependency installation')
|
|
1199
|
+
.option('--no-git', 'Skip git repository initialization')
|
|
1200
|
+
.option('--styling <solution>', 'Styling solution: tailwind, styled-components, css-modules, vanilla')
|
|
1201
|
+
.option('--features <features>', 'Comma-separated features: linting,testing,pwa,i18n,analyzer,docker,github-actions,analytics')
|
|
1202
|
+
.action(createProject);
|
|
1316
1203
|
|
|
1317
|
-
// Default command when no arguments
|
|
1204
|
+
// Default command when no arguments - show enhanced dashboard
|
|
1318
1205
|
if (process.argv.length <= 2) {
|
|
1319
|
-
|
|
1206
|
+
displayBanner();
|
|
1320
1207
|
} else {
|
|
1321
1208
|
program.parse(process.argv);
|
|
1322
1209
|
}
|