-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathelectron-build-preload.ts
More file actions
145 lines (120 loc) · 3.63 KB
/
Copy pathelectron-build-preload.ts
File metadata and controls
145 lines (120 loc) · 3.63 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
/**
* Cross-platform preload build script with verification.
*
* Builds BOTH preload entry points:
* - apps/electron/src/preload/bootstrap.ts -> dist/bootstrap-preload.cjs
* - apps/electron/src/preload/browser-toolbar.ts -> dist/browser-toolbar-preload.cjs
*/
import { spawn } from "bun";
import { existsSync, statSync, mkdirSync } from "fs";
import { join } from "path";
const ROOT_DIR = join(import.meta.dir, "..");
const DIST_DIR = join(ROOT_DIR, "apps/electron/dist");
const OUTPUTS = [
{
entry: "apps/electron/src/preload/bootstrap.ts",
outfile: "apps/electron/dist/bootstrap-preload.cjs",
label: "bootstrap-preload.cjs",
},
{
entry: "apps/electron/src/preload/browser-toolbar.ts",
outfile: "apps/electron/dist/browser-toolbar-preload.cjs",
label: "browser-toolbar-preload.cjs",
},
] as const;
// Wait for file to stabilize (no size changes)
async function waitForFileStable(filePath: string, timeoutMs = 10000): Promise<boolean> {
const startTime = Date.now();
let lastSize = -1;
let stableCount = 0;
while (Date.now() - startTime < timeoutMs) {
if (!existsSync(filePath)) {
await Bun.sleep(100);
continue;
}
const stats = statSync(filePath);
if (stats.size === lastSize) {
stableCount++;
if (stableCount >= 3) {
return true;
}
} else {
stableCount = 0;
lastSize = stats.size;
}
await Bun.sleep(100);
}
return false;
}
// Verify a JavaScript file is syntactically valid
async function verifyJsFile(filePath: string): Promise<{ valid: boolean; error?: string }> {
if (!existsSync(filePath)) {
return { valid: false, error: "File does not exist" };
}
const stats = statSync(filePath);
if (stats.size === 0) {
return { valid: false, error: "File is empty" };
}
const proc = spawn({
cmd: ["node", "--check", filePath],
stdout: "pipe",
stderr: "pipe",
});
const stderr = await new Response(proc.stderr).text();
const exitCode = await proc.exited;
if (exitCode !== 0) {
return { valid: false, error: stderr || "Syntax error" };
}
return { valid: true };
}
async function buildEntry(entry: string, outfile: string): Promise<number> {
const proc = spawn({
cmd: [
"bun", "run", "esbuild",
entry,
"--bundle",
"--platform=node",
"--format=cjs",
`--outfile=${outfile}`,
"--external:electron",
],
cwd: ROOT_DIR,
stdout: "inherit",
stderr: "inherit",
});
return proc.exited;
}
async function main(): Promise<void> {
if (!existsSync(DIST_DIR)) {
mkdirSync(DIST_DIR, { recursive: true });
}
console.log("🔨 Building preload entries...");
for (const output of OUTPUTS) {
const exitCode = await buildEntry(output.entry, output.outfile);
if (exitCode !== 0) {
console.error(`❌ Failed to build ${output.label} (exit code ${exitCode})`);
process.exit(exitCode);
}
}
console.log("⏳ Waiting for preload outputs to stabilize...");
for (const output of OUTPUTS) {
const outputPath = join(ROOT_DIR, output.outfile);
const stable = await waitForFileStable(outputPath);
if (!stable) {
console.error(`❌ ${output.label} did not stabilize`);
process.exit(1);
}
}
console.log("🔍 Verifying preload outputs...");
for (const output of OUTPUTS) {
const outputPath = join(ROOT_DIR, output.outfile);
const verification = await verifyJsFile(outputPath);
if (!verification.valid) {
console.error(`❌ ${output.label} verification failed:`, verification.error);
process.exit(1);
}
}
console.log("✅ Preload builds complete and verified");
process.exit(0);
}
main();