code-mon-config 1.0.7 ā 1.0.8
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/index.js +262 -50
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -9,6 +9,7 @@ const open = require("open");
|
|
|
9
9
|
const WebSocket = require("ws");
|
|
10
10
|
|
|
11
11
|
const app = express();
|
|
12
|
+
|
|
12
13
|
app.use(cors());
|
|
13
14
|
app.use(express.json());
|
|
14
15
|
|
|
@@ -16,162 +17,373 @@ const PORT = 3000;
|
|
|
16
17
|
const ROOT = process.cwd();
|
|
17
18
|
|
|
18
19
|
/* ---------------- PROCESS MANAGER ---------------- */
|
|
20
|
+
|
|
19
21
|
let processes = {};
|
|
20
22
|
let processId = 0;
|
|
21
23
|
|
|
24
|
+
/* ---------------- SAFE PATH ---------------- */
|
|
25
|
+
|
|
26
|
+
function safePath(filename) {
|
|
27
|
+
|
|
28
|
+
if (!filename) {
|
|
29
|
+
throw new Error("Filename required");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const resolved = path.join(ROOT, filename);
|
|
33
|
+
|
|
34
|
+
if (!resolved.startsWith(ROOT)) {
|
|
35
|
+
throw new Error("Invalid path");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return resolved;
|
|
39
|
+
}
|
|
40
|
+
|
|
22
41
|
/* ---------------- FILE TREE ---------------- */
|
|
42
|
+
|
|
23
43
|
function getTree(dir, base = "") {
|
|
44
|
+
|
|
24
45
|
let results = [];
|
|
25
46
|
const list = fs.readdirSync(dir);
|
|
26
47
|
|
|
27
48
|
list.forEach(file => {
|
|
49
|
+
|
|
28
50
|
const full = path.join(dir, file);
|
|
29
51
|
const rel = path.join(base, file);
|
|
30
52
|
const stat = fs.statSync(full);
|
|
31
53
|
|
|
32
54
|
if (stat.isDirectory()) {
|
|
55
|
+
|
|
33
56
|
results.push(rel + "/");
|
|
34
57
|
results = results.concat(getTree(full, rel));
|
|
58
|
+
|
|
35
59
|
} else {
|
|
60
|
+
|
|
36
61
|
results.push(rel);
|
|
62
|
+
|
|
37
63
|
}
|
|
64
|
+
|
|
38
65
|
});
|
|
39
66
|
|
|
40
67
|
return results;
|
|
41
68
|
}
|
|
42
69
|
|
|
43
70
|
/* ---------------- FILE APIs ---------------- */
|
|
71
|
+
|
|
44
72
|
app.get("/list", (req, res) => {
|
|
73
|
+
|
|
45
74
|
try {
|
|
75
|
+
|
|
46
76
|
const tree = getTree(ROOT);
|
|
47
|
-
|
|
77
|
+
|
|
78
|
+
res.json({
|
|
79
|
+
root: ROOT,
|
|
80
|
+
files: tree
|
|
81
|
+
});
|
|
82
|
+
|
|
48
83
|
} catch (err) {
|
|
84
|
+
|
|
49
85
|
res.json({ error: err.message });
|
|
86
|
+
|
|
50
87
|
}
|
|
88
|
+
|
|
51
89
|
});
|
|
52
90
|
|
|
91
|
+
/* LOAD FILE */
|
|
92
|
+
|
|
53
93
|
app.get("/load", (req, res) => {
|
|
54
|
-
const filename = req.query.filename;
|
|
55
|
-
const filePath = path.join(ROOT, filename);
|
|
56
94
|
|
|
57
|
-
|
|
95
|
+
try {
|
|
96
|
+
|
|
97
|
+
const filename = req.query.filename;
|
|
98
|
+
const filePath = safePath(filename);
|
|
99
|
+
|
|
100
|
+
if (!fs.existsSync(filePath)) {
|
|
101
|
+
return res.json({ error: "File not found" });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
105
|
+
|
|
106
|
+
res.json({ content });
|
|
107
|
+
|
|
108
|
+
} catch (err) {
|
|
109
|
+
|
|
110
|
+
res.json({ error: err.message });
|
|
111
|
+
|
|
112
|
+
}
|
|
58
113
|
|
|
59
|
-
const content = fs.readFileSync(filePath, "utf8");
|
|
60
|
-
res.json({ content });
|
|
61
114
|
});
|
|
62
115
|
|
|
116
|
+
/* SAVE FILE */
|
|
117
|
+
|
|
63
118
|
app.post("/save", (req, res) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
|
|
122
|
+
const { filename, content } = req.body;
|
|
123
|
+
|
|
124
|
+
const filePath = safePath(filename);
|
|
125
|
+
|
|
126
|
+
fs.writeFileSync(filePath, content || "");
|
|
127
|
+
|
|
128
|
+
res.json({ success: true });
|
|
129
|
+
|
|
130
|
+
} catch (err) {
|
|
131
|
+
|
|
132
|
+
res.json({ error: err.message });
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
68
136
|
});
|
|
69
137
|
|
|
138
|
+
/* CREATE FILE */
|
|
139
|
+
|
|
70
140
|
app.post("/create", (req, res) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
|
|
144
|
+
const { filename } = req.body;
|
|
145
|
+
|
|
146
|
+
const filePath = safePath(filename);
|
|
147
|
+
|
|
148
|
+
fs.writeFileSync(filePath, "");
|
|
149
|
+
|
|
150
|
+
res.json({ success: true });
|
|
151
|
+
|
|
152
|
+
} catch (err) {
|
|
153
|
+
|
|
154
|
+
res.json({ error: err.message });
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
75
158
|
});
|
|
76
159
|
|
|
160
|
+
/* DELETE FILE */
|
|
161
|
+
|
|
77
162
|
app.delete("/delete", (req, res) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
|
|
166
|
+
const { filename } = req.body;
|
|
167
|
+
|
|
168
|
+
const filePath = safePath(filename);
|
|
169
|
+
|
|
170
|
+
if (fs.existsSync(filePath)) {
|
|
171
|
+
fs.unlinkSync(filePath);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
res.json({ success: true });
|
|
175
|
+
|
|
176
|
+
} catch (err) {
|
|
177
|
+
|
|
178
|
+
res.json({ error: err.message });
|
|
179
|
+
|
|
180
|
+
}
|
|
181
|
+
|
|
82
182
|
});
|
|
83
183
|
|
|
84
184
|
/* ---------------- EXECUTE COMMAND ---------------- */
|
|
185
|
+
|
|
85
186
|
app.post("/execute", (req, res) => {
|
|
86
|
-
const { command } = req.body;
|
|
87
|
-
if (!command) return res.json({ error: "Command required" });
|
|
88
187
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
processes[id] = proc;
|
|
188
|
+
try {
|
|
189
|
+
|
|
190
|
+
const { command } = req.body;
|
|
93
191
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
192
|
+
if (!command) {
|
|
193
|
+
return res.json({ error: "Command required" });
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const parts = command.split(" ");
|
|
197
|
+
|
|
198
|
+
const proc = spawn(parts[0], parts.slice(1), {
|
|
199
|
+
cwd: ROOT,
|
|
200
|
+
shell: true
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const id = processId++;
|
|
204
|
+
|
|
205
|
+
processes[id] = proc;
|
|
206
|
+
|
|
207
|
+
proc.stdout.on("data", data => {
|
|
208
|
+
console.log(`[${id}]`, data.toString());
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
proc.stderr.on("data", data => {
|
|
212
|
+
console.error(`[${id}]`, data.toString());
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
proc.on("close", code => {
|
|
216
|
+
|
|
217
|
+
delete processes[id];
|
|
218
|
+
|
|
219
|
+
console.log(`Process ${id} exited`);
|
|
220
|
+
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
res.json({
|
|
224
|
+
success: true,
|
|
225
|
+
processId: id
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
} catch (err) {
|
|
229
|
+
|
|
230
|
+
res.json({ error: err.message });
|
|
231
|
+
|
|
232
|
+
}
|
|
100
233
|
|
|
101
|
-
res.json({ success: true, processId: id });
|
|
102
234
|
});
|
|
103
235
|
|
|
104
236
|
/* ---------------- PROCESS LIST ---------------- */
|
|
237
|
+
|
|
105
238
|
app.get("/processes", (req, res) => {
|
|
106
|
-
|
|
239
|
+
|
|
240
|
+
const list = Object.keys(processes).map(id => ({
|
|
241
|
+
id
|
|
242
|
+
}));
|
|
243
|
+
|
|
107
244
|
res.json(list);
|
|
245
|
+
|
|
108
246
|
});
|
|
109
247
|
|
|
110
248
|
/* ---------------- STOP PROCESS ---------------- */
|
|
249
|
+
|
|
111
250
|
app.post("/stop-process", (req, res) => {
|
|
112
|
-
const { id } = req.body;
|
|
113
|
-
if (!processes[id]) return res.json({ error: "Process not found" });
|
|
114
251
|
|
|
115
|
-
|
|
116
|
-
|
|
252
|
+
try {
|
|
253
|
+
|
|
254
|
+
const { id } = req.body;
|
|
255
|
+
|
|
256
|
+
if (!processes[id]) {
|
|
257
|
+
return res.json({ error: "Process not found" });
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
processes[id].kill();
|
|
261
|
+
|
|
262
|
+
delete processes[id];
|
|
263
|
+
|
|
264
|
+
res.json({
|
|
265
|
+
success: true,
|
|
266
|
+
message: "Process stopped"
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
} catch (err) {
|
|
270
|
+
|
|
271
|
+
res.json({ error: err.message });
|
|
272
|
+
|
|
273
|
+
}
|
|
117
274
|
|
|
118
|
-
res.json({ success: true, message: "Process stopped" });
|
|
119
275
|
});
|
|
120
276
|
|
|
121
277
|
/* ---------------- EXTENSION LOADER ---------------- */
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
278
|
+
|
|
279
|
+
const EXTENSIONS_DIR = path.join(ROOT, "extensions");
|
|
280
|
+
|
|
281
|
+
if (fs.existsSync(EXTENSIONS_DIR)) {
|
|
282
|
+
|
|
283
|
+
fs.readdirSync(EXTENSIONS_DIR).forEach(file => {
|
|
284
|
+
|
|
125
285
|
if (file.endsWith(".js")) {
|
|
286
|
+
|
|
126
287
|
try {
|
|
127
|
-
|
|
288
|
+
|
|
289
|
+
require(path.join(EXTENSIONS_DIR, file))({
|
|
290
|
+
app,
|
|
291
|
+
ROOT,
|
|
292
|
+
spawn,
|
|
293
|
+
processes
|
|
294
|
+
});
|
|
295
|
+
|
|
128
296
|
console.log(`š Loaded extension: ${file}`);
|
|
129
|
-
|
|
130
|
-
|
|
297
|
+
|
|
298
|
+
} catch (err) {
|
|
299
|
+
|
|
300
|
+
console.log(`ā Failed to load extension: ${file}`);
|
|
301
|
+
|
|
131
302
|
}
|
|
303
|
+
|
|
132
304
|
}
|
|
305
|
+
|
|
133
306
|
});
|
|
307
|
+
|
|
134
308
|
}
|
|
135
309
|
|
|
136
310
|
/* ---------------- START SERVER ---------------- */
|
|
311
|
+
|
|
137
312
|
const server = app.listen(PORT, async () => {
|
|
138
|
-
|
|
313
|
+
|
|
314
|
+
console.log("\nš Code Mon Config Starting...\n");
|
|
315
|
+
|
|
139
316
|
console.log("š Connected Folder:", ROOT);
|
|
317
|
+
|
|
140
318
|
console.log("\nā
Your terminal has been connected with Code Mon Code Space\n");
|
|
141
319
|
|
|
142
|
-
const url =
|
|
320
|
+
const url = "http://localhost:3000";
|
|
321
|
+
|
|
143
322
|
console.log("š Opening:", url);
|
|
144
|
-
|
|
323
|
+
|
|
324
|
+
try {
|
|
325
|
+
|
|
326
|
+
await open(url);
|
|
327
|
+
|
|
328
|
+
} catch {
|
|
329
|
+
|
|
330
|
+
console.log("Open manually:", url);
|
|
331
|
+
|
|
332
|
+
}
|
|
333
|
+
|
|
145
334
|
});
|
|
146
335
|
|
|
147
336
|
/* ---------------- WEBSOCKET TERMINAL ---------------- */
|
|
337
|
+
|
|
148
338
|
const wss = new WebSocket.Server({ server });
|
|
149
339
|
|
|
150
340
|
wss.on("connection", ws => {
|
|
341
|
+
|
|
151
342
|
console.log("š¢ Terminal connected");
|
|
152
343
|
|
|
153
344
|
let proc;
|
|
345
|
+
|
|
154
346
|
ws.on("message", msg => {
|
|
347
|
+
|
|
155
348
|
const command = msg.toString();
|
|
156
349
|
|
|
157
350
|
if (!proc) {
|
|
158
|
-
proc = spawn(command, { cwd: ROOT, shell: true });
|
|
159
351
|
|
|
160
|
-
proc
|
|
161
|
-
|
|
352
|
+
proc = spawn(command, {
|
|
353
|
+
cwd: ROOT,
|
|
354
|
+
shell: true
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
proc.stdout.on("data", data => {
|
|
358
|
+
ws.send(data.toString());
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
proc.stderr.on("data", data => {
|
|
362
|
+
ws.send(data.toString());
|
|
363
|
+
});
|
|
162
364
|
|
|
163
365
|
proc.on("close", code => {
|
|
366
|
+
|
|
164
367
|
ws.send(`\nProcess exited with code ${code}\n`);
|
|
368
|
+
|
|
165
369
|
proc = null;
|
|
370
|
+
|
|
166
371
|
});
|
|
167
372
|
|
|
168
373
|
} else {
|
|
169
|
-
|
|
374
|
+
|
|
375
|
+
proc.stdin.write(command + "\n");
|
|
376
|
+
|
|
170
377
|
}
|
|
378
|
+
|
|
171
379
|
});
|
|
172
380
|
|
|
173
381
|
ws.on("close", () => {
|
|
382
|
+
|
|
174
383
|
if (proc) proc.kill();
|
|
384
|
+
|
|
175
385
|
console.log("š“ Terminal disconnected");
|
|
386
|
+
|
|
176
387
|
});
|
|
388
|
+
|
|
177
389
|
});
|