n8n-nodes-formbase 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,9 +5,10 @@ Community node for [n8n](https://n8n.io) that starts workflows when a [formbase]
5
5
  ## Features
6
6
 
7
7
  - Trigger on completed submissions.
8
- - Trigger on abandoned submissions when partial submission tracking is enabled.
8
+ - Trigger on abandoned submissions after a selected 12-hour, 1-day, 3-day, or 1-week idle window.
9
9
  - Load forms dynamically from every workspace available to the credential.
10
10
  - Register and remove formbase webhook subscriptions with the n8n workflow lifecycle.
11
+ - Verify every webhook with HMAC-SHA256 and reject stale or forged requests.
11
12
  - Connect through workspace-scoped OAuth 2.1 with PKCE and automatic refresh-token rotation.
12
13
 
13
14
  ## Install
@@ -36,12 +37,20 @@ Self-hosted n8n must use configured HTTPS public URL for OAuth callback. Loopbac
36
37
  ## Use trigger
37
38
 
38
39
  1. Add **formbase Trigger** to a workflow.
39
- 2. Select form and event.
40
+ 2. Select form and event. For an abandoned-submission event, select how long the response must remain unchanged.
40
41
  3. For a test execution, select **Listen for Test Event**, then submit the selected form.
41
42
  4. Activate the workflow. n8n registers its production webhook with formbase and removes it when the workflow is deactivated or deleted.
42
43
 
43
44
  n8n webhook URL must be publicly reachable over HTTPS. For reverse-proxy or tunnel deployments, configure n8n's `WEBHOOK_URL` so generated webhook URLs use public origin.
44
45
 
46
+ n8n generates a separate 256-bit signing secret for each registration. Incoming requests must contain a valid `X-formbase-Signature` header with a timestamp no more than five minutes old. Missing, stale, or invalid signatures receive `401 Unauthorized` and do not start the workflow.
47
+
48
+ Abandoned-submission timing is enforced by formbase, not n8n. formbase checks incomplete responses hourly and calls the registered n8n webhook after the selected idle window, so delivery can occur up to about one hour after the threshold.
49
+
50
+ ## Example workflow
51
+
52
+ Import [`examples/formbase-submission.json`](examples/formbase-submission.json), connect formbase credential, select form, then activate workflow. Example maps event ID, event type, submission ID, respondent email, and form name into stable output fields.
53
+
45
54
  ## Output
46
55
 
47
56
  Each webhook produces one n8n item containing formbase payload:
@@ -76,7 +85,15 @@ Each webhook produces one n8n item containing formbase payload:
76
85
  }
77
86
  ```
78
87
 
79
- `eventType` is `SUBMIT_RESPONSE` for a new completed or abandoned response and `UPDATE_RESPONSE` when an existing response changes. Use `eventId` to deduplicate retries.
88
+ Delivered payloads use these `eventType` values:
89
+
90
+ | `eventType` | Meaning |
91
+ | ------------------ | ---------------------------------------------------------- |
92
+ | `SUBMIT_RESPONSE` | A respondent completed a new response. |
93
+ | `UPDATE_RESPONSE` | An existing completed response changed. |
94
+ | `ABANDON_RESPONSE` | An incomplete response reached the configured idle window. |
95
+
96
+ Webhook registration events (`submission_created` and `submission_abandoned`) select which deliveries trigger the workflow. Payload `eventType` identifies what happened to the response. Use `eventId` to deduplicate retries.
80
97
 
81
98
  Full contracts: [formbase API methods](https://docs.formbase.so/developers/rest-api) and [webhook reference](https://docs.formbase.so/developers/webhooks-reference).
82
99
 
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FormbaseTrigger = void 0;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
5
  const constants_1 = require("./constants");
6
+ const FormbaseWebhookSignature_1 = require("./FormbaseWebhookSignature");
6
7
  const GenericFunctions_1 = require("./GenericFunctions");
7
8
  const FORMS_PAGE_SIZE = 100;
8
9
  async function listWorkspaceForms(context, workspace) {
@@ -24,8 +25,29 @@ async function listWorkspaceForms(context, workspace) {
24
25
  } while (cursor);
25
26
  return forms;
26
27
  }
27
- function findWebhookSubscription(subscriptions, targetUrl, eventType) {
28
- return subscriptions.find((subscription) => subscription.targetUrl === targetUrl && subscription.provider === 'n8n' && subscription.eventType === eventType);
28
+ function findWebhookSubscription(subscriptions, targetUrl, eventType, idleWindow) {
29
+ return subscriptions.find((subscription) => subscription.targetUrl === targetUrl &&
30
+ subscription.provider === 'n8n' &&
31
+ subscription.eventType === eventType &&
32
+ subscription.idleWindow === idleWindow);
33
+ }
34
+ function findWebhookSubscriptionsByIdentity(subscriptions, targetUrl, eventType) {
35
+ return subscriptions.filter((subscription) => subscription.targetUrl === targetUrl && subscription.provider === 'n8n' && subscription.eventType === eventType);
36
+ }
37
+ function getIdleWindow(context, eventType) {
38
+ if (eventType === constants_1.FORMBASE_WEBHOOK_EVENTS.submissionCreated)
39
+ return undefined;
40
+ const idleWindow = context.getNodeParameter('idleWindow');
41
+ if (!(0, constants_1.isFormbaseIdleWindow)(idleWindow)) {
42
+ throw new n8n_workflow_1.NodeApiError(context.getNode(), {
43
+ message: `Idle window must be one of: ${constants_1.FORMBASE_IDLE_WINDOW_OPTIONS.map((option) => option.value).join(', ')}`,
44
+ });
45
+ }
46
+ return idleWindow;
47
+ }
48
+ function clearWebhookRegistration(webhookData) {
49
+ delete webhookData.subscriptionId;
50
+ delete webhookData.webhookSecret;
29
51
  }
30
52
  class FormbaseTrigger {
31
53
  constructor() {
@@ -37,7 +59,6 @@ class FormbaseTrigger {
37
59
  version: 1,
38
60
  subtitle: '={{ $parameter["event"] === "submission_created" ? "On submission created" : "On submission abandoned" }}',
39
61
  description: 'Starts the workflow when a formbase form receives a submission',
40
- usableAsTool: true,
41
62
  defaults: {
42
63
  name: 'formbase Trigger',
43
64
  },
@@ -98,6 +119,20 @@ class FormbaseTrigger {
98
119
  default: 'submission_created',
99
120
  description: 'Event to subscribe to. Abandoned submissions require partial submission tracking.',
100
121
  },
122
+ {
123
+ displayName: 'Consider Abandoned After',
124
+ name: 'idleWindow',
125
+ type: 'options',
126
+ displayOptions: {
127
+ show: {
128
+ event: [constants_1.FORMBASE_WEBHOOK_EVENTS.submissionAbandoned],
129
+ },
130
+ },
131
+ options: [...constants_1.FORMBASE_IDLE_WINDOW_OPTIONS],
132
+ default: '12h',
133
+ required: true,
134
+ description: 'Runs after the response has no saved changes for this long. The hourly sweep can add up to about one hour.',
135
+ },
101
136
  ],
102
137
  };
103
138
  this.methods = {
@@ -126,15 +161,29 @@ class FormbaseTrigger {
126
161
  if (!formId)
127
162
  return false;
128
163
  const eventType = this.getNodeParameter('event');
164
+ const idleWindow = getIdleWindow(this, eventType);
129
165
  const webhookData = this.getWorkflowStaticData('node');
130
166
  const result = (await GenericFunctions_1.formbaseApiRequest.call(this, 'webhooks.list', {
131
167
  formId,
132
168
  }));
133
- const match = findWebhookSubscription(result.items, webhookUrl, eventType);
134
- if (match) {
135
- webhookData.subscriptionId = match.subscriptionId;
136
- return true;
169
+ const match = findWebhookSubscription(result.items, webhookUrl, eventType, idleWindow);
170
+ const staleMatches = findWebhookSubscriptionsByIdentity(result.items, webhookUrl, eventType).filter((subscription) => subscription.subscriptionId !== (match === null || match === void 0 ? void 0 : match.subscriptionId));
171
+ for (const staleMatch of staleMatches) {
172
+ await GenericFunctions_1.formbaseApiRequest.call(this, 'webhooks.delete', {
173
+ subscriptionId: staleMatch.subscriptionId,
174
+ });
137
175
  }
176
+ if (!match) {
177
+ clearWebhookRegistration(webhookData);
178
+ return false;
179
+ }
180
+ const registrationMatchesStaticData = webhookData.subscriptionId === match.subscriptionId && typeof webhookData.webhookSecret === 'string';
181
+ if (registrationMatchesStaticData)
182
+ return true;
183
+ await GenericFunctions_1.formbaseApiRequest.call(this, 'webhooks.delete', {
184
+ subscriptionId: match.subscriptionId,
185
+ });
186
+ clearWebhookRegistration(webhookData);
138
187
  return false;
139
188
  },
140
189
  async create() {
@@ -143,21 +192,28 @@ class FormbaseTrigger {
143
192
  return false;
144
193
  const formId = this.getNodeParameter('formId');
145
194
  const eventType = this.getNodeParameter('event');
195
+ const idleWindow = getIdleWindow(this, eventType);
196
+ const webhookSecret = (0, FormbaseWebhookSignature_1.createFormbaseWebhookSecret)();
146
197
  const created = (await GenericFunctions_1.formbaseApiRequest.call(this, 'webhooks.create', {
147
198
  formId,
148
199
  targetUrl: webhookUrl,
149
200
  provider: 'n8n',
150
201
  eventType,
202
+ ...(idleWindow !== undefined ? { idleWindow } : {}),
203
+ signingSecret: webhookSecret,
151
204
  }));
152
205
  const webhookData = this.getWorkflowStaticData('node');
153
206
  webhookData.subscriptionId = created.subscriptionId;
207
+ webhookData.webhookSecret = webhookSecret;
154
208
  return true;
155
209
  },
156
210
  async delete() {
157
211
  const webhookData = this.getWorkflowStaticData('node');
158
212
  const subscriptionId = webhookData.subscriptionId;
159
- if (typeof subscriptionId !== 'string')
213
+ if (typeof subscriptionId !== 'string') {
214
+ clearWebhookRegistration(webhookData);
160
215
  return true;
216
+ }
161
217
  try {
162
218
  await GenericFunctions_1.formbaseApiRequest.call(this, 'webhooks.delete', {
163
219
  subscriptionId,
@@ -168,13 +224,17 @@ class FormbaseTrigger {
168
224
  return false;
169
225
  }
170
226
  }
171
- delete webhookData.subscriptionId;
227
+ clearWebhookRegistration(webhookData);
172
228
  return true;
173
229
  },
174
230
  },
175
231
  };
176
232
  }
177
233
  async webhook() {
234
+ if (!(0, FormbaseWebhookSignature_1.verifyFormbaseWebhookSignature)(this)) {
235
+ this.getResponseObject().status(401).send('Unauthorized').end();
236
+ return { noWebhookResponse: true };
237
+ }
178
238
  const body = this.getBodyData();
179
239
  return {
180
240
  workflowData: [this.helpers.returnJsonArray(body)],
@@ -1 +1 @@
1
- {"version":3,"file":"FormbaseTrigger.node.js","sourceRoot":"","sources":["../../../nodes/Formbase/FormbaseTrigger.node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FormbaseTrigger.node.js","sourceRoot":"","sources":["../../../nodes/Formbase/FormbaseTrigger.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { IWebhookFunctions } from 'n8n-workflow';
2
+ export declare function createFormbaseWebhookSecret(): string;
3
+ export declare function verifyFormbaseWebhookSignature(context: IWebhookFunctions): boolean;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createFormbaseWebhookSecret = createFormbaseWebhookSecret;
4
+ exports.verifyFormbaseWebhookSignature = verifyFormbaseWebhookSignature;
5
+ const node_crypto_1 = require("node:crypto");
6
+ const SIGNATURE_HEADER_PATTERN = /^t=(\d+),sha256=([a-f0-9]{64})$/;
7
+ const SIGNATURE_MAX_AGE_SECONDS = 5 * 60;
8
+ function getRawBody(request) {
9
+ if (!('rawBody' in request))
10
+ return undefined;
11
+ const rawBody = request.rawBody;
12
+ if (Buffer.isBuffer(rawBody))
13
+ return rawBody;
14
+ if (typeof rawBody === 'string')
15
+ return Buffer.from(rawBody);
16
+ return undefined;
17
+ }
18
+ function createFormbaseWebhookSecret() {
19
+ return `whsec_${(0, node_crypto_1.randomBytes)(32).toString('hex')}`;
20
+ }
21
+ function verifyFormbaseWebhookSignature(context) {
22
+ const webhookData = context.getWorkflowStaticData('node');
23
+ const secret = webhookData.webhookSecret;
24
+ if (typeof secret !== 'string' || secret.length === 0)
25
+ return false;
26
+ const signatureHeader = context.getHeaderData()['x-formbase-signature'];
27
+ if (typeof signatureHeader !== 'string')
28
+ return false;
29
+ const match = SIGNATURE_HEADER_PATTERN.exec(signatureHeader);
30
+ if (!match)
31
+ return false;
32
+ const [, timestamp, signatureHex] = match;
33
+ const timestampSeconds = Number(timestamp);
34
+ if (!Number.isSafeInteger(timestampSeconds))
35
+ return false;
36
+ const currentTimestampSeconds = Math.floor(Date.now() / 1000);
37
+ if (Math.abs(currentTimestampSeconds - timestampSeconds) > SIGNATURE_MAX_AGE_SECONDS)
38
+ return false;
39
+ const rawBody = getRawBody(context.getRequestObject());
40
+ if (!rawBody)
41
+ return false;
42
+ const expectedSignature = (0, node_crypto_1.createHmac)('sha256', secret).update(timestamp).update('.').update(rawBody).digest();
43
+ const receivedSignature = Buffer.from(signatureHex, 'hex');
44
+ return expectedSignature.length === receivedSignature.length && (0, node_crypto_1.timingSafeEqual)(expectedSignature, receivedSignature);
45
+ }
46
+ //# sourceMappingURL=FormbaseWebhookSignature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormbaseWebhookSignature.js","sourceRoot":"","sources":["../../../nodes/Formbase/FormbaseWebhookSignature.ts"],"names":[],"mappings":";;AAgBA,kEAEC;AAED,wEAyBC;AA7CD,6CAAsE;AAItE,MAAM,wBAAwB,GAAG,iCAAiC,CAAA;AAClE,MAAM,yBAAyB,GAAG,CAAC,GAAG,EAAE,CAAA;AAExC,SAAS,UAAU,CAAC,OAA0D;IAC5E,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,CAAC;QAAE,OAAO,SAAS,CAAA;IAE7C,MAAM,OAAO,GAAY,OAAO,CAAC,OAAO,CAAA;IACxC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAA;IAC5C,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5D,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAgB,2BAA2B;IACzC,OAAO,SAAS,IAAA,yBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAA;AACnD,CAAC;AAED,SAAgB,8BAA8B,CAAC,OAA0B;IACvE,MAAM,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAA;IACzD,MAAM,MAAM,GAAG,WAAW,CAAC,aAAa,CAAA;IACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAEnE,MAAM,eAAe,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,sBAAsB,CAAC,CAAA;IACvE,IAAI,OAAO,eAAe,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAErD,MAAM,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAC5D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAExB,MAAM,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAA;IACzC,MAAM,gBAAgB,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;IAC1C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC;QAAE,OAAO,KAAK,CAAA;IAEzD,MAAM,uBAAuB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IAC7D,IAAI,IAAI,CAAC,GAAG,CAAC,uBAAuB,GAAG,gBAAgB,CAAC,GAAG,yBAAyB;QAAE,OAAO,KAAK,CAAA;IAElG,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAA;IACtD,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAE1B,MAAM,iBAAiB,GAAG,IAAA,wBAAU,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAA;IAC7G,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;IAE1D,OAAO,iBAAiB,CAAC,MAAM,KAAK,iBAAiB,CAAC,MAAM,IAAI,IAAA,6BAAe,EAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAA;AACvH,CAAC"}
@@ -7,3 +7,18 @@ export declare const FORMBASE_WEBHOOK_EVENTS: {
7
7
  readonly submissionAbandoned: "submission_abandoned";
8
8
  };
9
9
  export type FormbaseWebhookEvent = (typeof FORMBASE_WEBHOOK_EVENTS)[keyof typeof FORMBASE_WEBHOOK_EVENTS];
10
+ export declare const FORMBASE_IDLE_WINDOW_OPTIONS: readonly [{
11
+ readonly name: "1 Day";
12
+ readonly value: "1d";
13
+ }, {
14
+ readonly name: "1 Week";
15
+ readonly value: "1w";
16
+ }, {
17
+ readonly name: "12 Hours";
18
+ readonly value: "12h";
19
+ }, {
20
+ readonly name: "3 Days";
21
+ readonly value: "3d";
22
+ }];
23
+ export type FormbaseIdleWindow = (typeof FORMBASE_IDLE_WINDOW_OPTIONS)[number]['value'];
24
+ export declare function isFormbaseIdleWindow(value: unknown): value is FormbaseIdleWindow;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FORMBASE_WEBHOOK_EVENTS = exports.FORMBASE_OAUTH2_CREDENTIAL_NAME = exports.FORMBASE_API_RESOURCE_URL = exports.FORMBASE_API_PATH = exports.DEFAULT_FORMBASE_API_URL = void 0;
3
+ exports.FORMBASE_IDLE_WINDOW_OPTIONS = exports.FORMBASE_WEBHOOK_EVENTS = exports.FORMBASE_OAUTH2_CREDENTIAL_NAME = exports.FORMBASE_API_RESOURCE_URL = exports.FORMBASE_API_PATH = exports.DEFAULT_FORMBASE_API_URL = void 0;
4
+ exports.isFormbaseIdleWindow = isFormbaseIdleWindow;
4
5
  exports.DEFAULT_FORMBASE_API_URL = 'https://api.formbase.so';
5
6
  exports.FORMBASE_API_PATH = '/api/v1';
6
7
  exports.FORMBASE_API_RESOURCE_URL = `${exports.DEFAULT_FORMBASE_API_URL}${exports.FORMBASE_API_PATH}`;
@@ -9,4 +10,14 @@ exports.FORMBASE_WEBHOOK_EVENTS = {
9
10
  submissionCreated: 'submission_created',
10
11
  submissionAbandoned: 'submission_abandoned',
11
12
  };
13
+ exports.FORMBASE_IDLE_WINDOW_OPTIONS = [
14
+ { name: '1 Day', value: '1d' },
15
+ { name: '1 Week', value: '1w' },
16
+ { name: '12 Hours', value: '12h' },
17
+ { name: '3 Days', value: '3d' },
18
+ ];
19
+ const FORMBASE_IDLE_WINDOW_VALUES = new Set(exports.FORMBASE_IDLE_WINDOW_OPTIONS.map((option) => option.value));
20
+ function isFormbaseIdleWindow(value) {
21
+ return typeof value === 'string' && FORMBASE_IDLE_WINDOW_VALUES.has(value);
22
+ }
12
23
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../nodes/Formbase/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,wBAAwB,GAAG,yBAAyB,CAAA;AAEpD,QAAA,iBAAiB,GAAG,SAAS,CAAA;AAE7B,QAAA,yBAAyB,GAAG,GAAG,gCAAwB,GAAG,yBAAiB,EAAE,CAAA;AAE7E,QAAA,+BAA+B,GAAG,mBAAmB,CAAA;AAErD,QAAA,uBAAuB,GAAG;IACrC,iBAAiB,EAAE,oBAAoB;IACvC,mBAAmB,EAAE,sBAAsB;CACnC,CAAA"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../nodes/Formbase/constants.ts"],"names":[],"mappings":";;;AA4BA,oDAEC;AA9BY,QAAA,wBAAwB,GAAG,yBAAyB,CAAA;AAEpD,QAAA,iBAAiB,GAAG,SAAS,CAAA;AAE7B,QAAA,yBAAyB,GAAG,GAAG,gCAAwB,GAAG,yBAAiB,EAAE,CAAA;AAE7E,QAAA,+BAA+B,GAAG,mBAAmB,CAAA;AAErD,QAAA,uBAAuB,GAAG;IACrC,iBAAiB,EAAE,oBAAoB;IACvC,mBAAmB,EAAE,sBAAsB;CACnC,CAAA;AAIG,QAAA,4BAA4B,GAAG;IAC1C,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE;IAC9B,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;IAC/B,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE;IAClC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;CACvB,CAAA;AAIV,MAAM,2BAA2B,GAAwB,IAAI,GAAG,CAC9D,oCAA4B,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAC3D,CAAA;AAED,SAAgB,oBAAoB,CAAC,KAAc;IACjD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,2BAA2B,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AAC5E,CAAC"}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-formbase",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "description": "n8n community node for formbase — trigger workflows from form submissions.",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -32,7 +32,8 @@
32
32
  "prepublishOnly": "npm test && npm run build && npm run lint"
33
33
  },
34
34
  "files": [
35
- "dist"
35
+ "dist",
36
+ "examples"
36
37
  ],
37
38
  "engines": {
38
39
  "node": ">=22"
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "Handle formbase submission",
3
+ "nodes": [
4
+ {
5
+ "parameters": {
6
+ "formId": "",
7
+ "event": "submission_created"
8
+ },
9
+ "type": "n8n-nodes-formbase.formbaseTrigger",
10
+ "typeVersion": 1,
11
+ "position": [0, 0],
12
+ "id": "16e911f0-6385-4acc-8286-1afb15eb035c",
13
+ "name": "formbase Trigger"
14
+ },
15
+ {
16
+ "parameters": {
17
+ "assignments": {
18
+ "assignments": [
19
+ {
20
+ "id": "cdcb57d7-377e-45e2-8da9-63e52f4690b4",
21
+ "name": "eventId",
22
+ "value": "={{ $json.eventId }}",
23
+ "type": "string"
24
+ },
25
+ {
26
+ "id": "9da94c68-fcf8-4f79-b78e-5bb78c043aec",
27
+ "name": "eventType",
28
+ "value": "={{ $json.eventType }}",
29
+ "type": "string"
30
+ },
31
+ {
32
+ "id": "b27b42be-fc5d-491f-a93b-02a7fa4e63f8",
33
+ "name": "submissionId",
34
+ "value": "={{ $json.submission.id }}",
35
+ "type": "string"
36
+ },
37
+ {
38
+ "id": "2b171786-cb32-4e73-96e5-d60f39060fe1",
39
+ "name": "respondentEmail",
40
+ "value": "={{ $json.submission.respondentEmail }}",
41
+ "type": "string"
42
+ },
43
+ {
44
+ "id": "a6366cdf-c3b9-4bdc-be3c-723d2bfab7a4",
45
+ "name": "formName",
46
+ "value": "={{ $json.form.name }}",
47
+ "type": "string"
48
+ }
49
+ ]
50
+ },
51
+ "options": {}
52
+ },
53
+ "type": "n8n-nodes-base.set",
54
+ "typeVersion": 3.4,
55
+ "position": [240, 0],
56
+ "id": "27abc7e3-21e9-4654-9078-b12b60420f6d",
57
+ "name": "Prepare submission"
58
+ }
59
+ ],
60
+ "pinData": {},
61
+ "connections": {
62
+ "formbase Trigger": {
63
+ "main": [
64
+ [
65
+ {
66
+ "node": "Prepare submission",
67
+ "type": "main",
68
+ "index": 0
69
+ }
70
+ ]
71
+ ]
72
+ }
73
+ },
74
+ "active": false,
75
+ "settings": {
76
+ "executionOrder": "v1"
77
+ },
78
+ "versionId": "0f0cc0ea-543e-43ac-bf55-9256b1ee5f85",
79
+ "meta": {
80
+ "templateCredsSetupCompleted": false
81
+ },
82
+ "tags": []
83
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-formbase",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "description": "n8n community node for formbase — trigger workflows from form submissions.",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -32,7 +32,8 @@
32
32
  "prepublishOnly": "npm test && npm run build && npm run lint"
33
33
  },
34
34
  "files": [
35
- "dist"
35
+ "dist",
36
+ "examples"
36
37
  ],
37
38
  "engines": {
38
39
  "node": ">=22"