thinkncollab-cli 0.0.85 → 0.0.87

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.
@@ -57,133 +57,129 @@ async function createTask() {
57
57
  return;
58
58
  }
59
59
 
60
- // console.log(chalk.green(`✅ Room ID: ${roomId}`));
61
- // console.log(chalk.green(`✅ Token: ${token.substring(0, 10)}...${token.substring(token.length - 10)}\n`));
60
+ // STEP 1: Find available port FIRST
61
+ console.log(chalk.gray('🔍 Finding available port for callback server...'));
62
+ const PORT = await findAvailablePort(3002);
63
+ console.log(chalk.green(`✅ Callback server will run on port: ${PORT}`));
62
64
 
63
- // Construct the URL with CLI flag
64
- const redirectUrl = `https://thinkncollab.in/cli/tasks/${roomId}/${token}/create?cli=true`;
65
+ // STEP 2: Construct the URL with the found port
66
+ const redirectUrl = `https://thinkncollab.in/cli/tasks/${roomId}/${token}/create?cli=true&callbackPort=${PORT}`;
65
67
 
66
68
  const spinner = createSpinner('Preparing task creation interface...');
67
69
 
68
70
  console.log(chalk.blue('🔗 Opening task creation interface in your browser...'));
69
71
  console.log(chalk.gray(`URL: ${redirectUrl}`));
70
72
 
71
- // Find available port
72
- const PORT = await findAvailablePort(3002);
73
73
  spinner.stop();
74
74
 
75
- // Create callback server
76
- // Create callback server with better CORS and request handling
77
- const server = http.createServer((req, res) => {
78
- console.log(chalk.yellow(`\n📨 Callback received: ${req.url}`));
79
-
80
- // CORS headers for all responses
81
- res.setHeader('Access-Control-Allow-Origin', '*');
82
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
83
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-CLI-Callback-URL');
84
- res.setHeader('Access-Control-Max-Age', '86400'); // 24 hours
85
-
86
- // Handle preflight
87
- if (req.method === 'OPTIONS') {
88
- res.writeHead(200);
89
- res.end();
90
- return;
91
- }
92
-
93
- // Parse URL
94
- const url = new URL(req.url, `http://localhost:${PORT}`);
95
-
96
- // Check for callback (handle both /callback and direct query params)
97
- if (req.url.includes('/callback') || url.searchParams.has('taskId')) {
98
- const taskId = url.searchParams.get('taskId');
99
- const attachments = url.searchParams.get('attachments');
100
- const status = url.searchParams.get('status');
101
-
102
- // Log success
103
- if (status === 'error') {
104
- console.log(chalk.red('\n❌ Task creation failed!'));
105
- } else {
106
- console.log(chalk.green('\n✅ Task created successfully!'));
107
- if (taskId) {
108
- console.log(chalk.blue(`📋 Task ID: ${taskId}`));
109
-
110
- // Save task ID to file
111
- const taskMetaPath = path.join(CWD, ".tnc", "last-task.json");
112
- fs.writeFileSync(taskMetaPath, JSON.stringify({
113
- taskId,
114
- attachments: attachments ? attachments.length : 0,
115
- timestamp: new Date().toISOString(),
116
- roomId
117
- }, null, 2));
118
- console.log(chalk.gray(`📝 Task ID saved to .tnc/last-task.json`));
75
+ // STEP 3: Create callback server
76
+ const server = http.createServer((req, res) => {
77
+ console.log(chalk.yellow(`\n📨 Callback received: ${req.url}`));
78
+
79
+ // CORS headers for all responses
80
+ res.setHeader('Access-Control-Allow-Origin', '*');
81
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
82
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-CLI-Callback-URL');
83
+ res.setHeader('Access-Control-Max-Age', '86400'); // 24 hours
84
+
85
+ // Handle preflight
86
+ if (req.method === 'OPTIONS') {
87
+ res.writeHead(200);
88
+ res.end();
89
+ return;
119
90
  }
120
- if (attachments) {
121
- // console.log(chalk.blue(`📎 Attachments: ${attachments}`));
91
+
92
+ // Parse URL
93
+ const url = new URL(req.url, `http://localhost:${PORT}`);
94
+
95
+ // Check for callback (handle both /callback and direct query params)
96
+ if (req.url.includes('/callback') || url.searchParams.has('taskId')) {
97
+ const taskId = url.searchParams.get('taskId');
98
+ const attachments = url.searchParams.get('attachments');
99
+ const status = url.searchParams.get('status');
100
+
101
+ // Log success
102
+ if (status === 'error') {
103
+ console.log(chalk.red('\n❌ Task creation failed!'));
104
+ } else {
105
+ console.log(chalk.green('\n✅ Task created successfully!'));
106
+ if (taskId) {
107
+ console.log(chalk.blue(`📋 Task ID: ${taskId}`));
108
+
109
+ // Save task ID to file
110
+ const taskMetaPath = path.join(CWD, ".tnc", "last-task.json");
111
+ fs.writeFileSync(taskMetaPath, JSON.stringify({
112
+ taskId,
113
+ attachments: attachments ? parseInt(attachments) : 0,
114
+ timestamp: new Date().toISOString(),
115
+ roomId
116
+ }, null, 2));
117
+ console.log(chalk.gray(`📝 Task ID saved to .tnc/last-task.json`));
118
+ }
119
+ }
120
+
121
+ // Send response to close browser (HTML with auto-close)
122
+ res.writeHead(200, {
123
+ 'Content-Type': 'text/html',
124
+ 'Access-Control-Allow-Origin': '*'
125
+ });
126
+ res.end(`
127
+ <!DOCTYPE html>
128
+ <html>
129
+ <head>
130
+ <title>${status === 'error' ? 'Failed' : 'Success'}</title>
131
+ <style>
132
+ body {
133
+ font-family: Arial, sans-serif;
134
+ display: flex;
135
+ justify-content: center;
136
+ align-items: center;
137
+ height: 100vh;
138
+ margin: 0;
139
+ background: ${status === 'error' ? '#f44336' : '#4CAF50'};
140
+ color: white;
141
+ }
142
+ .message {
143
+ text-align: center;
144
+ padding: 20px;
145
+ }
146
+ </style>
147
+ </head>
148
+ <body>
149
+ <div class="message">
150
+ <h1>${status === 'error' ? '❌ Task Failed' : '✅ Task Created'}</h1>
151
+ ${taskId ? `<p>Task ID: ${taskId}</p>` : ''}
152
+ <p>Closing in 3 seconds...</p>
153
+ </div>
154
+ <script>
155
+ // Send one more callback to ensure it was received
156
+ fetch(window.location.href, { method: 'GET', mode: 'no-cors' });
157
+
158
+ // Auto close
159
+ setTimeout(() => window.close(), 3000);
160
+
161
+ // Fallback
162
+ setTimeout(() => {
163
+ window.location.href = 'about:blank';
164
+ setTimeout(() => window.close(), 100);
165
+ }, 4000);
166
+ </script>
167
+ </body>
168
+ </html>
169
+ `);
170
+
171
+ // Close server after response
172
+ setTimeout(() => {
173
+ server.close();
174
+ console.log(chalk.gray('\n📡 Callback server closed'));
175
+ process.exit(0);
176
+ }, 2000);
177
+ } else {
178
+ // Handle other requests (like favicon)
179
+ res.writeHead(404);
180
+ res.end('Not found');
122
181
  }
123
- }
124
-
125
- // Send response to close browser (HTML with auto-close)
126
- res.writeHead(200, {
127
- 'Content-Type': 'text/html',
128
- 'Access-Control-Allow-Origin': '*'
129
182
  });
130
- res.end(`
131
- <!DOCTYPE html>
132
- <html>
133
- <head>
134
- <title>${status === 'error' ? 'Failed' : 'Success'}</title>
135
- <style>
136
- body {
137
- font-family: Arial, sans-serif;
138
- display: flex;
139
- justify-content: center;
140
- align-items: center;
141
- height: 100vh;
142
- margin: 0;
143
- background: ${status === 'error' ? '#f44336' : '#4CAF50'};
144
- color: white;
145
- }
146
- .message {
147
- text-align: center;
148
- padding: 20px;
149
- }
150
- </style>
151
- </head>
152
- <body>
153
- <div class="message">
154
- <h1>${status === 'error' ? '❌ Task Failed' : '✅ Task Created'}</h1>
155
- ${taskId ? `<p>Task ID: ${taskId}</p>` : ''}
156
- <p>Closing in 3 seconds...</p>
157
- </div>
158
- <script>
159
- // Send one more callback to ensure it was received
160
- fetch(window.location.href, { method: 'GET', mode: 'no-cors' });
161
-
162
- // Auto close
163
- setTimeout(() => window.close(), 3000);
164
-
165
- // Fallback
166
- setTimeout(() => {
167
- window.location.href = 'about:blank';
168
- setTimeout(() => window.close(), 100);
169
- }, 4000);
170
- </script>
171
- </body>
172
- </html>
173
- `);
174
-
175
- // Close server after response
176
- setTimeout(() => {
177
- server.close();
178
- console.log(chalk.gray('\n📡 Callback server closed'));
179
- process.exit(0);
180
- }, 2000);
181
- } else {
182
- // Handle other requests (like favicon)
183
- res.writeHead(404);
184
- res.end('Not found');
185
- }
186
- });
187
183
 
188
184
  // Server error handling
189
185
  server.on('error', (err) => {
@@ -197,15 +193,14 @@ const server = http.createServer((req, res) => {
197
193
 
198
194
  // Start server
199
195
  server.listen(PORT, () => {
200
- // console.log(chalk.gray(`📡 Waiting for callback on http://localhost:${PORT}/callback`));
201
- // console.log(chalk.gray('The browser will automatically close after task creation\n'));
196
+ console.log(chalk.gray(`📡 Waiting for callback on http://localhost:${PORT}/callback`));
202
197
  });
203
198
 
204
199
  // Open browser
205
200
  setTimeout(async () => {
206
201
  try {
207
202
  await open(redirectUrl);
208
- // console.log(chalk.green('✅ Browser opened successfully!'));
203
+ console.log(chalk.green('✅ Browser opened successfully!'));
209
204
  } catch (err) {
210
205
  if (err.message.includes('No application')) {
211
206
  console.error(chalk.red('❌ Could not open browser automatically.'));
@@ -1,44 +1,75 @@
1
1
  import axios from "axios";
2
2
  import fs from "fs";
3
- import os from "os";
4
3
  import path from "path";
5
4
  import machine from "node-machine-id";
6
5
  import chalk from "chalk";
7
- import FormData from "form-data";
8
6
  import getVerify from "../lib/getVerify.js";
9
7
 
10
8
  const CWD = process.cwd();
11
- const TNC_API_URL = "http://localhost:3001/";
9
+ const TNC_API_URL = "https://thinkncollab.com/";
12
10
  const metaDataFile = path.join(CWD, ".tnc", ".tncmeta.json");
13
- const metaData = JSON.parse(fs.readFileSync(metaDataFile, "utf-8"));
14
- const roomId = metaData.roomId;
15
11
 
16
12
  async function myTeam() {
17
13
  try {
14
+ // ✅ Check initialization first
15
+ if (!fs.existsSync(metaDataFile)) {
16
+ console.log(chalk.red("❌ Project not initialized."));
17
+ console.log(chalk.yellow("👉 Run `tnc init` first."));
18
+ return;
19
+ }
20
+
21
+ const metaData = JSON.parse(
22
+ fs.readFileSync(metaDataFile, "utf-8")
23
+ );
24
+
25
+ if (!metaData.roomId) {
26
+ console.log(chalk.red("❌ No room associated with this project."));
27
+ return;
28
+ }
29
+
30
+ const roomId = metaData.roomId;
31
+
18
32
  const verifyData = await getVerify();
19
33
  const { email, token } = verifyData;
20
- const response = await axios.get(`${TNC_API_URL}cli/myTeam/${roomId}`, {
21
- headers: {
22
- email,
23
- token,
24
- machineId: machine.machineIdSync(),
25
- },
26
- });
34
+
35
+ const response = await axios.get(
36
+ `${TNC_API_URL}cli/myTeam/${roomId}`,
37
+ {
38
+ headers: {
39
+ email,
40
+ token,
41
+ machineId: machine.machineIdSync(),
42
+ },
43
+ }
44
+ );
45
+
27
46
  const teamMembers = response.data.RoomMembers || [];
47
+
28
48
  if (teamMembers.length === 0) {
29
49
  console.log(chalk.yellow("⚠️ You are not part of any team yet."));
30
50
  return;
31
51
  }
32
- console.log(chalk.green("👥 Your Team Members:"))
52
+
53
+ console.log(chalk.green("👥 Your Team Members:"));
33
54
  teamMembers.forEach(member => {
34
- console.log(chalk.blue(`- ${member.name} (${member.email})`));
55
+ console.log(
56
+ chalk.blue(`- ${member.name} (${member.email})`)
57
+ );
35
58
  });
59
+
36
60
  } catch (err) {
37
61
  if (err.response) {
38
- console.error(chalk.red("❌ Error:"), chalk.red(err.response.data.error));
62
+ console.error(
63
+ chalk.red("❌ Error:"),
64
+ chalk.red(err.response.data.error)
65
+ );
39
66
  } else {
40
- console.error(chalk.red("❌ Error:"), chalk.red(err.message));
67
+ console.error(
68
+ chalk.red("❌ Error:"),
69
+ chalk.red(err.message)
70
+ );
41
71
  }
42
72
  }
43
73
  }
44
- export default myTeam;
74
+
75
+ export default myTeam;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "thinkncollab-cli",
3
3
  "author": "Raman Singh",
4
- "version": "0.0.85",
4
+ "version": "0.0.87",
5
5
  "description": "CLI tool for ThinkNCollab",
6
6
  "main": "index.js",
7
7
  "bin": {