Files
WRNexusJS/packages/csr/src/actions.ts
T
Clintchiz 586a6db8ff
Quality / quality (ubuntu-latest) (push) Failing after 21s
Quality / quality (windows-latest) (push) Canceled after 0s
release: WRNexusJS 0.8.0
2026-08-02 23:18:51 +05:30

47 lines
1.5 KiB
TypeScript

export interface ActionClientOptions<I> {
signal?: AbortSignal;
csrfToken?: string;
headers?: HeadersInit;
serialize?: (input: I) => BodyInit;
}
export interface ActionResult<O> {
data: O;
invalidated: string[];
}
export class ActionClientError extends Error {
constructor(
public readonly status: number,
public readonly errors?: Record<string, string>,
) {
super(`Server action failed with status ${status}.`);
this.name = "ActionClientError";
}
}
export function createActionClient<I, O>(route: string, name: string) {
return async (input: I, options: ActionClientOptions<I> = {}): Promise<ActionResult<O>> => {
const headers = new Headers(options.headers);
headers.set("accept", "application/json");
headers.set("x-wrnexus-action", name);
if (options.csrfToken) headers.set("x-csrf-token", options.csrfToken);
const body = options.serialize ? options.serialize(input) : JSON.stringify(input);
if (!options.serialize) headers.set("content-type", "application/json");
const response = await fetch(route, {
method: "POST",
credentials: "same-origin",
signal: options.signal,
headers,
body,
});
const payload = (await response.json()) as {
data?: O;
invalidated?: string[];
errors?: Record<string, string>;
};
if (!response.ok) throw new ActionClientError(response.status, payload.errors);
return { data: payload.data as O, invalidated: payload.invalidated ?? [] };
};
}