Load rule templates from API

This commit is contained in:
adilallo
2026-04-12 21:56:34 -06:00
parent cae4df261e
commit a39b4aa04b
17 changed files with 698 additions and 429 deletions
+30 -6
View File
@@ -9,16 +9,36 @@ export type RuleTemplateDto = {
category: string | null;
description: string | null;
body: unknown;
sortOrder: number;
featured: boolean;
};
type TemplatesResponse = { templates?: RuleTemplateDto[] };
export async function fetchTemplates(): Promise<
RuleTemplateDto[] | { error: string }
> {
export type FetchTemplatesOptions = {
signal?: AbortSignal;
};
function isAbortError(e: unknown): boolean {
return (
(e instanceof DOMException && e.name === "AbortError") ||
(e instanceof Error && e.name === "AbortError")
);
}
/** For callers that `catch` around `fetchTemplates` / `fetchTemplateBySlug`. */
export function isTemplatesFetchAborted(e: unknown): boolean {
return isAbortError(e);
}
export async function fetchTemplates(
options?: FetchTemplatesOptions,
): Promise<RuleTemplateDto[] | { error: string }> {
try {
const res = await fetch("/api/templates", { credentials: "include" });
const res = await fetch("/api/templates", {
credentials: "include",
signal: options?.signal,
});
const data = (await res.json()) as TemplatesResponse & { error?: string };
if (!res.ok) {
return {
@@ -29,15 +49,19 @@ export async function fetchTemplates(): Promise<
};
}
return Array.isArray(data.templates) ? data.templates : [];
} catch {
} catch (e) {
if (isAbortError(e)) {
throw e;
}
return { error: "Could not load templates" };
}
}
export async function fetchTemplateBySlug(
slug: string,
options?: FetchTemplatesOptions,
): Promise<RuleTemplateDto | null | { error: string }> {
const result = await fetchTemplates();
const result = await fetchTemplates(options);
if ("error" in result) {
return result;
}