vibex-sh 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +211 -57
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -29,12 +29,11 @@ try {
29
29
  }
30
30
  }
31
31
 
32
- import crypto from 'crypto';
33
-
32
+ // Session ID generation is now handled by the server
33
+ // This function is kept for backward compatibility but should not be used for new sessions
34
34
  function generateSessionId() {
35
- // Generate secure random session ID with 12 characters (as per security plan)
36
- // Format: vibex-{12 random alphanumeric chars}
37
- // Using crypto for better randomness
35
+ // DEPRECATED: Session IDs should be generated by the server
36
+ // This is only used as a fallback if server creation fails
38
37
  const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
39
38
  let result = 'vibex-';
40
39
 
@@ -370,41 +369,63 @@ async function main() {
370
369
  .parse();
371
370
 
372
371
  const options = program.opts();
373
-
374
- // Normalize session ID - add 'vibex-' prefix if missing
375
- const rawSessionId = options.sessionId || generateSessionId();
376
- const sessionId = normalizeSessionId(rawSessionId);
377
372
  const { webUrl, socketUrl } = getUrls(options);
378
373
 
379
374
  // Get token from flag, env var, or stored config
380
375
  let token = options.token || process.env.VIBEX_TOKEN || await getStoredToken();
381
376
 
382
- // Auto-claim session if token is available and fetch auth code
377
+ let sessionId;
383
378
  let authCode = null;
384
- if (token) {
385
- // Try to claim session (works for both new and existing sessions)
386
- // For new sessions, this will create and claim
387
- // For existing sessions, this will return the auth code if user owns it
388
- authCode = await claimSession(sessionId, token, webUrl);
389
- if (authCode && !options.sessionId) {
390
- // Only show claim message for new sessions
391
- console.log(' ✓ Session automatically claimed to your account\n');
392
- }
393
- }
394
379
 
395
- // For unclaimed sessions, auth code will come from socket.io 'session-auth-code' event
396
- // We'll set it when we receive it from the socket
397
-
398
- // Print banner only once, and show how to reuse session
399
- if (!options.sessionId) {
400
- printBanner(sessionId, webUrl, authCode);
401
- const localFlag = webUrl.includes('localhost') ? ' --local' : '';
402
- const sessionSlug = sessionId.replace(/^vibex-/, ''); // Remove prefix for example
403
- console.log(' 💡 Tip: Use -s to send more logs to this session');
404
- console.log(` Example: echo '{"cpu": 45, "memory": 78}' | npx vibex-sh -s ${sessionSlug}${localFlag}\n`);
405
- } else {
406
- // When reusing a session, show minimal info (no auth code)
380
+ // If session ID is provided, use it (existing session)
381
+ if (options.sessionId) {
382
+ sessionId = normalizeSessionId(options.sessionId);
383
+
384
+ // If token is available, try to claim the session
385
+ if (token) {
386
+ authCode = await claimSession(sessionId, token, webUrl);
387
+ }
388
+
389
+ // When reusing a session, show minimal info
407
390
  console.log(` 🔍 Sending logs to session: ${sessionId}\n`);
391
+ } else {
392
+ // No session ID provided - create a new anonymous session
393
+ try {
394
+ const createUrl = `${webUrl}/api/sessions/create-anonymous`;
395
+ const response = await httpRequest(createUrl, {
396
+ method: 'POST',
397
+ headers: { 'Content-Type': 'application/json' },
398
+ });
399
+
400
+ if (!response.ok) {
401
+ const errorData = await response.json();
402
+ console.error(` ✗ Failed to create session: ${errorData.message || 'Unknown error'}`);
403
+ process.exit(1);
404
+ }
405
+
406
+ const data = await response.json();
407
+ sessionId = data.sessionId; // Server-generated unique session ID
408
+ authCode = data.authCode; // Server-generated auth code
409
+
410
+ // If token is available, claim the session
411
+ if (token) {
412
+ const claimAuthCode = await claimSession(sessionId, token, webUrl);
413
+ if (claimAuthCode) {
414
+ authCode = claimAuthCode;
415
+ console.log(' ✓ Session automatically claimed to your account\n');
416
+ }
417
+ }
418
+
419
+ // Print banner for new session
420
+ printBanner(sessionId, webUrl, authCode);
421
+ const localFlag = webUrl.includes('localhost') ? ' --local' : '';
422
+ const sessionSlug = sessionId.replace(/^vibex-/, ''); // Remove prefix for example
423
+ console.log(' 💡 Tip: Use -s to send more logs to this session');
424
+ console.log(` Example: echo '{"cpu": 45, "memory": 78}' | npx vibex-sh -s ${sessionSlug}${localFlag}\n`);
425
+ } catch (error: any) {
426
+ console.error(` ✗ Error creating session: ${error.message}`);
427
+ process.exit(1);
428
+ }
408
429
  }
409
430
 
410
431
  let socket = null;
@@ -475,14 +496,22 @@ async function main() {
475
496
  break;
476
497
 
477
498
  case 'error':
478
- if (message.error === 'Rate Limit Exceeded') {
499
+ const errorType = message.error || 'Error';
500
+ const errorMsg = message.message || 'An unexpected error occurred';
501
+ const statusCode = message.statusCode || 0;
502
+
503
+ // Handle specific error types
504
+ if (errorType === 'Rate Limit Exceeded' || statusCode === 429) {
479
505
  console.error('\n ⚠️ Rate Limit Exceeded');
480
- console.error(` ${message.message || 'Too many requests. Please try again later.'}`);
506
+ console.error(` ${errorMsg}`);
507
+ if (message.retryAfter) {
508
+ console.error(` ⏱️ Retry after: ${message.retryAfter} seconds`);
509
+ }
481
510
  console.error('');
482
511
  logQueue.length = 0;
483
- } else if (message.error === 'History Limit Reached') {
512
+ } else if (errorType === 'History Limit Reached' || (statusCode === 403 && errorMsg.includes('History Limit'))) {
484
513
  console.error('\n 🚫 History Limit Reached');
485
- console.error(` ${message.message || 'Session history limit reached'}`);
514
+ console.error(` ${errorMsg}`);
486
515
  if (message.limit !== undefined && message.current !== undefined) {
487
516
  console.error(` Current: ${message.current} / ${message.limit} logs`);
488
517
  }
@@ -493,10 +522,69 @@ async function main() {
493
522
  console.error('');
494
523
  logQueue.length = 0;
495
524
  hasJoinedSession = false;
525
+ } else if (statusCode === 401 || errorType === 'Unauthorized') {
526
+ if (errorMsg.includes('expired')) {
527
+ console.error('\n 🔑 Token Expired');
528
+ console.error(' Your authentication token has expired.');
529
+ console.error(' 💡 Run: npx vibex-sh login');
530
+ } else {
531
+ console.error('\n 🔑 Unauthorized');
532
+ console.error(` ${errorMsg}`);
533
+ console.error(' 💡 Run: npx vibex-sh login');
534
+ }
535
+ console.error('');
536
+ logQueue.length = 0;
537
+ hasJoinedSession = false;
538
+ } else if (statusCode === 403 || errorType === 'Forbidden') {
539
+ if (errorMsg.includes('access') || errorMsg.includes('belongs')) {
540
+ console.error('\n 🚫 Access Denied');
541
+ console.error(` ${errorMsg}`);
542
+ console.error(' 💡 This session belongs to another user or is not accessible');
543
+ console.error(' 💡 Make sure you are using the correct token and session ID');
544
+ } else if (errorMsg.includes('archived')) {
545
+ console.error('\n 🚫 Session Archived');
546
+ console.error(` ${errorMsg}`);
547
+ console.error(' 💡 This session is archived and cannot accept new logs');
548
+ } else {
549
+ console.error('\n 🚫 Forbidden');
550
+ console.error(` ${errorMsg}`);
551
+ }
552
+ console.error('');
553
+ logQueue.length = 0;
554
+ hasJoinedSession = false;
555
+ } else if (statusCode === 404 || errorType === 'Not Found') {
556
+ console.error('\n 🔍 Session Not Found');
557
+ console.error(` ${errorMsg}`);
558
+ console.error(' 💡 Make sure the session ID is correct');
559
+ console.error(' 💡 Check if the session exists in your dashboard');
560
+ console.error('');
561
+ logQueue.length = 0;
562
+ hasJoinedSession = false;
563
+ } else if (statusCode === 400 || errorType === 'Bad Request') {
564
+ console.error('\n 📝 Bad Request');
565
+ console.error(` ${errorMsg}`);
566
+ if (errorMsg.includes('sessionId')) {
567
+ console.error(' 💡 Make sure you provided a valid session ID with -s or --session');
568
+ } else if (errorMsg.includes('logs')) {
569
+ console.error(' 💡 Make sure you are sending valid log data');
570
+ }
571
+ console.error('');
572
+ logQueue.length = 0;
573
+ } else if (statusCode >= 500 || errorType === 'Internal Server Error') {
574
+ console.error('\n 🔴 Server Error');
575
+ console.error(` ${errorMsg}`);
576
+ console.error(' 💡 This is a server-side issue. Please try again later.');
577
+ console.error(' 💡 If the problem persists, contact support');
578
+ console.error('');
579
+ logQueue.length = 0;
496
580
  } else {
497
- console.error('\n ✗ Server Error');
498
- console.error(` ${message.error || message.message || 'An unexpected error occurred'}`);
581
+ console.error('\n ✗ Error');
582
+ console.error(` ${errorType}: ${errorMsg}`);
583
+ if (statusCode) {
584
+ console.error(` Status Code: ${statusCode}`);
585
+ }
499
586
  console.error('');
587
+ logQueue.length = 0;
500
588
  }
501
589
  break;
502
590
 
@@ -544,12 +632,8 @@ async function main() {
544
632
 
545
633
  // Send logs via HTTP POST (non-blocking, same as SDKs)
546
634
  // Use Cloudflare Worker endpoint (port 8787 for local, or Worker URL for production)
635
+ // Token is optional - anonymous sessions can send logs without authentication
547
636
  const sendLogViaHTTP = async (logData) => {
548
- if (!token) {
549
- console.error(' ✗ No token available for sending logs');
550
- return;
551
- }
552
-
553
637
  try {
554
638
  // Determine ingest URL
555
639
  let ingestUrl;
@@ -567,12 +651,17 @@ async function main() {
567
651
 
568
652
  console.log(` 📤 Sending log to: ${ingestUrl}`);
569
653
 
654
+ // Build headers - only include Authorization if token exists
655
+ const headers = {
656
+ 'Content-Type': 'application/json',
657
+ };
658
+ if (token) {
659
+ headers['Authorization'] = `Bearer ${token}`;
660
+ }
661
+
570
662
  const response = await fetch(ingestUrl, {
571
663
  method: 'POST',
572
- headers: {
573
- 'Authorization': `Bearer ${token}`,
574
- 'Content-Type': 'application/json',
575
- },
664
+ headers,
576
665
  body: JSON.stringify({
577
666
  sessionId,
578
667
  logs: [logData],
@@ -581,19 +670,84 @@ async function main() {
581
670
 
582
671
  if (!response.ok) {
583
672
  const errorData = await response.json().catch(() => ({}));
584
- console.error(` ✗ HTTP ${response.status}: ${errorData.message || response.statusText}`);
585
- if (response.status === 429) {
586
- console.error('\n ⚠️ Rate Limit Exceeded');
587
- console.error(` ${errorData.message || 'Too many requests. Please try again later.'}`);
673
+ const errorMessage = errorData.message || response.statusText || 'Unknown error';
674
+
675
+ console.error(`\n HTTP ${response.status}: ${errorMessage}`);
676
+
677
+ // Handle specific error cases
678
+ if (response.status === 401) {
679
+ if (errorMessage.includes('expired')) {
680
+ console.error('\n 🔑 Token Expired');
681
+ console.error(' Your authentication token has expired.');
682
+ console.error(' 💡 Run: npx vibex-sh login');
683
+ console.error('');
684
+ } else if (errorMessage.includes('Invalid') || errorMessage.includes('invalid')) {
685
+ console.error('\n 🔑 Invalid Token');
686
+ console.error(' Your authentication token is invalid or missing.');
687
+ console.error(' 💡 Run: npx vibex-sh login');
688
+ console.error('');
689
+ } else {
690
+ console.error('\n 🔑 Unauthorized');
691
+ console.error(` ${errorMessage}`);
692
+ console.error(' 💡 Run: npx vibex-sh login');
693
+ console.error('');
694
+ }
695
+ } else if (response.status === 400) {
696
+ console.error('\n 📝 Bad Request');
697
+ console.error(` ${errorMessage}`);
698
+ if (errorMessage.includes('sessionId')) {
699
+ console.error(' 💡 Make sure you provided a valid session ID with -s or --session');
700
+ } else if (errorMessage.includes('logs')) {
701
+ console.error(' 💡 Make sure you are sending valid log data');
702
+ }
703
+ console.error('');
704
+ } else if (response.status === 403) {
705
+ if (errorMessage.includes('History Limit')) {
706
+ console.error('\n 🚫 History Limit Reached');
707
+ console.error(` ${errorMessage}`);
708
+ if (errorData.upgradeRequired) {
709
+ console.error(' 💡 Upgrade to Pro to unlock 30 days retention');
710
+ console.error(' 🌐 Visit: https://vibex.sh/pricing');
711
+ }
712
+ console.error('');
713
+ } else if (errorMessage.includes('access') || errorMessage.includes('belongs')) {
714
+ console.error('\n 🚫 Access Denied');
715
+ console.error(` ${errorMessage}`);
716
+ console.error(' 💡 This session belongs to another user or is not accessible');
717
+ console.error(' 💡 Make sure you are using the correct token and session ID');
718
+ console.error('');
719
+ } else if (errorMessage.includes('archived')) {
720
+ console.error('\n 🚫 Session Archived');
721
+ console.error(` ${errorMessage}`);
722
+ console.error(' 💡 This session is archived and cannot accept new logs');
723
+ console.error('');
724
+ } else {
725
+ console.error('\n 🚫 Forbidden');
726
+ console.error(` ${errorMessage}`);
727
+ console.error('');
728
+ }
729
+ } else if (response.status === 404) {
730
+ console.error('\n 🔍 Session Not Found');
731
+ console.error(` ${errorMessage}`);
732
+ console.error(' 💡 Make sure the session ID is correct');
733
+ console.error(' 💡 Check if the session exists in your dashboard');
588
734
  console.error('');
589
- } else if (response.status === 403 && errorData.message?.includes('History Limit')) {
590
- console.error('\n 🚫 History Limit Reached');
591
- console.error(` ${errorData.message || 'Session history limit reached'}`);
592
- if (errorData.upgradeRequired) {
593
- console.error(' 💡 Upgrade to Pro to unlock 30 days retention');
594
- console.error(' 🌐 Visit: https://vibex.sh/pricing');
735
+ } else if (response.status === 429) {
736
+ console.error('\n ⚠️ Rate Limit Exceeded');
737
+ console.error(` ${errorMessage}`);
738
+ if (errorData.retryAfter) {
739
+ console.error(` ⏱️ Retry after: ${errorData.retryAfter} seconds`);
595
740
  }
596
741
  console.error('');
742
+ } else if (response.status >= 500) {
743
+ console.error('\n 🔴 Server Error');
744
+ console.error(` ${errorMessage}`);
745
+ console.error(' 💡 This is a server-side issue. Please try again later.');
746
+ console.error(' 💡 If the problem persists, contact support');
747
+ console.error('');
748
+ } else {
749
+ console.error(` ${errorMessage}`);
750
+ console.error('');
597
751
  }
598
752
  } else {
599
753
  const result = await response.json().catch(() => ({}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibex-sh",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "Zero-config observability CLI - pipe logs and visualize instantly",
5
5
  "type": "module",
6
6
  "bin": {