diff --git a/fixtures/webstudio-cloudflare-template/app/routes/[another-page]._index.tsx b/fixtures/webstudio-cloudflare-template/app/routes/[another-page]._index.tsx index 8622c19e2bf1..12e5c008f8bc 100644 --- a/fixtures/webstudio-cloudflare-template/app/routes/[another-page]._index.tsx +++ b/fixtures/webstudio-cloudflare-template/app/routes/[another-page]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-cloudflare-template/app/routes/_index.tsx b/fixtures/webstudio-cloudflare-template/app/routes/_index.tsx index 65b10c483a1d..e81c409fa11a 100644 --- a/fixtures/webstudio-cloudflare-template/app/routes/_index.tsx +++ b/fixtures/webstudio-cloudflare-template/app/routes/_index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-custom-template/app/routes/[script-test]._index.tsx b/fixtures/webstudio-custom-template/app/routes/[script-test]._index.tsx index 9265e97c6d71..42dfb885b7b9 100644 --- a/fixtures/webstudio-custom-template/app/routes/[script-test]._index.tsx +++ b/fixtures/webstudio-custom-template/app/routes/[script-test]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-custom-template/app/routes/[world]._index.tsx b/fixtures/webstudio-custom-template/app/routes/[world]._index.tsx index 99b6ccf3dc2c..e76587ec62f5 100644 --- a/fixtures/webstudio-custom-template/app/routes/[world]._index.tsx +++ b/fixtures/webstudio-custom-template/app/routes/[world]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-custom-template/app/routes/_index.tsx b/fixtures/webstudio-custom-template/app/routes/_index.tsx index 65b10c483a1d..e81c409fa11a 100644 --- a/fixtures/webstudio-custom-template/app/routes/_index.tsx +++ b/fixtures/webstudio-custom-template/app/routes/_index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-netlify-edge-functions/app/routes/[another-page]._index.tsx b/fixtures/webstudio-remix-netlify-edge-functions/app/routes/[another-page]._index.tsx index 8622c19e2bf1..12e5c008f8bc 100644 --- a/fixtures/webstudio-remix-netlify-edge-functions/app/routes/[another-page]._index.tsx +++ b/fixtures/webstudio-remix-netlify-edge-functions/app/routes/[another-page]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-netlify-edge-functions/app/routes/_index.tsx b/fixtures/webstudio-remix-netlify-edge-functions/app/routes/_index.tsx index 65b10c483a1d..e81c409fa11a 100644 --- a/fixtures/webstudio-remix-netlify-edge-functions/app/routes/_index.tsx +++ b/fixtures/webstudio-remix-netlify-edge-functions/app/routes/_index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-netlify-functions/app/routes/[another-page]._index.tsx b/fixtures/webstudio-remix-netlify-functions/app/routes/[another-page]._index.tsx index 8622c19e2bf1..12e5c008f8bc 100644 --- a/fixtures/webstudio-remix-netlify-functions/app/routes/[another-page]._index.tsx +++ b/fixtures/webstudio-remix-netlify-functions/app/routes/[another-page]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-netlify-functions/app/routes/_index.tsx b/fixtures/webstudio-remix-netlify-functions/app/routes/_index.tsx index 65b10c483a1d..e81c409fa11a 100644 --- a/fixtures/webstudio-remix-netlify-functions/app/routes/_index.tsx +++ b/fixtures/webstudio-remix-netlify-functions/app/routes/_index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-vercel/app/routes/[_route_with_symbols_]._index.tsx b/fixtures/webstudio-remix-vercel/app/routes/[_route_with_symbols_]._index.tsx index b9ce6211a20a..064fa757b345 100644 --- a/fixtures/webstudio-remix-vercel/app/routes/[_route_with_symbols_]._index.tsx +++ b/fixtures/webstudio-remix-vercel/app/routes/[_route_with_symbols_]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-vercel/app/routes/[form]._index.tsx b/fixtures/webstudio-remix-vercel/app/routes/[form]._index.tsx index 345ae907e0c2..9eff1b923fa2 100644 --- a/fixtures/webstudio-remix-vercel/app/routes/[form]._index.tsx +++ b/fixtures/webstudio-remix-vercel/app/routes/[form]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-vercel/app/routes/[heading-with-id]._index.tsx b/fixtures/webstudio-remix-vercel/app/routes/[heading-with-id]._index.tsx index 490c3162b62c..3f06d379694b 100644 --- a/fixtures/webstudio-remix-vercel/app/routes/[heading-with-id]._index.tsx +++ b/fixtures/webstudio-remix-vercel/app/routes/[heading-with-id]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-vercel/app/routes/[nested].[nested-page]._index.tsx b/fixtures/webstudio-remix-vercel/app/routes/[nested].[nested-page]._index.tsx index 0f4e81134fa2..88fed5c32dc6 100644 --- a/fixtures/webstudio-remix-vercel/app/routes/[nested].[nested-page]._index.tsx +++ b/fixtures/webstudio-remix-vercel/app/routes/[nested].[nested-page]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-vercel/app/routes/[radix]._index.tsx b/fixtures/webstudio-remix-vercel/app/routes/[radix]._index.tsx index f4519185907e..82fd24c9429d 100644 --- a/fixtures/webstudio-remix-vercel/app/routes/[radix]._index.tsx +++ b/fixtures/webstudio-remix-vercel/app/routes/[radix]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-vercel/app/routes/[resources]._index.tsx b/fixtures/webstudio-remix-vercel/app/routes/[resources]._index.tsx index a8555e29c98b..320dae4d41ee 100644 --- a/fixtures/webstudio-remix-vercel/app/routes/[resources]._index.tsx +++ b/fixtures/webstudio-remix-vercel/app/routes/[resources]._index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/fixtures/webstudio-remix-vercel/app/routes/_index.tsx b/fixtures/webstudio-remix-vercel/app/routes/_index.tsx index 65b10c483a1d..e81c409fa11a 100644 --- a/fixtures/webstudio-remix-vercel/app/routes/_index.tsx +++ b/fixtures/webstudio-remix-vercel/app/routes/_index.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/packages/cli/templates/defaults/app/route-templates/html.tsx b/packages/cli/templates/defaults/app/route-templates/html.tsx index 565aec5d0928..59b6538f9a4a 100644 --- a/packages/cli/templates/defaults/app/route-templates/html.tsx +++ b/packages/cli/templates/defaults/app/route-templates/html.tsx @@ -10,7 +10,11 @@ import { redirect, } from "@remix-run/server-runtime"; import { useLoaderData } from "@remix-run/react"; -import { isLocalResource, loadResources } from "@webstudio-is/sdk"; +import { + isLocalResource, + loadResource, + loadResources, +} from "@webstudio-is/sdk"; import { ReactSdkContext } from "@webstudio-is/react-sdk"; import { n8nHandler, @@ -297,22 +301,32 @@ export const action = async ({ throw new Error(`Form bot value invalid ${formBotValue}`); } + formData.delete(formIdFieldName); + formData.delete(formBotFieldName); + + if (resource) { + const { ok, statusText } = await loadResource(fetch, { + ...resource, + body: Object.fromEntries(formData), + }); + if (ok) { + return { success: true }; + } + return { success: false, errors: [statusText] }; + } + if (contactEmail === undefined) { throw new Error("Contact email not found"); } - const formInfo = { - formData, - projectId, - action: resource?.url ?? null, - method: getMethod(resource?.method), - pageUrl: pageUrl.toString(), - toEmail: contactEmail, - fromEmail: pageUrl.hostname + "@webstudio.email", - } as const; - const result = await n8nHandler({ - formInfo, + formInfo: { + formId: [projectId, resourceName].join("--"), + formData, + pageUrl: pageUrl.toString(), + toEmail: contactEmail, + fromEmail: pageUrl.hostname + "@webstudio.email", + }, hookUrl: context.N8N_FORM_EMAIL_HOOK, }); diff --git a/packages/form-handlers/src/n8n.ts b/packages/form-handlers/src/n8n.ts index 22fa52e972db..8b89901b5f2c 100644 --- a/packages/form-handlers/src/n8n.ts +++ b/packages/form-handlers/src/n8n.ts @@ -2,10 +2,8 @@ import { type FormInfo, type Result, formToEmail, - getFormEntries, getErrors, getResponseBody, - formIdFieldName, } from "./shared"; const getAuth = (hookUrl: string) => { @@ -40,19 +38,13 @@ export const n8nHandler = async ({ headers["Authorization"] = `Basic ${btoa([username, password].join(":"))}`; } - const formId = formInfo.formData.get(formIdFieldName); - - if (formId === undefined) { - return { success: false, errors: ["No form id in FormData"] }; - } - const payload = { email: formToEmail(formInfo), // globally unique form id (can be used for unsubscribing) - formId: [formInfo.projectId, formId].join("--"), - action: formInfo.action, - method: formInfo.method, - formData: Object.fromEntries(getFormEntries(formInfo.formData)), + formId: formInfo.formId, + action: null, + method: "post", + formData: formInfo.formData, }; let response: Response; diff --git a/packages/form-handlers/src/shared.ts b/packages/form-handlers/src/shared.ts index 9742deca72b1..24560ee6ad1f 100644 --- a/packages/form-handlers/src/shared.ts +++ b/packages/form-handlers/src/shared.ts @@ -5,14 +5,11 @@ export const formBotFieldName = `${formHiddenFieldPrefix}-bot`; // Input data common for all handlers export type FormInfo = { - projectId: string; + formId: string; pageUrl: string; formData: FormData; toEmail: string; fromEmail: string; - // null as serializable - action: string | null; - method: "get" | "post"; }; export type EmailInfo = { @@ -26,14 +23,6 @@ export type EmailInfo = { export type Result = { success: true } | { success: false; errors: string[] }; -/** Returns form entries that should be send in email: removes `File` entries and `formId` */ -export const getFormEntries = (formData: FormData): [string, string][] => - [...formData.entries()].flatMap(([key, value]) => - key.startsWith(formHiddenFieldPrefix) === false && typeof value === "string" - ? [[key, value]] - : [] - ); - const getDomain = (url: string) => { try { return new URL(url).hostname; @@ -53,7 +42,7 @@ export const formToEmail = ({ html += ""; - for (const [key, value] of getFormEntries(formData)) { + for (const [key, value] of formData) { html += ``; txt += `${key}: ${value}\n`; } diff --git a/packages/sdk/src/resource-loader.ts b/packages/sdk/src/resource-loader.ts index 7b5e81487860..bb6c5afdcc8e 100644 --- a/packages/sdk/src/resource-loader.ts +++ b/packages/sdk/src/resource-loader.ts @@ -28,14 +28,15 @@ export const loadResource = async ( if ( response.ok && // accept json by default and when specified explicitly - (requestHeaders.has("accept") === false || - requestHeaders.get("accept") === "application/json") + (response.headers.has("content-type") === false || + response.headers.get("content-type")?.includes("application/json")) ) { data = await response.json(); } else { data = await response.text(); } return { + ok: response.ok, data, status: response.status, statusText: response.statusText, @@ -43,6 +44,7 @@ export const loadResource = async ( } catch (error) { const message = (error as unknown as Error).message; return { + ok: false, data: undefined, status: 500, statusText: message,
${key}:${value}