zero-doc 1.0.9 → 1.0.10

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/dist/cli.js CHANGED
@@ -39,8 +39,11 @@ const ai_analyzer_1 = require("./ai-analyzer");
39
39
  const fs = __importStar(require("fs"));
40
40
  const path = __importStar(require("path"));
41
41
  const child_process_1 = require("child_process");
42
+ const os = __importStar(require("os"));
42
43
  const tmp = __importStar(require("tmp"));
43
44
  const fse = __importStar(require("fs-extra"));
45
+ const http = __importStar(require("http"));
46
+ const url_1 = require("url");
44
47
  function updateProgress(current, total, label = '') {
45
48
  const percentage = Math.min(100, Math.round((current / total) * 100));
46
49
  const barLength = 30;
@@ -63,13 +66,32 @@ function displayUrl(url) {
63
66
  const underline = '\x1b[4m';
64
67
  process.stdout.write(`${red}➜${reset} ${bold}Local:${reset} ${blue}${underline}${url}${reset}\n`);
65
68
  }
69
+ function getBaseUrl() {
70
+ const configPath = path.join(__dirname, 'config.json');
71
+ if (fs.existsSync(configPath)) {
72
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
73
+ if (config.baseUrl) {
74
+ return config.baseUrl;
75
+ }
76
+ }
77
+ }
66
78
  function displayPlansLink() {
67
79
  const reset = '\x1b[0m';
68
80
  const red = '\x1b[31m';
69
81
  const blue = '\x1b[34m';
70
82
  const bold = '\x1b[1m';
71
83
  const underline = '\x1b[4m';
72
- process.stdout.write(`${red}➜${reset} ${bold}Access plans:${reset} ${blue}${underline}https://zero-doc.com/plans${reset}\n`);
84
+ const baseUrl = getBaseUrl();
85
+ process.stdout.write(`${red}➜${reset} ${bold}Access plans:${reset} ${blue}${underline}${baseUrl}/plans${reset}\n`);
86
+ }
87
+ function displayLoginLink() {
88
+ const reset = '\x1b[0m';
89
+ const red = '\x1b[31m';
90
+ const blue = '\x1b[34m';
91
+ const bold = '\x1b[1m';
92
+ const underline = '\x1b[4m';
93
+ const baseUrl = getBaseUrl();
94
+ process.stdout.write(`${red}➜${reset} ${bold}Login:${reset} ${blue}${underline}${baseUrl}/login${reset}\n`);
73
95
  }
74
96
  commander_1.program
75
97
  .name('zero-doc')
@@ -448,8 +470,8 @@ commander_1.program
448
470
  clearProgress();
449
471
  process.stdout.write('\n');
450
472
  const errorMessage = error instanceof Error ? error.message : String(error);
451
- // Check if it's a 403 error
452
- if (errorMessage.includes('403')) {
473
+ // Check if it's a 401 or 403 error
474
+ if (errorMessage.includes('401') || errorMessage.includes('403')) {
453
475
  // Extract the actual error message from the API response
454
476
  let apiErrorMessage = errorMessage;
455
477
  try {
@@ -467,7 +489,15 @@ commander_1.program
467
489
  // If parsing fails, use the original message
468
490
  }
469
491
  console.error('❌ Error:', apiErrorMessage);
470
- displayPlansLink();
492
+ if (errorMessage.includes('401')) {
493
+ // For 401, show only login
494
+ displayLoginLink();
495
+ }
496
+ else {
497
+ // For 403, show plans and login
498
+ displayPlansLink();
499
+ displayLoginLink();
500
+ }
471
501
  // Don't exit - keep the session open
472
502
  }
473
503
  else {
@@ -476,6 +506,170 @@ commander_1.program
476
506
  }
477
507
  }
478
508
  });
509
+ commander_1.program
510
+ .command('login')
511
+ .description('Login to zero-doc and save authentication token')
512
+ .action(async () => {
513
+ const CALLBACK_PORT = 7778;
514
+ const CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;
515
+ const baseUrl = getBaseUrl();
516
+ const LOGIN_URL = `${baseUrl}/login?callback=${encodeURIComponent(CALLBACK_URL)}`;
517
+ const TOKEN_FILE = path.join(os.homedir(), '.zero-doc', 'token.json');
518
+ console.log('🔐 Starting login process...\n');
519
+ // Create directory if it doesn't exist
520
+ const tokenDir = path.dirname(TOKEN_FILE);
521
+ if (!fs.existsSync(tokenDir)) {
522
+ fs.mkdirSync(tokenDir, { recursive: true });
523
+ }
524
+ return new Promise((resolve, reject) => {
525
+ let server = null;
526
+ let timeout = null;
527
+ const cleanup = () => {
528
+ if (timeout) {
529
+ clearTimeout(timeout);
530
+ timeout = null;
531
+ }
532
+ if (server) {
533
+ server.close();
534
+ server = null;
535
+ }
536
+ };
537
+ // 5 minute timeout
538
+ timeout = setTimeout(() => {
539
+ cleanup();
540
+ console.error('\n❌ Timeout: Login was not completed within 5 minutes');
541
+ process.exit(1);
542
+ }, 5 * 60 * 1000);
543
+ server = http.createServer((req, res) => {
544
+ if (req.url?.startsWith('/callback')) {
545
+ try {
546
+ const url = new url_1.URL(req.url, `http://localhost:${CALLBACK_PORT}`);
547
+ const token = url.searchParams.get('token');
548
+ const error = url.searchParams.get('error');
549
+ if (error) {
550
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
551
+ res.end(`
552
+ <!DOCTYPE html>
553
+ <html>
554
+ <head>
555
+ <title>Login Error</title>
556
+ <style>
557
+ body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
558
+ .error { color: #dc2626; }
559
+ </style>
560
+ </head>
561
+ <body>
562
+ <h1 class="error">Login Error</h1>
563
+ <p>${error}</p>
564
+ <p>You can close this window.</p>
565
+ </body>
566
+ </html>
567
+ `);
568
+ cleanup();
569
+ console.error(`\n❌ Error: ${error}`);
570
+ process.exit(1);
571
+ return;
572
+ }
573
+ if (token) {
574
+ // Save token
575
+ const tokenData = {
576
+ token: token,
577
+ savedAt: new Date().toISOString()
578
+ };
579
+ fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokenData, null, 2), 'utf-8');
580
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
581
+ res.end(`
582
+ <!DOCTYPE html>
583
+ <html>
584
+ <head>
585
+ <title>Login Successful</title>
586
+ <style>
587
+ body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
588
+ .success { color: #16a34a; }
589
+ </style>
590
+ </head>
591
+ <body>
592
+ <h1 class="success">✅ Login Successful!</h1>
593
+ <p>Token saved successfully.</p>
594
+ <p>You can close this window and return to the terminal.</p>
595
+ </body>
596
+ </html>
597
+ `);
598
+ cleanup();
599
+ console.log('\n✅ Login successful!');
600
+ console.log(`💾 Token saved to: ${TOKEN_FILE}`);
601
+ resolve();
602
+ }
603
+ else {
604
+ res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
605
+ res.end(`
606
+ <!DOCTYPE html>
607
+ <html>
608
+ <head>
609
+ <title>Error</title>
610
+ <style>
611
+ body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
612
+ .error { color: #dc2626; }
613
+ </style>
614
+ </head>
615
+ <body>
616
+ <h1 class="error">Token not received</h1>
617
+ <p>You can close this window and try again.</p>
618
+ </body>
619
+ </html>
620
+ `);
621
+ }
622
+ }
623
+ catch (error) {
624
+ res.writeHead(500, { 'Content-Type': 'text/plain' });
625
+ res.end('Internal Server Error');
626
+ cleanup();
627
+ reject(error);
628
+ }
629
+ }
630
+ else {
631
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
632
+ res.end('Not Found');
633
+ }
634
+ });
635
+ server.listen(CALLBACK_PORT, () => {
636
+ console.log(`📡 Callback server started at http://localhost:${CALLBACK_PORT}`);
637
+ console.log(`🌐 Opening browser...\n`);
638
+ // Open browser
639
+ let openCommand;
640
+ if (process.platform === 'win32') {
641
+ openCommand = 'start';
642
+ }
643
+ else if (process.platform === 'darwin') {
644
+ openCommand = 'open';
645
+ }
646
+ else {
647
+ openCommand = 'xdg-open';
648
+ }
649
+ (0, child_process_1.spawn)(openCommand, [LOGIN_URL], { shell: true, stdio: 'ignore' });
650
+ console.log('⏳ Waiting for authentication in browser...');
651
+ console.log('💡 If the browser does not open automatically, visit:');
652
+ console.log(` ${LOGIN_URL}\n`);
653
+ });
654
+ server.on('error', (error) => {
655
+ if (error.code === 'EADDRINUSE') {
656
+ console.error(`❌ Error: Port ${CALLBACK_PORT} is already in use`);
657
+ console.error('💡 Close other processes using this port or wait a few seconds');
658
+ }
659
+ else {
660
+ console.error('❌ Error starting server:', error.message);
661
+ }
662
+ cleanup();
663
+ process.exit(1);
664
+ });
665
+ // Cleanup on exit
666
+ process.on('SIGINT', () => {
667
+ cleanup();
668
+ console.log('\n❌ Login cancelled');
669
+ process.exit(0);
670
+ });
671
+ });
672
+ });
479
673
  commander_1.program
480
674
  .command('deploy')
481
675
  .description('Deploy documentation to zero-doc cloud')
package/dist/config.json CHANGED
@@ -1,3 +1,4 @@
1
1
  {
2
- "apiUrl": "https://zero-doc-api.lucassens.com.br/chat"
2
+ "apiUrl": "https://zero-doc-api.lucassens.com.br/chat",
3
+ "baseUrl": "https://zero-doc.lucassens.com.br"
3
4
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zero-doc",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "Zero-Config API Documentation Generator - Generate beautiful API docs from your code automatically",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -24,15 +24,17 @@ if (fs.existsSync(envPath)) {
24
24
  // Get API URL from environment variables
25
25
  // Priority: Environment variable (CI/CD) > .env file
26
26
  const apiUrl = process.env.ZERO_DOC_API_URL;
27
+ const baseUrl = process.env.ZERO_DOC_URL;
27
28
 
28
29
  // Ensure dist directory exists
29
30
  if (!fs.existsSync(distDir)) {
30
31
  fs.mkdirSync(distDir, { recursive: true });
31
32
  }
32
33
 
33
- // Create config file with API URL
34
+ // Create config file with API URL and base URL
34
35
  const config = {
35
- apiUrl: apiUrl || ''
36
+ apiUrl: apiUrl || '',
37
+ baseUrl: baseUrl
36
38
  };
37
39
 
38
40
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
@@ -44,3 +46,5 @@ if (apiUrl) {
44
46
  console.warn(' Set ZERO_DOC_API_URL in .env or CI/CD environment variables.');
45
47
  }
46
48
 
49
+ console.log(`✅ Base URL set to: ${baseUrl}`);
50
+