vibex-sh 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +95 -19
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -3,18 +3,47 @@ import { io } from 'socket.io-client';
3
3
  import { program, Command } from 'commander';
4
4
  import { readFile, writeFile, mkdir } from 'fs/promises';
5
5
  import { existsSync, readFileSync } from 'fs';
6
- import { join } from 'path';
6
+ import { join, dirname } from 'path';
7
7
  import { homedir } from 'os';
8
8
  import { spawn } from 'child_process';
9
9
  import http from 'http';
10
10
  import https from 'https';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ // Get version from package.json
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = dirname(__filename);
16
+ const packageJsonPath = join(__dirname, 'package.json');
17
+ let cliVersion = '0.0.0';
18
+ try {
19
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
20
+ cliVersion = packageJson.version || '0.0.0';
21
+ } catch (error) {
22
+ // Fallback if package.json can't be read - try to read from parent directory
23
+ try {
24
+ const parentPackageJsonPath = join(__dirname, '..', 'package.json');
25
+ const packageJson = JSON.parse(readFileSync(parentPackageJsonPath, 'utf8'));
26
+ cliVersion = packageJson.version || '0.0.0';
27
+ } catch (e) {
28
+ // If both fail, use default
29
+ }
30
+ }
31
+
32
+ import crypto from 'crypto';
11
33
 
12
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
13
38
  const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
14
39
  let result = 'vibex-';
15
- for (let i = 0; i < 6; i++) {
16
- result += chars[Math.floor(Math.random() * chars.length)];
40
+
41
+ // Use crypto.randomBytes for cryptographically secure random generation
42
+ const randomBytes = crypto.randomBytes(12);
43
+ for (let i = 0; i < 12; i++) {
44
+ result += chars[randomBytes[i] % chars.length];
17
45
  }
46
+
18
47
  return result;
19
48
  }
20
49
 
@@ -148,7 +177,7 @@ async function handleLogin(webUrl) {
148
177
  const configPath = getConfigPath();
149
178
  const existingConfig = getStoredConfig();
150
179
 
151
- console.log('\n 🔐 Vibex CLI Authentication\n');
180
+ console.log('\n 🔐 vibex.sh CLI Authentication\n');
152
181
  console.log(` 📁 Config location: ${configPath}`);
153
182
 
154
183
  if (existingConfig?.token) {
@@ -235,7 +264,7 @@ function httpRequest(url, options) {
235
264
  }
236
265
 
237
266
  async function claimSession(sessionId, token, webUrl) {
238
- if (!token) return false;
267
+ if (!token) return null; // Return null instead of false to indicate no claim attempted
239
268
 
240
269
  try {
241
270
  // Normalize session ID before claiming
@@ -249,32 +278,55 @@ async function claimSession(sessionId, token, webUrl) {
249
278
  }),
250
279
  });
251
280
 
252
- return response.ok;
281
+ if (response.ok) {
282
+ // Parse response to get auth code
283
+ const responseData = await response.json();
284
+ return responseData.authCode || null;
285
+ }
286
+
287
+ return null;
253
288
  } catch (error) {
254
- return false;
289
+ return null;
255
290
  }
256
291
  }
257
292
 
258
- function printBanner(sessionId, webUrl) {
259
- const dashboardUrl = `${webUrl}/${sessionId}`;
293
+ // Removed getSessionAuthCode - auth codes should only come from:
294
+ // 1. claim-session-with-token response (for claimed sessions)
295
+ // 2. socket.io session-auth-code event (for unclaimed sessions)
296
+ // Never fetch auth codes via public API endpoint - security vulnerability
297
+
298
+ function printBanner(sessionId, webUrl, authCode = null) {
299
+ const dashboardUrl = authCode
300
+ ? `${webUrl}/${sessionId}?auth=${authCode}`
301
+ : `${webUrl}/${sessionId}`;
260
302
 
261
303
  console.log('\n');
262
304
  console.log(' ╔═══════════════════════════════════════╗');
263
- console.log(' ║ 🔍 Vibex is watching... ║');
305
+ console.log(' ║ 🔍 vibex.sh is watching... ║');
264
306
  console.log(' ╚═══════════════════════════════════════╝');
265
307
  console.log('\n');
266
308
  console.log(` Session ID: ${sessionId}`);
309
+ if (authCode) {
310
+ console.log(` Auth Code: ${authCode}`);
311
+ }
267
312
  console.log(` Dashboard: ${dashboardUrl}`);
268
313
  console.log('\n');
269
314
  }
270
315
 
271
316
  async function main() {
272
- // Handle login command separately - check BEFORE commander parses
273
- // Check process.argv directly - look for 'login' as a standalone argument
274
- // This must happen FIRST, before any commander parsing
317
+ // Handle --version flag early (before commander parses)
275
318
  const allArgs = process.argv;
276
319
  const args = process.argv.slice(2);
277
320
 
321
+ // Check for --version or -V flag
322
+ if (allArgs.includes('--version') || allArgs.includes('-V') || args.includes('--version') || args.includes('-V')) {
323
+ console.log(cliVersion);
324
+ process.exit(0);
325
+ }
326
+
327
+ // Handle login command separately - check BEFORE commander parses
328
+ // Check process.argv directly - look for 'login' as a standalone argument
329
+ // This must happen FIRST, before any commander parsing
278
330
  // Check if 'login' appears anywhere in process.argv (works with npx too)
279
331
  const hasLogin = allArgs.includes('login') || args.includes('login');
280
332
 
@@ -304,6 +356,7 @@ async function main() {
304
356
  }
305
357
 
306
358
  program
359
+ .version(cliVersion, '-v, --version', 'Display version number')
307
360
  .option('-s, --session-id <id>', 'Reuse existing session ID')
308
361
  .option('-l, --local', 'Use localhost (web: 3000, socket: 3001)')
309
362
  .option('--web <url>', 'Web server URL (e.g., http://localhost:3000)')
@@ -322,26 +375,36 @@ async function main() {
322
375
  // Get token from flag, env var, or stored config
323
376
  let token = options.token || process.env.VIBEX_TOKEN || await getStoredToken();
324
377
 
325
- // Auto-claim session if token is available
378
+ // Auto-claim session if token is available and fetch auth code
379
+ let authCode = null;
326
380
  if (token && !options.sessionId) {
327
381
  // Only auto-claim new sessions (not when reusing existing session)
328
- const claimed = await claimSession(sessionId, token, webUrl);
329
- if (claimed) {
382
+ authCode = await claimSession(sessionId, token, webUrl);
383
+ if (authCode) {
330
384
  console.log(' ✓ Session automatically claimed to your account\n');
331
385
  }
332
386
  }
387
+
388
+ // For unclaimed sessions, auth code will come from socket.io 'session-auth-code' event
389
+ // We'll set it when we receive it from the socket
333
390
 
334
391
  // Print banner only once, and show how to reuse session
335
392
  if (!options.sessionId) {
336
- printBanner(sessionId, webUrl);
393
+ printBanner(sessionId, webUrl, authCode);
337
394
  const localFlag = webUrl.includes('localhost') ? ' --local' : '';
338
395
  const sessionSlug = sessionId.replace(/^vibex-/, ''); // Remove prefix for example
339
396
  console.log(' 💡 Tip: Use -s to send more logs to this session');
340
- console.log(` Example: echo '{"cpu": 45, "memory": 78, "timestamp": "${new Date().toISOString()}"}' | npx vibex-sh -s ${sessionSlug}${localFlag}\n`);
397
+ console.log(` Example: echo '{"cpu": 45, "memory": 78}' | npx vibex-sh -s ${sessionSlug}${localFlag}\n`);
341
398
  } else {
342
399
  // When reusing a session, show minimal info
400
+ const dashboardUrl = authCode
401
+ ? `${webUrl}/${sessionId}?auth=${authCode}`
402
+ : `${webUrl}/${sessionId}`;
343
403
  console.log(` 🔍 Sending logs to session: ${sessionId}`);
344
- console.log(` Dashboard: ${webUrl}/${sessionId}\n`);
404
+ if (authCode) {
405
+ console.log(` Auth Code: ${authCode}`);
406
+ }
407
+ console.log(` Dashboard: ${dashboardUrl}\n`);
345
408
  }
346
409
 
347
410
  const socket = io(socketUrl, {
@@ -359,6 +422,9 @@ async function main() {
359
422
  let hasJoinedSession = false;
360
423
  const logQueue = [];
361
424
 
425
+ // Store auth code received from socket
426
+ let receivedAuthCode = authCode;
427
+
362
428
  socket.on('connect', () => {
363
429
  isConnected = true;
364
430
  console.log(' ✓ Connected to server\n');
@@ -378,6 +444,16 @@ async function main() {
378
444
  }, 100);
379
445
  });
380
446
 
447
+ // Listen for auth code from socket.io (for unclaimed sessions)
448
+ socket.on('session-auth-code', (data) => {
449
+ if (data.sessionId === sessionId && data.authCode && !receivedAuthCode) {
450
+ receivedAuthCode = data.authCode;
451
+ // Display auth code when received (for both new and existing sessions)
452
+ console.log(` 🔑 Auth Code: ${receivedAuthCode}`);
453
+ console.log(` 📋 Dashboard: ${webUrl}/${sessionId}?auth=${receivedAuthCode}\n`);
454
+ }
455
+ });
456
+
381
457
  socket.on('reconnect', (attemptNumber) => {
382
458
  console.log(` ↻ Reconnected (attempt ${attemptNumber})\n`);
383
459
  isConnected = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibex-sh",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Zero-config observability CLI - pipe logs and visualize instantly",
5
5
  "type": "module",
6
6
  "bin": {