thinkncollab-shell 0.0.7 → 0.0.9

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/thinknsh.js CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- /**
4
- * ThinkNCollab Shell - CLI Entry Point
5
- *
6
- * Usage:
7
- * thinknsh - Start interactive shell
8
- * thinknsh <command> - Run single command
9
- * thinknsh --help - Show help
3
+ /*
4
+ ThinkNCollab Shell - CLI Entry Point
5
+
6
+
7
+
8
+ Usage:
9
+ thinknsh - Start interactive shell
10
+ thinknsh <command> - Run single command
11
+ thinknsh --help - Show help
10
12
  */
11
13
 
12
14
  const path = require('path');
@@ -46,9 +48,9 @@ if (args.includes('--version') || args.includes('-v')) {
46
48
  }
47
49
 
48
50
  const shell = new ThinkNCollabShell({
49
- serverUrl: process.env.THINKNCOLLAB_SERVER || 'http://localhost:3001', // ← /thinknsh hata
50
- apiUrl: process.env.THINKNCOLLAB_API_URL || 'http://localhost:3001',
51
- wsUrl: process.env.THINKNCOLLAB_WS_URL || 'http://localhost:3001',
51
+ serverUrl: process.env.THINKNCOLLAB_SERVER || 'https://thinkncollab.com',
52
+ apiUrl: process.env.THINKNCOLLAB_API_URL || 'https://thinkncollab.com',
53
+ wsUrl: process.env.THINKNCOLLAB_WS_URL || 'https://thinkncollab.com',
52
54
  autoConnect: process.env.THINKNCOLLAB_AUTO_CONNECT === 'true'
53
55
  });
54
56
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkncollab-shell",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "ThinkNCollab Custom Shell with WebSocket collaboration",
5
5
  "main": "src/core/shell.js",
6
6
  "bin": {
@@ -1,77 +1,77 @@
1
- /**
2
- * commands/auth/login.js
3
- */
4
-
5
- const chalk = require('chalk');
6
- const inquirer = require('inquirer');
7
-
8
- module.exports = {
9
- name: 'login',
10
- description: 'Login to ThinkNCollab',
11
- aliases: ['signin'],
12
- requiresAuth: false,
13
-
14
- async execute(args, shell) {
15
- // Already logged in?
16
- if (shell.api.isAuthenticated()) {
17
- const u = shell.api.getUser();
18
- console.log(chalk.green(`✅ Already logged in as ${u.name} (${u.email})`));
19
- console.log(chalk.dim(' Run "logout" first to switch accounts.'));
20
- return;
21
- }
22
-
23
- // Collect credentials
24
- let email = args[0];
25
- let password = args[1];
26
-
27
- if (!email || !password) {
28
- const answers = await inquirer.prompt([
29
- !email && { type: 'input', name: 'email', message: 'Email:', validate: v => v.includes('@') || 'Enter a valid email' },
30
- !password && { type: 'password', name: 'password', message: 'Password:', mask: '*', validate: v => v.length >= 1 || 'Password required' },
31
- ].filter(Boolean));
32
- email = email || answers.email;
33
- password = password || answers.password;
34
- }
35
-
36
- console.log(chalk.blue('🔐 Logging in...'));
37
-
38
- try {
39
- const result = await shell.api.login(email, password);
40
-
41
- // result.user is already normalised by api-client.getUser()
42
- // shape: { _id, userId, email, name, userType }
43
- const user = result.user;
44
-
45
- // ★ Tell the WebSocket manager who the user is + pass the token
46
- // This must happen BEFORE any join attempt
47
- shell.ws.setUser(user, result.token);
48
-
49
- // Connect WebSocket if not already connected
50
- if (!shell.ws.isConnected()) {
51
- try {
52
- await shell.ws.connect(result.token);
53
- console.log(chalk.dim(' 🔌 Connected to ThinkNCollab server'));
54
- } catch (wsErr) {
55
- // Non-fatal — user can still use REST commands
56
- console.log(chalk.yellow(` ⚠️ WebSocket unavailable: ${wsErr.message}`));
57
- }
58
- } else {
59
- // Already connected — re-announce with new user identity
60
- shell.ws._announceUser?.();
61
- }
62
-
63
- console.log(chalk.green(`✅ Welcome, ${user.name}!`));
64
- console.log(chalk.dim(` Logged in as ${user.email}`));
65
-
66
- } catch (err) {
67
- if (err.message.includes('401') || err.message.toLowerCase().includes('invalid') ||
68
- err.message.toLowerCase().includes('unauthorized')) {
69
- console.log(chalk.red('❌ Invalid email or password'));
70
- } else if (err.message.includes('connect') || err.message.includes('ECONNREFUSED')) {
71
- console.log(chalk.red(`❌ Cannot reach server — is it running?`));
72
- } else {
73
- console.log(chalk.red(`❌ Login failed: ${err.message}`));
74
- }
75
- }
76
- }
1
+ /*
2
+ commands/auth/login.js
3
+ */
4
+
5
+ const chalk = require('chalk');
6
+ const inquirer = require('inquirer');
7
+
8
+ module.exports = {
9
+ name: 'login',
10
+ description: 'Login to ThinkNCollab',
11
+ aliases: ['signin'],
12
+ requiresAuth: false,
13
+
14
+ async execute(args, shell) {
15
+ // Already logged in?
16
+ if (shell.api.isAuthenticated()) {
17
+ const u = shell.api.getUser();
18
+ console.log(chalk.green(`✅ Already logged in as ${u.name} (${u.email})`));
19
+ console.log(chalk.dim(' Run "logout" first to switch accounts.'));
20
+ return;
21
+ }
22
+
23
+ // Collect credentials
24
+ let email = args[0];
25
+ let password = args[1];
26
+
27
+ if (!email || !password) {
28
+ const answers = await inquirer.prompt([
29
+ !email && { type: 'input', name: 'email', message: 'Email:', validate: v => v.includes('@') || 'Enter a valid email' },
30
+ !password && { type: 'password', name: 'password', message: 'Password:', mask: '*', validate: v => v.length >= 1 || 'Password required' },
31
+ ].filter(Boolean));
32
+ email = email || answers.email;
33
+ password = password || answers.password;
34
+ }
35
+
36
+ console.log(chalk.blue('🔐 Logging in...'));
37
+
38
+ try {
39
+ const result = await shell.api.login(email, password);
40
+
41
+ // result.user is already normalised by api-client.getUser()
42
+ // shape: { _id, userId, email, name, userType }
43
+ const user = result.user;
44
+
45
+ // ★ Tell the WebSocket manager who the user is + pass the token
46
+ // This must happen BEFORE any join attempt
47
+ shell.ws.setUser(user, result.token);
48
+
49
+ // Connect WebSocket if not already connected
50
+ if (!shell.ws.isConnected()) {
51
+ try {
52
+ await shell.ws.connect(result.token);
53
+ console.log(chalk.dim(' 🔌 Connected to ThinkNCollab server'));
54
+ } catch (wsErr) {
55
+ // Non-fatal — user can still use REST commands
56
+ console.log(chalk.yellow(` ⚠️ WebSocket unavailable: ${wsErr.message}`));
57
+ }
58
+ } else {
59
+ // Already connected — re-announce with new user identity
60
+ shell.ws._announceUser?.();
61
+ }
62
+
63
+ console.log(chalk.green(`✅ Welcome, ${user.name}!`));
64
+ console.log(chalk.dim(` Logged in as ${user.email}`));
65
+
66
+ } catch (err) {
67
+ if (err.message.includes('401') || err.message.toLowerCase().includes('invalid') ||
68
+ err.message.toLowerCase().includes('unauthorized')) {
69
+ console.log(chalk.red('❌ Invalid email or password'));
70
+ } else if (err.message.includes('connect') || err.message.includes('ECONNREFUSED')) {
71
+ console.log(chalk.red(`❌ Cannot reach server — is it running?`));
72
+ } else {
73
+ console.log(chalk.red(`❌ Login failed: ${err.message}`));
74
+ }
75
+ }
76
+ }
77
77
  };
@@ -1,32 +1,32 @@
1
- /**
2
- * Logout Command
3
- *
4
- * Usage: logout
5
- */
6
-
7
- const chalk = require('chalk');
8
- const fs = require('fs-extra');
9
-
10
- module.exports = {
11
- name: 'logout',
12
- description: 'Logout from ThinkNCollab',
13
- aliases: ['signout', 'exit'],
14
- requiresAuth: true,
15
-
16
- async execute(args, shell) {
17
- shell.printMessage(chalk.cyan('👋 Logging out...'));
18
-
19
- try {
20
- await shell.api.logout();
21
-
22
- // Remove session file
23
- const sessionPath = shell.getSessionPath();
24
- await fs.remove(sessionPath);
25
-
26
- shell.printMessage(chalk.green('✅ Logged out successfully'));
27
-
28
- } catch (error) {
29
- shell.printMessage(chalk.red(`❌ Logout failed: ${error.message}`));
30
- }
31
- }
1
+ /*
2
+ Logout Command
3
+
4
+ Usage: logout
5
+ */
6
+
7
+ const chalk = require('chalk');
8
+ const fs = require('fs-extra');
9
+
10
+ module.exports = {
11
+ name: 'logout',
12
+ description: 'Logout from ThinkNCollab',
13
+ aliases: ['signout', 'exit'],
14
+ requiresAuth: true,
15
+
16
+ async execute(args, shell) {
17
+ shell.printMessage(chalk.cyan('👋 Logging out...'));
18
+
19
+ try {
20
+ await shell.api.logout();
21
+
22
+ // Remove session file
23
+ const sessionPath = shell.getSessionPath();
24
+ await fs.remove(sessionPath);
25
+
26
+ shell.printMessage(chalk.green('✅ Logged out successfully'));
27
+
28
+ } catch (error) {
29
+ shell.printMessage(chalk.red(`❌ Logout failed: ${error.message}`));
30
+ }
31
+ }
32
32
  };
@@ -1,52 +1,52 @@
1
- /**
2
- * src/commands/auth/register.js
3
- * Register new account — opens browser with pre-auth session
4
- */
5
-
6
- const chalk = require('chalk');
7
- const { exec } = require('child_process');
8
-
9
- module.exports = {
10
- name: 'register',
11
- description: 'Create a new ThinkNCollab account',
12
- aliases: ['signup', 'reg'],
13
- requiresAuth: false,
14
-
15
- async execute(args, shell) {
16
- try {
17
- console.log(chalk.cyan('🌐 Opening registration in browser...'));
18
-
19
- const baseUrl = shell.api.apiUrl || 'http://localhost:3001';
20
-
21
- // Generate a CLI source token so backend knows it came from terminal
22
- const crypto = require('crypto');
23
- const cliRef = crypto.randomBytes(8).toString('hex');
24
-
25
- const url = `${baseUrl}/register?ref=cli&cliRef=${cliRef}`;
26
-
27
- // Open browser cross-platform
28
- const openCmd = process.platform === 'win32'
29
- ? `start "" "${url}"`
30
- : process.platform === 'darwin'
31
- ? `open "${url}"`
32
- : `xdg-open "${url}"`;
33
-
34
- exec(openCmd, (err) => {
35
- if (err) {
36
- console.log(chalk.yellow('⚠️ Could not open browser automatically.'));
37
- console.log(chalk.dim(' Open this URL manually:'));
38
- console.log(chalk.cyan(` ${url}`));
39
- }
40
- });
41
-
42
- console.log(chalk.green(`✅ Registration page opened!`));
43
- console.log(chalk.dim(` URL: ${url}`));
44
- console.log('');
45
- console.log(chalk.dim(' After registering, come back and run:'));
46
- console.log(chalk.cyan(' login'));
47
-
48
- } catch (err) {
49
- console.log(chalk.red(`❌ Error: ${err.message}`));
50
- }
51
- }
1
+ /*
2
+ src/commands/auth/register.js
3
+ Register new account — opens browser with pre-auth session
4
+ */
5
+
6
+ const chalk = require('chalk');
7
+ const { exec } = require('child_process');
8
+
9
+ module.exports = {
10
+ name: 'register',
11
+ description: 'Create a new ThinkNCollab account',
12
+ aliases: ['signup', 'reg'],
13
+ requiresAuth: false,
14
+
15
+ async execute(args, shell) {
16
+ try {
17
+ console.log(chalk.cyan('🌐 Opening registration in browser...'));
18
+
19
+ const baseUrl = shell.api.apiUrl || 'http://localhost:3001';
20
+
21
+ // Generate a CLI source token so backend knows it came from terminal
22
+ const crypto = require('crypto');
23
+ const cliRef = crypto.randomBytes(8).toString('hex');
24
+
25
+ const url = `${baseUrl}/register?ref=cli&cliRef=${cliRef}`;
26
+
27
+ // Open browser cross-platform
28
+ const openCmd = process.platform === 'win32'
29
+ ? `start "" "${url}"`
30
+ : process.platform === 'darwin'
31
+ ? `open "${url}"`
32
+ : `xdg-open "${url}"`;
33
+
34
+ exec(openCmd, (err) => {
35
+ if (err) {
36
+ console.log(chalk.yellow('⚠️ Could not open browser automatically.'));
37
+ console.log(chalk.dim(' Open this URL manually:'));
38
+ console.log(chalk.cyan(` ${url}`));
39
+ }
40
+ });
41
+
42
+ console.log(chalk.green(`✅ Registration page opened!`));
43
+ console.log(chalk.dim(` URL: ${url}`));
44
+ console.log('');
45
+ console.log(chalk.dim(' After registering, come back and run:'));
46
+ console.log(chalk.cyan(' login'));
47
+
48
+ } catch (err) {
49
+ console.log(chalk.red(`❌ Error: ${err.message}`));
50
+ }
51
+ }
52
52
  };
@@ -1,52 +1,52 @@
1
- const chalk = require('chalk');
2
-
3
- module.exports = {
4
- name: 'whoami',
5
- description: 'Show current user information',
6
- aliases: ['user', 'me'],
7
- requiresAuth: false,
8
-
9
- async execute(args, shell) {
10
- const user = shell.api.getUser();
11
- const room = shell.ws.getCurrentRoom?.();
12
- const session = shell.api.session;
13
-
14
- // ✅ Server se last session history fetch karo
15
- let lastSession = null;
16
- try {
17
- const history = await shell.api._request('GET', '/thinknsh/session/history');
18
- // Current session chhod ke last wali lo
19
- const prev = history.find(s => s._id !== session?.shellSessionId);
20
- if (prev) lastSession = prev;
21
- } catch {}
22
-
23
- console.log(chalk.cyan('\n👤 User Information:'));
24
- console.log(chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
25
- console.log(` ${chalk.yellow('Name:')} ${user.name || 'Not set'}`);
26
- console.log(` ${chalk.yellow('Email:')} ${user.email}`);
27
- console.log(` ${chalk.yellow('User ID:')} ${user._id || 'N/A'}`);
28
- console.log(` ${chalk.yellow('Type:')} ${user.userType || 'User'}`);
29
- console.log(` ${chalk.yellow('Status:')} ${shell.ws.isConnected?.() ? chalk.green('● Online') : chalk.gray('○ Offline')}`);
30
-
31
- if (room) {
32
- console.log(` ${chalk.yellow('Room:')} ${chalk.cyan(room)}`);
33
- }
34
-
35
- if (session?.timestamp) {
36
- console.log(` ${chalk.yellow('Login At:')} ${chalk.dim(new Date(session.timestamp).toLocaleString())}`);
37
- }
38
-
39
- // ✅ Server se actual logout time
40
- if (lastSession?.logoutAt) {
41
- console.log(` ${chalk.yellow('Last Logout:')} ${chalk.dim(new Date(lastSession.logoutAt).toLocaleString())}`);
42
- } else if (lastSession?.lastSeenAt) {
43
- console.log(` ${chalk.yellow('Last Seen:')} ${chalk.dim(new Date(lastSession.lastSeenAt).toLocaleString())} ${chalk.red('(crash?)')}`);
44
- }
45
-
46
- if (lastSession?.machineId) {
47
- console.log(` ${chalk.yellow('Last Machine:')} ${chalk.dim(lastSession.machineId)}`);
48
- }
49
-
50
- console.log();
51
- }
1
+ const chalk = require('chalk');
2
+
3
+ module.exports = {
4
+ name: 'whoami',
5
+ description: 'Show current user information',
6
+ aliases: ['user', 'me'],
7
+ requiresAuth: false,
8
+
9
+ async execute(args, shell) {
10
+ const user = shell.api.getUser();
11
+ const room = shell.ws.getCurrentRoom?.();
12
+ const session = shell.api.session;
13
+
14
+ // ✅ Server se last session history fetch karo
15
+ let lastSession = null;
16
+ try {
17
+ const history = await shell.api._request('GET', '/thinknsh/session/history');
18
+ // Current session chhod ke last wali lo
19
+ const prev = history.find(s => s._id !== session?.shellSessionId);
20
+ if (prev) lastSession = prev;
21
+ } catch {}
22
+
23
+ console.log(chalk.cyan('\n👤 User Information:'));
24
+ console.log(chalk.dim('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
25
+ console.log(` ${chalk.yellow('Name:')} ${user.name || 'Not set'}`);
26
+ console.log(` ${chalk.yellow('Email:')} ${user.email}`);
27
+ console.log(` ${chalk.yellow('User ID:')} ${user._id || 'N/A'}`);
28
+ console.log(` ${chalk.yellow('Type:')} ${user.userType || 'User'}`);
29
+ console.log(` ${chalk.yellow('Status:')} ${shell.ws.isConnected?.() ? chalk.green('● Online') : chalk.gray('○ Offline')}`);
30
+
31
+ if (room) {
32
+ console.log(` ${chalk.yellow('Room:')} ${chalk.cyan(room)}`);
33
+ }
34
+
35
+ if (session?.timestamp) {
36
+ console.log(` ${chalk.yellow('Login At:')} ${chalk.dim(new Date(session.timestamp).toLocaleString())}`);
37
+ }
38
+
39
+ // ✅ Server se actual logout time
40
+ if (lastSession?.logoutAt) {
41
+ console.log(` ${chalk.yellow('Last Logout:')} ${chalk.dim(new Date(lastSession.logoutAt).toLocaleString())}`);
42
+ } else if (lastSession?.lastSeenAt) {
43
+ console.log(` ${chalk.yellow('Last Seen:')} ${chalk.dim(new Date(lastSession.lastSeenAt).toLocaleString())} ${chalk.red('(crash?)')}`);
44
+ }
45
+
46
+ if (lastSession?.machineId) {
47
+ console.log(` ${chalk.yellow('Last Machine:')} ${chalk.dim(lastSession.machineId)}`);
48
+ }
49
+
50
+ console.log();
51
+ }
52
52
  };