@@ -78,7 +78,7 @@ export function createLoaderApiRoute<
7878 const authenticationResult = await authenticateApiRequest(request, { allowJWT });
7979
8080 if (!authenticationResult) {
81- return wrapResponse(
81+ return await wrapResponse(
8282 request,
8383 json({ error: "Invalid or Missing API key" }, { status: 401 }),
8484 corsStrategy !== "none"
@@ -89,7 +89,7 @@ export function createLoaderApiRoute<
8989 if (paramsSchema) {
9090 const parsed = paramsSchema.safeParse(params);
9191 if (!parsed.success) {
92- return wrapResponse(
92+ return await wrapResponse(
9393 request,
9494 json(
9595 { error: "Params Error", details: fromZodError(parsed.error).details },
@@ -106,7 +106,7 @@ export function createLoaderApiRoute<
106106 const searchParams = Object.fromEntries(new URL(request.url).searchParams);
107107 const parsed = searchParamsSchema.safeParse(searchParams);
108108 if (!parsed.success) {
109- return wrapResponse(
109+ return await wrapResponse(
110110 request,
111111 json(
112112 { error: "Query Error", details: fromZodError(parsed.error).details },
@@ -123,7 +123,7 @@ export function createLoaderApiRoute<
123123 const rawHeaders = Object.fromEntries(request.headers);
124124 const headers = headersSchema.safeParse(rawHeaders);
125125 if (!headers.success) {
126- return wrapResponse(
126+ return await wrapResponse(
127127 request,
128128 json(
129129 { error: "Headers Error", details: fromZodError(headers.error).details },
@@ -154,7 +154,7 @@ export function createLoaderApiRoute<
154154 );
155155
156156 if (!authorizationResult.authorized) {
157- return wrapResponse(
157+ return await wrapResponse(
158158 request,
159159 json(
160160 {
@@ -177,16 +177,22 @@ export function createLoaderApiRoute<
177177 authentication: authenticationResult,
178178 request,
179179 });
180- return wrapResponse(request, result, corsStrategy !== "none");
180+ return await wrapResponse(request, result, corsStrategy !== "none");
181181 } catch (error) {
182- if (error instanceof Response) {
183- return wrapResponse(request, error, corsStrategy !== "none");
182+ try {
183+ if (error instanceof Response) {
184+ return await wrapResponse(request, error, corsStrategy !== "none");
185+ }
186+ return await wrapResponse(
187+ request,
188+ json({ error: "Internal Server Error" }, { status: 500 }),
189+ corsStrategy !== "none"
190+ );
191+ } catch (innerError) {
192+ logger.error("[apiBuilder] Failed to handle error", { error, innerError });
193+
194+ return json({ error: "Internal Server Error" }, { status: 500 });
184195 }
185- return wrapResponse(
186- request,
187- json({ error: "Internal Server Error" }, { status: 500 }),
188- corsStrategy !== "none"
189- );
190196 }
191197 };
192198}
@@ -240,7 +246,7 @@ export function createLoaderPATApiRoute<
240246 const authenticationResult = await authenticateApiRequestWithPersonalAccessToken(request);
241247
242248 if (!authenticationResult) {
243- return wrapResponse(
249+ return await wrapResponse(
244250 request,
245251 json({ error: "Invalid or Missing API key" }, { status: 401 }),
246252 corsStrategy !== "none"
@@ -251,7 +257,7 @@ export function createLoaderPATApiRoute<
251257 if (paramsSchema) {
252258 const parsed = paramsSchema.safeParse(params);
253259 if (!parsed.success) {
254- return wrapResponse(
260+ return await wrapResponse(
255261 request,
256262 json(
257263 { error: "Params Error", details: fromZodError(parsed.error).details },
@@ -268,7 +274,7 @@ export function createLoaderPATApiRoute<
268274 const searchParams = Object.fromEntries(new URL(request.url).searchParams);
269275 const parsed = searchParamsSchema.safeParse(searchParams);
270276 if (!parsed.success) {
271- return wrapResponse(
277+ return await wrapResponse(
272278 request,
273279 json(
274280 { error: "Query Error", details: fromZodError(parsed.error).details },
@@ -285,7 +291,7 @@ export function createLoaderPATApiRoute<
285291 const rawHeaders = Object.fromEntries(request.headers);
286292 const headers = headersSchema.safeParse(rawHeaders);
287293 if (!headers.success) {
288- return wrapResponse(
294+ return await wrapResponse(
289295 request,
290296 json(
291297 { error: "Headers Error", details: fromZodError(headers.error).details },
@@ -304,17 +310,22 @@ export function createLoaderPATApiRoute<
304310 authentication: authenticationResult,
305311 request,
306312 });
307- return wrapResponse(request, result, corsStrategy !== "none");
313+ return await wrapResponse(request, result, corsStrategy !== "none");
308314 } catch (error) {
309- console.error("Error in API route:", error);
310- if (error instanceof Response) {
311- return wrapResponse(request, error, corsStrategy !== "none");
315+ try {
316+ if (error instanceof Response) {
317+ return await wrapResponse(request, error, corsStrategy !== "none");
318+ }
319+ return await wrapResponse(
320+ request,
321+ json({ error: "Internal Server Error" }, { status: 500 }),
322+ corsStrategy !== "none"
323+ );
324+ } catch (innerError) {
325+ logger.error("[apiBuilder] Failed to handle error", { error, innerError });
326+
327+ return json({ error: "Internal Server Error" }, { status: 500 });
312328 }
313- return wrapResponse(
314- request,
315- json({ error: "Internal Server Error" }, { status: 500 }),
316- corsStrategy !== "none"
317- );
318329 }
319330 };
320331}
@@ -388,7 +399,7 @@ export function createActionApiRoute<
388399 const authenticationResult = await authenticateApiRequest(request, { allowJWT });
389400
390401 if (!authenticationResult) {
391- return wrapResponse(
402+ return await wrapResponse(
392403 request,
393404 json({ error: "Invalid or Missing API key" }, { status: 401 }),
394405 corsStrategy !== "none"
@@ -407,7 +418,7 @@ export function createActionApiRoute<
407418 if (paramsSchema) {
408419 const parsed = paramsSchema.safeParse(params);
409420 if (!parsed.success) {
410- return wrapResponse(
421+ return await wrapResponse(
411422 request,
412423 json(
413424 { error: "Params Error", details: fromZodError(parsed.error).details },
@@ -424,7 +435,7 @@ export function createActionApiRoute<
424435 const searchParams = Object.fromEntries(new URL(request.url).searchParams);
425436 const parsed = searchParamsSchema.safeParse(searchParams);
426437 if (!parsed.success) {
427- return wrapResponse(
438+ return await wrapResponse(
428439 request,
429440 json(
430441 { error: "Query Error", details: fromZodError(parsed.error).details },
@@ -441,7 +452,7 @@ export function createActionApiRoute<
441452 const rawHeaders = Object.fromEntries(request.headers);
442453 const headers = headersSchema.safeParse(rawHeaders);
443454 if (!headers.success) {
444- return wrapResponse(
455+ return await wrapResponse(
445456 request,
446457 json(
447458 { error: "Headers Error", details: fromZodError(headers.error).details },
@@ -457,7 +468,7 @@ export function createActionApiRoute<
457468 if (bodySchema) {
458469 const rawBody = await request.text();
459470 if (rawBody.length === 0) {
460- return wrapResponse(
471+ return await wrapResponse(
461472 request,
462473 json({ error: "Request body is empty" }, { status: 400 }),
463474 corsStrategy !== "none"
@@ -467,7 +478,7 @@ export function createActionApiRoute<
467478 const rawParsedJson = safeJsonParse(rawBody);
468479
469480 if (!rawParsedJson) {
470- return wrapResponse(
481+ return await wrapResponse(
471482 request,
472483 json({ error: "Invalid JSON" }, { status: 400 }),
473484 corsStrategy !== "none"
@@ -476,7 +487,7 @@ export function createActionApiRoute<
476487
477488 const body = bodySchema.safeParse(rawParsedJson);
478489 if (!body.success) {
479- return wrapResponse(
490+ return await wrapResponse(
480491 request,
481492 json({ error: fromZodError(body.error).toString() }, { status: 400 }),
482493 corsStrategy !== "none"
@@ -497,7 +508,7 @@ export function createActionApiRoute<
497508 });
498509
499510 if (!checkAuthorization(authenticationResult, action, $resource, superScopes)) {
500- return wrapResponse(
511+ return await wrapResponse(
501512 request,
502513 json({ error: "Unauthorized" }, { status: 403 }),
503514 corsStrategy !== "none"
@@ -513,24 +524,36 @@ export function createActionApiRoute<
513524 authentication: authenticationResult,
514525 request,
515526 });
516- return wrapResponse(request, result, corsStrategy !== "none");
527+ return await wrapResponse(request, result, corsStrategy !== "none");
517528 } catch (error) {
518- if (error instanceof Response) {
519- return wrapResponse(request, error, corsStrategy !== "none");
529+ try {
530+ if (error instanceof Response) {
531+ return await wrapResponse(request, error, corsStrategy !== "none");
532+ }
533+ return await wrapResponse(
534+ request,
535+ json({ error: "Internal Server Error" }, { status: 500 }),
536+ corsStrategy !== "none"
537+ );
538+ } catch (innerError) {
539+ logger.error("[apiBuilder] Failed to handle error", { error, innerError });
540+
541+ return json({ error: "Internal Server Error" }, { status: 500 });
520542 }
521- return wrapResponse(
522- request,
523- json({ error: "Internal Server Error" }, { status: 500 }),
524- corsStrategy !== "none"
525- );
526543 }
527544 }
528545
529546 return { loader, action };
530547}
531548
532- function wrapResponse(request: Request, response: Response, useCors: boolean) {
549+ async function wrapResponse(
550+ request: Request,
551+ response: Response,
552+ useCors: boolean
553+ ): Promise<Response> {
533554 return useCors
534- ? apiCors(request, response, { exposedHeaders: ["x-trigger-jwt", "x-trigger-jwt-claims"] })
555+ ? await apiCors(request, response, {
556+ exposedHeaders: ["x-trigger-jwt", "x-trigger-jwt-claims"],
557+ })
535558 : response;
536559}
0 commit comments