n8n-nodes-formbase 0.9.1 → 0.10.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 +74 -13
- package/dist/credentials/FormbaseOAuth2Api.credentials.js +1 -1
- package/dist/credentials/FormbaseOAuth2Api.credentials.js.map +1 -1
- package/dist/nodes/Formbase/FormFields.d.ts +11 -0
- package/dist/nodes/Formbase/FormFields.js +97 -0
- package/dist/nodes/Formbase/FormFields.js.map +1 -0
- package/dist/nodes/Formbase/Formbase.node.d.ts +12 -5
- package/dist/nodes/Formbase/Formbase.node.js +23 -742
- package/dist/nodes/Formbase/Formbase.node.js.map +1 -1
- package/dist/nodes/Formbase/FormbaseCatalog.d.ts +20 -0
- package/dist/nodes/Formbase/FormbaseCatalog.js +20 -0
- package/dist/nodes/Formbase/FormbaseCatalog.js.map +1 -1
- package/dist/nodes/Formbase/FormbaseMethods.d.ts +15 -0
- package/dist/nodes/Formbase/FormbaseMethods.js +68 -0
- package/dist/nodes/Formbase/FormbaseMethods.js.map +1 -0
- package/dist/nodes/Formbase/FormbaseTrigger.node.d.ts +3 -2
- package/dist/nodes/Formbase/FormbaseTrigger.node.js +38 -49
- package/dist/nodes/Formbase/FormbaseTrigger.node.js.map +1 -1
- package/dist/nodes/Formbase/GenericFunctions.js +2 -2
- package/dist/nodes/Formbase/GenericFunctions.js.map +1 -1
- package/dist/nodes/Formbase/actions/RequestCreate.d.ts +4 -0
- package/dist/nodes/Formbase/actions/RequestCreate.js +142 -0
- package/dist/nodes/Formbase/actions/RequestCreate.js.map +1 -0
- package/dist/nodes/Formbase/actions/RequestDescription.d.ts +3 -0
- package/dist/nodes/Formbase/actions/RequestDescription.js +468 -0
- package/dist/nodes/Formbase/actions/RequestDescription.js.map +1 -0
- package/dist/nodes/Formbase/actions/RequestOperations.d.ts +7 -0
- package/dist/nodes/Formbase/actions/RequestOperations.js +45 -0
- package/dist/nodes/Formbase/actions/RequestOperations.js.map +1 -0
- package/dist/nodes/Formbase/constants.d.ts +1 -1
- package/dist/nodes/Formbase/constants.js +2 -2
- package/dist/nodes/Formbase/constants.js.map +1 -1
- package/dist/package.json +3 -3
- package/examples/formbase-request-wait.json +23 -11
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -5,10 +5,12 @@ Community nodes for [n8n](https://n8n.io) that create [formbase](https://formbas
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **formbase** node: create a request for a form and a recipient, with prefilled and read-only fields, context, reminders, expiry and delivery by email; get, cancel, remind, list requests; replay a request's callback.
|
|
8
|
+
- Map a request's fields like any n8n mapping: pick the form, and **Fields** lists its questions with a dropdown for each choice, a number or date input where formbase expects one, and the form's context fields. **Map Automatically** sends an input item's keys that match the form's field keys.
|
|
9
|
+
- Search forms by name, and pick a request from the workspace's newest ones, or pass an ID.
|
|
8
10
|
- Pause a workflow until the recipient answers: **Wait for the Outcome** points the request's callback at n8n's Wait node, so the workflow resumes with the completed, expired or canceled request as its input.
|
|
9
11
|
- **formbase Trigger** node: start a workflow when a request is completed, expires or is canceled, or when a respondent submits a form through its public link. `data.request` carries the request ID and the caller's `externalId` and `metadata`, so the workflow that created the request can pick up where it left off.
|
|
10
12
|
- Trigger on abandoned submissions after a selected 12-hour, 1-day, 3-day, or 1-week idle window.
|
|
11
|
-
- Load forms dynamically from the workspace the credential is scoped to, across every page.
|
|
13
|
+
- Load forms dynamically from the workspace the credential is scoped to, across every page, with unpublished forms marked.
|
|
12
14
|
- Register and remove formbase webhook subscriptions with the n8n workflow lifecycle.
|
|
13
15
|
- Verify every webhook with HMAC-SHA256 and reject stale or forged requests.
|
|
14
16
|
- Connect through workspace-scoped OAuth 2.1 with PKCE and automatic refresh-token rotation.
|
|
@@ -51,17 +53,35 @@ Add **formbase** to a workflow, select the **Request** resource and an operation
|
|
|
51
53
|
|
|
52
54
|
### Create a request
|
|
53
55
|
|
|
54
|
-
1. Pick the **Form
|
|
56
|
+
1. Pick the **Form**: search the credential's workspace by name, or paste its ID. Forms that are not published yet read "(not published)"; a request needs a published form.
|
|
55
57
|
2. Enter the **Recipient Email** when formbase should email the link or send reminders; leave it empty for a request you hand out yourself.
|
|
56
|
-
3. Under **
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
3. Under **Fields**, fill in the answers the recipient should find prefilled, and the form's context fields (marked `· context`): values stored with the request and returned with the answers that the recipient never sees. Each field shows its question and field key, and takes the shape formbase expects:
|
|
59
|
+
|
|
60
|
+
| Field | Input |
|
|
61
|
+
| ------------------------------------ | ------------------------------------------------------------ |
|
|
62
|
+
| Text, email, phone, URL, long text | Text |
|
|
63
|
+
| Number, rating, scale | Number |
|
|
64
|
+
| Switch | On or off |
|
|
65
|
+
| Date, time | Date or time picker; a date is sent as `2026-03-04` |
|
|
66
|
+
| Single choice (radio, select) | Dropdown of the options; the option key is sent |
|
|
67
|
+
| Multiple choice, ranking, pictures | JSON list of option keys, such as `["news", "offers"]`; the label lists the keys |
|
|
68
|
+
| Matrix | JSON object of row key to column key |
|
|
69
|
+
| Repeating group | JSON list of rows, such as `[{ "name": "Ada" }]` |
|
|
70
|
+
|
|
71
|
+
Leave a field empty to leave it unanswered. With **Map Automatically**, the node sends every key of the input item that is a field key of the form and ignores the rest, so an item like `{ "company_name": "Acme", "case_id": "CASE-9" }` needs no mapping at all. Fields a caller can never fill in, such as file uploads, signatures, payments, bookings and calculated fields, are not listed.
|
|
72
|
+
4. Under **Read-Only Fields**, pick the prefilled fields the recipient may see but not change.
|
|
73
|
+
5. Under **Documents**, add the files the recipient should read or download, such as a contract or a price list. Each entry names an **Input Binary Field** of the incoming item (a file from an HTTP Request, Google Drive or Read Binary File node), an optional **Name** the recipient sees, and the **Documents Block** it goes into. The form needs a Documents block; leave the block empty when the form has one, and pick it when the form has several. Files are PDFs or images of up to 25 MB. The node uploads each file before it creates the request, and the recipient sees them below the documents the form already has.
|
|
74
|
+
6. In **Additional Fields**, set **Delivery** to `Email` to have formbase send the link, **Reminders** such as `2d, 5d` (leave the field empty to send none; remove it to inherit the form's schedule), **Expires At**, **Language**, **Recipient Name**, **Metadata** (a JSON object handed back with every event), **Test Mode**, or a **Callback URL** of your own.
|
|
75
|
+
7. Set **External ID** to your own identifier, for example `{{ $execution.id }}`. The node also sends it as the request's `idempotencyKey`, so a retried execution gets the same request back (`deduplicated: true`) instead of creating a second one.
|
|
62
76
|
|
|
63
77
|
Every request also carries `formId`, `status`, `url`, `externalId`, `isTest`, `deliveryStatus`, `hasCallback`, `remindersSent`, `expiresAt` and `createdAt` in its summary.
|
|
64
78
|
|
|
79
|
+
**Get**, **Remind**, **Cancel** and **Replay Callback** take the **Request** by ID, usually `{{ $json.id }}` from a Create node, or from a list of the workspace's newest requests, labelled by recipient, status and External ID.
|
|
80
|
+
|
|
81
|
+
#### Node versions
|
|
82
|
+
|
|
83
|
+
New nodes are version 2. A workflow saved with version 1 keeps it and keeps working unchanged: its Form is a plain dropdown, its Request ID a text box, and it lists **Prefill** and **Context** values as key/value rows, with **Parse as JSON** for a value that is not text. To move such a node to the Fields mapper, add a new formbase node and copy the values over.
|
|
84
|
+
|
|
65
85
|
### Wait for the outcome
|
|
66
86
|
|
|
67
87
|
A request is answered minutes or days later. To pause the workflow until then:
|
|
@@ -107,7 +127,7 @@ One channel, one event: **Public Link Submission Created** runs for public-link
|
|
|
107
127
|
|
|
108
128
|
## Example workflows
|
|
109
129
|
|
|
110
|
-
- [`examples/formbase-request-wait.json`](examples/formbase-request-wait.json): a formbase **Create** node with **Wait for the Outcome**, a **Wait** node, a **Switch** on `request.completed` / `request.expired` / `request.canceled`, and a **Set** node that reads the request ID, outcome and an answer. Connect the credential, pick a form with a `company_name` field (or change the
|
|
130
|
+
- [`examples/formbase-request-wait.json`](examples/formbase-request-wait.json): a formbase **Create** node with **Wait for the Outcome**, a **Wait** node, a **Switch** on `request.completed` / `request.expired` / `request.canceled`, and a **Set** node that reads the request ID, outcome and an answer. Connect the credential, pick a form with a `company_name` field (or change the Fields mapping and the Set node), and run it.
|
|
111
131
|
- [`examples/formbase-submission.json`](examples/formbase-submission.json): a **formbase Trigger** that maps event ID, event type, submission ID, respondent email, and form name into stable output fields. Connect the credential, select a form, then activate the workflow.
|
|
112
132
|
|
|
113
133
|
## Output
|
|
@@ -119,7 +139,7 @@ Each webhook produces one n8n item containing the formbase event envelope. Every
|
|
|
119
139
|
"id": "evt_abc123",
|
|
120
140
|
"type": "submission.completed",
|
|
121
141
|
"createdAt": "2026-04-25T12:34:56.000Z",
|
|
122
|
-
"apiVersion": "2026-09-
|
|
142
|
+
"apiVersion": "2026-09-24",
|
|
123
143
|
"test": false,
|
|
124
144
|
"data": {
|
|
125
145
|
"form": { "id": "frm_abc123", "name": "Customer Feedback", "snapshotId": "snp_..." },
|
|
@@ -132,14 +152,53 @@ Each webhook produces one n8n item containing the formbase event envelope. Every
|
|
|
132
152
|
"pdfUrl": null,
|
|
133
153
|
"language": "en"
|
|
134
154
|
},
|
|
135
|
-
"answers": {
|
|
136
|
-
|
|
155
|
+
"answers": {
|
|
156
|
+
"recommend": 9,
|
|
157
|
+
"plan": "pro",
|
|
158
|
+
"book_a_call": {
|
|
159
|
+
"status": "confirmed",
|
|
160
|
+
"start": "2026-04-29T07:00:00.000Z",
|
|
161
|
+
"end": "2026-04-29T07:30:00.000Z",
|
|
162
|
+
"timeZone": "Europe/Oslo",
|
|
163
|
+
"attendee": { "name": "Grace Hopper", "email": "respondent@example.com" },
|
|
164
|
+
"meetingUrl": "https://app.cal.com/video/...",
|
|
165
|
+
"provider": "cal.com",
|
|
166
|
+
"providerBookingId": "...",
|
|
167
|
+
"eventTitle": "Intro call"
|
|
168
|
+
},
|
|
169
|
+
"pay_the_fee": {
|
|
170
|
+
"status": "paid",
|
|
171
|
+
"amount": 40,
|
|
172
|
+
"currency": "USD",
|
|
173
|
+
"amountRefunded": 0,
|
|
174
|
+
"receiptUrl": "https://pay.stripe.com/receipts/...",
|
|
175
|
+
"paidAt": "2026-04-25T12:30:00.000Z",
|
|
176
|
+
"refundedAt": null,
|
|
177
|
+
"disputedAt": null,
|
|
178
|
+
"provider": "stripe",
|
|
179
|
+
"providerPaymentIntentId": "pi_..."
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"display": {
|
|
183
|
+
"recommend": "9",
|
|
184
|
+
"plan": "Pro",
|
|
185
|
+
"book_a_call": "Intro call · Apr 29, 2026, 9:00 AM - 9:30 AM (Europe/Oslo) · Grace Hopper <respondent@example.com> · https://app.cal.com/video/...",
|
|
186
|
+
"pay_the_fee": "$40.00 USD · Paid"
|
|
187
|
+
}
|
|
137
188
|
}
|
|
138
189
|
}
|
|
139
190
|
```
|
|
140
191
|
|
|
141
192
|
Read a value with `{{ $json.data.answers.recommend }}`; the field keys come from `fields.list` (or the form's field Configure menu). A choice answer holds the readable option key (`"pro"`), and `display` holds its label (`"Pro"`). A repeating group is an array of row objects in `answers` and one joined line in `display`.
|
|
142
193
|
|
|
194
|
+
A **Schedule appointment** answer and a **Payment** answer are objects, and `display` keeps one line of text for each. Read one property with `{{ $json.data.answers.book_a_call.start }}` or `{{ $json.data.answers.pay_the_fee.amount }}`.
|
|
195
|
+
|
|
196
|
+
- A booking is `{ status, start, end, timeZone, attendee: { name, email }, meetingUrl, provider, providerBookingId, eventTitle }`. `status` is `confirmed`, `rescheduled`, `cancelled`, `rejected` or `no_show`. `start` and `end` are ISO 8601 instants. `meetingUrl` and `eventTitle` may be `null`.
|
|
197
|
+
- A payment is `{ status, amount, currency, amountRefunded, receiptUrl, paidAt, refundedAt, disputedAt, provider, providerPaymentIntentId }`. `status` is `paid`, `partially_refunded`, `refunded` or `disputed`. `amount` and `amountRefunded` are in the currency's major unit (`40` is $40.00), `currency` is upper-case ISO 4217, and the timestamps are ISO 8601 or `null`.
|
|
198
|
+
- formbase keeps both current: a rescheduled booking, a refund or a dispute rewrites the stored answer, so later events carry the new state. The change itself sends no event.
|
|
199
|
+
|
|
200
|
+
Before event `apiVersion` `2026-09-24`, a booking arrived as one sentence and a payment question had no answer. A workflow that read the booking as text reads `data.display.<field_key>` instead.
|
|
201
|
+
|
|
143
202
|
The node passes the envelope through unchanged — it does not flatten answers into the top level of the item. Nothing is dropped, every key stays where the formbase contract puts it, and a field key can never collide with an envelope key such as `type` or `test`. Map the handful of values a workflow needs with a Set node, as the example workflow does.
|
|
144
203
|
|
|
145
204
|
A submission event carries no channel field; the event `type` already says it came through the public link. `submission.updated` keeps the original `submittedAt`, and the envelope's `createdAt` is the time of the edit. `data.submission.updatedAt` is when the submission was last edited (`null` until the first edit), and `data.submission.editCount` counts the edits (`0` on a fresh submission).
|
|
@@ -153,7 +212,7 @@ A request event carries the request itself in `data.request`: `id`, `status`, `o
|
|
|
153
212
|
"id": "evt_req123",
|
|
154
213
|
"type": "request.completed",
|
|
155
214
|
"createdAt": "2026-09-22T12:34:56.000Z",
|
|
156
|
-
"apiVersion": "2026-09-
|
|
215
|
+
"apiVersion": "2026-09-24",
|
|
157
216
|
"test": false,
|
|
158
217
|
"data": {
|
|
159
218
|
"request": {
|
|
@@ -205,6 +264,8 @@ npm run build
|
|
|
205
264
|
npm run lint
|
|
206
265
|
```
|
|
207
266
|
|
|
267
|
+
The formbase node lives in `nodes/Formbase/`: `Formbase.node.ts` wires the node together, `actions/` holds its parameters (`RequestDescription.ts`), what each operation calls (`RequestOperations.ts`) and how Create builds its body (`RequestCreate.ts`), `FormFields.ts` maps `fields.list` onto the Fields mapper, and `FormbaseMethods.ts` holds the pickers both nodes share.
|
|
268
|
+
|
|
208
269
|
`npm test` runs unit tests plus lifecycle tests that drive both nodes against an in-process formbase API over real HTTP (`test/fakeFormbase.mts`). `npm run dev` starts n8n with the node loaded and rebuilds on changes. Compiled package files are written to `dist/`. Run `npm pack --dry-run` before publishing to inspect package contents.
|
|
209
270
|
|
|
210
271
|
### Run locally against formbase
|
|
@@ -4,7 +4,7 @@ exports.FormbaseOAuth2Api = void 0;
|
|
|
4
4
|
const constants_1 = require("../nodes/Formbase/constants");
|
|
5
5
|
class FormbaseOAuth2Api {
|
|
6
6
|
constructor() {
|
|
7
|
-
this.name = constants_1.
|
|
7
|
+
this.name = constants_1.FORMBASE_CREDENTIAL_TYPE;
|
|
8
8
|
this.extends = ['oAuth2Api'];
|
|
9
9
|
this.displayName = 'formbase OAuth2 API';
|
|
10
10
|
this.icon = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormbaseOAuth2Api.credentials.js","sourceRoot":"","sources":["../../credentials/FormbaseOAuth2Api.credentials.ts"],"names":[],"mappings":";;;AAEA,
|
|
1
|
+
{"version":3,"file":"FormbaseOAuth2Api.credentials.js","sourceRoot":"","sources":["../../credentials/FormbaseOAuth2Api.credentials.ts"],"names":[],"mappings":";;;AAEA,2DAAiG;AAEjG,MAAa,iBAAiB;IAA9B;QACE,SAAI,GAAG,oCAAwB,CAAA;QAE/B,YAAO,GAAG,CAAC,WAAW,CAAC,CAAA;QAGvB,gBAAW,GAAG,qBAAqB,CAAA;QAEnC,SAAI,GAAS;YACX,KAAK,EAAE,0CAA0C;YACjD,IAAI,EAAE,+CAA+C;SACtD,CAAA;QAED,qBAAgB,GAAG,wEAAwE,CAAA;QAE3F,eAAU,GAAsB;YAC9B;gBACE,WAAW,EAAE,iCAAiC;gBAC9C,IAAI,EAAE,8BAA8B;gBACpC,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,IAAI;aACd;YACD;gBACE,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,qCAAyB;gBAClC,QAAQ,EAAE,IAAI;aACf;SACF,CAAA;QAED,SAAI,GAA2B;YAC7B,OAAO,EAAE;gBACP,GAAG,EAAE,6BAA6B;gBAClC,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE;oBACJ,MAAM,EAAE,QAAQ;oBAChB,MAAM,EAAE,EAAE;iBACX;aACF;SACF,CAAA;IACH,CAAC;CAAA;AAzCD,8CAyCC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { INodePropertyOptions, ResourceMapperField } from 'n8n-workflow';
|
|
2
|
+
import type { FormField } from './FormbaseCatalog';
|
|
3
|
+
export interface FieldValues {
|
|
4
|
+
prefill: Record<string, unknown>;
|
|
5
|
+
context: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export declare function isPrefillable(field: FormField): boolean;
|
|
8
|
+
export declare function fieldOption(field: FormField): INodePropertyOptions;
|
|
9
|
+
export declare function mappableFields(fields: FormField[]): FormField[];
|
|
10
|
+
export declare function mapperField(field: FormField): ResourceMapperField;
|
|
11
|
+
export declare function splitFieldValues(fields: FormField[], values: Record<string, unknown>, onlyFormFields: boolean): FieldValues;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPrefillable = isPrefillable;
|
|
4
|
+
exports.fieldOption = fieldOption;
|
|
5
|
+
exports.mappableFields = mappableFields;
|
|
6
|
+
exports.mapperField = mapperField;
|
|
7
|
+
exports.splitFieldValues = splitFieldValues;
|
|
8
|
+
function isPrefillable(field) {
|
|
9
|
+
if (field.context === true)
|
|
10
|
+
return false;
|
|
11
|
+
if (field.calculated === true)
|
|
12
|
+
return false;
|
|
13
|
+
return field.prefillable !== false;
|
|
14
|
+
}
|
|
15
|
+
function fieldLabel(field) {
|
|
16
|
+
return field.title ? `${field.title} (${field.key})` : field.key;
|
|
17
|
+
}
|
|
18
|
+
function fieldOption(field) {
|
|
19
|
+
return { name: fieldLabel(field), value: field.key };
|
|
20
|
+
}
|
|
21
|
+
const SINGLE_CHOICE_TYPES = new Set(['radio', 'select']);
|
|
22
|
+
const MAPPER_TYPE_BY_FIELD_TYPE = {
|
|
23
|
+
number: 'number',
|
|
24
|
+
rating: 'number',
|
|
25
|
+
scale: 'number',
|
|
26
|
+
switch: 'boolean',
|
|
27
|
+
date: 'dateTime',
|
|
28
|
+
time: 'time',
|
|
29
|
+
checkbox: 'array',
|
|
30
|
+
ranking: 'array',
|
|
31
|
+
'picture-choice': 'array',
|
|
32
|
+
matrix: 'object',
|
|
33
|
+
group: 'array',
|
|
34
|
+
};
|
|
35
|
+
function shapeHint(field) {
|
|
36
|
+
const type = MAPPER_TYPE_BY_FIELD_TYPE[field.type];
|
|
37
|
+
if (type === 'array' && field.options)
|
|
38
|
+
return `list of: ${field.options.map((option) => option.key).join(', ')}`;
|
|
39
|
+
if (field.type === 'matrix')
|
|
40
|
+
return 'row key → column key';
|
|
41
|
+
if (field.type === 'group' && field.members)
|
|
42
|
+
return `rows of: ${field.members.map((member) => member.key).join(', ')}`;
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
function mappableFields(fields) {
|
|
46
|
+
return fields.filter((field) => field.context === true || isPrefillable(field));
|
|
47
|
+
}
|
|
48
|
+
function mapperField(field) {
|
|
49
|
+
var _a;
|
|
50
|
+
const base = { id: field.key, required: false, defaultMatch: false, canBeUsedToMatch: false, display: true };
|
|
51
|
+
if (field.context === true)
|
|
52
|
+
return { ...base, displayName: `${fieldLabel(field)} · context`, type: 'string' };
|
|
53
|
+
if (SINGLE_CHOICE_TYPES.has(field.type) && field.options) {
|
|
54
|
+
const options = field.options.map((option) => ({ name: option.label, value: option.key }));
|
|
55
|
+
return { ...base, displayName: fieldLabel(field), type: 'options', options };
|
|
56
|
+
}
|
|
57
|
+
const hint = shapeHint(field);
|
|
58
|
+
const displayName = hint ? `${fieldLabel(field)} · ${hint}` : fieldLabel(field);
|
|
59
|
+
return { ...base, displayName, type: (_a = MAPPER_TYPE_BY_FIELD_TYPE[field.type]) !== null && _a !== void 0 ? _a : 'string' };
|
|
60
|
+
}
|
|
61
|
+
function isBlank(value) {
|
|
62
|
+
return value === undefined || value === null || value === '';
|
|
63
|
+
}
|
|
64
|
+
function hasToIsoDate(value) {
|
|
65
|
+
return typeof value === 'object' && value !== null && 'toISODate' in value && typeof value.toISODate === 'function';
|
|
66
|
+
}
|
|
67
|
+
const ISO_DATE_PREFIX = /^\d{4}-\d{2}-\d{2}/;
|
|
68
|
+
function toIsoDate(value) {
|
|
69
|
+
if (hasToIsoDate(value))
|
|
70
|
+
return value.toISODate();
|
|
71
|
+
if (value instanceof Date)
|
|
72
|
+
return value.toISOString().slice(0, 10);
|
|
73
|
+
if (typeof value === 'string' && ISO_DATE_PREFIX.test(value))
|
|
74
|
+
return value.slice(0, 10);
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
function splitFieldValues(fields, values, onlyFormFields) {
|
|
78
|
+
const byKey = new Map(fields.map((field) => [field.key, field]));
|
|
79
|
+
const prefill = {};
|
|
80
|
+
const context = {};
|
|
81
|
+
for (const [key, value] of Object.entries(values)) {
|
|
82
|
+
if (isBlank(value))
|
|
83
|
+
continue;
|
|
84
|
+
const field = byKey.get(key);
|
|
85
|
+
if (!field) {
|
|
86
|
+
if (!onlyFormFields)
|
|
87
|
+
prefill[key] = value;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (field.context === true)
|
|
91
|
+
context[key] = value;
|
|
92
|
+
else if (isPrefillable(field))
|
|
93
|
+
prefill[key] = field.type === 'date' ? toIsoDate(value) : value;
|
|
94
|
+
}
|
|
95
|
+
return { prefill, context };
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=FormFields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormFields.js","sourceRoot":"","sources":["../../../nodes/Formbase/FormFields.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import type { IExecuteFunctions,
|
|
1
|
+
import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
2
|
export declare class Formbase implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
4
|
methods: {
|
|
5
5
|
loadOptions: {
|
|
6
|
-
getForms
|
|
7
|
-
getPrefillKeys(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
getForms: typeof import("./FormbaseMethods").getForms;
|
|
7
|
+
getPrefillKeys(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
|
|
8
|
+
getContextKeys(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
|
|
9
|
+
getDocumentsKeys(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
|
|
10
|
+
};
|
|
11
|
+
listSearch: {
|
|
12
|
+
searchForms(this: import("n8n-workflow").ILoadOptionsFunctions, filter?: string): Promise<import("n8n-workflow").INodeListSearchResult>;
|
|
13
|
+
searchRequests(this: import("n8n-workflow").ILoadOptionsFunctions, _filter?: string, paginationToken?: string): Promise<import("n8n-workflow").INodeListSearchResult>;
|
|
14
|
+
};
|
|
15
|
+
resourceMapping: {
|
|
16
|
+
getMappingFields(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").ResourceMapperFields>;
|
|
10
17
|
};
|
|
11
18
|
};
|
|
12
19
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|