11const API_BASE =
22 process . env . NEXT_PUBLIC_STABLEROUTE_API_BASE ?? "http://localhost:3001" ;
33
4+ /**
5+ * Canonical JSON error envelope returned by the StableRoute backend.
6+ *
7+ * `requestId` is optional because network failures and some legacy responses
8+ * may not include the backend correlation id.
9+ */
410export type ApiError = {
511 error : string ;
612 message : string ;
@@ -10,14 +16,38 @@ export type ApiError = {
1016type AuthErrorHandler = ( status : 401 | 403 ) => void ;
1117let _authErrorHandler : AuthErrorHandler | null = null ;
1218
13- /** Called once by <ApiAuthGuard> when it mounts inside <ToastProvider>. */
19+ /**
20+ * Register the single global auth-error handler.
21+ *
22+ * The latest registration replaces any previous handler. `ApiAuthGuard` calls
23+ * this while mounted inside `ToastProvider`, then calls the returned unregister
24+ * function on unmount. The guard is notified for backend `401` and `403`
25+ * responses, but the original request still rejects normally.
26+ *
27+ * @param handler - Callback invoked with the auth failure status.
28+ * @returns A cleanup function that unregisters `handler` if it is still active.
29+ */
1430export function registerAuthErrorHandler ( handler : AuthErrorHandler ) : ( ) => void {
1531 _authErrorHandler = handler ;
1632 return ( ) => {
1733 if ( _authErrorHandler === handler ) _authErrorHandler = null ;
1834 } ;
1935}
2036
37+ /**
38+ * Fetch JSON from the StableRoute API.
39+ *
40+ * Requests are made relative to `NEXT_PUBLIC_STABLEROUTE_API_BASE` and include
41+ * `Content-Type: application/json` by default. `204 No Content` resolves to
42+ * `undefined`. Non-empty successful responses must be valid JSON. Failed
43+ * responses reject with an `Error` whose message comes from the backend
44+ * `ApiError.message` when present, with `status` and any parsed error fields
45+ * attached to the thrown object.
46+ *
47+ * @param path - Backend path beginning with `/`.
48+ * @param init - Optional fetch init merged with the default JSON header.
49+ * @returns The parsed response body typed as `T`.
50+ */
2151export async function apiFetch < T > (
2252 path : string ,
2353 init : RequestInit = { }
@@ -48,10 +78,14 @@ export async function apiFetch<T>(
4878 return body as T ;
4979}
5080
81+ /** GET a JSON resource from the StableRoute API. */
5182export const apiGet = < T > ( path : string ) => apiFetch < T > ( path ) ;
83+ /** POST a JSON body and parse the JSON response. */
5284export const apiPost = < T > ( path : string , body : unknown ) =>
5385 apiFetch < T > ( path , { method : "POST" , body : JSON . stringify ( body ) } ) ;
86+ /** PATCH a JSON body and parse the JSON response. */
5487export const apiPatch = < T > ( path : string , body : unknown ) =>
5588 apiFetch < T > ( path , { method : "PATCH" , body : JSON . stringify ( body ) } ) ;
89+ /** DELETE a resource, resolving to `undefined` for a 204 response. */
5690export const apiDelete = ( path : string ) =>
5791 apiFetch < void > ( path , { method : "DELETE" } ) ;
0 commit comments