diff --git a/apps/desktop/src/app/DesktopPreReadyPlatform.test.ts b/apps/desktop/src/app/DesktopPreReadyPlatform.test.ts index a29e0fd3baf..6e8d597c692 100644 --- a/apps/desktop/src/app/DesktopPreReadyPlatform.test.ts +++ b/apps/desktop/src/app/DesktopPreReadyPlatform.test.ts @@ -78,6 +78,37 @@ describe("DesktopPreReadyPlatform", () => { assert.isNull(value); }); + it("detects --version and -V as whole-token version requests", () => { + assert.isTrue(DesktopPreReadyPlatform.isVersionRequest(["--version"])); + assert.isTrue(DesktopPreReadyPlatform.isVersionRequest(["-V"])); + assert.isFalse(DesktopPreReadyPlatform.isVersionRequest(["--no-sandbox"])); + assert.isFalse(DesktopPreReadyPlatform.isVersionRequest(["--version=1"])); + assert.isFalse(DesktopPreReadyPlatform.isVersionRequest(["--version-foo"])); + assert.isFalse(DesktopPreReadyPlatform.isVersionRequest(["-v"])); + assert.isFalse(DesktopPreReadyPlatform.isVersionRequest([])); + }); + + it("writes a version line to stdout synchronously and swallows EPIPE", () => { + const writes: Array<{ fd: number; data: string }> = []; + DesktopPreReadyPlatform.writeStdoutLineSync("1.2.3", (fd, data) => { + writes.push({ fd, data }); + }); + assert.deepEqual(writes, [{ fd: 1, data: "1.2.3\n" }]); + + DesktopPreReadyPlatform.writeStdoutLineSync("1.2.3", () => { + throw Object.assign(new Error("broken pipe"), { code: "EPIPE" }); + }); + + try { + DesktopPreReadyPlatform.writeStdoutLineSync("1.2.3", () => { + throw Object.assign(new Error("bad fd"), { code: "EBADF" }); + }); + assert.fail("expected EBADF to propagate"); + } catch (error) { + assert.equal((error as NodeJS.ErrnoException).code, "EBADF"); + } + }); + it.effect( "acquires a synchronous pre-ready layer before an asynchronous Clerk-shaped layer", () => diff --git a/apps/desktop/src/app/DesktopPreReadyPlatform.ts b/apps/desktop/src/app/DesktopPreReadyPlatform.ts index 7d145632d0b..f4014b38b4b 100644 --- a/apps/desktop/src/app/DesktopPreReadyPlatform.ts +++ b/apps/desktop/src/app/DesktopPreReadyPlatform.ts @@ -29,6 +29,24 @@ export function readCommandLineSwitchValue( return value.length > 0 ? value : null; } +export function isVersionRequest(argv: ReadonlyArray): boolean { + return argv.includes("--version") || argv.includes("-V"); +} + +export function writeStdoutLineSync( + line: string, + writeSync: (fd: number, data: string) => void = (fd, data) => { + NodeFS.writeSync(fd, data); + }, +): void { + try { + writeSync(1, `${line}\n`); + } catch (error) { + const err = error as NodeJS.ErrnoException; + if (err.code !== "EPIPE") throw error; + } +} + export const resolveEarlyLinuxElectronOptionsFromProcess = (): DesktopEarlyElectronStartup.EarlyLinuxElectronOptions => DesktopEarlyElectronStartup.resolveEarlyLinuxElectronOptions({ diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index 14caeed8a9a..9fb08388384 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -216,4 +216,9 @@ const desktopRuntimeLayer = desktopClerkLayer.pipe( Layer.provideMerge(DesktopPreReadyPlatform.layer), ); +if (DesktopPreReadyPlatform.isVersionRequest(process.argv)) { + DesktopPreReadyPlatform.writeStdoutLineSync(Electron.app.getVersion()); + process.exit(0); +} + DesktopApp.program.pipe(Effect.provide(desktopRuntimeLayer), NodeRuntime.runMain);