chore: pr feedbacks

This commit is contained in:
Nicolas Meienberger 2026-04-29 23:36:09 +02:00
parent 95067c39fa
commit 0b98402b26
No known key found for this signature in database
4 changed files with 42 additions and 4 deletions

View file

@ -7,8 +7,12 @@ const webhookHeadersSchema = z.string().refine(
.split("\n")
.map((header) => header.trim())
.filter(Boolean)
.every((header) => header.includes(":")),
{ message: "Headers must use Key: Value format" },
.every((header) => {
const [key, value] = header.split(":", 2);
return /^[A-Za-z0-9-]+$/.test(key.trim()) && (value?.trim().length ?? 0) > 0;
}),
{ message: "Headers must use non-empty Key: Value format with valid header names" },
);
export const internalFormSchema = z.object({

View file

@ -15,11 +15,14 @@ export const parseMultilineEntries = (value?: string) => {
export const toWebhookConfig = (url?: string, headers?: string, body?: string) => {
const trimmedUrl = url?.trim();
const trimmedBody = body?.trim();
const parsedHeaders = parseMultilineEntries(headers);
return trimmedUrl
? { url: trimmedUrl, headers: parsedHeaders.length > 0 ? parsedHeaders : undefined, body: trimmedBody || undefined }
? {
url: trimmedUrl,
headers: parsedHeaders.length > 0 ? parsedHeaders : undefined,
body: body === "" ? undefined : body,
}
: null;
};

View file

@ -353,3 +353,31 @@ test("cancels before the pre-backup webhook without running the backup", async (
expect(backupRan).toBe(false);
expect(result).toEqual({ status: "cancelled", message: "Backup was cancelled" });
});
test("cancels after the pre-backup webhook without running the backup", async () => {
const abortController = new AbortController();
let backupRan = false;
server.use(
http.post("http://localhost:8080/pre", () => {
abortController.abort(new Error("Backup was cancelled"));
return new HttpResponse(null, { status: 204 });
}),
);
const result = await runWithHooks({
webhooks: {
pre: { url: "http://localhost:8080/pre" },
post: null,
},
signal: abortController.signal,
runBackup: () =>
Effect.sync(() => {
backupRan = true;
return { exitCode: 0, result: null, warningDetails: null };
}),
});
expect(backupRan).toBe(false);
expect(result).toEqual({ status: "cancelled", message: "Backup was cancelled" });
});

View file

@ -220,6 +220,9 @@ export const runBackupLifecycle = <TResult>({
return { status: "failed", error: preHookError };
}
if (signal.aborted) {
return { status: "cancelled", message: formatError(signal.reason) };
}
const backupResult = yield* Effect.suspend(() =>
restic.backup(repositoryConfig, sourcePath, { ...options, organizationId, signal, onProgress }),