commentme 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 +55 -0
- package/auth/authGuard.js +23 -0
- package/auth/login.js +160 -0
- package/auth/logout.js +6 -0
- package/auth/signup.js +71 -0
- package/bin/commentme.js +147 -0
- package/config/db.js +19 -0
- package/deletecoms.js +96 -0
- package/editcoms.js +97 -0
- package/getcoms.js +86 -0
- package/getspeccoms.js +101 -0
- package/package.json +28 -0
- package/skimcoms.js +221 -0
- package/unskimcoms.js +147 -0
- package/utils/commentPatterns.js +233 -0
- package/utils/config.js +1 -0
- package/utils/currentUser.js +9 -0
- package/utils/passwordPrompt.js +51 -0
- package/utils/session.js +22 -0
package/getcoms.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// import fs from "fs";
|
|
2
|
+
|
|
3
|
+
// export function getAllComments() {
|
|
4
|
+
// if (!fs.existsSync("output.json")) {
|
|
5
|
+
// throw new Error("output.json not found. Run skim first.");
|
|
6
|
+
// }
|
|
7
|
+
|
|
8
|
+
// const raw = fs.readFileSync("output.json", "utf8");
|
|
9
|
+
// const comments = JSON.parse(raw);
|
|
10
|
+
|
|
11
|
+
// console.log(comments);
|
|
12
|
+
// }
|
|
13
|
+
// import { CommentStore } from "./models/CommentStore.js";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { getCurrentUserId } from "./utils/currentUser.js";
|
|
16
|
+
import { getSession } from "./utils/session.js";
|
|
17
|
+
import { API_BASE_URL } from "./utils/config.js";
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
export async function getAllComments(filePath = null) {
|
|
21
|
+
const codebase = filePath ? path.basename(filePath) : "default";
|
|
22
|
+
|
|
23
|
+
// Check if user is logged in
|
|
24
|
+
try {
|
|
25
|
+
getCurrentUserId();
|
|
26
|
+
} catch (e) {
|
|
27
|
+
console.error(e.message);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const session = getSession();
|
|
32
|
+
const token = session.token; // Try to get token if saved, though current saveSession only saves userId.
|
|
33
|
+
// If auth middleware requires token, this needs to be updated.
|
|
34
|
+
// However, the user instruction implies we just need to hit the API.
|
|
35
|
+
// We'll pass the token in Authorization header if it exists.
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(`${API_BASE_URL}/comments?codebase=${encodeURIComponent(codebase)}`, {
|
|
39
|
+
method: "GET",
|
|
40
|
+
headers: {
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
"Authorization": token ? `Bearer ${token}` : "" // Sending token if available
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const data = await response.json();
|
|
47
|
+
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
// Gracefully handle empty or error
|
|
50
|
+
if (response.status === 404) {
|
|
51
|
+
console.log("{}");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
throw new Error(data.message || "Failed to fetch comments");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log(data); // The API returns the comments object directly
|
|
58
|
+
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error.code === 'ECONNREFUSED') {
|
|
61
|
+
console.error("Error: Could not connect to the backend server. Is it running on port 8080?");
|
|
62
|
+
} else {
|
|
63
|
+
console.error("Error:", error.message);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/*
|
|
68
|
+
const userId = getCurrentUserId();
|
|
69
|
+
const store = await CommentStore.findOne({ userId });
|
|
70
|
+
|
|
71
|
+
if (!store) {
|
|
72
|
+
console.log("{}");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const codebaseIndex= store.comments.findIndex(c => c.codebase === codebase);
|
|
77
|
+
|
|
78
|
+
if (codebaseIndex === -1 || !store.comments[codebaseIndex].filecomment) {
|
|
79
|
+
console.log("{}");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const codebaseEntry = store.comments[codebaseIndex];
|
|
83
|
+
|
|
84
|
+
console.log(Object.fromEntries(codebaseEntry.filecomment));
|
|
85
|
+
*/
|
|
86
|
+
}
|
package/getspeccoms.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// import fs from "fs";
|
|
2
|
+
|
|
3
|
+
// export function getSpecificComment(key, silent = false) {
|
|
4
|
+
// if (!fs.existsSync("output.json")) {
|
|
5
|
+
// throw new Error("output.json not found. Run skim first.");
|
|
6
|
+
// }
|
|
7
|
+
|
|
8
|
+
// const raw = fs.readFileSync("output.json", "utf8");
|
|
9
|
+
// const comments = JSON.parse(raw);
|
|
10
|
+
|
|
11
|
+
// if (!comments[key]) {
|
|
12
|
+
// throw new Error(`No comment found for key: ${key}`);
|
|
13
|
+
// }
|
|
14
|
+
|
|
15
|
+
// if (!silent) {
|
|
16
|
+
// console.log(`✔ Comment for ${key}:`);
|
|
17
|
+
// console.log(comments[key]);
|
|
18
|
+
// }
|
|
19
|
+
|
|
20
|
+
// return comments[key]; // IMPORTANT for edit flow
|
|
21
|
+
// }
|
|
22
|
+
|
|
23
|
+
// import { CommentStore } from "./models/CommentStore.js";
|
|
24
|
+
import path from "path";
|
|
25
|
+
import { getCurrentUserId } from "./utils/currentUser.js";
|
|
26
|
+
import { getSession } from "./utils/session.js";
|
|
27
|
+
import { API_BASE_URL } from "./utils/config.js";
|
|
28
|
+
|
|
29
|
+
export async function getSpecificComment(key, silent = false, filePath = null) {
|
|
30
|
+
const codebase = filePath ? path.basename(filePath) : "default";
|
|
31
|
+
|
|
32
|
+
// Check authentication
|
|
33
|
+
try {
|
|
34
|
+
getCurrentUserId();
|
|
35
|
+
} catch (e) {
|
|
36
|
+
if (!silent) console.error(e.message);
|
|
37
|
+
throw e;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const session = getSession();
|
|
41
|
+
const token = session ? session.token : null;
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const response = await fetch(`${API_BASE_URL}/comments/${encodeURIComponent(key)}?codebase=${encodeURIComponent(codebase)}`, {
|
|
45
|
+
method: "GET",
|
|
46
|
+
headers: {
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
"Authorization": token ? `Bearer ${token}` : ""
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const data = await response.json();
|
|
53
|
+
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
// Handle error, throw regular error to match previous behavior for catch blocks up the chain
|
|
56
|
+
throw new Error(data.message || `No comment found for key: ${key}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const value = data.comment; // Backend returns { key, comment }
|
|
60
|
+
|
|
61
|
+
if (!silent) {
|
|
62
|
+
console.log(`✔ Comment for ${key}:`);
|
|
63
|
+
console.log(value);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return value;
|
|
67
|
+
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error.code === 'ECONNREFUSED') {
|
|
70
|
+
if (!silent) console.error("Error: Could not connect to the backend server. Is it running on port 8080?");
|
|
71
|
+
throw new Error("Connection failed");
|
|
72
|
+
} else {
|
|
73
|
+
// Re-throw so caller can handle "No comment found" etc.
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
const userId = getCurrentUserId();
|
|
80
|
+
const store = await CommentStore.findOne({ userId });
|
|
81
|
+
|
|
82
|
+
if (!store) {
|
|
83
|
+
throw new Error(`No comment found for key: ${key}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const codebaseIndex = store.comments.findIndex(c => c.codebase === codebase);
|
|
87
|
+
|
|
88
|
+
if (codebaseIndex === -1 || !store.comments[codebaseIndex].filecomment.has(key)) {
|
|
89
|
+
throw new Error(`No comment found for key: ${key}`);
|
|
90
|
+
}
|
|
91
|
+
const codebaseEntry = store.comments[codebaseIndex];
|
|
92
|
+
const value = codebaseEntry.filecomment.get(key);
|
|
93
|
+
|
|
94
|
+
if (!silent) {
|
|
95
|
+
console.log(`✔ Comment for ${key}:`);
|
|
96
|
+
console.log(value);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return value;
|
|
100
|
+
*/
|
|
101
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "commentme",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A CLI tool to manage, redact and unredact your comments keeping the codebase clutterfree.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"commentme": "./bin/commentme.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "bin/commentme.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"utils/",
|
|
13
|
+
"config/",
|
|
14
|
+
"auth/",
|
|
15
|
+
"*.js"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
19
|
+
},
|
|
20
|
+
"author": "dotlasher",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"acorn": "^8.15.0",
|
|
24
|
+
"bcryptjs": "^3.0.3",
|
|
25
|
+
"dotenv": "^17.2.3",
|
|
26
|
+
"mongoose": "^9.0.1"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/skimcoms.js
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// import * as acorn from "acorn";
|
|
2
|
+
// import fs from "fs";
|
|
3
|
+
|
|
4
|
+
// export function removeCommentsFromFile(filePath) {
|
|
5
|
+
// const code = fs.readFileSync(filePath, "utf8");
|
|
6
|
+
|
|
7
|
+
// const comments = [];
|
|
8
|
+
// const commentJSON = {};
|
|
9
|
+
|
|
10
|
+
// acorn.parse(code, {
|
|
11
|
+
// ecmaVersion: 2020,
|
|
12
|
+
// locations: true,
|
|
13
|
+
// onComment: (isBlock, text, start, end, startLoc, endLoc) => {
|
|
14
|
+
// comments.push({
|
|
15
|
+
// start,
|
|
16
|
+
// end,
|
|
17
|
+
// text,
|
|
18
|
+
// lineStart: startLoc.line,
|
|
19
|
+
// lineEnd: endLoc.line
|
|
20
|
+
// });
|
|
21
|
+
// }
|
|
22
|
+
// });
|
|
23
|
+
|
|
24
|
+
// for (const c of comments) {
|
|
25
|
+
// const key = `${c.lineStart}-${c.lineEnd}`;
|
|
26
|
+
// commentJSON[key] = c.text.trim();
|
|
27
|
+
// }
|
|
28
|
+
|
|
29
|
+
// comments.sort((a, b) => b.start - a.start);
|
|
30
|
+
|
|
31
|
+
// let cleaned = code;
|
|
32
|
+
// for (const c of comments) {
|
|
33
|
+
// cleaned = cleaned.slice(0, c.start) + cleaned.slice(c.end);
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
// fs.writeFileSync(filePath, cleaned, "utf8");
|
|
37
|
+
// fs.writeFileSync("output.json", JSON.stringify(commentJSON, null, 2));
|
|
38
|
+
|
|
39
|
+
// return { cleaned, commentJSON };
|
|
40
|
+
// }
|
|
41
|
+
import * as acorn from "acorn";
|
|
42
|
+
import fs from "fs";
|
|
43
|
+
import path from "path";
|
|
44
|
+
// import { CommentStore } from "./models/CommentStore.js";
|
|
45
|
+
import { getSession } from "./utils/session.js";
|
|
46
|
+
import { API_BASE_URL } from "./utils/config.js";
|
|
47
|
+
import { getCurrentUserId } from "./utils/currentUser.js";
|
|
48
|
+
import { getCommentPattern, detectComments, formatReferenceComment } from "./utils/commentPatterns.js";
|
|
49
|
+
|
|
50
|
+
export async function removeCommentsFromFile(filePath, codebase = null) {
|
|
51
|
+
if (!fs.existsSync(filePath)) {
|
|
52
|
+
throw new Error(`File not found: ${filePath}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Use filename as codebase if not provided
|
|
56
|
+
if (!codebase) {
|
|
57
|
+
codebase = path.basename(filePath);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check authentication
|
|
61
|
+
try {
|
|
62
|
+
getCurrentUserId();
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.error(e.message);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const code = fs.readFileSync(filePath, "utf8");
|
|
69
|
+
|
|
70
|
+
const comments = [];
|
|
71
|
+
const commentMap = {};
|
|
72
|
+
const ext = path.extname(filePath).slice(1).toLowerCase();
|
|
73
|
+
|
|
74
|
+
// Use acorn for JavaScript files (more accurate), regex for others
|
|
75
|
+
if (ext === "js" || ext === "jsx" || ext === "ts" || ext === "tsx") {
|
|
76
|
+
try {
|
|
77
|
+
// Parse comments using acorn with module support
|
|
78
|
+
acorn.parse(code, {
|
|
79
|
+
ecmaVersion: 2020,
|
|
80
|
+
sourceType: "module",
|
|
81
|
+
locations: true,
|
|
82
|
+
onComment: (isBlock, text, start, end, startLoc, endLoc) => {
|
|
83
|
+
// Skip reference comments
|
|
84
|
+
if (text.trim().startsWith("#ref")) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
comments.push({
|
|
88
|
+
start,
|
|
89
|
+
end,
|
|
90
|
+
text,
|
|
91
|
+
lineStart: startLoc.line,
|
|
92
|
+
lineEnd: endLoc.line,
|
|
93
|
+
isBlock: isBlock
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
} catch (e) {
|
|
98
|
+
// Clear half-populated comments from failed acorn parse
|
|
99
|
+
comments.length = 0;
|
|
100
|
+
// Fallback to regex-based detection if acorn fails (e.g., on JSX or TS syntax)
|
|
101
|
+
const pattern = getCommentPattern(filePath);
|
|
102
|
+
const detectedComments = detectComments(code, pattern);
|
|
103
|
+
comments.push(...detectedComments);
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
// Use regex-based detection for other file types
|
|
107
|
+
const pattern = getCommentPattern(filePath);
|
|
108
|
+
const detectedComments = detectComments(code, pattern);
|
|
109
|
+
comments.push(...detectedComments);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Build key-value map
|
|
113
|
+
for (const c of comments) {
|
|
114
|
+
const key = `${c.lineStart}-${c.lineEnd}`;
|
|
115
|
+
commentMap[key] = c.text.trim();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Replace comments with reference comments (descending order to preserve positions)
|
|
119
|
+
comments.sort((a, b) => b.start - a.start);
|
|
120
|
+
|
|
121
|
+
let result = code;
|
|
122
|
+
const pattern = getCommentPattern(filePath);
|
|
123
|
+
|
|
124
|
+
for (const c of comments) {
|
|
125
|
+
const key = `${c.lineStart}-${c.lineEnd}`;
|
|
126
|
+
const refComment = formatReferenceComment(key, pattern, c.isBlock);
|
|
127
|
+
|
|
128
|
+
if (c.isInline) {
|
|
129
|
+
// For inline comments: replace comment with reference, preserve code
|
|
130
|
+
// The slice already preserves code before (c.start is at comment start)
|
|
131
|
+
result = result.slice(0, c.start) + refComment + result.slice(c.end);
|
|
132
|
+
} else {
|
|
133
|
+
// Full line comment: replace entire comment
|
|
134
|
+
result = result.slice(0, c.start) + refComment + result.slice(c.end);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Move file write after successful backend storage
|
|
139
|
+
const session = getSession();
|
|
140
|
+
const token = session ? session.token : null;
|
|
141
|
+
|
|
142
|
+
if (!token) {
|
|
143
|
+
throw new Error("Authentication token missing. Please log in again.");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const response = await fetch(`${API_BASE_URL}/comments/upload`, {
|
|
148
|
+
method: "POST",
|
|
149
|
+
headers: {
|
|
150
|
+
"Content-Type": "application/json",
|
|
151
|
+
"Authorization": `Bearer ${token}`
|
|
152
|
+
},
|
|
153
|
+
body: JSON.stringify({ codebase: codebase, comments: commentMap })
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const data = await response.json();
|
|
157
|
+
|
|
158
|
+
if (!response.ok) {
|
|
159
|
+
throw new Error(data.message || `Failed to upload comments for codebase: ${codebase}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ONLY write the file after successful backup to the server
|
|
163
|
+
fs.writeFileSync(filePath, result, "utf8");
|
|
164
|
+
console.log(`✔ File skimmed and comments stored in database (codebase: ${codebase})`);
|
|
165
|
+
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (error.code === 'ECONNREFUSED') {
|
|
168
|
+
console.error("Error: Could not connect to the backend server. Is it running on Render?");
|
|
169
|
+
} else {
|
|
170
|
+
console.error("Error:", error.message);
|
|
171
|
+
}
|
|
172
|
+
// Return early to prevent returning the "successful" state
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/*
|
|
177
|
+
const userId = getCurrentUserId();
|
|
178
|
+
|
|
179
|
+
// 🔥 SAVE/UPDATE COMMENTS TO MONGODB
|
|
180
|
+
let store = await CommentStore.findOne({ userId });
|
|
181
|
+
|
|
182
|
+
if (!store) {
|
|
183
|
+
store = await CommentStore.create({ userId, comments: [] });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Find codebase index
|
|
187
|
+
let codebaseIndex = store.comments.findIndex(c => c.codebase === codebase);
|
|
188
|
+
|
|
189
|
+
if (codebaseIndex === -1) {
|
|
190
|
+
// Create new codebase entry
|
|
191
|
+
store.comments.push({
|
|
192
|
+
codebase,
|
|
193
|
+
filecomment: new Map()
|
|
194
|
+
});
|
|
195
|
+
codebaseIndex = store.comments.length - 1;
|
|
196
|
+
await store.save(); // Save to get the new entry properly initialized
|
|
197
|
+
store = await CommentStore.findById(store._id); // Re-fetch to get proper Mongoose document
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Get the codebase entry
|
|
201
|
+
const codebaseEntry = store.comments[codebaseIndex];
|
|
202
|
+
|
|
203
|
+
// Ensure filecomment is a Map
|
|
204
|
+
if (!(codebaseEntry.filecomment instanceof Map)) {
|
|
205
|
+
codebaseEntry.filecomment = new Map(Object.entries(codebaseEntry.filecomment || {}));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Update existing comments or add new ones
|
|
209
|
+
for (const [key, value] of Object.entries(commentMap)) {
|
|
210
|
+
codebaseEntry.filecomment.set(key, value);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Mark as modified and save
|
|
214
|
+
store.markModified(`comments.${codebaseIndex}.filecomment`);
|
|
215
|
+
await store.save();
|
|
216
|
+
|
|
217
|
+
console.log(`✔ File skimmed and comments stored in database (codebase: ${codebase})`);
|
|
218
|
+
*/
|
|
219
|
+
|
|
220
|
+
return { cleaned: result, commentMap };
|
|
221
|
+
}
|
package/unskimcoms.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
// import { CommentStore } from "./models/CommentStore.js";
|
|
4
|
+
import { getCurrentUserId } from "./utils/currentUser.js";
|
|
5
|
+
import { getSession } from "./utils/session.js";
|
|
6
|
+
import { API_BASE_URL } from "./utils/config.js";
|
|
7
|
+
import { getCommentPattern, formatComment } from "./utils/commentPatterns.js";
|
|
8
|
+
|
|
9
|
+
export async function unskimComments(filePath, codebase = null) {
|
|
10
|
+
if (!fs.existsSync(filePath)) {
|
|
11
|
+
throw new Error(`File not found: ${filePath}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Use filename as codebase if not provided
|
|
15
|
+
if (!codebase) {
|
|
16
|
+
codebase = path.basename(filePath);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Check authentication
|
|
20
|
+
try {
|
|
21
|
+
getCurrentUserId();
|
|
22
|
+
} catch (e) {
|
|
23
|
+
console.error(e.message);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const session = getSession();
|
|
28
|
+
const token = session ? session.token : null;
|
|
29
|
+
if (!token) {
|
|
30
|
+
throw new Error("Authentication token missing. Please log in again.");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let comments = {};
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(`${API_BASE_URL}/comments?codebase=${encodeURIComponent(codebase)}`, {
|
|
37
|
+
method: "GET",
|
|
38
|
+
headers: {
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
"Authorization": `Bearer ${token}`
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const data = await response.json();
|
|
45
|
+
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
if (response.status === 404) {
|
|
48
|
+
throw new Error(`No comments found for codebase: ${codebase}`);
|
|
49
|
+
}
|
|
50
|
+
throw new Error(data.message || `Failed to fetch comments for codebase: ${codebase}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
comments = data;
|
|
54
|
+
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (error.code === 'ECONNREFUSED') {
|
|
57
|
+
console.error("Error: Could not connect to the backend server. Is it running on port 8080?");
|
|
58
|
+
return;
|
|
59
|
+
} else {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
const userId = getCurrentUserId();
|
|
67
|
+
|
|
68
|
+
// Fetch comments from DB
|
|
69
|
+
const store = await CommentStore.findOne({ userId });
|
|
70
|
+
|
|
71
|
+
if (!store) {
|
|
72
|
+
throw new Error("No comments found for this user");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Find the specific codebase
|
|
76
|
+
const codebaseEntry = store.comments.find(c => c.codebase === codebase);
|
|
77
|
+
|
|
78
|
+
if (!codebaseEntry) {
|
|
79
|
+
throw new Error(`No comments found for codebase: ${codebase}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Ensure filecomment is a Map
|
|
83
|
+
let filecommentMap;
|
|
84
|
+
if (codebaseEntry.filecomment instanceof Map) {
|
|
85
|
+
filecommentMap = codebaseEntry.filecomment;
|
|
86
|
+
} else {
|
|
87
|
+
filecommentMap = new Map(Object.entries(codebaseEntry.filecomment || {}));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (filecommentMap.size === 0) {
|
|
91
|
+
throw new Error(`No comments found for codebase: ${codebase}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const comments = Object.fromEntries(filecommentMap);
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
// Get comment pattern based on file extension
|
|
98
|
+
const pattern = getCommentPattern(filePath);
|
|
99
|
+
|
|
100
|
+
// Load file
|
|
101
|
+
const code = fs.readFileSync(filePath, "utf8");
|
|
102
|
+
let lines = code.split("\n");
|
|
103
|
+
|
|
104
|
+
// Replace reference comments with actual comments
|
|
105
|
+
for (let i = 0; i < lines.length; i++) {
|
|
106
|
+
const line = lines[i];
|
|
107
|
+
|
|
108
|
+
// Match reference comment pattern (works for different comment styles, including block)
|
|
109
|
+
const refCommentMatch = line.match(/(\/\/|#|--|;|<!--|%|\/\*)\s*#ref\s+(\d+-\d+)\s*(-->|\*\/)?/);
|
|
110
|
+
|
|
111
|
+
if (refCommentMatch) {
|
|
112
|
+
const fullMatch = refCommentMatch[0];
|
|
113
|
+
const prefix = refCommentMatch[1];
|
|
114
|
+
const key = refCommentMatch[2];
|
|
115
|
+
const suffix = refCommentMatch[3] || "";
|
|
116
|
+
const commentText = comments[key];
|
|
117
|
+
|
|
118
|
+
if (commentText) {
|
|
119
|
+
let restoredComment = "";
|
|
120
|
+
|
|
121
|
+
if (prefix === "/*") {
|
|
122
|
+
// Mirror block comment style
|
|
123
|
+
restoredComment = `/* ${commentText} */`;
|
|
124
|
+
} else if (prefix === "<!--") {
|
|
125
|
+
// Mirror HTML comment style
|
|
126
|
+
restoredComment = `<!-- ${commentText} -->`;
|
|
127
|
+
} else {
|
|
128
|
+
// Default to line comment style
|
|
129
|
+
restoredComment = `${prefix} ${commentText}`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Replace only the reference part, preserving everything else on the line
|
|
133
|
+
lines[i] = line.replace(fullMatch, restoredComment);
|
|
134
|
+
} else {
|
|
135
|
+
// Key not found in DB - remove the reference comment part
|
|
136
|
+
lines[i] = line.replace(fullMatch, "").trimEnd();
|
|
137
|
+
// If line is now just whitespace, clear it to preserve line numbers if possible
|
|
138
|
+
if (lines[i].trim().length === 0) lines[i] = "";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Write restored file
|
|
144
|
+
fs.writeFileSync(filePath, lines.join("\n"), "utf8");
|
|
145
|
+
|
|
146
|
+
console.log(`✔ Comments successfully restored from database (codebase: ${codebase})`);
|
|
147
|
+
}
|