-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathdev-with-daemon.ts
More file actions
executable file
·204 lines (173 loc) · 6.21 KB
/
dev-with-daemon.ts
File metadata and controls
executable file
·204 lines (173 loc) · 6.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#!/usr/bin/env bun
/**
* Development script that:
* 1. Builds the daemon (dev profile)
* 2. Starts the daemon
* 3. Waits for it to be ready
* 4. Starts Vite dev server
* 5. Cleans up daemon on exit
*/
import { spawn } from "child_process";
import { existsSync, unlinkSync } from "fs";
import { join, resolve, dirname } from "path";
import { homedir, platform } from "os";
import { fileURLToPath } from "url";
// Get script directory
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Detect Platform
const IS_WIN = platform() === "win32";
// Paths relative to this script (apps/tauri/scripts/)
// Script is at: PROJECT_ROOT/apps/tauri/scripts/
// So PROJECT_ROOT is: ../../../
const PROJECT_ROOT = resolve(__dirname, "../../../");
// FIX: Add .exe extension if on Windows
const BIN_NAME = IS_WIN ? "sd-daemon.exe" : "sd-daemon";
const DAEMON_BIN = join(PROJECT_ROOT, "target/debug", BIN_NAME);
const DAEMON_PORT = 6969;
const DAEMON_ADDR = `127.0.0.1:${DAEMON_PORT}`;
// Fix Data Directory for Windows (Optional but recommended)
const DATA_DIR = IS_WIN
? join(homedir(), "AppData/Roaming/spacedrive")
: join(homedir(), "Library/Application Support/spacedrive");
let daemonProcess: any = null;
let viteProcess: any = null;
let startedDaemon = false;
// Cleanup function
function cleanup() {
console.log("\nCleaning up...");
if (viteProcess) {
console.log("Stopping Vite...");
viteProcess.kill();
}
if (daemonProcess && startedDaemon) {
console.log("Stopping daemon (started by us)...");
daemonProcess.kill();
} else if (!startedDaemon) {
console.log("Leaving existing daemon running...");
}
process.exit(0);
}
// Handle signals
process.on("SIGINT", cleanup);
process.on("SIGTERM", cleanup);
async function main() {
// Check if daemon is already running by trying to connect to TCP port
let daemonAlreadyRunning = false;
console.log(`Checking if daemon is running on ${DAEMON_ADDR}...`);
try {
const { connect } = await import("net");
await new Promise<void>((resolve, reject) => {
const client = connect(DAEMON_PORT, "127.0.0.1");
client.on("connect", () => {
daemonAlreadyRunning = true;
client.end();
resolve();
});
client.on("error", () => {
reject();
});
setTimeout(() => reject(), 1000);
});
} catch (e) {
// Connection failed, daemon not running
daemonAlreadyRunning = false;
}
if (daemonAlreadyRunning) {
console.log("Daemon already running, will connect to existing instance");
startedDaemon = false;
} else {
console.log("Building daemon (dev profile)...");
console.log("Project root:", PROJECT_ROOT);
console.log("Daemon binary:", DAEMON_BIN);
// Build daemon
// On Windows, the binary target name is still just "sd-daemon" (Cargo handles the .exe)
const build = spawn("cargo", ["build", "--bin", "sd-daemon"], {
cwd: PROJECT_ROOT,
stdio: "inherit",
shell: IS_WIN, // shell: true is often needed on Windows for spawn to work correctly
});
await new Promise<void>((resolve, reject) => {
build.on("exit", (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Daemon build failed with code ${code}`));
}
});
});
console.log("Daemon built successfully");
// Start daemon
console.log("Starting daemon...");
startedDaemon = true;
// Verify binary exists
if (!existsSync(DAEMON_BIN)) {
throw new Error(`Daemon binary not found at: ${DAEMON_BIN}`);
}
const depsLibPath = join(PROJECT_ROOT, "apps/.deps/lib");
const depsBinPath = join(PROJECT_ROOT, "apps/.deps/bin");
daemonProcess = spawn(DAEMON_BIN, ["--data-dir", DATA_DIR], {
cwd: PROJECT_ROOT,
stdio: ["ignore", "pipe", "pipe"],
env: {
...process.env,
// macOS library path
DYLD_LIBRARY_PATH: depsLibPath,
// Windows: Add DLLs directory to PATH
PATH: IS_WIN
? `${depsBinPath};${process.env.PATH || ""}`
: process.env.PATH,
},
});
// Log daemon output
daemonProcess.stdout.on("data", (data: Buffer) => {
const lines = data.toString().trim().split("\n");
for (const line of lines) {
console.log(`[daemon] ${line}`);
}
});
daemonProcess.stderr.on("data", (data: Buffer) => {
const lines = data.toString().trim().split("\n");
for (const line of lines) {
console.log(`[daemon] ${line}`);
}
});
// Wait for daemon to be ready
console.log("Waiting for daemon to be ready...");
for (let i = 0; i < 30; i++) {
try {
const { connect } = await import("net");
await new Promise<void>((resolve, reject) => {
const client = connect(DAEMON_PORT, "127.0.0.1");
client.on("connect", () => {
client.end();
resolve();
});
client.on("error", reject);
setTimeout(() => reject(), 500);
});
console.log(`Daemon ready at ${DAEMON_ADDR}`);
break;
} catch (e) {
if (i === 29) {
throw new Error("Daemon failed to start (connection not available)");
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
}
// Start Vite
console.log("Starting Vite dev server...");
// Use 'bun' explicitly, with shell true for Windows compatibility
viteProcess = spawn("bun", ["run", "dev"], {
stdio: "inherit",
shell: IS_WIN,
});
// Keep running
await new Promise(() => {});
}
main().catch((error) => {
console.error("Error:", error);
cleanup();
process.exit(1);
});