247-cli 0.3.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 +112 -0
- package/agent/dist/config.d.ts +29 -0
- package/agent/dist/config.d.ts.map +1 -0
- package/agent/dist/config.js +56 -0
- package/agent/dist/config.js.map +1 -0
- package/agent/dist/db/environments.d.ts +60 -0
- package/agent/dist/db/environments.d.ts.map +1 -0
- package/agent/dist/db/environments.js +235 -0
- package/agent/dist/db/environments.js.map +1 -0
- package/agent/dist/db/history.d.ts +37 -0
- package/agent/dist/db/history.d.ts.map +1 -0
- package/agent/dist/db/history.js +98 -0
- package/agent/dist/db/history.js.map +1 -0
- package/agent/dist/db/index.d.ts +37 -0
- package/agent/dist/db/index.d.ts.map +1 -0
- package/agent/dist/db/index.js +225 -0
- package/agent/dist/db/index.js.map +1 -0
- package/agent/dist/db/schema.d.ts +70 -0
- package/agent/dist/db/schema.d.ts.map +1 -0
- package/agent/dist/db/schema.js +79 -0
- package/agent/dist/db/schema.js.map +1 -0
- package/agent/dist/db/sessions.d.ts +75 -0
- package/agent/dist/db/sessions.d.ts.map +1 -0
- package/agent/dist/db/sessions.js +244 -0
- package/agent/dist/db/sessions.js.map +1 -0
- package/agent/dist/editor.d.ts +18 -0
- package/agent/dist/editor.d.ts.map +1 -0
- package/agent/dist/editor.js +222 -0
- package/agent/dist/editor.js.map +1 -0
- package/agent/dist/environments.d.ts +59 -0
- package/agent/dist/environments.d.ts.map +1 -0
- package/agent/dist/environments.js +229 -0
- package/agent/dist/environments.js.map +1 -0
- package/agent/dist/git.d.ts +39 -0
- package/agent/dist/git.d.ts.map +1 -0
- package/agent/dist/git.js +436 -0
- package/agent/dist/git.js.map +1 -0
- package/agent/dist/index.d.ts +2 -0
- package/agent/dist/index.d.ts.map +1 -0
- package/agent/dist/index.js +18 -0
- package/agent/dist/index.js.map +1 -0
- package/agent/dist/logger.d.ts +15 -0
- package/agent/dist/logger.d.ts.map +1 -0
- package/agent/dist/logger.js +44 -0
- package/agent/dist/logger.js.map +1 -0
- package/agent/dist/routes/editor.d.ts +9 -0
- package/agent/dist/routes/editor.d.ts.map +1 -0
- package/agent/dist/routes/editor.js +63 -0
- package/agent/dist/routes/editor.js.map +1 -0
- package/agent/dist/routes/environments.d.ts +6 -0
- package/agent/dist/routes/environments.d.ts.map +1 -0
- package/agent/dist/routes/environments.js +94 -0
- package/agent/dist/routes/environments.js.map +1 -0
- package/agent/dist/routes/files.d.ts +6 -0
- package/agent/dist/routes/files.d.ts.map +1 -0
- package/agent/dist/routes/files.js +84 -0
- package/agent/dist/routes/files.js.map +1 -0
- package/agent/dist/routes/hooks.d.ts +6 -0
- package/agent/dist/routes/hooks.d.ts.map +1 -0
- package/agent/dist/routes/hooks.js +80 -0
- package/agent/dist/routes/hooks.js.map +1 -0
- package/agent/dist/routes/index.d.ts +10 -0
- package/agent/dist/routes/index.d.ts.map +1 -0
- package/agent/dist/routes/index.js +10 -0
- package/agent/dist/routes/index.js.map +1 -0
- package/agent/dist/routes/projects.d.ts +6 -0
- package/agent/dist/routes/projects.d.ts.map +1 -0
- package/agent/dist/routes/projects.js +69 -0
- package/agent/dist/routes/projects.js.map +1 -0
- package/agent/dist/routes/sessions.d.ts +6 -0
- package/agent/dist/routes/sessions.d.ts.map +1 -0
- package/agent/dist/routes/sessions.js +194 -0
- package/agent/dist/routes/sessions.js.map +1 -0
- package/agent/dist/server.d.ts +6 -0
- package/agent/dist/server.d.ts.map +1 -0
- package/agent/dist/server.js +129 -0
- package/agent/dist/server.js.map +1 -0
- package/agent/dist/status.d.ts +42 -0
- package/agent/dist/status.d.ts.map +1 -0
- package/agent/dist/status.js +134 -0
- package/agent/dist/status.js.map +1 -0
- package/agent/dist/terminal.d.ts +15 -0
- package/agent/dist/terminal.d.ts.map +1 -0
- package/agent/dist/terminal.js +135 -0
- package/agent/dist/terminal.js.map +1 -0
- package/agent/dist/websocket-handlers.d.ts +13 -0
- package/agent/dist/websocket-handlers.d.ts.map +1 -0
- package/agent/dist/websocket-handlers.js +266 -0
- package/agent/dist/websocket-handlers.js.map +1 -0
- package/agent/node_modules/247-shared/dist/index.d.ts +2 -0
- package/agent/node_modules/247-shared/dist/index.d.ts.map +1 -0
- package/agent/node_modules/247-shared/dist/index.js +2 -0
- package/agent/node_modules/247-shared/dist/index.js.map +1 -0
- package/agent/node_modules/247-shared/dist/types/index.d.ts +215 -0
- package/agent/node_modules/247-shared/dist/types/index.d.ts.map +1 -0
- package/agent/node_modules/247-shared/dist/types/index.js +48 -0
- package/agent/node_modules/247-shared/dist/types/index.js.map +1 -0
- package/agent/node_modules/247-shared/package.json +29 -0
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +279 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/hooks.d.ts +3 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +127 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +130 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/logs.d.ts +3 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +38 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/profile.d.ts +3 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +156 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/service.d.ts +3 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +235 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +120 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +62 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +3 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +23 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +121 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/hooks/installer.d.ts +36 -0
- package/dist/hooks/installer.d.ts.map +1 -0
- package/dist/hooks/installer.js +175 -0
- package/dist/hooks/installer.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +71 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +161 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/paths.d.ts +34 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +76 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/prerequisites.d.ts +36 -0
- package/dist/lib/prerequisites.d.ts.map +1 -0
- package/dist/lib/prerequisites.js +181 -0
- package/dist/lib/prerequisites.js.map +1 -0
- package/dist/lib/process.d.ts +40 -0
- package/dist/lib/process.d.ts.map +1 -0
- package/dist/lib/process.js +192 -0
- package/dist/lib/process.js.map +1 -0
- package/dist/service/index.d.ts +44 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +18 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/launchd.d.ts +18 -0
- package/dist/service/launchd.d.ts.map +1 -0
- package/dist/service/launchd.js +208 -0
- package/dist/service/launchd.js.map +1 -0
- package/dist/service/systemd.d.ts +18 -0
- package/dist/service/systemd.d.ts.map +1 -0
- package/dist/service/systemd.js +196 -0
- package/dist/service/systemd.js.map +1 -0
- package/hooks/.claude-plugin/plugin.json +5 -0
- package/hooks/hooks/hooks.json +66 -0
- package/hooks/scripts/check-duplication.sh +91 -0
- package/hooks/scripts/notify-status.sh +89 -0
- package/package.json +77 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import * as fs from 'fs/promises';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
// Check if a directory is a git repository
|
|
8
|
+
export async function isGitRepo(projectPath) {
|
|
9
|
+
try {
|
|
10
|
+
const gitDir = path.join(projectPath, '.git');
|
|
11
|
+
const stat = await fs.stat(gitDir);
|
|
12
|
+
return stat.isDirectory();
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Get git status for all files in a project
|
|
19
|
+
export async function getGitStatus(projectPath) {
|
|
20
|
+
const statusMap = new Map();
|
|
21
|
+
// Check if it's a git repo
|
|
22
|
+
if (!(await isGitRepo(projectPath))) {
|
|
23
|
+
return statusMap;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
// git status --porcelain returns: XY filename
|
|
27
|
+
// X = staged status, Y = working tree status
|
|
28
|
+
const { stdout } = await execAsync('git status --porcelain', {
|
|
29
|
+
cwd: projectPath,
|
|
30
|
+
timeout: 10000,
|
|
31
|
+
});
|
|
32
|
+
const lines = stdout.trim().split('\n').filter(Boolean);
|
|
33
|
+
for (const line of lines) {
|
|
34
|
+
if (line.length < 4)
|
|
35
|
+
continue;
|
|
36
|
+
const statusCode = line.substring(0, 2).trim();
|
|
37
|
+
const filePath = line.substring(3);
|
|
38
|
+
// Determine status from git code
|
|
39
|
+
// M = modified, A = added, D = deleted, ?? = untracked, UU = conflicted
|
|
40
|
+
let status;
|
|
41
|
+
switch (statusCode) {
|
|
42
|
+
case 'M':
|
|
43
|
+
case 'MM':
|
|
44
|
+
case 'AM':
|
|
45
|
+
status = 'modified';
|
|
46
|
+
break;
|
|
47
|
+
case 'A':
|
|
48
|
+
status = 'added';
|
|
49
|
+
break;
|
|
50
|
+
case 'D':
|
|
51
|
+
case 'AD':
|
|
52
|
+
status = 'deleted';
|
|
53
|
+
break;
|
|
54
|
+
case '??':
|
|
55
|
+
status = 'untracked';
|
|
56
|
+
break;
|
|
57
|
+
case 'UU':
|
|
58
|
+
case 'AA':
|
|
59
|
+
case 'DD':
|
|
60
|
+
status = 'conflicted';
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
status = 'modified';
|
|
64
|
+
}
|
|
65
|
+
statusMap.set(filePath, status);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
console.error(`[Git] Failed to get status for ${projectPath}:`, err.message);
|
|
70
|
+
}
|
|
71
|
+
return statusMap;
|
|
72
|
+
}
|
|
73
|
+
// Check if a path should be ignored (node_modules, .git, etc.)
|
|
74
|
+
function shouldIgnore(name, isDir) {
|
|
75
|
+
const ignoredDirs = [
|
|
76
|
+
'node_modules',
|
|
77
|
+
'.git',
|
|
78
|
+
'.next',
|
|
79
|
+
'dist',
|
|
80
|
+
'build',
|
|
81
|
+
'.turbo',
|
|
82
|
+
'coverage',
|
|
83
|
+
'.vscode',
|
|
84
|
+
'.idea',
|
|
85
|
+
];
|
|
86
|
+
const ignoredFiles = [
|
|
87
|
+
'.DS_Store',
|
|
88
|
+
'Thumbs.db',
|
|
89
|
+
'*.log',
|
|
90
|
+
];
|
|
91
|
+
if (isDir && ignoredDirs.includes(name)) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
if (!isDir && ignoredFiles.includes(name)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
// Get file extension for syntax highlighting
|
|
100
|
+
function getFileExtension(filename) {
|
|
101
|
+
const parts = filename.split('.');
|
|
102
|
+
if (parts.length > 1) {
|
|
103
|
+
return parts[parts.length - 1].toLowerCase();
|
|
104
|
+
}
|
|
105
|
+
return '';
|
|
106
|
+
}
|
|
107
|
+
// Recursively build file tree
|
|
108
|
+
async function buildFileTree(dirPath, relativePath, gitStatus) {
|
|
109
|
+
const nodes = [];
|
|
110
|
+
try {
|
|
111
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
112
|
+
// Sort: directories first, then files, both alphabetically
|
|
113
|
+
const sortedEntries = entries.sort((a, b) => {
|
|
114
|
+
if (a.isDirectory() && !b.isDirectory())
|
|
115
|
+
return -1;
|
|
116
|
+
if (!a.isDirectory() && b.isDirectory())
|
|
117
|
+
return 1;
|
|
118
|
+
return a.name.localeCompare(b.name, undefined, { numeric: true });
|
|
119
|
+
});
|
|
120
|
+
for (const entry of sortedEntries) {
|
|
121
|
+
if (shouldIgnore(entry.name, entry.isDirectory())) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const entryRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
125
|
+
const entryFullPath = path.join(dirPath, entry.name);
|
|
126
|
+
if (entry.isDirectory()) {
|
|
127
|
+
// Recursively process directory
|
|
128
|
+
const children = await buildFileTree(entryFullPath, entryRelativePath, gitStatus);
|
|
129
|
+
// Skip empty directories that aren't in git
|
|
130
|
+
if (children.length === 0 && !gitStatus.has(entryRelativePath + '/')) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
// Directory status is derived from children (most "significant" status)
|
|
134
|
+
const dirStatus = getDirectoryStatus(entryRelativePath, gitStatus, children);
|
|
135
|
+
nodes.push({
|
|
136
|
+
path: entryRelativePath,
|
|
137
|
+
name: entry.name,
|
|
138
|
+
type: 'directory',
|
|
139
|
+
status: dirStatus,
|
|
140
|
+
children,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// File node
|
|
145
|
+
nodes.push({
|
|
146
|
+
path: entryRelativePath,
|
|
147
|
+
name: entry.name,
|
|
148
|
+
type: 'file',
|
|
149
|
+
status: gitStatus.get(entryRelativePath),
|
|
150
|
+
extension: getFileExtension(entry.name),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
console.error(`[Git] Failed to read directory ${dirPath}:`, err.message);
|
|
157
|
+
}
|
|
158
|
+
return nodes;
|
|
159
|
+
}
|
|
160
|
+
// Determine directory status based on its contents
|
|
161
|
+
function getDirectoryStatus(dirPath, gitStatus, children) {
|
|
162
|
+
// Check if directory itself has a status (e.g., deleted)
|
|
163
|
+
const dirWithSlash = dirPath + '/';
|
|
164
|
+
if (gitStatus.has(dirWithSlash)) {
|
|
165
|
+
return gitStatus.get(dirWithSlash);
|
|
166
|
+
}
|
|
167
|
+
// Check children for status (priority: conflicted > modified > added > deleted > untracked)
|
|
168
|
+
const statusPriority = ['conflicted', 'modified', 'added', 'deleted', 'untracked'];
|
|
169
|
+
for (const status of statusPriority) {
|
|
170
|
+
const hasChildWithStatus = children.some(child => {
|
|
171
|
+
if (child.status === status)
|
|
172
|
+
return true;
|
|
173
|
+
if (child.children) {
|
|
174
|
+
return child.children.some(c => c.status === status);
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
});
|
|
178
|
+
if (hasChildWithStatus)
|
|
179
|
+
return status;
|
|
180
|
+
}
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
// List all files in a project as a tree
|
|
184
|
+
export async function listFiles(projectPath) {
|
|
185
|
+
// Get git status first
|
|
186
|
+
const gitStatus = await getGitStatus(projectPath);
|
|
187
|
+
// Build file tree
|
|
188
|
+
const tree = await buildFileTree(projectPath, '', gitStatus);
|
|
189
|
+
return tree;
|
|
190
|
+
}
|
|
191
|
+
// Get file content for preview
|
|
192
|
+
export async function getFileContent(projectPath, filePath) {
|
|
193
|
+
const fullPath = path.join(projectPath, filePath);
|
|
194
|
+
try {
|
|
195
|
+
const stats = await fs.stat(fullPath);
|
|
196
|
+
// Check if file is too large (>1MB)
|
|
197
|
+
if (stats.size > 1024 * 1024) {
|
|
198
|
+
return {
|
|
199
|
+
content: '// File too large to preview (>1MB)',
|
|
200
|
+
encoding: 'utf-8',
|
|
201
|
+
size: stats.size,
|
|
202
|
+
isBinary: false,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
// Try to read as text
|
|
206
|
+
const buffer = await fs.readFile(fullPath);
|
|
207
|
+
// Check for binary files (null bytes common in binaries)
|
|
208
|
+
if (buffer.includes(0)) {
|
|
209
|
+
return {
|
|
210
|
+
content: '// Binary file - cannot preview',
|
|
211
|
+
encoding: 'utf-8',
|
|
212
|
+
size: stats.size,
|
|
213
|
+
isBinary: true,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// Convert to string
|
|
217
|
+
const content = buffer.toString('utf-8');
|
|
218
|
+
return {
|
|
219
|
+
content,
|
|
220
|
+
encoding: 'utf-8',
|
|
221
|
+
size: stats.size,
|
|
222
|
+
isBinary: false,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
throw new Error(`Failed to read file: ${err.message}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Open a file in the local editor (VS Code, Cursor, etc.)
|
|
230
|
+
export async function openFileInEditor(projectPath, filePath) {
|
|
231
|
+
const fullPath = path.join(projectPath, filePath);
|
|
232
|
+
// Check file exists
|
|
233
|
+
try {
|
|
234
|
+
await fs.access(fullPath);
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return {
|
|
238
|
+
success: false,
|
|
239
|
+
error: 'File not found',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
// Try different editors in order of preference
|
|
243
|
+
const editors = [
|
|
244
|
+
{ cmd: 'cursor', args: ['--goto'] },
|
|
245
|
+
{ cmd: 'code', args: ['--goto'] },
|
|
246
|
+
{ cmd: 'code', args: [] }, // Fallback without --goto
|
|
247
|
+
{ cmd: 'subl', args: [] },
|
|
248
|
+
{ cmd: 'vim', args: [] },
|
|
249
|
+
];
|
|
250
|
+
for (const editor of editors) {
|
|
251
|
+
try {
|
|
252
|
+
// Check if editor is available
|
|
253
|
+
await execAsync(`which ${editor.cmd}`, { timeout: 1000 });
|
|
254
|
+
// Open file using spawn (detached)
|
|
255
|
+
const args = [...editor.args, fullPath];
|
|
256
|
+
spawn(editor.cmd, args, {
|
|
257
|
+
cwd: projectPath,
|
|
258
|
+
stdio: 'ignore',
|
|
259
|
+
detached: true,
|
|
260
|
+
}).unref();
|
|
261
|
+
return {
|
|
262
|
+
success: true,
|
|
263
|
+
command: editor.cmd,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Editor not available, try next
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
success: false,
|
|
273
|
+
error: 'No suitable editor found (install VS Code, Cursor, or Sublime Text)',
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
// Get summary of changes
|
|
277
|
+
export async function getChangesSummary(projectPath) {
|
|
278
|
+
const gitStatus = await getGitStatus(projectPath);
|
|
279
|
+
const summary = {
|
|
280
|
+
modified: 0,
|
|
281
|
+
added: 0,
|
|
282
|
+
deleted: 0,
|
|
283
|
+
untracked: 0,
|
|
284
|
+
conflicted: 0,
|
|
285
|
+
};
|
|
286
|
+
for (const status of gitStatus.values()) {
|
|
287
|
+
switch (status) {
|
|
288
|
+
case 'modified':
|
|
289
|
+
summary.modified++;
|
|
290
|
+
break;
|
|
291
|
+
case 'added':
|
|
292
|
+
summary.added++;
|
|
293
|
+
break;
|
|
294
|
+
case 'deleted':
|
|
295
|
+
summary.deleted++;
|
|
296
|
+
break;
|
|
297
|
+
case 'untracked':
|
|
298
|
+
summary.untracked++;
|
|
299
|
+
break;
|
|
300
|
+
case 'conflicted':
|
|
301
|
+
summary.conflicted++;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return summary;
|
|
306
|
+
}
|
|
307
|
+
// Validate git URL to prevent injection attacks
|
|
308
|
+
function isValidGitUrl(url) {
|
|
309
|
+
// Allow common git URL formats
|
|
310
|
+
const patterns = [
|
|
311
|
+
// HTTPS URLs
|
|
312
|
+
/^https?:\/\/[\w.-]+\/[\w.-]+\/[\w.-]+(?:\.git)?$/,
|
|
313
|
+
// SSH URLs (git@host:user/repo)
|
|
314
|
+
/^git@[\w.-]+:[\w.-]+\/[\w.-]+(?:\.git)?$/,
|
|
315
|
+
// GitHub shorthand
|
|
316
|
+
/^[\w.-]+\/[\w.-]+$/,
|
|
317
|
+
];
|
|
318
|
+
return patterns.some(pattern => pattern.test(url));
|
|
319
|
+
}
|
|
320
|
+
// Extract project name from git URL
|
|
321
|
+
export function extractProjectName(url) {
|
|
322
|
+
// Remove trailing .git if present
|
|
323
|
+
let cleanUrl = url.replace(/\.git$/, '');
|
|
324
|
+
// Handle different URL formats
|
|
325
|
+
if (cleanUrl.includes(':') && !cleanUrl.includes('://')) {
|
|
326
|
+
// SSH format: git@github.com:user/repo
|
|
327
|
+
cleanUrl = cleanUrl.split(':').pop() || '';
|
|
328
|
+
}
|
|
329
|
+
else if (cleanUrl.includes('://')) {
|
|
330
|
+
// HTTPS format: https://github.com/user/repo
|
|
331
|
+
cleanUrl = cleanUrl.split('/').slice(-2).join('/');
|
|
332
|
+
}
|
|
333
|
+
// Get the last part (repo name)
|
|
334
|
+
const parts = cleanUrl.split('/');
|
|
335
|
+
return parts[parts.length - 1] || 'cloned-repo';
|
|
336
|
+
}
|
|
337
|
+
// Validate project name
|
|
338
|
+
function isValidProjectName(name) {
|
|
339
|
+
// Allow alphanumeric, hyphens, underscores, dots
|
|
340
|
+
return /^[\w.-]+$/.test(name) && name.length > 0 && name.length <= 100;
|
|
341
|
+
}
|
|
342
|
+
// Clone a git repository
|
|
343
|
+
export async function cloneRepo(repoUrl, basePath, projectName) {
|
|
344
|
+
// Validate URL
|
|
345
|
+
if (!isValidGitUrl(repoUrl)) {
|
|
346
|
+
return {
|
|
347
|
+
success: false,
|
|
348
|
+
projectName: '',
|
|
349
|
+
path: '',
|
|
350
|
+
error: 'Invalid git URL format',
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
// Determine project name
|
|
354
|
+
const finalProjectName = projectName || extractProjectName(repoUrl);
|
|
355
|
+
// Validate project name
|
|
356
|
+
if (!isValidProjectName(finalProjectName)) {
|
|
357
|
+
return {
|
|
358
|
+
success: false,
|
|
359
|
+
projectName: finalProjectName,
|
|
360
|
+
path: '',
|
|
361
|
+
error: 'Invalid project name (use alphanumeric, hyphens, underscores)',
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
// Resolve paths
|
|
365
|
+
const resolvedBasePath = basePath.replace('~', process.env.HOME || '');
|
|
366
|
+
const targetPath = path.join(resolvedBasePath, finalProjectName);
|
|
367
|
+
// Check if directory already exists
|
|
368
|
+
try {
|
|
369
|
+
await fs.access(targetPath);
|
|
370
|
+
return {
|
|
371
|
+
success: false,
|
|
372
|
+
projectName: finalProjectName,
|
|
373
|
+
path: targetPath,
|
|
374
|
+
error: `Directory already exists: ${finalProjectName}`,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
// Directory doesn't exist, good to proceed
|
|
379
|
+
}
|
|
380
|
+
// Run git clone
|
|
381
|
+
try {
|
|
382
|
+
console.log(`[Git] Cloning ${repoUrl} to ${targetPath}...`);
|
|
383
|
+
// Use SSH if available, otherwise HTTPS
|
|
384
|
+
// The git command will use the user's SSH keys automatically
|
|
385
|
+
const { stderr } = await execAsync(`git clone "${repoUrl}" "${targetPath}"`, {
|
|
386
|
+
cwd: resolvedBasePath,
|
|
387
|
+
timeout: 300000, // 5 minute timeout for large repos
|
|
388
|
+
});
|
|
389
|
+
// Check for any errors in stderr (git outputs progress to stderr)
|
|
390
|
+
if (stderr && stderr.includes('fatal:')) {
|
|
391
|
+
throw new Error(stderr);
|
|
392
|
+
}
|
|
393
|
+
console.log(`[Git] Successfully cloned ${repoUrl}`);
|
|
394
|
+
return {
|
|
395
|
+
success: true,
|
|
396
|
+
projectName: finalProjectName,
|
|
397
|
+
path: targetPath,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
catch (err) {
|
|
401
|
+
const error = err;
|
|
402
|
+
console.error(`[Git] Clone failed:`, error.message);
|
|
403
|
+
// Clean up partial clone if it exists
|
|
404
|
+
try {
|
|
405
|
+
await fs.rm(targetPath, { recursive: true, force: true });
|
|
406
|
+
}
|
|
407
|
+
catch {
|
|
408
|
+
// Ignore cleanup errors
|
|
409
|
+
}
|
|
410
|
+
// Parse common error messages
|
|
411
|
+
let errorMessage = 'Clone failed';
|
|
412
|
+
const errOutput = error.stderr || error.message || '';
|
|
413
|
+
if (errOutput.includes('Permission denied')) {
|
|
414
|
+
errorMessage = 'Permission denied - check SSH keys or use HTTPS URL';
|
|
415
|
+
}
|
|
416
|
+
else if (errOutput.includes('Repository not found')) {
|
|
417
|
+
errorMessage = 'Repository not found - check URL and access permissions';
|
|
418
|
+
}
|
|
419
|
+
else if (errOutput.includes('Authentication failed')) {
|
|
420
|
+
errorMessage = 'Authentication failed - check credentials';
|
|
421
|
+
}
|
|
422
|
+
else if (errOutput.includes('Could not resolve host')) {
|
|
423
|
+
errorMessage = 'Could not resolve host - check network connection';
|
|
424
|
+
}
|
|
425
|
+
else if (error.message) {
|
|
426
|
+
errorMessage = error.message;
|
|
427
|
+
}
|
|
428
|
+
return {
|
|
429
|
+
success: false,
|
|
430
|
+
projectName: finalProjectName,
|
|
431
|
+
path: targetPath,
|
|
432
|
+
error: errorMessage,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAoBlC,2CAA2C;AAC3C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,WAAmB;IACjD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,4CAA4C;AAC5C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB;IACpD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEnD,2BAA2B;IAC3B,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QACpC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,8CAA8C;QAC9C,6CAA6C;QAC7C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,wBAAwB,EAAE;YAC3D,GAAG,EAAE,WAAW;YAChB,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAExD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS;YAE9B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAEnC,iCAAiC;YACjC,wEAAwE;YACxE,IAAI,MAAqB,CAAC;YAC1B,QAAQ,UAAU,EAAE,CAAC;gBACnB,KAAK,GAAG,CAAC;gBACT,KAAK,IAAI,CAAC;gBACV,KAAK,IAAI;oBACP,MAAM,GAAG,UAAU,CAAC;oBACpB,MAAM;gBACR,KAAK,GAAG;oBACN,MAAM,GAAG,OAAO,CAAC;oBACjB,MAAM;gBACR,KAAK,GAAG,CAAC;gBACT,KAAK,IAAI;oBACP,MAAM,GAAG,SAAS,CAAC;oBACnB,MAAM;gBACR,KAAK,IAAI;oBACP,MAAM,GAAG,WAAW,CAAC;oBACrB,MAAM;gBACR,KAAK,IAAI,CAAC;gBACV,KAAK,IAAI,CAAC;gBACV,KAAK,IAAI;oBACP,MAAM,GAAG,YAAY,CAAC;oBACtB,MAAM;gBACR;oBACE,MAAM,GAAG,UAAU,CAAC;YACxB,CAAC;YAED,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,WAAW,GAAG,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;IAC1F,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+DAA+D;AAC/D,SAAS,YAAY,CAAC,IAAY,EAAE,KAAc;IAChD,MAAM,WAAW,GAAG;QAClB,cAAc;QACd,MAAM;QACN,OAAO;QACP,MAAM;QACN,OAAO;QACP,QAAQ;QACR,UAAU;QACV,SAAS;QACT,OAAO;KACR,CAAC;IAEF,MAAM,YAAY,GAAG;QACnB,WAAW;QACX,WAAW;QACX,OAAO;KACR,CAAC;IAEF,IAAI,KAAK,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,6CAA6C;AAC7C,SAAS,gBAAgB,CAAC,QAAgB;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,8BAA8B;AAC9B,KAAK,UAAU,aAAa,CAC1B,OAAe,EACf,YAAoB,EACpB,SAAqC;IAErC,MAAM,KAAK,GAAe,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAEnE,2DAA2D;QAC3D,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1C,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE;gBAAE,OAAO,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,OAAO,CAAC,CAAC;YAClD,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;YAClC,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAClD,SAAS;YACX,CAAC;YAED,MAAM,iBAAiB,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;YACtF,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAErD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,gCAAgC;gBAChC,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,aAAa,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;gBAElF,4CAA4C;gBAC5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,GAAG,GAAG,CAAC,EAAE,CAAC;oBACrE,SAAS;gBACX,CAAC;gBAED,wEAAwE;gBACxE,MAAM,SAAS,GAAG,kBAAkB,CAAC,iBAAiB,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;gBAE7E,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,SAAS;oBACjB,QAAQ;iBACT,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,YAAY;gBACZ,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,IAAI,EAAE,MAAM;oBACZ,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC;oBACxC,SAAS,EAAE,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC;iBACxC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,OAAO,GAAG,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mDAAmD;AACnD,SAAS,kBAAkB,CACzB,OAAe,EACf,SAAqC,EACrC,QAAoB;IAEpB,yDAAyD;IACzD,MAAM,YAAY,GAAG,OAAO,GAAG,GAAG,CAAC;IACnC,IAAI,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACrC,CAAC;IAED,4FAA4F;IAC5F,MAAM,cAAc,GAAoB,CAAC,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAEpG,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;QACpC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;gBAAE,OAAO,IAAI,CAAC;YACzC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QACH,IAAI,kBAAkB;YAAE,OAAO,MAAM,CAAC;IACxC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,wCAAwC;AACxC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,WAAmB;IACjD,uBAAuB;IACvB,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;IAElD,kBAAkB;IAClB,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;IAE7D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+BAA+B;AAC/B,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB,EAAE,QAAgB;IAMxE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEtC,oCAAoC;QACpC,IAAI,KAAK,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;YAC7B,OAAO;gBACL,OAAO,EAAE,qCAAqC;gBAC9C,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;QAED,sBAAsB;QACtB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE3C,yDAAyD;QACzD,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE,iCAAiC;gBAC1C,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,QAAQ,EAAE,IAAI;aACf,CAAC;QACJ,CAAC;QAED,oBAAoB;QACpB,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAEzC,OAAO;YACL,OAAO;YACP,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wBAAyB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAmB,EAAE,QAAgB;IAK1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAElD,oBAAoB;IACpB,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,gBAAgB;SACxB,CAAC;IACJ,CAAC;IAED,+CAA+C;IAC/C,MAAM,OAAO,GAAG;QACd,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE;QACnC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE;QACjC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,0BAA0B;QACrD,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;QACzB,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;KACzB,CAAC;IAEF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,+BAA+B;YAC/B,MAAM,SAAS,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAE1D,mCAAmC;YACnC,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACxC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE;gBACtB,GAAG,EAAE,WAAW;gBAChB,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC,KAAK,EAAE,CAAC;YAEX,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,MAAM,CAAC,GAAG;aACpB,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;YACjC,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,qEAAqE;KAC7E,CAAC;AACJ,CAAC;AAED,yBAAyB;AACzB,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,WAAmB;IAOzD,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG;QACd,QAAQ,EAAE,CAAC;QACX,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,CAAC;KACd,CAAC;IAEF,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QACxC,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,UAAU;gBACb,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM;YACR,KAAK,OAAO;gBACV,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChB,MAAM;YACR,KAAK,SAAS;gBACZ,OAAO,CAAC,OAAO,EAAE,CAAC;gBAClB,MAAM;YACR,KAAK,WAAW;gBACd,OAAO,CAAC,SAAS,EAAE,CAAC;gBACpB,MAAM;YACR,KAAK,YAAY;gBACf,OAAO,CAAC,UAAU,EAAE,CAAC;gBACrB,MAAM;QACV,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gDAAgD;AAChD,SAAS,aAAa,CAAC,GAAW;IAChC,+BAA+B;IAC/B,MAAM,QAAQ,GAAG;QACf,aAAa;QACb,kDAAkD;QAClD,gCAAgC;QAChC,0CAA0C;QAC1C,mBAAmB;QACnB,oBAAoB;KACrB,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,kCAAkC;IAClC,IAAI,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEzC,+BAA+B;IAC/B,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,uCAAuC;QACvC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAC7C,CAAC;SAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,6CAA6C;QAC7C,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,gCAAgC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,aAAa,CAAC;AAClD,CAAC;AAED,wBAAwB;AACxB,SAAS,kBAAkB,CAAC,IAAY;IACtC,iDAAiD;IACjD,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;AACzE,CAAC;AAED,yBAAyB;AACzB,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAe,EACf,QAAgB,EAChB,WAAoB;IAEpB,eAAe;IACf,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,wBAAwB;SAChC,CAAC;IACJ,CAAC;IAED,yBAAyB;IACzB,MAAM,gBAAgB,GAAG,WAAW,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAEpE,wBAAwB;IACxB,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC1C,OAAO;YACL,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,gBAAgB;YAC7B,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,+DAA+D;SACvE,CAAC;IACJ,CAAC;IAED,gBAAgB;IAChB,MAAM,gBAAgB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;IAEjE,oCAAoC;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5B,OAAO;YACL,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,gBAAgB;YAC7B,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,6BAA6B,gBAAgB,EAAE;SACvD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,2CAA2C;IAC7C,CAAC;IAED,gBAAgB;IAChB,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,iBAAiB,OAAO,OAAO,UAAU,KAAK,CAAC,CAAC;QAE5D,wCAAwC;QACxC,6DAA6D;QAC7D,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAChC,cAAc,OAAO,MAAM,UAAU,GAAG,EACxC;YACE,GAAG,EAAE,gBAAgB;YACrB,OAAO,EAAE,MAAM,EAAE,mCAAmC;SACrD,CACF,CAAC;QAEF,kEAAkE;QAClE,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;QACpD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,gBAAgB;YAC7B,IAAI,EAAE,UAAU;SACjB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,GAAkC,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAEpD,sCAAsC;QACtC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;QAED,8BAA8B;QAC9B,IAAI,YAAY,GAAG,cAAc,CAAC;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;QAEtD,IAAI,SAAS,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5C,YAAY,GAAG,qDAAqD,CAAC;QACvE,CAAC;aAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;YACtD,YAAY,GAAG,yDAAyD,CAAC;QAC3E,CAAC;aAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;YACvD,YAAY,GAAG,2CAA2C,CAAC;QAC7D,CAAC;aAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;YACxD,YAAY,GAAG,mDAAmD,CAAC;QACrE,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACzB,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;QAC/B,CAAC;QAED,OAAO;YACL,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,gBAAgB;YAC7B,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,YAAY;SACpB,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createServer } from './server.js';
|
|
2
|
+
import { config } from './config.js';
|
|
3
|
+
import { logger } from './logger.js';
|
|
4
|
+
const PORT = config.agent?.port || 4678;
|
|
5
|
+
async function main() {
|
|
6
|
+
logger.main.info({ machine: config.machine.name }, 'Starting 247 Agent');
|
|
7
|
+
const server = await createServer();
|
|
8
|
+
server.listen(PORT, () => {
|
|
9
|
+
logger.main.info({ port: PORT }, 'Agent running');
|
|
10
|
+
logger.main.info({ url: `ws://localhost:${PORT}` }, 'Dashboard connection URL');
|
|
11
|
+
logger.main.info('For remote access, use Tailscale Funnel, Cloudflare Tunnel, or SSH tunnel');
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
main().catch((err) => {
|
|
15
|
+
logger.main.error(err, 'Agent startup failed');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
});
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC;AAExC,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAEzE,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IAEpC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACvB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,kBAAkB,IAAI,EAAE,EAAE,EAAE,0BAA0B,CAAC,CAAC;QAChF,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
export declare const logger: {
|
|
3
|
+
main: pino.Logger<never, boolean>;
|
|
4
|
+
server: pino.Logger<never, boolean>;
|
|
5
|
+
db: pino.Logger<never, boolean>;
|
|
6
|
+
session: pino.Logger<never, boolean>;
|
|
7
|
+
terminal: pino.Logger<never, boolean>;
|
|
8
|
+
editor: pino.Logger<never, boolean>;
|
|
9
|
+
git: pino.Logger<never, boolean>;
|
|
10
|
+
env: pino.Logger<never, boolean>;
|
|
11
|
+
connections: pino.Logger<never, boolean>;
|
|
12
|
+
hooks: pino.Logger<never, boolean>;
|
|
13
|
+
};
|
|
14
|
+
export default logger;
|
|
15
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAwBxB,eAAO,MAAM,MAAM;;;;;;;;;;;CA8BlB,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
// Get log level from environment or default to 'info'
|
|
3
|
+
const level = process.env.LOG_LEVEL || 'info';
|
|
4
|
+
// Check if we're in development mode (for pretty printing)
|
|
5
|
+
const isDev = process.env.NODE_ENV !== 'production';
|
|
6
|
+
// Create base logger
|
|
7
|
+
const baseLogger = pino({
|
|
8
|
+
level,
|
|
9
|
+
...(isDev && {
|
|
10
|
+
transport: {
|
|
11
|
+
target: 'pino-pretty',
|
|
12
|
+
options: {
|
|
13
|
+
colorize: true,
|
|
14
|
+
translateTime: 'HH:MM:ss',
|
|
15
|
+
ignore: 'pid,hostname',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
// Create child loggers for each module
|
|
21
|
+
export const logger = {
|
|
22
|
+
// Main logger for generic messages
|
|
23
|
+
main: baseLogger,
|
|
24
|
+
// Server/API related logs
|
|
25
|
+
server: baseLogger.child({ module: 'Server' }),
|
|
26
|
+
// Database related logs
|
|
27
|
+
db: baseLogger.child({ module: 'DB' }),
|
|
28
|
+
// Session management logs
|
|
29
|
+
session: baseLogger.child({ module: 'Session' }),
|
|
30
|
+
// Terminal/PTY related logs
|
|
31
|
+
terminal: baseLogger.child({ module: 'Terminal' }),
|
|
32
|
+
// Editor (code-server) related logs
|
|
33
|
+
editor: baseLogger.child({ module: 'Editor' }),
|
|
34
|
+
// Git operations logs
|
|
35
|
+
git: baseLogger.child({ module: 'Git' }),
|
|
36
|
+
// Environment management logs
|
|
37
|
+
env: baseLogger.child({ module: 'Environments' }),
|
|
38
|
+
// Connection management logs
|
|
39
|
+
connections: baseLogger.child({ module: 'Connections' }),
|
|
40
|
+
// Hook status logs
|
|
41
|
+
hooks: baseLogger.child({ module: 'Hooks' }),
|
|
42
|
+
};
|
|
43
|
+
export default logger;
|
|
44
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,sDAAsD;AACtD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,CAAC;AAE9C,2DAA2D;AAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAEpD,qBAAqB;AACrB,MAAM,UAAU,GAAG,IAAI,CAAC;IACtB,KAAK;IACL,GAAG,CAAC,KAAK,IAAI;QACX,SAAS,EAAE;YACT,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE;gBACP,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,UAAU;gBACzB,MAAM,EAAE,cAAc;aACvB;SACF;KACF,CAAC;CACH,CAAC,CAAC;AAEH,uCAAuC;AACvC,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,mCAAmC;IACnC,IAAI,EAAE,UAAU;IAEhB,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAE9C,wBAAwB;IACxB,EAAE,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAEtC,0BAA0B;IAC1B,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAEhD,4BAA4B;IAC5B,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAElD,oCAAoC;IACpC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAE9C,sBAAsB;IACtB,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAExC,8BAA8B;IAC9B,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAEjD,6BAA6B;IAC7B,WAAW,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAExD,mBAAmB;IACnB,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;CAC7C,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editor API routes: start/stop code-server, status checks.
|
|
3
|
+
*/
|
|
4
|
+
import { Router } from 'express';
|
|
5
|
+
import { getOrStartEditor, updateEditorActivity } from '../editor.js';
|
|
6
|
+
export declare function isProjectAllowed(project: string): boolean;
|
|
7
|
+
export declare function createEditorRoutes(): Router;
|
|
8
|
+
export { updateEditorActivity, getOrStartEditor };
|
|
9
|
+
//# sourceMappingURL=editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/routes/editor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,OAAO,EACL,gBAAgB,EAIhB,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAGtB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CA0D3C;AAGD,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editor API routes: start/stop code-server, status checks.
|
|
3
|
+
*/
|
|
4
|
+
import { Router } from 'express';
|
|
5
|
+
import { config } from '../config.js';
|
|
6
|
+
import { getOrStartEditor, stopEditor, getEditorStatus, getAllEditors, updateEditorActivity, } from '../editor.js';
|
|
7
|
+
// Helper to check if project is allowed (whitelist empty = allow any)
|
|
8
|
+
export function isProjectAllowed(project) {
|
|
9
|
+
const whitelist = config.projects.whitelist;
|
|
10
|
+
const hasWhitelist = whitelist && whitelist.length > 0;
|
|
11
|
+
return hasWhitelist ? whitelist.includes(project) : true;
|
|
12
|
+
}
|
|
13
|
+
export function createEditorRoutes() {
|
|
14
|
+
const router = Router();
|
|
15
|
+
const typedConfig = config;
|
|
16
|
+
// Get editor status for a project
|
|
17
|
+
router.get('/:project/status', (req, res) => {
|
|
18
|
+
const { project } = req.params;
|
|
19
|
+
if (!isProjectAllowed(project)) {
|
|
20
|
+
return res.status(403).json({ error: 'Project not allowed' });
|
|
21
|
+
}
|
|
22
|
+
res.json(getEditorStatus(project));
|
|
23
|
+
});
|
|
24
|
+
// Start editor for a project
|
|
25
|
+
router.post('/:project/start', async (req, res) => {
|
|
26
|
+
const { project } = req.params;
|
|
27
|
+
if (!isProjectAllowed(project)) {
|
|
28
|
+
return res.status(403).json({ error: 'Project not allowed' });
|
|
29
|
+
}
|
|
30
|
+
if (!typedConfig.editor?.enabled) {
|
|
31
|
+
return res.status(400).json({ error: 'Editor is disabled in config' });
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const editor = await getOrStartEditor(project);
|
|
35
|
+
res.json({
|
|
36
|
+
success: true,
|
|
37
|
+
port: editor.port,
|
|
38
|
+
startedAt: editor.startedAt,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
console.error('[Editor] Failed to start:', err);
|
|
43
|
+
res.status(500).json({ error: 'Failed to start editor', message: err.message });
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
// Stop editor for a project
|
|
47
|
+
router.post('/:project/stop', (req, res) => {
|
|
48
|
+
const { project } = req.params;
|
|
49
|
+
if (!isProjectAllowed(project)) {
|
|
50
|
+
return res.status(403).json({ error: 'Project not allowed' });
|
|
51
|
+
}
|
|
52
|
+
const stopped = stopEditor(project);
|
|
53
|
+
res.json({ success: stopped });
|
|
54
|
+
});
|
|
55
|
+
// List all running editors
|
|
56
|
+
router.get('/', (_req, res) => {
|
|
57
|
+
res.json(getAllEditors());
|
|
58
|
+
});
|
|
59
|
+
return router;
|
|
60
|
+
}
|
|
61
|
+
// Export helper for proxy middleware
|
|
62
|
+
export { updateEditorActivity, getOrStartEditor };
|
|
63
|
+
//# sourceMappingURL=editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/routes/editor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,sEAAsE;AACtE,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAqB,CAAC;IACxD,MAAM,YAAY,GAAG,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IACvD,OAAO,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,MAAM,WAAW,GAAG,MAAgC,CAAC;IAErD,kCAAkC;IAClC,MAAM,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC1C,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QAE/B,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAChD,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QAE/B,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YACjC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC;gBACP,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;YAChD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,OAAO,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,4BAA4B;IAC5B,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACzC,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QAE/B,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QACpC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,2BAA2B;IAC3B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qCAAqC;AACrC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../../src/routes/environments.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAUjC,wBAAgB,uBAAuB,IAAI,MAAM,CAiGhD"}
|