baraqex 1.0.20 → 1.0.21

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 ADDED
@@ -0,0 +1,612 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import inquirer from 'inquirer';
5
+ import chalk from 'chalk';
6
+ import gradient from 'gradient-string';
7
+ import { createSpinner } from 'nanospinner';
8
+ import path from 'path';
9
+ import fs from 'fs-extra';
10
+ import { fileURLToPath } from 'url';
11
+ import { exec } from 'child_process';
12
+ import { promisify } from 'util';
13
+ import boxen from 'boxen';
14
+ import terminalLink from 'terminal-link';
15
+ import updateNotifier from 'update-notifier';
16
+ import ora from 'ora';
17
+ import figlet from 'figlet';
18
+
19
+ // Convert to ESM-friendly __dirname equivalent
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = path.dirname(__filename);
22
+ const execAsync = promisify(exec);
23
+
24
+ // Check for package updates
25
+ try {
26
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
27
+ const notifier = updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 * 24 });
28
+
29
+ if (notifier.update) {
30
+ const updateMessage = boxen(
31
+ `Update available: ${chalk.dim(notifier.update.current)} → ${chalk.green(notifier.update.latest)}\n` +
32
+ `Run ${chalk.cyan('npm i -g baraqex')} to update`,
33
+ {
34
+ padding: 1,
35
+ margin: 1,
36
+ borderStyle: 'round',
37
+ borderColor: 'cyan'
38
+ }
39
+ );
40
+ console.log(updateMessage);
41
+ }
42
+ } catch (error) {
43
+ // Silently continue if update check fails
44
+ }
45
+
46
+ // CLI instance
47
+ const program = new Command();
48
+
49
+ // Create beautiful ASCII art banner with gradient colors
50
+ const displayBanner = () => {
51
+ const titleText = figlet.textSync('Baraqex', {
52
+ font: 'Standard',
53
+ horizontalLayout: 'default',
54
+ verticalLayout: 'default'
55
+ });
56
+
57
+ console.log('\n' + gradient.pastel.multiline(titleText));
58
+
59
+ console.log(boxen(
60
+ `${chalk.bold('A powerful full-stack framework with WebAssembly integration')}\n\n` +
61
+ `${chalk.dim('Version:')} ${chalk.cyan(JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')).version)}\n` +
62
+ `${chalk.dim('Website:')} ${terminalLink('www.baraqex.tech', 'https://www.baraqex.tech')}`,
63
+ {
64
+ padding: 1,
65
+ margin: { top: 1, bottom: 1 },
66
+ borderStyle: 'round',
67
+ borderColor: 'cyan'
68
+ }
69
+ ));
70
+ };
71
+
72
+ // Version and description
73
+ program
74
+ .name('baraqex')
75
+ .description('CLI for Baraqex - A powerful full-stack JavaScript/TypeScript framework with WebAssembly integration')
76
+ .version(JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')).version);
77
+
78
+ // Helper for creating visually consistent sections
79
+ const createSection = (title) => {
80
+ console.log('\n' + chalk.bold.cyan(`◆ ${title}`));
81
+ console.log(chalk.cyan('─'.repeat(60)) + '\n');
82
+ };
83
+
84
+ // Helper for checking dependencies with improved feedback
85
+ async function checkDependencies() {
86
+ const spinner = ora({
87
+ text: 'Checking environment...',
88
+ spinner: 'dots',
89
+ color: 'cyan'
90
+ }).start();
91
+
92
+ try {
93
+ // Check Node version
94
+ const nodeVersionOutput = await execAsync('node --version');
95
+ const nodeVersion = nodeVersionOutput.stdout.trim().replace('v', '');
96
+ const requiredNodeVersion = '14.0.0';
97
+
98
+ if (compareVersions(nodeVersion, requiredNodeVersion) < 0) {
99
+ spinner.fail(`Node.js ${requiredNodeVersion}+ required, but found ${nodeVersion}`);
100
+ console.log(chalk.yellow(`Please upgrade Node.js: ${terminalLink('https://nodejs.org', 'https://nodejs.org')}`));
101
+ return false;
102
+ }
103
+
104
+ // Check npm version
105
+ const npmVersionOutput = await execAsync('npm --version');
106
+ const npmVersion = npmVersionOutput.stdout.trim();
107
+ const requiredNpmVersion = '6.0.0';
108
+
109
+ if (compareVersions(npmVersion, requiredNpmVersion) < 0) {
110
+ spinner.fail(`npm ${requiredNpmVersion}+ required, but found ${npmVersion}`);
111
+ console.log(chalk.yellow(`Please upgrade npm: ${chalk.cyan('npm install -g npm')}`));
112
+ return false;
113
+ }
114
+
115
+ // Check for Go (optional, for WASM features)
116
+ try {
117
+ const goVersionOutput = await execAsync('go version');
118
+ const goVersion = goVersionOutput.stdout.match(/go(\d+\.\d+\.\d+)/)?.[1] || 'unknown';
119
+ spinner.succeed(`Environment ready: Node ${chalk.green(nodeVersion)}, npm ${chalk.green(npmVersion)}, Go ${chalk.green(goVersion)}`);
120
+ } catch (error) {
121
+ spinner.succeed(`Environment ready: Node ${chalk.green(nodeVersion)}, npm ${chalk.green(npmVersion)} ${chalk.yellow('(Go not found - WebAssembly features limited)')}`);
122
+ }
123
+
124
+ return true;
125
+ } catch (error) {
126
+ spinner.fail('Environment check failed');
127
+ console.log(chalk.red('Error: Node.js and npm are required to use this tool.'));
128
+ return false;
129
+ }
130
+ }
131
+
132
+ // Compare versions helper
133
+ function compareVersions(a, b) {
134
+ const aParts = a.split('.').map(Number);
135
+ const bParts = b.split('.').map(Number);
136
+
137
+ for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
138
+ const aVal = aParts[i] || 0;
139
+ const bVal = bParts[i] || 0;
140
+
141
+ if (aVal > bVal) return 1;
142
+ if (aVal < bVal) return -1;
143
+ }
144
+
145
+ return 0;
146
+ }
147
+
148
+ // Choose template interactively with improved visualization
149
+ async function chooseTemplate() {
150
+ const templatesPath = path.join(__dirname, '..', 'templates');
151
+
152
+ // Create templates directory if it doesn't exist
153
+ if (!fs.existsSync(templatesPath)) {
154
+ fs.mkdirSync(templatesPath, { recursive: true });
155
+ }
156
+
157
+ const templates = fs.readdirSync(templatesPath).filter(file =>
158
+ fs.statSync(path.join(templatesPath, file)).isDirectory()
159
+ );
160
+
161
+ // If no templates exist, create default ones
162
+ if (templates.length === 0) {
163
+ await createDefaultTemplates(templatesPath);
164
+ const newTemplates = fs.readdirSync(templatesPath).filter(file =>
165
+ fs.statSync(path.join(templatesPath, file)).isDirectory()
166
+ );
167
+ templates.push(...newTemplates);
168
+ }
169
+
170
+ // Emoji indicators for templates
171
+ const templateIcons = {
172
+ 'basic-app': '🚀',
173
+ 'ssr-template': '🌐',
174
+ 'fullstack-app': '⚡',
175
+ 'go-wasm-app': '🔄',
176
+ };
177
+
178
+ // Detailed descriptions
179
+ const templateDescriptions = {
180
+ 'basic-app': 'Single-page application with just the essentials. Perfect for learning the framework or building simple apps.',
181
+ 'ssr-template': 'Server-side rendered application with hydration. Optimized for SEO and fast initial load.',
182
+ 'fullstack-app': 'Complete solution with API routes, authentication, and database integration ready to go.',
183
+ 'go-wasm-app': 'WebAssembly integration with Go for high-performance computing in the browser and Node.js.'
184
+ };
185
+
186
+ console.log(boxen(
187
+ `${chalk.bold('Available Project Templates')}\n\n` +
188
+ templates.map(template => {
189
+ const icon = templateIcons[template] || '📦';
190
+ const shortDesc = {
191
+ 'basic-app': 'Simple client-side application',
192
+ 'ssr-template': 'Server-side rendering with hydration',
193
+ 'fullstack-app': 'Complete fullstack application with API',
194
+ 'go-wasm-app': 'WebAssembly integration with Go'
195
+ }[template] || 'Application template';
196
+
197
+ return `${icon} ${chalk.cyan(template)}\n ${chalk.dim(shortDesc)}`;
198
+ }).join('\n\n'),
199
+ {
200
+ padding: 1,
201
+ margin: 1,
202
+ borderStyle: 'round',
203
+ borderColor: 'cyan'
204
+ }
205
+ ));
206
+
207
+ const templateChoices = templates.map(template => ({
208
+ name: `${templateIcons[template] || '📦'} ${chalk.bold(template)}`,
209
+ value: template,
210
+ description: templateDescriptions[template] || 'An application template'
211
+ }));
212
+
213
+ const answers = await inquirer.prompt([
214
+ {
215
+ type: 'list',
216
+ name: 'template',
217
+ message: chalk.green('Select a project template:'),
218
+ choices: templateChoices,
219
+ loop: false,
220
+ pageSize: 10
221
+ },
222
+ {
223
+ type: 'confirm',
224
+ name: 'viewDetails',
225
+ message: 'Would you like to see template details before proceeding?',
226
+ default: false
227
+ }
228
+ ]);
229
+
230
+ if (answers.viewDetails) {
231
+ const detailedDescription = {
232
+ 'basic-app': [
233
+ `${chalk.bold('Basic App Template')} ${templateIcons['basic-app']}`,
234
+ '',
235
+ `${chalk.dim('A lightweight client-side application template.')}`,
236
+ '',
237
+ `${chalk.yellow('Features:')}`,
238
+ '• Modern JSX components without dependencies',
239
+ '• Built-in state management with hooks',
240
+ '• Component-based architecture',
241
+ '• Zero-config development setup',
242
+ '',
243
+ `${chalk.yellow('Best for:')}`,
244
+ '• Simple web applications',
245
+ '• Learning the framework',
246
+ '• Quick prototyping',
247
+ ],
248
+ 'ssr-template': [
249
+ `${chalk.bold('SSR Template')} ${templateIcons['ssr-template']}`,
250
+ '',
251
+ `${chalk.dim('Server-side rendering with client hydration.')}`,
252
+ '',
253
+ `${chalk.yellow('Features:')}`,
254
+ '• SEO-friendly rendered HTML',
255
+ '• Fast initial page load',
256
+ '• Smooth client-side transitions',
257
+ '• Built-in dynamic meta tag generation',
258
+ '• Express.js integration',
259
+ '',
260
+ `${chalk.yellow('Best for:')}`,
261
+ '• Production websites needing SEO',
262
+ '• Content-focused applications',
263
+ '• Sites requiring social sharing previews'
264
+ ],
265
+ 'fullstack-app': [
266
+ `${chalk.bold('Fullstack App Template')} ${templateIcons['fullstack-app']}`,
267
+ '',
268
+ `${chalk.dim('Complete solution with frontend and backend.')}`,
269
+ '',
270
+ `${chalk.yellow('Features:')}`,
271
+ '• API routes with Express integration',
272
+ '• File-based routing system',
273
+ '• Authentication system with JWT',
274
+ '• Database connectors (MongoDB, MySQL, PostgreSQL)',
275
+ '• Server-side rendering with hydration',
276
+ '• WebSocket support',
277
+ '',
278
+ `${chalk.yellow('Best for:')}`,
279
+ '• Full production applications',
280
+ '• Apps needing authentication',
281
+ '• Projects requiring database integration'
282
+ ],
283
+ 'go-wasm-app': [
284
+ `${chalk.bold('Go WASM App Template')} ${templateIcons['go-wasm-app'] || '🔄'}`,
285
+ '',
286
+ `${chalk.dim('WebAssembly integration with Go programming language.')}`,
287
+ '',
288
+ `${chalk.yellow('Features:')}`,
289
+ '• Go + WebAssembly integration',
290
+ '• High-performance computation in browser',
291
+ '• Server-side WASM processing',
292
+ '• Shared code between Go and JavaScript',
293
+ '• Optimized build pipeline',
294
+ '',
295
+ `${chalk.yellow('Best for:')}`,
296
+ '• Computation-heavy applications',
297
+ '• Projects requiring Go libraries',
298
+ '• Performance-critical features'
299
+ ]
300
+ }[answers.template] || ['No detailed information available for this template'];
301
+
302
+ console.log(boxen(detailedDescription.join('\n'), {
303
+ padding: 1,
304
+ margin: 1,
305
+ title: answers.template,
306
+ titleAlignment: 'center',
307
+ borderStyle: 'round',
308
+ borderColor: 'yellow'
309
+ }));
310
+
311
+ const proceed = await inquirer.prompt([{
312
+ type: 'confirm',
313
+ name: 'continue',
314
+ message: 'Continue with this template?',
315
+ default: true
316
+ }]);
317
+
318
+ if (!proceed.continue) {
319
+ return chooseTemplate();
320
+ }
321
+ }
322
+
323
+ return answers.template;
324
+ }
325
+
326
+ // Create default templates if they don't exist
327
+ async function createDefaultTemplates(templatesPath) {
328
+ const templates = {
329
+ 'basic-app': {
330
+ 'package.json': {
331
+ name: 'baraqex-basic-app',
332
+ version: '1.0.0',
333
+ scripts: {
334
+ dev: 'baraqex dev',
335
+ build: 'baraqex build',
336
+ start: 'baraqex start'
337
+ },
338
+ dependencies: {
339
+ baraqex: '^1.0.0'
340
+ }
341
+ },
342
+ 'src/App.jsx': `import { jsx, useState } from 'baraqex';
343
+
344
+ export default function App() {
345
+ const [count, setCount] = useState(0);
346
+
347
+ return (
348
+ <div>
349
+ <h1>Welcome to Baraqex!</h1>
350
+ <p>Count: {count}</p>
351
+ <button onClick={() => setCount(count + 1)}>
352
+ Increment
353
+ </button>
354
+ </div>
355
+ );
356
+ }`,
357
+ 'public/index.html': `<!DOCTYPE html>
358
+ <html lang="en">
359
+ <head>
360
+ <meta charset="UTF-8">
361
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
362
+ <title>Baraqex App</title>
363
+ </head>
364
+ <body>
365
+ <div id="root"></div>
366
+ <script src="/src/App.jsx" type="module"></script>
367
+ </body>
368
+ </html>`
369
+ },
370
+ 'fullstack-app': {
371
+ 'package.json': {
372
+ name: 'baraqex-fullstack-app',
373
+ version: '1.0.0',
374
+ scripts: {
375
+ dev: 'baraqex dev',
376
+ build: 'baraqex build',
377
+ start: 'baraqex start',
378
+ test: 'baraqex test'
379
+ },
380
+ dependencies: {
381
+ baraqex: '^1.0.0'
382
+ }
383
+ },
384
+ 'src/pages/index.jsx': `import { jsx } from 'baraqex';
385
+
386
+ export default function HomePage(props) {
387
+ return (
388
+ <html>
389
+ <head>
390
+ <title>Baraqex Fullstack App</title>
391
+ </head>
392
+ <body>
393
+ <h1>Welcome to Baraqex!</h1>
394
+ <p>Server time: {props.api.serverTime}</p>
395
+ </body>
396
+ </html>
397
+ );
398
+ }`,
399
+ 'src/api/hello.js': `export async function get(req, res) {
400
+ res.json({ message: 'Hello from Baraqex API!' });
401
+ }`
402
+ }
403
+ };
404
+
405
+ for (const [templateName, files] of Object.entries(templates)) {
406
+ const templatePath = path.join(templatesPath, templateName);
407
+ await fs.ensureDir(templatePath);
408
+
409
+ for (const [filePath, content] of Object.entries(files)) {
410
+ const fullPath = path.join(templatePath, filePath);
411
+ await fs.ensureDir(path.dirname(fullPath));
412
+
413
+ if (typeof content === 'object') {
414
+ await fs.writeJson(fullPath, content, { spaces: 2 });
415
+ } else {
416
+ await fs.writeFile(fullPath, content);
417
+ }
418
+ }
419
+ }
420
+ }
421
+
422
+ // Create a new project with enhanced visuals and status updates
423
+ async function createProject(projectName, options) {
424
+ displayBanner();
425
+ createSection('Project Setup');
426
+
427
+ if (!projectName) {
428
+ const answers = await inquirer.prompt([
429
+ {
430
+ type: 'input',
431
+ name: 'projectName',
432
+ message: chalk.green('What is your project name?'),
433
+ default: 'my-baraqex-app',
434
+ validate: input =>
435
+ /^[a-z0-9-_]+$/.test(input)
436
+ ? true
437
+ : 'Project name can only contain lowercase letters, numbers, hyphens, and underscores'
438
+ }
439
+ ]);
440
+ projectName = answers.projectName;
441
+ }
442
+
443
+ if (!await checkDependencies()) return;
444
+
445
+ let template = options.template || await chooseTemplate();
446
+
447
+ const targetDir = path.resolve(projectName);
448
+ const templateDir = path.join(__dirname, '..', 'templates', template);
449
+
450
+ if (fs.existsSync(targetDir)) {
451
+ const answers = await inquirer.prompt([
452
+ {
453
+ type: 'confirm',
454
+ name: 'overwrite',
455
+ message: chalk.yellow(`Directory ${projectName} already exists. Overwrite?`),
456
+ default: false
457
+ }
458
+ ]);
459
+ if (!answers.overwrite) {
460
+ console.log(chalk.red('✖ Operation cancelled'));
461
+ return;
462
+ }
463
+ }
464
+
465
+ // Multi-step execution with progress reporting
466
+ console.log(chalk.dim('\nCreating your new Baraqex project...'));
467
+
468
+ // Step 1: Create directory
469
+ const step1 = ora({text: 'Creating project directory', color: 'cyan'}).start();
470
+ try {
471
+ await fs.ensureDir(targetDir);
472
+ step1.succeed();
473
+ } catch (error) {
474
+ step1.fail();
475
+ console.error(chalk.red(`Error creating directory: ${error.message}`));
476
+ return;
477
+ }
478
+
479
+ // Step 2: Copy template files
480
+ const step2 = ora({text: 'Copying template files', color: 'cyan'}).start();
481
+ try {
482
+ await fs.copy(templateDir, targetDir, { overwrite: true });
483
+ step2.succeed();
484
+ } catch (error) {
485
+ step2.fail();
486
+ console.error(chalk.red(`Error copying files: ${error.message}`));
487
+ return;
488
+ }
489
+
490
+ // Step 3: Update package.json
491
+ const step3 = ora({text: 'Configuring package.json', color: 'cyan'}).start();
492
+ try {
493
+ const pkgJsonPath = path.join(targetDir, 'package.json');
494
+ if (fs.existsSync(pkgJsonPath)) {
495
+ const pkgJson = await fs.readJson(pkgJsonPath);
496
+ pkgJson.name = projectName;
497
+ await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
498
+ step3.succeed();
499
+ } else {
500
+ step3.warn('No package.json found in template');
501
+ }
502
+ } catch (error) {
503
+ step3.fail();
504
+ console.error(chalk.red(`Error updating package.json: ${error.message}`));
505
+ return;
506
+ }
507
+
508
+ // Final success message with helpful instructions
509
+ console.log('\n' + boxen(
510
+ `${chalk.bold.green('Project created successfully!')}\n\n` +
511
+ `${chalk.bold('Project:')} ${chalk.cyan(projectName)}\n` +
512
+ `${chalk.bold('Template:')} ${chalk.cyan(template)}\n` +
513
+ `${chalk.bold('Location:')} ${chalk.cyan(targetDir)}\n\n` +
514
+ `${chalk.bold.yellow('Next steps:')}\n\n` +
515
+ ` ${chalk.dim('1.')} ${chalk.cyan(`cd ${projectName}`)}\n` +
516
+ ` ${chalk.dim('2.')} ${chalk.cyan('npm install')}\n` +
517
+ ` ${chalk.dim('3.')} ${chalk.cyan('npm run dev')}\n\n` +
518
+ `${chalk.dim('For help and documentation:')} ${terminalLink('www.baraqex.tech', 'https://www.baraqex.tech')}`,
519
+ {
520
+ padding: 1,
521
+ margin: 1,
522
+ borderStyle: 'round',
523
+ borderColor: 'green'
524
+ }
525
+ ));
526
+
527
+ // Suggest next command
528
+ console.log(`\n${chalk.cyan('Tip:')} Run ${chalk.bold.green(`cd ${projectName} && npm install`)} to get started right away.\n`);
529
+ }
530
+
531
+ // ...existing code... (add:component, dev:tools, and all other functions remain the same but update references)
532
+
533
+ // Dashboard when no commands are specified
534
+ function showDashboard() {
535
+ displayBanner();
536
+
537
+ const commands = [
538
+ { name: 'create', description: 'Create a new project', command: 'baraqex create my-app' },
539
+ { name: 'add:component', description: 'Add a new UI component', command: 'baraqex add:component Button' },
540
+ { name: 'add:page', description: 'Create a new page', command: 'baraqex add:page home' },
541
+ { name: 'add:api', description: 'Create a new API endpoint', command: 'baraqex add:api users' },
542
+ { name: 'dev:tools', description: 'Show development tools', command: 'baraqex dev:tools' },
543
+ { name: 'test:server', description: 'Test server functions', command: 'baraqex test:server' }
544
+ ];
545
+
546
+ console.log(boxen(
547
+ `${chalk.bold.cyan('Welcome to Baraqex CLI!')}\n\n` +
548
+ `Select a command to get started or run ${chalk.yellow('baraqex <command> --help')} for more info.\n`,
549
+ {
550
+ padding: 1,
551
+ margin: { top: 1, bottom: 1 },
552
+ borderStyle: 'round',
553
+ borderColor: 'cyan'
554
+ }
555
+ ));
556
+
557
+ console.log(`${chalk.bold.cyan('Available Commands:')}\n`);
558
+ commands.forEach((cmd, i) => {
559
+ console.log(` ${chalk.green((i+1) + '.')} ${chalk.bold(cmd.name.padEnd(15))} ${chalk.dim(cmd.description)}`);
560
+ console.log(` ${chalk.yellow(cmd.command)}\n`);
561
+ });
562
+
563
+ console.log(boxen(
564
+ `${chalk.bold('Quick Start:')} ${chalk.yellow('baraqex create my-app')}\n` +
565
+ `${chalk.dim('More info:')} ${terminalLink('www.baraqex.tech', 'https://www.baraqex.tech')}`,
566
+ {
567
+ padding: 0.5,
568
+ margin: { top: 1 },
569
+ borderStyle: 'round',
570
+ borderColor: 'blue'
571
+ }
572
+ ));
573
+ }
574
+
575
+ // Register commands with improved descriptions
576
+ program
577
+ .command('create [name]')
578
+ .description('Create a new Baraqex project')
579
+ .option('-t, --template <template>', 'Specify template (basic-app, ssr-template, fullstack-app, go-wasm-app)')
580
+ .action(createProject);
581
+
582
+ program
583
+ .command('test:server')
584
+ .description('Run server function tests')
585
+ .action(async () => {
586
+ displayBanner();
587
+ createSection('Server Function Testing');
588
+
589
+ const spinner = ora('Running server tests...').start();
590
+
591
+ try {
592
+ // Import and run the test-server.js file
593
+ const { runAllTests } = await import('../test-server.js');
594
+ const success = await runAllTests();
595
+
596
+ if (success) {
597
+ spinner.succeed('All server tests passed!');
598
+ } else {
599
+ spinner.fail('Some server tests failed');
600
+ }
601
+ } catch (error) {
602
+ spinner.fail('Failed to run server tests');
603
+ console.error(chalk.red(`Error: ${error.message}`));
604
+ }
605
+ });
606
+
607
+ // Default command when no arguments
608
+ if (process.argv.length <= 2) {
609
+ showDashboard();
610
+ } else {
611
+ program.parse(process.argv);
612
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"api-router.d.ts","sourceRoot":"","sources":["../../src/server/api-router.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAkBxC,qBAAa,SAAS;IACb,MAAM,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAqB;gBAErB,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,WAAW,GAAG,IAAW;IAQ3D,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;YAiBN,aAAa;IAgC3B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,WAAW;CASpB"}
1
+ {"version":3,"file":"api-router.d.ts","sourceRoot":"","sources":["../../src/server/api-router.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAmBxC,qBAAa,SAAS;IACb,MAAM,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAqB;gBAErB,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,WAAW,GAAG,IAAW;IAQ3D,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;YAiBN,aAAa;IAuE3B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,WAAW;CASpB"}
@@ -1,6 +1,7 @@
1
1
  import express from 'express';
2
2
  import path from 'path';
3
3
  import fs from 'fs';
4
+ import { pathToFileURL } from 'url';
4
5
  export class ApiRouter {
5
6
  constructor(apiDir, auth = null) {
6
7
  this.router = express.Router();
@@ -50,21 +51,48 @@ export class ApiRouter {
50
51
  }
51
52
  async registerRoute(filePath, routePath) {
52
53
  try {
53
- // Dynamic import the route file
54
- const routeModule = await import(filePath);
55
- if (!this.isValidRouteModule(routeModule)) {
56
- console.warn(`Invalid route module: ${filePath}`);
57
- return;
54
+ // Ensure we have an absolute path and normalize it
55
+ const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath);
56
+ // Convert to proper file:// URL for Windows
57
+ const fileUrl = pathToFileURL(absolutePath).href;
58
+ if (process.platform === 'win32') {
59
+ // Add timestamp to force reload on Windows
60
+ const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`;
61
+ // Dynamic import the route file
62
+ const routeModule = await import(urlWithTimestamp);
63
+ if (!this.isValidRouteModule(routeModule)) {
64
+ console.warn(`Invalid route module: ${filePath}`);
65
+ return;
66
+ }
67
+ console.log(`Registering API route: ${routePath}`);
68
+ // Register middleware if any
69
+ const middleware = routeModule.middleware || [];
70
+ // Register HTTP methods
71
+ for (const method of ['get', 'post', 'put', 'delete', 'patch', 'options']) {
72
+ const handler = routeModule[method];
73
+ if (typeof handler === 'function') {
74
+ const routerMethod = this.router[method];
75
+ routerMethod.call(this.router, routePath, ...middleware, this.wrapHandler(handler));
76
+ }
77
+ }
58
78
  }
59
- console.log(`Registering API route: ${routePath}`);
60
- // Register middleware if any
61
- const middleware = routeModule.middleware || [];
62
- // Register HTTP methods
63
- for (const method of ['get', 'post', 'put', 'delete', 'patch', 'options']) {
64
- const handler = routeModule[method];
65
- if (typeof handler === 'function') {
66
- const routerMethod = this.router[method];
67
- routerMethod(routePath, ...middleware, this.wrapHandler(handler));
79
+ else {
80
+ // Non-Windows platforms
81
+ const routeModule = await import(fileUrl);
82
+ if (!this.isValidRouteModule(routeModule)) {
83
+ console.warn(`Invalid route module: ${filePath}`);
84
+ return;
85
+ }
86
+ console.log(`Registering API route: ${routePath}`);
87
+ // Register middleware if any
88
+ const middleware = routeModule.middleware || [];
89
+ // Register HTTP methods
90
+ for (const method of ['get', 'post', 'put', 'delete', 'patch', 'options']) {
91
+ const handler = routeModule[method];
92
+ if (typeof handler === 'function') {
93
+ const routerMethod = this.router[method];
94
+ routerMethod.call(this.router, routePath, ...middleware, this.wrapHandler(handler));
95
+ }
68
96
  }
69
97
  }
70
98
  }