diff --git a/apps/builder/app/routes/rest.resources-loader.ts b/apps/builder/app/routes/rest.resources-loader.ts index 0954d19295ac..94c239a89b31 100644 --- a/apps/builder/app/routes/rest.resources-loader.ts +++ b/apps/builder/app/routes/rest.resources-loader.ts @@ -25,32 +25,35 @@ export const action = async ({ request }: ActionFunctionArgs) => { }; const requestJson = await request.json(); + const requestList = z.array(z.unknown()).safeParse(requestJson); - const computedResourcesParsed = z - .array(ResourceRequest) - .safeParse(requestJson); - - if (computedResourcesParsed.success === false) { - console.error( - "computedResources.parse", - computedResourcesParsed.error.toString() - ); + if (requestList.success === false) { console.error("data:", requestJson); - - throw data(computedResourcesParsed.error, { + throw data(requestList.error, { status: 400, }); } - const computedResources = computedResourcesParsed.data; - - const responses = await Promise.all( - computedResources.map((resource) => loadResource(customFetch, resource)) + const output = await Promise.all( + requestList.data.map(async (item) => { + const resource = ResourceRequest.safeParse(item); + if (resource.success === false) { + return [ + getResourceKey(item as ResourceRequest), + { + ok: false, + data: resource.error.format(), + status: 403, + statusText: "Resource validation error", + }, + ]; + } + return [ + getResourceKey(resource.data), + await loadResource(customFetch, resource.data), + ]; + }) ); - const output: [string, unknown][] = []; - responses.forEach((response, index) => { - const request = computedResources[index]; - output.push([getResourceKey(request), response]); - }); + return output; }; diff --git a/apps/builder/app/shared/resources.ts b/apps/builder/app/shared/resources.ts index 815368b595b0..3f4078eb6fc6 100644 --- a/apps/builder/app/shared/resources.ts +++ b/apps/builder/app/shared/resources.ts @@ -7,18 +7,24 @@ import { fetch } from "./fetch.client"; const MAX_PENDING_RESOURCES = 5; -export const getResourceKey = (resource: ResourceRequest) => - hash( - JSON.stringify([ - // explicitly list all fields to keep hash stable - resource.name, - resource.method, - resource.url, - resource.searchParams, - resource.headers, - resource.body, - ]) - ); +export const getResourceKey = (resource: ResourceRequest) => { + try { + return hash( + JSON.stringify([ + // explicitly list all fields to keep hash stable + resource.name, + resource.method, + resource.url, + resource.searchParams, + resource.headers, + resource.body, + ]) + ); + } catch { + // guard from invalid resources + return ""; + } +}; const queue = new Map(); const pending = new Map();