From e3bd05ca210f5b176ef5655e71b15aa4570e974b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20F=C3=B6rtsch?= Date: Tue, 10 Mar 2026 11:26:11 +0100 Subject: [PATCH] add sync orchestrator wrapping mbsync, notmuch Co-Authored-By: Claude Opus 4.6 --- backend/src/services/orchestrator.test.ts | 15 ++++++++++ backend/src/services/orchestrator.ts | 34 +++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 backend/src/services/orchestrator.test.ts create mode 100644 backend/src/services/orchestrator.ts diff --git a/backend/src/services/orchestrator.test.ts b/backend/src/services/orchestrator.test.ts new file mode 100644 index 0000000..e8a5b6c --- /dev/null +++ b/backend/src/services/orchestrator.test.ts @@ -0,0 +1,15 @@ +import { describe, expect, test } from "bun:test"; +import { runCommand } from "./orchestrator"; + +describe("runCommand", () => { + test("runs a command and returns stdout", async () => { + const result = await runCommand("echo", ["hello"]); + expect(result.stdout.trim()).toBe("hello"); + expect(result.exitCode).toBe(0); + }); + + test("returns non-zero exit code on failure", async () => { + const result = await runCommand("false", []); + expect(result.exitCode).not.toBe(0); + }); +}); diff --git a/backend/src/services/orchestrator.ts b/backend/src/services/orchestrator.ts new file mode 100644 index 0000000..380e847 --- /dev/null +++ b/backend/src/services/orchestrator.ts @@ -0,0 +1,34 @@ +export interface CommandResult { + stdout: string; + stderr: string; + exitCode: number; +} + +export async function runCommand(cmd: string, args: string[]): Promise { + const proc = Bun.spawn([cmd, ...args], { + stdout: "pipe", + stderr: "pipe", + }); + + const stdout = await new Response(proc.stdout).text(); + const stderr = await new Response(proc.stderr).text(); + const exitCode = await proc.exited; + + return { stdout, stderr, exitCode }; +} + +export async function syncMail(channelName: string): Promise { + return runCommand("mbsync", [channelName]); +} + +export async function indexMail(): Promise { + return runCommand("notmuch", ["new"]); +} + +export async function syncAndIndex(channelName: string): Promise { + const syncResult = await syncMail(channelName); + if (syncResult.exitCode !== 0) { + return syncResult; + } + return indexMail(); +}