n8n-nodes-formbase 0.9.2 → 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 +31 -9
- 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
|
@@ -1,182 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Formbase = void 0;
|
|
4
|
-
const node_crypto_1 = require("node:crypto");
|
|
5
4
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const RequestDescription_1 = require("./actions/RequestDescription");
|
|
6
|
+
const RequestOperations_1 = require("./actions/RequestOperations");
|
|
6
7
|
const constants_1 = require("./constants");
|
|
7
8
|
const FormbaseCatalog_1 = require("./FormbaseCatalog");
|
|
8
|
-
const
|
|
9
|
+
const FormbaseMethods_1 = require("./FormbaseMethods");
|
|
9
10
|
const NodeErrors_1 = require("./NodeErrors");
|
|
10
|
-
function
|
|
11
|
-
const
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return
|
|
19
|
-
return field.prefillable !== false;
|
|
20
|
-
}
|
|
21
|
-
function readPairs(context, parameter, itemIndex) {
|
|
22
|
-
var _a;
|
|
23
|
-
const collection = context.getNodeParameter(parameter, itemIndex, {});
|
|
24
|
-
const values = {};
|
|
25
|
-
for (const pair of (_a = collection.values) !== null && _a !== void 0 ? _a : []) {
|
|
26
|
-
if (!pair.key) {
|
|
27
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Every ${parameter} entry needs a field key`, { itemIndex });
|
|
28
|
-
}
|
|
29
|
-
if (pair.key in values) {
|
|
30
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Field key "${pair.key}" is listed twice in ${parameter}`, { itemIndex });
|
|
31
|
-
}
|
|
32
|
-
values[pair.key] = pair.json ? parseJsonValue(context, pair.value, `${parameter} value for "${pair.key}"`, itemIndex) : pair.value;
|
|
33
|
-
}
|
|
34
|
-
return values;
|
|
35
|
-
}
|
|
36
|
-
function parseJsonValue(context, value, what, itemIndex) {
|
|
37
|
-
if (typeof value !== 'string')
|
|
38
|
-
return value;
|
|
39
|
-
try {
|
|
40
|
-
return JSON.parse(value);
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `The ${what} is not valid JSON`, { itemIndex });
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function readMetadata(context, metadata, itemIndex) {
|
|
47
|
-
if (metadata === undefined || metadata === '')
|
|
48
|
-
return undefined;
|
|
49
|
-
const parsed = parseJsonValue(context, metadata, 'metadata', itemIndex);
|
|
50
|
-
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
51
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Metadata must be a JSON object', { itemIndex });
|
|
52
|
-
}
|
|
53
|
-
return parsed;
|
|
54
|
-
}
|
|
55
|
-
function readExpiresAt(context, expiresAt, itemIndex) {
|
|
56
|
-
const timestamp = Date.parse(expiresAt);
|
|
57
|
-
if (Number.isNaN(timestamp)) {
|
|
58
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Expires At "${expiresAt}" is not a date`, { itemIndex });
|
|
59
|
-
}
|
|
60
|
-
return timestamp;
|
|
61
|
-
}
|
|
62
|
-
function readReminders(reminders) {
|
|
63
|
-
return reminders
|
|
64
|
-
.split(',')
|
|
65
|
-
.map((offset) => offset.trim())
|
|
66
|
-
.filter((offset) => offset.length > 0);
|
|
67
|
-
}
|
|
68
|
-
function readResumeUrl(context, itemIndex) {
|
|
69
|
-
const resumeUrl = context.evaluateExpression('{{ $execution.resumeUrl }}', itemIndex);
|
|
70
|
-
if (typeof resumeUrl !== 'string' || resumeUrl.length === 0) {
|
|
71
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'n8n did not provide a resume URL for this execution. Turn off "Wait for the Outcome", or run the workflow where a Wait node set to "On Webhook Call" can resume it.', { itemIndex });
|
|
72
|
-
}
|
|
73
|
-
return resumeUrl;
|
|
74
|
-
}
|
|
75
|
-
async function uploadDocuments(context, formId, itemIndex) {
|
|
76
|
-
var _a, _b, _c;
|
|
77
|
-
const collection = context.getNodeParameter('documents', itemIndex, {});
|
|
78
|
-
const documents = [];
|
|
79
|
-
for (const row of (_a = collection.values) !== null && _a !== void 0 ? _a : []) {
|
|
80
|
-
const binaryProperty = (_b = row.binaryProperty) === null || _b === void 0 ? void 0 : _b.trim();
|
|
81
|
-
if (!binaryProperty) {
|
|
82
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Every document needs the name of an input binary field', { itemIndex });
|
|
83
|
-
}
|
|
84
|
-
const binary = context.helpers.assertBinaryData(itemIndex, binaryProperty);
|
|
85
|
-
const bytes = await context.helpers.getBinaryDataBuffer(itemIndex, binaryProperty);
|
|
86
|
-
const name = ((_c = row.name) === null || _c === void 0 ? void 0 : _c.trim()) || binary.fileName;
|
|
87
|
-
if (!name) {
|
|
88
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `The file in "${binaryProperty}" has no file name; set a Name for it`, { itemIndex });
|
|
89
|
-
}
|
|
90
|
-
const reserved = await (0, GenericFunctions_1.formbaseApiRequest)(context, 'documents.create', {
|
|
91
|
-
formId,
|
|
92
|
-
name,
|
|
93
|
-
contentType: binary.mimeType,
|
|
94
|
-
size: bytes.length,
|
|
95
|
-
sha256: (0, node_crypto_1.createHash)('sha256').update(bytes).digest('hex'),
|
|
96
|
-
});
|
|
97
|
-
await context.helpers.httpRequest({
|
|
98
|
-
method: 'PUT',
|
|
99
|
-
url: reserved.uploadUrl,
|
|
100
|
-
body: bytes,
|
|
101
|
-
headers: { 'Content-Type': binary.mimeType },
|
|
102
|
-
});
|
|
103
|
-
documents.push({ documentId: reserved.id, ...(row.field ? { field: row.field } : {}) });
|
|
104
|
-
}
|
|
105
|
-
return documents;
|
|
106
|
-
}
|
|
107
|
-
async function buildCreateParams(context, itemIndex) {
|
|
108
|
-
const formId = context.getNodeParameter('formId', itemIndex);
|
|
109
|
-
const recipientEmail = context.getNodeParameter('recipientEmail', itemIndex, '');
|
|
110
|
-
const readonly = context.getNodeParameter('readonly', itemIndex, []);
|
|
111
|
-
const waitForOutcome = context.getNodeParameter('waitForOutcome', itemIndex, false);
|
|
112
|
-
const additional = context.getNodeParameter('additionalFields', itemIndex, {});
|
|
113
|
-
if (waitForOutcome && additional.callbackUrl) {
|
|
114
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), '"Wait for the Outcome" already sets the callback URL. Turn it off to use a Callback URL of your own.', { itemIndex });
|
|
115
|
-
}
|
|
116
|
-
const callbackUrl = waitForOutcome ? readResumeUrl(context, itemIndex) : additional.callbackUrl;
|
|
117
|
-
const prefill = readPairs(context, 'prefill', itemIndex);
|
|
118
|
-
const requestContext = readPairs(context, 'context', itemIndex);
|
|
119
|
-
const metadata = readMetadata(context, additional.metadata, itemIndex);
|
|
120
|
-
const expiresAt = additional.expiresAt ? readExpiresAt(context, additional.expiresAt, itemIndex) : undefined;
|
|
121
|
-
const documents = await uploadDocuments(context, formId, itemIndex);
|
|
122
|
-
const recipient = {
|
|
123
|
-
...(recipientEmail ? { email: recipientEmail } : {}),
|
|
124
|
-
...(additional.recipientName ? { name: additional.recipientName } : {}),
|
|
11
|
+
function createFieldLookup(context) {
|
|
12
|
+
const byForm = new Map();
|
|
13
|
+
return (formId) => {
|
|
14
|
+
const cached = byForm.get(formId);
|
|
15
|
+
if (cached)
|
|
16
|
+
return cached;
|
|
17
|
+
const fields = (0, FormbaseCatalog_1.listFields)(context, formId);
|
|
18
|
+
byForm.set(formId, fields);
|
|
19
|
+
return fields;
|
|
125
20
|
};
|
|
126
|
-
return {
|
|
127
|
-
formId,
|
|
128
|
-
...(Object.keys(recipient).length > 0 ? { recipient } : {}),
|
|
129
|
-
...(Object.keys(prefill).length > 0 ? { prefill } : {}),
|
|
130
|
-
...(Object.keys(requestContext).length > 0 ? { context: requestContext } : {}),
|
|
131
|
-
...(readonly.length > 0 ? { readonly } : {}),
|
|
132
|
-
...(documents.length > 0 ? { documents } : {}),
|
|
133
|
-
...(additional.language ? { language: additional.language } : {}),
|
|
134
|
-
...(additional.delivery ? { delivery: additional.delivery } : {}),
|
|
135
|
-
...(additional.reminders !== undefined ? { reminders: readReminders(additional.reminders) } : {}),
|
|
136
|
-
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
137
|
-
...(additional.externalId ? { externalId: additional.externalId, idempotencyKey: additional.externalId } : {}),
|
|
138
|
-
...(metadata ? { metadata } : {}),
|
|
139
|
-
...(callbackUrl ? { callbackUrl } : {}),
|
|
140
|
-
...(additional.test ? { test: true } : {}),
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
async function listRequests(context, itemIndex) {
|
|
144
|
-
const returnAll = context.getNodeParameter('returnAll', itemIndex);
|
|
145
|
-
const max = returnAll ? Number.POSITIVE_INFINITY : context.getNodeParameter('limit', itemIndex);
|
|
146
|
-
const scope = context.getNodeParameter('scope', itemIndex);
|
|
147
|
-
const filters = context.getNodeParameter('filters', itemIndex, {});
|
|
148
|
-
const scopeParams = scope === 'form'
|
|
149
|
-
? { formId: context.getNodeParameter('formId', itemIndex) }
|
|
150
|
-
: { workspaceId: (await (0, FormbaseCatalog_1.readWorkspace)(context)).id };
|
|
151
|
-
return (0, FormbaseCatalog_1.collectPages)(context, 'requests.list', {
|
|
152
|
-
...scopeParams,
|
|
153
|
-
...(filters.status ? { status: filters.status } : {}),
|
|
154
|
-
...(filters.outcome ? { outcome: filters.outcome } : {}),
|
|
155
|
-
...(filters.externalId ? { externalId: filters.externalId } : {}),
|
|
156
|
-
...(filters.includeTest ? { includeTest: true } : {}),
|
|
157
|
-
}, max);
|
|
158
|
-
}
|
|
159
|
-
async function runOperation(context, operation, itemIndex) {
|
|
160
|
-
if (operation === 'create') {
|
|
161
|
-
return (0, GenericFunctions_1.formbaseApiRequest)(context, 'requests.create', await buildCreateParams(context, itemIndex));
|
|
162
|
-
}
|
|
163
|
-
if (operation === 'getAll')
|
|
164
|
-
return listRequests(context, itemIndex);
|
|
165
|
-
const requestId = context.getNodeParameter('requestId', itemIndex);
|
|
166
|
-
if (operation === 'get')
|
|
167
|
-
return (0, GenericFunctions_1.formbaseApiRequest)(context, 'requests.get', { requestId });
|
|
168
|
-
if (operation === 'remind')
|
|
169
|
-
return (0, GenericFunctions_1.formbaseApiRequest)(context, 'requests.remind', { requestId });
|
|
170
|
-
if (operation === 'replayCallback') {
|
|
171
|
-
return (0, GenericFunctions_1.formbaseApiRequest)(context, 'requests.replayCallback', { requestId });
|
|
172
|
-
}
|
|
173
|
-
if (operation === 'cancel') {
|
|
174
|
-
const reason = context.getNodeParameter('reason', itemIndex, '');
|
|
175
|
-
return (0, GenericFunctions_1.formbaseApiRequest)(context, 'requests.cancel', { requestId, ...(reason ? { reason } : {}) });
|
|
176
|
-
}
|
|
177
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `The operation "${String(operation)}" is not supported`, { itemIndex });
|
|
178
21
|
}
|
|
179
|
-
const REQUEST_ID_OPERATIONS = ['cancel', 'get', 'remind', 'replayCallback'];
|
|
180
22
|
class Formbase {
|
|
181
23
|
constructor() {
|
|
182
24
|
this.description = {
|
|
@@ -184,7 +26,8 @@ class Formbase {
|
|
|
184
26
|
name: 'formbase',
|
|
185
27
|
icon: { light: 'file:formbase-logo.svg', dark: 'file:formbase-logo.dark.svg' },
|
|
186
28
|
group: ['transform'],
|
|
187
|
-
version: 1,
|
|
29
|
+
version: [1, 2],
|
|
30
|
+
defaultVersion: 2,
|
|
188
31
|
subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}',
|
|
189
32
|
description: 'Create, read, cancel and remind formbase requests, and pause a workflow until a customer completes one',
|
|
190
33
|
defaults: {
|
|
@@ -195,588 +38,26 @@ class Formbase {
|
|
|
195
38
|
usableAsTool: true,
|
|
196
39
|
credentials: [
|
|
197
40
|
{
|
|
198
|
-
name: constants_1.
|
|
199
|
-
required: true,
|
|
200
|
-
},
|
|
201
|
-
],
|
|
202
|
-
properties: [
|
|
203
|
-
{
|
|
204
|
-
displayName: 'Resource',
|
|
205
|
-
name: 'resource',
|
|
206
|
-
type: 'options',
|
|
207
|
-
noDataExpression: true,
|
|
208
|
-
options: [
|
|
209
|
-
{
|
|
210
|
-
name: 'Request',
|
|
211
|
-
value: 'request',
|
|
212
|
-
},
|
|
213
|
-
],
|
|
214
|
-
default: 'request',
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
displayName: 'Operation',
|
|
218
|
-
name: 'operation',
|
|
219
|
-
type: 'options',
|
|
220
|
-
noDataExpression: true,
|
|
221
|
-
displayOptions: {
|
|
222
|
-
show: {
|
|
223
|
-
resource: ['request'],
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
options: [
|
|
227
|
-
{
|
|
228
|
-
name: 'Cancel',
|
|
229
|
-
value: 'cancel',
|
|
230
|
-
action: 'Cancel a request',
|
|
231
|
-
description: 'Withdraw a pending request so its link stops working',
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
name: 'Create',
|
|
235
|
-
value: 'create',
|
|
236
|
-
action: 'Create a request',
|
|
237
|
-
description: 'Ask one recipient to complete a published form',
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
name: 'Get',
|
|
241
|
-
value: 'get',
|
|
242
|
-
action: 'Get a request',
|
|
243
|
-
description: 'Read a request, with its answers once it is completed',
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
name: 'Get Many',
|
|
247
|
-
value: 'getAll',
|
|
248
|
-
action: 'Get many requests',
|
|
249
|
-
description: 'List the requests of a form or of the workspace',
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
name: 'Remind',
|
|
253
|
-
value: 'remind',
|
|
254
|
-
action: 'Remind a request recipient',
|
|
255
|
-
description: 'Email the recipient a reminder now, outside the reminder schedule',
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
name: 'Replay Callback',
|
|
259
|
-
value: 'replayCallback',
|
|
260
|
-
action: 'Replay a request callback',
|
|
261
|
-
description: 'Send the callback of a completed, expired or canceled request again',
|
|
262
|
-
},
|
|
263
|
-
],
|
|
264
|
-
default: 'create',
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
displayName: 'Form Name or ID',
|
|
268
|
-
name: 'formId',
|
|
269
|
-
type: 'options',
|
|
270
|
-
typeOptions: {
|
|
271
|
-
loadOptionsMethod: 'getForms',
|
|
272
|
-
},
|
|
273
|
-
displayOptions: {
|
|
274
|
-
show: {
|
|
275
|
-
resource: ['request'],
|
|
276
|
-
operation: ['create'],
|
|
277
|
-
},
|
|
278
|
-
},
|
|
279
|
-
default: '',
|
|
280
|
-
required: true,
|
|
281
|
-
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
displayName: 'Recipient Email',
|
|
285
|
-
name: 'recipientEmail',
|
|
286
|
-
type: 'string',
|
|
287
|
-
placeholder: 'name@email.com',
|
|
288
|
-
displayOptions: {
|
|
289
|
-
show: {
|
|
290
|
-
resource: ['request'],
|
|
291
|
-
operation: ['create'],
|
|
292
|
-
},
|
|
293
|
-
},
|
|
294
|
-
default: '',
|
|
295
|
-
description: 'Who the request is for. Needed to send the invitation email and reminders.',
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
displayName: 'Prefill',
|
|
299
|
-
name: 'prefill',
|
|
300
|
-
type: 'fixedCollection',
|
|
301
|
-
placeholder: 'Add Answer',
|
|
302
|
-
typeOptions: {
|
|
303
|
-
multipleValues: true,
|
|
304
|
-
},
|
|
305
|
-
displayOptions: {
|
|
306
|
-
show: {
|
|
307
|
-
resource: ['request'],
|
|
308
|
-
operation: ['create'],
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
default: {},
|
|
312
|
-
description: 'Initial answers the recipient sees, keyed by field key',
|
|
313
|
-
options: [
|
|
314
|
-
{
|
|
315
|
-
name: 'values',
|
|
316
|
-
displayName: 'Answer',
|
|
317
|
-
values: [
|
|
318
|
-
{
|
|
319
|
-
displayName: 'Field Name or ID',
|
|
320
|
-
name: 'key',
|
|
321
|
-
type: 'options',
|
|
322
|
-
typeOptions: {
|
|
323
|
-
loadOptionsMethod: 'getPrefillKeys',
|
|
324
|
-
loadOptionsDependsOn: ['formId'],
|
|
325
|
-
},
|
|
326
|
-
default: '',
|
|
327
|
-
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
displayName: 'Value',
|
|
331
|
-
name: 'value',
|
|
332
|
-
type: 'string',
|
|
333
|
-
default: '',
|
|
334
|
-
description: 'Sent as text, or as the value it decodes to when Parse as JSON is on',
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
displayName: 'Parse as JSON',
|
|
338
|
-
name: 'json',
|
|
339
|
-
type: 'boolean',
|
|
340
|
-
default: false,
|
|
341
|
-
description: 'Whether to decode the value as JSON: a number, true or false, a list of option keys, a matrix object or the rows of a repeating group',
|
|
342
|
-
},
|
|
343
|
-
],
|
|
344
|
-
},
|
|
345
|
-
],
|
|
346
|
-
},
|
|
347
|
-
{
|
|
348
|
-
displayName: 'Context',
|
|
349
|
-
name: 'context',
|
|
350
|
-
type: 'fixedCollection',
|
|
351
|
-
placeholder: 'Add Context Value',
|
|
352
|
-
typeOptions: {
|
|
353
|
-
multipleValues: true,
|
|
354
|
-
},
|
|
355
|
-
displayOptions: {
|
|
356
|
-
show: {
|
|
357
|
-
resource: ['request'],
|
|
358
|
-
operation: ['create'],
|
|
359
|
-
},
|
|
360
|
-
},
|
|
361
|
-
default: {},
|
|
362
|
-
description: 'Hidden-field values the recipient never sees or edits, keyed by field key and echoed in every callback',
|
|
363
|
-
options: [
|
|
364
|
-
{
|
|
365
|
-
name: 'values',
|
|
366
|
-
displayName: 'Context Value',
|
|
367
|
-
values: [
|
|
368
|
-
{
|
|
369
|
-
displayName: 'Field Name or ID',
|
|
370
|
-
name: 'key',
|
|
371
|
-
type: 'options',
|
|
372
|
-
typeOptions: {
|
|
373
|
-
loadOptionsMethod: 'getContextKeys',
|
|
374
|
-
loadOptionsDependsOn: ['formId'],
|
|
375
|
-
},
|
|
376
|
-
default: '',
|
|
377
|
-
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
378
|
-
},
|
|
379
|
-
{
|
|
380
|
-
displayName: 'Value',
|
|
381
|
-
name: 'value',
|
|
382
|
-
type: 'string',
|
|
383
|
-
default: '',
|
|
384
|
-
description: 'Sent as text, or as the value it decodes to when Parse as JSON is on',
|
|
385
|
-
},
|
|
386
|
-
{
|
|
387
|
-
displayName: 'Parse as JSON',
|
|
388
|
-
name: 'json',
|
|
389
|
-
type: 'boolean',
|
|
390
|
-
default: false,
|
|
391
|
-
description: 'Whether to decode the value as JSON instead of sending it as text',
|
|
392
|
-
},
|
|
393
|
-
],
|
|
394
|
-
},
|
|
395
|
-
],
|
|
396
|
-
},
|
|
397
|
-
{
|
|
398
|
-
displayName: 'Read-Only Field Names or IDs',
|
|
399
|
-
name: 'readonly',
|
|
400
|
-
type: 'multiOptions',
|
|
401
|
-
typeOptions: {
|
|
402
|
-
loadOptionsMethod: 'getPrefillKeys',
|
|
403
|
-
loadOptionsDependsOn: ['formId'],
|
|
404
|
-
},
|
|
405
|
-
displayOptions: {
|
|
406
|
-
show: {
|
|
407
|
-
resource: ['request'],
|
|
408
|
-
operation: ['create'],
|
|
409
|
-
},
|
|
410
|
-
},
|
|
411
|
-
default: [],
|
|
412
|
-
description: 'Prefilled fields the recipient may see but not change. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
413
|
-
},
|
|
414
|
-
{
|
|
415
|
-
displayName: 'Documents',
|
|
416
|
-
name: 'documents',
|
|
417
|
-
type: 'fixedCollection',
|
|
418
|
-
placeholder: 'Add Document',
|
|
419
|
-
typeOptions: {
|
|
420
|
-
multipleValues: true,
|
|
421
|
-
},
|
|
422
|
-
displayOptions: {
|
|
423
|
-
show: {
|
|
424
|
-
resource: ['request'],
|
|
425
|
-
operation: ['create'],
|
|
426
|
-
},
|
|
427
|
-
},
|
|
428
|
-
default: {},
|
|
429
|
-
description: 'Files from the input item the recipient gets in the form\'s Documents block, below the documents the form already has. PDF or image, up to 25 MB each.',
|
|
430
|
-
options: [
|
|
431
|
-
{
|
|
432
|
-
name: 'values',
|
|
433
|
-
displayName: 'Document',
|
|
434
|
-
values: [
|
|
435
|
-
{
|
|
436
|
-
displayName: 'Input Binary Field',
|
|
437
|
-
name: 'binaryProperty',
|
|
438
|
-
type: 'string',
|
|
439
|
-
default: 'data',
|
|
440
|
-
required: true,
|
|
441
|
-
hint: 'The name of the input binary field containing the file',
|
|
442
|
-
},
|
|
443
|
-
{
|
|
444
|
-
displayName: 'Name',
|
|
445
|
-
name: 'name',
|
|
446
|
-
type: 'string',
|
|
447
|
-
default: '',
|
|
448
|
-
description: 'The name the recipient sees. Defaults to the file name.',
|
|
449
|
-
},
|
|
450
|
-
{
|
|
451
|
-
displayName: 'Documents Block Name or ID',
|
|
452
|
-
name: 'field',
|
|
453
|
-
type: 'options',
|
|
454
|
-
typeOptions: {
|
|
455
|
-
loadOptionsMethod: 'getDocumentsKeys',
|
|
456
|
-
loadOptionsDependsOn: ['formId'],
|
|
457
|
-
},
|
|
458
|
-
default: '',
|
|
459
|
-
description: 'The Documents block the file goes into. Leave empty when the form has one. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
460
|
-
},
|
|
461
|
-
],
|
|
462
|
-
},
|
|
463
|
-
],
|
|
464
|
-
},
|
|
465
|
-
{
|
|
466
|
-
displayName: 'Wait for the Outcome',
|
|
467
|
-
name: 'waitForOutcome',
|
|
468
|
-
type: 'boolean',
|
|
469
|
-
displayOptions: {
|
|
470
|
-
show: {
|
|
471
|
-
resource: ['request'],
|
|
472
|
-
operation: ['create'],
|
|
473
|
-
},
|
|
474
|
-
},
|
|
475
|
-
default: false,
|
|
476
|
-
description: 'Whether to point the request callback at this execution\'s resume URL. Follow this node with a Wait node set to "On Webhook Call": the workflow resumes with the request event when the request is completed, expires or is canceled.',
|
|
477
|
-
},
|
|
478
|
-
{
|
|
479
|
-
displayName: 'Additional Fields',
|
|
480
|
-
name: 'additionalFields',
|
|
481
|
-
type: 'collection',
|
|
482
|
-
placeholder: 'Add Field',
|
|
483
|
-
displayOptions: {
|
|
484
|
-
show: {
|
|
485
|
-
resource: ['request'],
|
|
486
|
-
operation: ['create'],
|
|
487
|
-
},
|
|
488
|
-
},
|
|
489
|
-
default: {},
|
|
490
|
-
options: [
|
|
491
|
-
{
|
|
492
|
-
displayName: 'Callback URL',
|
|
493
|
-
name: 'callbackUrl',
|
|
494
|
-
type: 'string',
|
|
495
|
-
default: '',
|
|
496
|
-
description: 'An HTTPS URL of your own that receives the signed request callback. Leave empty when Wait for the Outcome is on.',
|
|
497
|
-
},
|
|
498
|
-
{
|
|
499
|
-
displayName: 'Delivery',
|
|
500
|
-
name: 'delivery',
|
|
501
|
-
type: 'options',
|
|
502
|
-
options: [
|
|
503
|
-
{
|
|
504
|
-
name: 'Email the Invitation',
|
|
505
|
-
value: 'email',
|
|
506
|
-
description: 'Sends the recipient the link by email; needs a recipient email',
|
|
507
|
-
},
|
|
508
|
-
{
|
|
509
|
-
name: 'None',
|
|
510
|
-
value: 'none',
|
|
511
|
-
description: 'You deliver the returned link yourself',
|
|
512
|
-
},
|
|
513
|
-
],
|
|
514
|
-
default: 'none',
|
|
515
|
-
},
|
|
516
|
-
{
|
|
517
|
-
displayName: 'Expires At',
|
|
518
|
-
name: 'expiresAt',
|
|
519
|
-
type: 'dateTime',
|
|
520
|
-
default: '',
|
|
521
|
-
description: 'When the link stops working. Defaults to 30 days, at most 365.',
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
displayName: 'External ID',
|
|
525
|
-
name: 'externalId',
|
|
526
|
-
type: 'string',
|
|
527
|
-
default: '',
|
|
528
|
-
description: 'Your ID for this request, such as the run or ticket it belongs to. Also used as the idempotency key, so a retried run reuses the request instead of creating a second one.',
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
displayName: 'Language',
|
|
532
|
-
name: 'language',
|
|
533
|
-
type: 'string',
|
|
534
|
-
default: '',
|
|
535
|
-
placeholder: 'en',
|
|
536
|
-
description: 'Language the form opens in and the invitation is written in; must be published for the form',
|
|
537
|
-
},
|
|
538
|
-
{
|
|
539
|
-
displayName: 'Metadata',
|
|
540
|
-
name: 'metadata',
|
|
541
|
-
type: 'json',
|
|
542
|
-
default: '{}',
|
|
543
|
-
description: 'JSON object for your own bookkeeping. Never shown to the recipient, echoed in every callback.',
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
displayName: 'Recipient Name',
|
|
547
|
-
name: 'recipientName',
|
|
548
|
-
type: 'string',
|
|
549
|
-
default: '',
|
|
550
|
-
},
|
|
551
|
-
{
|
|
552
|
-
displayName: 'Reminders',
|
|
553
|
-
name: 'reminders',
|
|
554
|
-
type: 'string',
|
|
555
|
-
default: '',
|
|
556
|
-
placeholder: '2d, 5d',
|
|
557
|
-
description: 'Idle offsets after which to remind the recipient, comma-separated, at most five. Leave empty to send no reminders; remove the field to inherit the form\'s schedule.',
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
displayName: 'Test Mode',
|
|
561
|
-
name: 'test',
|
|
562
|
-
type: 'boolean',
|
|
563
|
-
default: false,
|
|
564
|
-
description: 'Whether to create a test request: nothing is emailed, the callback carries test: true, and nothing counts against the quota',
|
|
565
|
-
},
|
|
566
|
-
],
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
displayName: 'Request ID',
|
|
570
|
-
name: 'requestId',
|
|
571
|
-
type: 'string',
|
|
572
|
-
displayOptions: {
|
|
573
|
-
show: {
|
|
574
|
-
resource: ['request'],
|
|
575
|
-
operation: REQUEST_ID_OPERATIONS,
|
|
576
|
-
},
|
|
577
|
-
},
|
|
578
|
-
default: '',
|
|
579
|
-
required: true,
|
|
580
|
-
description: 'The ID formbase returned when the request was created',
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
displayName: 'Reason',
|
|
584
|
-
name: 'reason',
|
|
585
|
-
type: 'string',
|
|
586
|
-
displayOptions: {
|
|
587
|
-
show: {
|
|
588
|
-
resource: ['request'],
|
|
589
|
-
operation: ['cancel'],
|
|
590
|
-
},
|
|
591
|
-
},
|
|
592
|
-
default: '',
|
|
593
|
-
description: 'Why the request is withdrawn; echoed in the request.canceled callback',
|
|
594
|
-
},
|
|
595
|
-
{
|
|
596
|
-
displayName: 'Return All',
|
|
597
|
-
name: 'returnAll',
|
|
598
|
-
type: 'boolean',
|
|
599
|
-
displayOptions: {
|
|
600
|
-
show: {
|
|
601
|
-
resource: ['request'],
|
|
602
|
-
operation: ['getAll'],
|
|
603
|
-
},
|
|
604
|
-
},
|
|
605
|
-
default: false,
|
|
606
|
-
description: 'Whether to return all results or only up to a given limit',
|
|
607
|
-
},
|
|
608
|
-
{
|
|
609
|
-
displayName: 'Limit',
|
|
610
|
-
name: 'limit',
|
|
611
|
-
type: 'number',
|
|
612
|
-
typeOptions: {
|
|
613
|
-
minValue: 1,
|
|
614
|
-
},
|
|
615
|
-
displayOptions: {
|
|
616
|
-
show: {
|
|
617
|
-
resource: ['request'],
|
|
618
|
-
operation: ['getAll'],
|
|
619
|
-
returnAll: [false],
|
|
620
|
-
},
|
|
621
|
-
},
|
|
622
|
-
default: 50,
|
|
623
|
-
description: 'Max number of results to return',
|
|
624
|
-
},
|
|
625
|
-
{
|
|
626
|
-
displayName: 'Scope',
|
|
627
|
-
name: 'scope',
|
|
628
|
-
type: 'options',
|
|
629
|
-
displayOptions: {
|
|
630
|
-
show: {
|
|
631
|
-
resource: ['request'],
|
|
632
|
-
operation: ['getAll'],
|
|
633
|
-
},
|
|
634
|
-
},
|
|
635
|
-
options: [
|
|
636
|
-
{
|
|
637
|
-
name: 'Form',
|
|
638
|
-
value: 'form',
|
|
639
|
-
description: 'The requests of one form',
|
|
640
|
-
},
|
|
641
|
-
{
|
|
642
|
-
name: 'Workspace',
|
|
643
|
-
value: 'workspace',
|
|
644
|
-
description: 'Every request of the connected workspace',
|
|
645
|
-
},
|
|
646
|
-
],
|
|
647
|
-
default: 'form',
|
|
648
|
-
},
|
|
649
|
-
{
|
|
650
|
-
displayName: 'Form Name or ID',
|
|
651
|
-
name: 'formId',
|
|
652
|
-
type: 'options',
|
|
653
|
-
typeOptions: {
|
|
654
|
-
loadOptionsMethod: 'getForms',
|
|
655
|
-
},
|
|
656
|
-
displayOptions: {
|
|
657
|
-
show: {
|
|
658
|
-
resource: ['request'],
|
|
659
|
-
operation: ['getAll'],
|
|
660
|
-
scope: ['form'],
|
|
661
|
-
},
|
|
662
|
-
},
|
|
663
|
-
default: '',
|
|
41
|
+
name: constants_1.FORMBASE_CREDENTIAL_TYPE,
|
|
664
42
|
required: true,
|
|
665
|
-
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
666
|
-
},
|
|
667
|
-
{
|
|
668
|
-
displayName: 'Filters',
|
|
669
|
-
name: 'filters',
|
|
670
|
-
type: 'collection',
|
|
671
|
-
placeholder: 'Add Filter',
|
|
672
|
-
displayOptions: {
|
|
673
|
-
show: {
|
|
674
|
-
resource: ['request'],
|
|
675
|
-
operation: ['getAll'],
|
|
676
|
-
},
|
|
677
|
-
},
|
|
678
|
-
default: {},
|
|
679
|
-
options: [
|
|
680
|
-
{
|
|
681
|
-
displayName: 'External ID',
|
|
682
|
-
name: 'externalId',
|
|
683
|
-
type: 'string',
|
|
684
|
-
default: '',
|
|
685
|
-
description: 'Only the requests created with this external ID',
|
|
686
|
-
},
|
|
687
|
-
{
|
|
688
|
-
displayName: 'Include Test Requests',
|
|
689
|
-
name: 'includeTest',
|
|
690
|
-
type: 'boolean',
|
|
691
|
-
default: false,
|
|
692
|
-
description: 'Whether to include requests created in test mode',
|
|
693
|
-
},
|
|
694
|
-
{
|
|
695
|
-
displayName: 'Outcome',
|
|
696
|
-
name: 'outcome',
|
|
697
|
-
type: 'options',
|
|
698
|
-
options: [
|
|
699
|
-
{
|
|
700
|
-
name: 'Approve',
|
|
701
|
-
value: 'approve',
|
|
702
|
-
},
|
|
703
|
-
{
|
|
704
|
-
name: 'Changes',
|
|
705
|
-
value: 'changes',
|
|
706
|
-
},
|
|
707
|
-
{
|
|
708
|
-
name: 'Decline',
|
|
709
|
-
value: 'decline',
|
|
710
|
-
},
|
|
711
|
-
],
|
|
712
|
-
default: 'approve',
|
|
713
|
-
description: 'Only completed requests with this verdict from the decision question; takes precedence over Status',
|
|
714
|
-
},
|
|
715
|
-
{
|
|
716
|
-
displayName: 'Status',
|
|
717
|
-
name: 'status',
|
|
718
|
-
type: 'options',
|
|
719
|
-
options: [
|
|
720
|
-
{
|
|
721
|
-
name: 'Canceled',
|
|
722
|
-
value: 'canceled',
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
name: 'Completed',
|
|
726
|
-
value: 'completed',
|
|
727
|
-
},
|
|
728
|
-
{
|
|
729
|
-
name: 'Expired',
|
|
730
|
-
value: 'expired',
|
|
731
|
-
},
|
|
732
|
-
{
|
|
733
|
-
name: 'Pending',
|
|
734
|
-
value: 'pending',
|
|
735
|
-
},
|
|
736
|
-
],
|
|
737
|
-
default: 'pending',
|
|
738
|
-
},
|
|
739
|
-
],
|
|
740
43
|
},
|
|
741
44
|
],
|
|
45
|
+
properties: RequestDescription_1.requestProperties,
|
|
742
46
|
};
|
|
743
|
-
this.methods = {
|
|
744
|
-
loadOptions: {
|
|
745
|
-
async getForms() {
|
|
746
|
-
const forms = await (0, FormbaseCatalog_1.listForms)(this);
|
|
747
|
-
return forms.map((form) => ({ name: form.name, value: form.id }));
|
|
748
|
-
},
|
|
749
|
-
async getPrefillKeys() {
|
|
750
|
-
const formId = this.getCurrentNodeParameter('formId');
|
|
751
|
-
if (typeof formId !== 'string' || !formId)
|
|
752
|
-
return [];
|
|
753
|
-
const fields = await (0, FormbaseCatalog_1.listFields)(this, formId);
|
|
754
|
-
return fields.filter(isPrefillable).map(fieldOption);
|
|
755
|
-
},
|
|
756
|
-
async getDocumentsKeys() {
|
|
757
|
-
const formId = this.getCurrentNodeParameter('formId');
|
|
758
|
-
if (typeof formId !== 'string' || !formId)
|
|
759
|
-
return [];
|
|
760
|
-
const fields = await (0, FormbaseCatalog_1.listFields)(this, formId);
|
|
761
|
-
return fields.filter((field) => field.type === 'documents').map(fieldOption);
|
|
762
|
-
},
|
|
763
|
-
async getContextKeys() {
|
|
764
|
-
const formId = this.getCurrentNodeParameter('formId');
|
|
765
|
-
if (typeof formId !== 'string' || !formId)
|
|
766
|
-
return [];
|
|
767
|
-
const fields = await (0, FormbaseCatalog_1.listFields)(this, formId);
|
|
768
|
-
return fields.filter((field) => field.context === true).map(fieldOption);
|
|
769
|
-
},
|
|
770
|
-
},
|
|
771
|
-
};
|
|
47
|
+
this.methods = { loadOptions: FormbaseMethods_1.loadOptions, listSearch: FormbaseMethods_1.listSearch, resourceMapping: FormbaseMethods_1.resourceMapping };
|
|
772
48
|
}
|
|
773
49
|
async execute() {
|
|
774
50
|
const items = this.getInputData();
|
|
775
51
|
const returnData = [];
|
|
776
52
|
const operation = this.getNodeParameter('operation', 0);
|
|
53
|
+
if (!(0, RequestOperations_1.isRequestOperation)(operation)) {
|
|
54
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation "${operation}" is not supported`);
|
|
55
|
+
}
|
|
56
|
+
const run = RequestOperations_1.REQUEST_OPERATIONS[operation];
|
|
57
|
+
const fieldsOf = createFieldLookup(this);
|
|
777
58
|
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
778
59
|
try {
|
|
779
|
-
const data = await
|
|
60
|
+
const data = await run(this, itemIndex, fieldsOf);
|
|
780
61
|
returnData.push(...this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(data), { itemData: { item: itemIndex } }));
|
|
781
62
|
}
|
|
782
63
|
catch (error) {
|