thinkncollab-cli 1.0.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.
- package/Readme.md +0 -0
- package/bin/index.js +91 -0
- package/bin/tnc.js +21 -0
- package/lib/api.js +28 -0
- package/lib/scanner.js +27 -0
- package/lib/uploader.js +5 -0
- package/package.json +17 -0
package/Readme.md
ADDED
|
File without changes
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import inquirer from "inquirer";
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import os from "os";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
const RC_FILE = path.join(os.homedir(), ".tncrc");
|
|
9
|
+
|
|
10
|
+
async function login() {
|
|
11
|
+
const answers = await inquirer.prompt([
|
|
12
|
+
{ type: "input", name: "email", message: "Email:" },
|
|
13
|
+
{ type: "password", name: "password", message: "Password:" }
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const res = await axios.post("http://localhost:3001/signin", {
|
|
18
|
+
email: answers.email,
|
|
19
|
+
password: answers.password
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const token = res.data.token;
|
|
23
|
+
fs.writeFileSync(RC_FILE, JSON.stringify({ token }, null, 2));
|
|
24
|
+
console.log("✅ Login successful! Token saved at", RC_FILE);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.error("❌ Login failed:", err.response?.data?.message || err.message);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function readToken() {
|
|
31
|
+
if (!fs.existsSync(RC_FILE)) {
|
|
32
|
+
console.error("❌ Not logged in. Run 'tnc login'");
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
const data = JSON.parse(fs.readFileSync(RC_FILE));
|
|
36
|
+
return data.token;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function scanFolder(folderPath) {
|
|
40
|
+
const items = fs.readdirSync(folderPath, { withFileTypes: true });
|
|
41
|
+
return items.map((item) => {
|
|
42
|
+
const fullPath = path.join(folderPath, item.name);
|
|
43
|
+
if (item.isDirectory()) {
|
|
44
|
+
return { name: item.name, type: "folder", children: scanFolder(fullPath) };
|
|
45
|
+
} else {
|
|
46
|
+
const stats = fs.statSync(fullPath);
|
|
47
|
+
return { name: item.name, type: "file", path: fullPath, size: stats.size };
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function push(roomId, targetPath) {
|
|
53
|
+
const token = readToken();
|
|
54
|
+
let content;
|
|
55
|
+
const stats = fs.statSync(targetPath);
|
|
56
|
+
if (stats.isDirectory()) {
|
|
57
|
+
content = scanFolder(targetPath);
|
|
58
|
+
} else {
|
|
59
|
+
content = [{ name: path.basename(targetPath), type: "file", path: targetPath, size: stats.size }];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
await axios.post(
|
|
64
|
+
`http://localhost:3001/rooms/${roomId}/upload`,
|
|
65
|
+
{ content },
|
|
66
|
+
{ headers: { Authorization: `Bearer ${token}` } }
|
|
67
|
+
);
|
|
68
|
+
console.log("✅ Upload successful!");
|
|
69
|
+
console.log(content);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.error("❌ Upload failed:", err.response?.data?.message || err.message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// CLI arguments - only ONE declaration
|
|
76
|
+
const args = process.argv.slice(2);
|
|
77
|
+
|
|
78
|
+
if (args[0] === "login") {
|
|
79
|
+
login();
|
|
80
|
+
} else if (args[0] === "push") {
|
|
81
|
+
const roomIndex = args.indexOf("--room");
|
|
82
|
+
if (roomIndex === -1 || !args[roomIndex + 1] || !args[roomIndex + 2]) {
|
|
83
|
+
console.error("Usage: tnc push --room <roomId> <file-or-folder-path>");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
const roomId = args[roomIndex + 1];
|
|
87
|
+
const targetPath = args[roomIndex + 2];
|
|
88
|
+
push(roomId, targetPath);
|
|
89
|
+
} else {
|
|
90
|
+
console.log("✅ TNC CLI is working! Use 'tnc login' or 'tnc push'");
|
|
91
|
+
}
|
package/bin/tnc.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from "commander";
|
|
3
|
+
import { pushToRoom } from "../lib/api.js";
|
|
4
|
+
|
|
5
|
+
program
|
|
6
|
+
.name("tnc")
|
|
7
|
+
.description("ThinkNCollab CLI tool")
|
|
8
|
+
.version("0.1.0");
|
|
9
|
+
|
|
10
|
+
program
|
|
11
|
+
.command("push")
|
|
12
|
+
.option("--room <roomId>", "Room ID to push files")
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
if (!opts.room) {
|
|
15
|
+
console.error("❌ Please provide a room id using --room <id>");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
await pushToRoom(opts.room);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
program.parse();
|
package/lib/api.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { scanDirectory } from "./scanner.js";
|
|
2
|
+
import { uploadFile } from "./uploader.js";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
|
|
6
|
+
export async function pushToRoom(roomId) {
|
|
7
|
+
const currentDir = process.cwd();
|
|
8
|
+
console.log(`📂 Scanning directory: ${currentDir}`);
|
|
9
|
+
|
|
10
|
+
const files = scanDirectory(currentDir);
|
|
11
|
+
|
|
12
|
+
const uploadedFiles = [];
|
|
13
|
+
for (let file of files) {
|
|
14
|
+
const url = await uploadFile(file);
|
|
15
|
+
uploadedFiles.push({
|
|
16
|
+
name: file.name,
|
|
17
|
+
path: file.path,
|
|
18
|
+
size: file.size,
|
|
19
|
+
url,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Instead of real backend, save JSON locally for now
|
|
24
|
+
const outputPath = path.join(currentDir, `tnc_snapshot_${roomId}.json`);
|
|
25
|
+
fs.writeFileSync(outputPath, JSON.stringify(uploadedFiles, null, 2));
|
|
26
|
+
|
|
27
|
+
console.log(`✅ Snapshot saved at ${outputPath}`);
|
|
28
|
+
}
|
package/lib/scanner.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export function scanDirectory(dirPath) {
|
|
5
|
+
const result = [];
|
|
6
|
+
|
|
7
|
+
function walk(dir) {
|
|
8
|
+
const files = fs.readdirSync(dir);
|
|
9
|
+
for (let file of files) {
|
|
10
|
+
const fullPath = path.join(dir, file);
|
|
11
|
+
const stat = fs.statSync(fullPath);
|
|
12
|
+
|
|
13
|
+
if (stat.isDirectory()) {
|
|
14
|
+
walk(fullPath);
|
|
15
|
+
} else {
|
|
16
|
+
result.push({
|
|
17
|
+
name: file,
|
|
18
|
+
path: fullPath,
|
|
19
|
+
size: stat.size,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
walk(dirPath);
|
|
26
|
+
return result;
|
|
27
|
+
}
|
package/lib/uploader.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "thinkncollab-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool for ThinkNCollab",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"tnc": "./bin/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/index.js"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"axios": "^1.12.2",
|
|
15
|
+
"inquirer": "^9.3.8"
|
|
16
|
+
}
|
|
17
|
+
}
|