thinkncollab-cli 0.0.19 → 0.0.21
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/index.js +26 -21
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -13,9 +13,6 @@ const VERSION_FILE = path.join(process.cwd(), ".tncversions");
|
|
|
13
13
|
const BASE_URL = "http://localhost:3001/rooms";
|
|
14
14
|
const CWD = process.cwd();
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
16
|
/** ------------------ LOGIN ------------------ **/
|
|
20
17
|
async function login() {
|
|
21
18
|
const answers = await inquirer.prompt([
|
|
@@ -131,10 +128,11 @@ function saveVersions(versionMap) {
|
|
|
131
128
|
|
|
132
129
|
function computeHashCLI(filePath) {
|
|
133
130
|
if (!fs.existsSync(filePath)) return null;
|
|
131
|
+
|
|
134
132
|
const stats = fs.statSync(filePath);
|
|
135
133
|
if (stats.isDirectory()) {
|
|
136
134
|
const items = fs.readdirSync(filePath);
|
|
137
|
-
const combined = items.map(name => computeHashCLI(path.join(filePath, name))).join("");
|
|
135
|
+
const combined = items.map(name => computeHashCLI(path.join(filePath, name)) || "").join("");
|
|
138
136
|
return crypto.createHash("sha256").update(filePath + combined).digest("hex");
|
|
139
137
|
} else {
|
|
140
138
|
const content = fs.readFileSync(filePath);
|
|
@@ -145,11 +143,22 @@ function computeHashCLI(filePath) {
|
|
|
145
143
|
function checkChanges(fileTree, versionMap, rootPath = CWD) {
|
|
146
144
|
return fileTree.map(item => {
|
|
147
145
|
const fullPath = path.join(rootPath, item.path || item.name);
|
|
148
|
-
|
|
146
|
+
let hash = null;
|
|
147
|
+
|
|
148
|
+
if (fs.existsSync(fullPath)) {
|
|
149
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
150
|
+
const children = fs.readdirSync(fullPath).map(name => computeHashCLI(path.join(fullPath, name)) || "").join("");
|
|
151
|
+
hash = crypto.createHash("sha256").update(fullPath + children).digest("hex");
|
|
152
|
+
} else {
|
|
153
|
+
const content = fs.readFileSync(fullPath);
|
|
154
|
+
hash = crypto.createHash("sha256").update(content).digest("hex");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
149
158
|
const prevHash = versionMap[item.path || fullPath] || null;
|
|
150
159
|
const changed = hash !== prevHash;
|
|
151
160
|
|
|
152
|
-
|
|
161
|
+
const newItem = { ...item, changed, hash };
|
|
153
162
|
|
|
154
163
|
if (item.type === "folder" && item.children.length > 0) {
|
|
155
164
|
newItem.children = checkChanges(item.children, versionMap, rootPath);
|
|
@@ -197,22 +206,12 @@ async function uploadTree(fileTree, folderHex, roomId, token, email, parentPath
|
|
|
197
206
|
|
|
198
207
|
if (node.type === "folder") {
|
|
199
208
|
const children = await uploadTree(node.children, folderHex, roomId, token, email, relativePath);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
path: relativePath,
|
|
204
|
-
children
|
|
205
|
-
});
|
|
206
|
-
} else if (node.changed) {
|
|
209
|
+
const folderHash = crypto.createHash("sha256").update(relativePath + children.map(c => c.hash || "").join("")).digest("hex");
|
|
210
|
+
uploaded.push({ ...node, children, hash: folderHash });
|
|
211
|
+
} else if (node.changed && node.path) {
|
|
207
212
|
const url = await uploadFileSigned(node.path, `tnc_uploads/${folderHex}`, roomId, token, email);
|
|
208
213
|
console.log(`📦 Uploaded: ${relativePath} → ${url}`);
|
|
209
|
-
uploaded.push({
|
|
210
|
-
name: node.name,
|
|
211
|
-
type: "file",
|
|
212
|
-
path: relativePath,
|
|
213
|
-
size: node.size,
|
|
214
|
-
url
|
|
215
|
-
});
|
|
214
|
+
uploaded.push({ ...node, url });
|
|
216
215
|
} else {
|
|
217
216
|
uploaded.push(node); // unchanged, no upload
|
|
218
217
|
}
|
|
@@ -231,6 +230,11 @@ async function push(roomId, targetPath) {
|
|
|
231
230
|
}
|
|
232
231
|
const meta = JSON.parse(fs.readFileSync(tncMetaPath, "utf-8"));
|
|
233
232
|
const projectId = meta.projectId;
|
|
233
|
+
if (!projectId) {
|
|
234
|
+
console.error("❌ Project ID missing in metadata. Run 'tnc init' again.");
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
|
|
234
238
|
const stats = fs.statSync(targetPath);
|
|
235
239
|
const rootFolder = stats.isDirectory() ? targetPath : path.dirname(targetPath);
|
|
236
240
|
const ignoreList = loadIgnore(rootFolder);
|
|
@@ -265,7 +269,8 @@ async function push(roomId, targetPath) {
|
|
|
265
269
|
console.log("🚀 Uploading to Cloudinary...");
|
|
266
270
|
const uploadedTree = await uploadTree(contentWithChanges, folderHex, roomId, token, email);
|
|
267
271
|
|
|
268
|
-
console.log("🗂️ Sending metadata
|
|
272
|
+
console.log("🗂️ Sending metadata:", { folderId: folderHex, content: uploadedTree, uploadedBy: email, projectId });
|
|
273
|
+
|
|
269
274
|
await axios.post(
|
|
270
275
|
`${BASE_URL}/${roomId}/upload`,
|
|
271
276
|
{ folderId: folderHex, content: uploadedTree, uploadedBy: email, projectId },
|