release: WRNexusJS 0.8.0
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
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 ?? [] };
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user