@ts47andres/exeggutor 1.1.2
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/LICENSE +201 -0
- package/README.md +230 -0
- package/bin/exeggutor.js +217 -0
- package/package.json +63 -0
- package/packages/backend/dist/gitWorktree.js +336 -0
- package/packages/backend/dist/index.js +538 -0
- package/packages/backend/dist/ptyManager.js +409 -0
- package/packages/backend/dist/tailscale.js +145 -0
- package/packages/backend/dist/workspaceDb.js +152 -0
- package/packages/backend/git-wrapper/git +60 -0
- package/packages/backend/native/FolderPicker.cs +139 -0
- package/packages/backend/package.json +25 -0
- package/packages/backend/scripts/compile-picker.js +61 -0
- package/packages/backend/scripts/git-guard.ps1 +48 -0
- package/packages/backend/src/gitWorktree.ts +320 -0
- package/packages/backend/src/index.ts +554 -0
- package/packages/backend/src/ptyManager.ts +414 -0
- package/packages/backend/src/tailscale.ts +138 -0
- package/packages/backend/src/workspaceDb.ts +151 -0
- package/packages/frontend/dist/assets/index-B3TWNlss.css +47 -0
- package/packages/frontend/dist/assets/index-DfUyE-fY.js +192 -0
- package/packages/frontend/dist/index.html +17 -0
- package/packages/frontend/package.json +29 -0
- package/src/autostart.js +162 -0
- package/src/cli.js +613 -0
- package/src/server-manager.js +139 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en" class="h-full bg-dark-900 text-slate-100">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='20' fill='%23000000'/%3E%3Ctext x='20' y='70' fill='white' font-family='monospace' font-size='60' font-weight='bold'%3E%26gt;_%3C/text%3E%3C/svg%3E" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Exeggutor</title>
|
|
8
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
|
+
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-DfUyE-fY.js"></script>
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B3TWNlss.css">
|
|
13
|
+
</head>
|
|
14
|
+
<body class="h-full antialiased selection:bg-white/30 selection:text-white overflow-hidden">
|
|
15
|
+
<div id="root" class="h-full"></div>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "frontend",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"lucide-react": "^0.395.0",
|
|
13
|
+
"react": "^18.3.1",
|
|
14
|
+
"react-dom": "^18.3.1",
|
|
15
|
+
"react-mosaic-component": "^6.1.1",
|
|
16
|
+
"xterm": "^5.3.0",
|
|
17
|
+
"xterm-addon-fit": "^0.8.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/react": "^18.3.3",
|
|
21
|
+
"@types/react-dom": "^18.3.0",
|
|
22
|
+
"@vitejs/plugin-react": "^4.3.1",
|
|
23
|
+
"autoprefixer": "^10.4.19",
|
|
24
|
+
"postcss": "^8.4.38",
|
|
25
|
+
"tailwindcss": "^3.4.4",
|
|
26
|
+
"typescript": "^5.2.2",
|
|
27
|
+
"vite": "^5.3.1"
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/autostart.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Exeggutor Autostart Manager.
|
|
2
|
+
// Installs or removes system-level auto-start configurations so that
|
|
3
|
+
// Exeggutor launches automatically when the user logs in.
|
|
4
|
+
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
const { existsSync, writeFileSync, unlinkSync, readFileSync } = require('fs');
|
|
7
|
+
const { resolve } = require('os');
|
|
8
|
+
const { homedir } = require('os');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const PLATFORM = process.platform;
|
|
12
|
+
|
|
13
|
+
// Installs the auto-start service for the current platform.
|
|
14
|
+
async function install(root) {
|
|
15
|
+
const exePath = process.execPath; // Full path to node executable
|
|
16
|
+
const cliPath = path.resolve(root, 'bin', 'exeggutor.js');
|
|
17
|
+
|
|
18
|
+
if (PLATFORM === 'win32') {
|
|
19
|
+
await installWindows(exePath, cliPath, root);
|
|
20
|
+
} else if (PLATFORM === 'darwin') {
|
|
21
|
+
await installMacOS(exePath, cliPath, root);
|
|
22
|
+
} else {
|
|
23
|
+
await installLinux(exePath, cliPath, root);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Removes the auto-start service for the current platform.
|
|
28
|
+
async function remove() {
|
|
29
|
+
if (PLATFORM === 'win32') {
|
|
30
|
+
await removeWindows();
|
|
31
|
+
} else if (PLATFORM === 'darwin') {
|
|
32
|
+
await removeMacOS();
|
|
33
|
+
} else {
|
|
34
|
+
await removeLinux();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Windows: creates a scheduled task to run on user logon.
|
|
39
|
+
async function installWindows(exePath, cliPath, root) {
|
|
40
|
+
const taskName = 'ExeggutorAutoStart';
|
|
41
|
+
const cmd = `schtasks /Create /TN "${taskName}" /TR "${exePath} ${cliPath}" /SC ONLOGON /DELAY 0000:15 /IT /RL HIGHEST /F`;
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
execSync(cmd, { stdio: 'pipe' });
|
|
45
|
+
console.log(`Scheduled task "${taskName}" created for user logon.`);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
// Try without /IT if it fails
|
|
48
|
+
try {
|
|
49
|
+
const fallbackCmd = `schtasks /Create /TN "${taskName}" /TR "${exePath} ${cliPath}" /SC ONLOGON /DELAY 0000:15 /RL HIGHEST /F`;
|
|
50
|
+
execSync(fallbackCmd, { stdio: 'pipe' });
|
|
51
|
+
console.log(`Scheduled task "${taskName}" created.`);
|
|
52
|
+
} catch (innerErr) {
|
|
53
|
+
throw new Error(`Failed to create scheduled task: ${innerErr.stderr ? innerErr.stderr.toString() : innerErr.message}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Windows: removes the scheduled task.
|
|
59
|
+
async function removeWindows() {
|
|
60
|
+
const taskName = 'ExeggutorAutoStart';
|
|
61
|
+
try {
|
|
62
|
+
execSync(`schtasks /Delete /TN "${taskName}" /F`, { stdio: 'pipe' });
|
|
63
|
+
console.log(`Scheduled task "${taskName}" removed.`);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
throw new Error(`Failed to remove scheduled task: ${err.stderr ? err.stderr.toString() : err.message}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// macOS: creates a launchd plist in ~/Library/LaunchAgents.
|
|
70
|
+
async function installMacOS(exePath, cliPath, root) {
|
|
71
|
+
const plistName = 'com.exeggutor.plist';
|
|
72
|
+
const plistPath = path.resolve(homedir(), 'Library', 'LaunchAgents', plistName);
|
|
73
|
+
|
|
74
|
+
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
75
|
+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
76
|
+
<plist version="1.0">
|
|
77
|
+
<dict>
|
|
78
|
+
<key>Label</key>
|
|
79
|
+
<string>com.exeggutor</string>
|
|
80
|
+
<key>ProgramArguments</key>
|
|
81
|
+
<array>
|
|
82
|
+
<string>${exePath}</string>
|
|
83
|
+
<string>${cliPath}</string>
|
|
84
|
+
</array>
|
|
85
|
+
<key>RunAtLoad</key>
|
|
86
|
+
<true/>
|
|
87
|
+
<key>KeepAlive</key>
|
|
88
|
+
<false/>
|
|
89
|
+
<key>WorkingDirectory</key>
|
|
90
|
+
<string>${root}</string>
|
|
91
|
+
<key>StandardOutPath</key>
|
|
92
|
+
<string>${homedir()}/.exeggutor-logs/autostart.log</string>
|
|
93
|
+
<key>StandardErrorPath</key>
|
|
94
|
+
<string>${homedir()}/.exeggutor-logs/autostart.log</string>
|
|
95
|
+
</dict>
|
|
96
|
+
</plist>`;
|
|
97
|
+
|
|
98
|
+
writeFileSync(plistPath, plistContent, 'utf8');
|
|
99
|
+
execSync(`launchctl load "${plistPath}"`, { stdio: 'pipe' });
|
|
100
|
+
console.log(`LaunchAgent installed at ${plistPath}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// macOS: unloads and removes the plist.
|
|
104
|
+
async function removeMacOS() {
|
|
105
|
+
const plistName = 'com.exeggutor.plist';
|
|
106
|
+
const plistPath = path.resolve(homedir(), 'Library', 'LaunchAgents', plistName);
|
|
107
|
+
|
|
108
|
+
if (existsSync(plistPath)) {
|
|
109
|
+
try {
|
|
110
|
+
execSync(`launchctl unload "${plistPath}"`, { stdio: 'pipe' });
|
|
111
|
+
} catch { /* ok */ }
|
|
112
|
+
unlinkSync(plistPath);
|
|
113
|
+
console.log('LaunchAgent removed.');
|
|
114
|
+
} else {
|
|
115
|
+
console.log('No LaunchAgent found.');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Linux: creates a systemd user service.
|
|
120
|
+
async function installLinux(exePath, cliPath, root) {
|
|
121
|
+
const serviceName = 'exeggutor.service';
|
|
122
|
+
const serviceDir = path.resolve(homedir(), '.config', 'systemd', 'user');
|
|
123
|
+
const servicePath = path.resolve(serviceDir, serviceName);
|
|
124
|
+
|
|
125
|
+
const unitContent = `[Unit]
|
|
126
|
+
Description=Exeggutor Terminal Multiplexer
|
|
127
|
+
After=network.target
|
|
128
|
+
|
|
129
|
+
[Service]
|
|
130
|
+
Type=oneshot
|
|
131
|
+
ExecStart=${exePath} ${cliPath}
|
|
132
|
+
WorkingDirectory=${root}
|
|
133
|
+
RemainAfterExit=yes
|
|
134
|
+
|
|
135
|
+
[Install]
|
|
136
|
+
WantedBy=default.target
|
|
137
|
+
`;
|
|
138
|
+
|
|
139
|
+
if (!existsSync(serviceDir)) {
|
|
140
|
+
require('fs').mkdirSync(serviceDir, { recursive: true });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
writeFileSync(servicePath, unitContent, 'utf8');
|
|
144
|
+
execSync(`systemctl --user daemon-reload`, { stdio: 'pipe' });
|
|
145
|
+
execSync(`systemctl --user enable ${serviceName}`, { stdio: 'pipe' });
|
|
146
|
+
console.log(`Systemd user service installed at ${servicePath}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Linux: disables and removes the systemd service.
|
|
150
|
+
async function removeLinux() {
|
|
151
|
+
const serviceName = 'exeggutor.service';
|
|
152
|
+
try {
|
|
153
|
+
execSync(`systemctl --user disable ${serviceName}`, { stdio: 'pipe' });
|
|
154
|
+
} catch { /* ok */ }
|
|
155
|
+
const servicePath = path.resolve(homedir(), '.config', 'systemd', 'user', serviceName);
|
|
156
|
+
if (existsSync(servicePath)) {
|
|
157
|
+
unlinkSync(servicePath);
|
|
158
|
+
console.log('Systemd service removed.');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
module.exports = { install, remove };
|