import type { AdminSettingsFormSchema } from "$admin-settings/form-schema"; import { Formality, Tone } from "./schemas"; import type { OrganizationMe } from "./types"; // ───────────────────────────────────────────────────────────────────────────── // Types // ───────────────────────────────────────────────────────────────────────────── export type GenerationStatus = "none" | "running" | "completed" | "error"; // ───────────────────────────────────────────────────────────────────────────── // Internal helpers // ───────────────────────────────────────────────────────────────────────────── /** * Try to obtain the WP nonce that authorises authenticated requests. */ function getNonce(): string | undefined { return window.productbird.nonce; } interface RequestOptions extends Omit { /** JSON body that will be stringified automatically. */ body?: unknown; /** Whether to automatically include the X-WP-Nonce header (default: true). */ auth?: boolean; } export class ApiError extends Error { constructor( message: string, public code: number, public statusText: string, public errorData?: { code?: string; message?: string; data?: { status: number }; }, ) { super(message); this.name = "ApiError"; this.code = code; this.statusText = statusText; } /** * Get the error message from the API response */ get userMessage(): string { // Use the message from the API response if available if (this.errorData?.message) { return this.errorData.message; } // Fallback to a generic message if no specific message is available return "An error occurred while performing this action. Please try again."; } } async function request( path: string, options: RequestOptions = {}, ): Promise { const { body, auth = true, headers, ...rest } = options; // Build full URL. const url = window.productbird.api_root_url + path; // Default headers. const defaultHeaders: HeadersInit = { Accept: "application/json", }; // Add nonce for mutating requests if available. if (auth && getNonce()) { defaultHeaders["X-WP-Nonce"] = getNonce() as string; } // If there is a body, stringify & set Content-Type. let fetchBody: RequestInit["body"] = undefined; if (body !== undefined) { fetchBody = JSON.stringify(body); defaultHeaders["Content-Type"] = "application/json"; } const response = await fetch(url, { credentials: "same-origin", headers: { ...defaultHeaders, ...headers, }, body: fetchBody, ...rest, }); if (!response.ok) { // Attempt to parse error JSON but fallback to text. let errorData: unknown = undefined; try { errorData = await response.json(); } catch (_) { errorData = await response.text(); } throw new ApiError( `Request failed: ${response.status} ${response.statusText}`, response.status, response.statusText, typeof errorData === "object" ? (errorData as { code?: string; message?: string; data?: { status: number }; }) : undefined, ); } // 204 No Content – nothing to parse. if (response.status === 204) { return undefined as unknown as T; } return (await response.json()) as T; } // ───────────────────────────────────────────────────────────────────────────── // Public helpers // ───────────────────────────────────────────────────────────────────────────── /** * Fetch the Productbird settings option from `/wp/v2/settings`. */ export async function getSettings(): Promise { const data = await request( "productbird/v1/settings", ); return data; } /** * Fetch the Productbird organizations from `/productbird/v1/organizations/me`. */ export async function getOrganizations(): Promise { const data = await request("productbird/v1/organizations"); return data; } /** * Update one or more Productbird settings. */ export async function updateSettings( partial: Partial, ): Promise { const data = await request( "productbird/v1/settings", { method: "POST", body: partial, }, ); return data; } /** * POST a list of Woo product IDs and receive their generation status. */ export async function checkGenerationStatus( productIds: number[], ): Promise> { return request>( "productbird/v1/check-generation-status", { method: "POST", body: { productIds }, }, ); } /** * Clear all Productbird post meta from products. */ export async function clearProductMeta(): Promise<{ success: boolean; cleared: number; }> { return request<{ success: boolean; cleared: number }>( "productbird/v1/clear-product-meta", { method: "POST", }, ); } // The module also re-exports the low-level request helper for advanced use. export { request as rawRequest };