Skip to content

Commit

Permalink
feat: submit webhook form without n8n
Browse files Browse the repository at this point in the history
Closes #3789

Here stopped submitting webhook form with custom action
to n8n and requested directly from generated code.
This has a few benefits

- self-hosted websites (vercel, netlify) no longer have to setup n8n to support forms
- we can pay n8n for these executions no more
- user no longer have to unsubscribe from emails when setup custom webhook
  • Loading branch information
TrySound committed Jul 28, 2024
1 parent d7531b7 commit 3afbc67
Show file tree
Hide file tree
Showing 20 changed files with 452 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
});

Expand Down
38 changes: 26 additions & 12 deletions fixtures/webstudio-cloudflare-template/app/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
});

Expand Down
38 changes: 26 additions & 12 deletions fixtures/webstudio-custom-template/app/routes/[world]._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
});

Expand Down
38 changes: 26 additions & 12 deletions fixtures/webstudio-custom-template/app/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
});

Expand Down
Loading

0 comments on commit 3afbc67

Please sign in to comment.