n8n-nodes-extended-forms 0.2.6 → 0.3.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.
Files changed (28) hide show
  1. package/dist/credentials/GithubIssuesApi.credentials.js +1 -36
  2. package/dist/credentials/GithubIssuesOAuth2Api.credentials.js +1 -53
  3. package/dist/nodes/Form123/Form.node.js +1 -388
  4. package/dist/nodes/Form123/Form.node.js.map +1 -1
  5. package/dist/nodes/Form123/FormTrigger.node.js +1 -27
  6. package/dist/nodes/Form123/common.descriptions.js +1 -647
  7. package/dist/nodes/Form123/cssVariables.js +1 -73
  8. package/dist/nodes/Form123/interfaces.d.ts +4 -0
  9. package/dist/nodes/Form123/interfaces.js +1 -4
  10. package/dist/nodes/Form123/interfaces.js.map +1 -1
  11. package/dist/nodes/Form123/templates/form-trigger-completion.handlebars +1 -1
  12. package/dist/nodes/Form123/templates/form-trigger.handlebars +694 -71
  13. package/dist/nodes/Form123/utils/descriptions.js +1 -10
  14. package/dist/nodes/Form123/utils/formCompletionUtils.js +1 -106
  15. package/dist/nodes/Form123/utils/formNodeUtils.js +3 -75
  16. package/dist/nodes/Form123/utils/formNodeUtils.js.map +1 -1
  17. package/dist/nodes/Form123/utils/templateRenderer.js +1 -71
  18. package/dist/nodes/Form123/utils/utilities.js +3 -47
  19. package/dist/nodes/Form123/utils/utils.d.ts +11 -3
  20. package/dist/nodes/Form123/utils/utils.js +3 -593
  21. package/dist/nodes/Form123/utils/utils.js.map +1 -1
  22. package/dist/nodes/Form123/utils/waitUtils.js +1 -67
  23. package/dist/nodes/Form123/v1/FormTriggerV1.node.js +1 -82
  24. package/dist/nodes/Form123/v2/FormTriggerV2.node.js +1 -193
  25. package/dist/nodes/Form123/v2/FormTriggerV2.node.js.map +1 -1
  26. package/dist/package.json +3 -1
  27. package/dist/tsconfig.tsbuildinfo +1 -1
  28. package/package.json +3 -1
@@ -1,593 +1,3 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.isFormConnected = exports.validateResponseModeConfiguration = exports.prepareFormFields = void 0;
40
- exports.sanitizeHtml = sanitizeHtml;
41
- exports.sanitizeCustomCss = sanitizeCustomCss;
42
- exports.createDescriptionMetadata = createDescriptionMetadata;
43
- exports.prepareFormData = prepareFormData;
44
- exports.addFormResponseDataToReturnItem = addFormResponseDataToReturnItem;
45
- exports.prepareFormReturnItem = prepareFormReturnItem;
46
- exports.renderForm = renderForm;
47
- exports.formWebhook = formWebhook;
48
- exports.resolveRawData = resolveRawData;
49
- const isbot_1 = require("isbot");
50
- const a = __importStar(require("node:assert"));
51
- const luxon_1 = require("luxon");
52
- const n8n_workflow_1 = require("n8n-workflow");
53
- const sanitize_html_1 = __importDefault(require("sanitize-html"));
54
- const utilities_1 = require("./utilities");
55
- const interfaces_1 = require("../interfaces");
56
- const templateRenderer_1 = require("./templateRenderer");
57
- function sanitizeHtml(text) {
58
- return (0, sanitize_html_1.default)(text, {
59
- allowedTags: [
60
- 'b',
61
- 'div',
62
- 'i',
63
- 'iframe',
64
- 'img',
65
- 'video',
66
- 'source',
67
- 'em',
68
- 'strong',
69
- 'a',
70
- 'h1',
71
- 'h2',
72
- 'h3',
73
- 'h4',
74
- 'h5',
75
- 'h6',
76
- 'u',
77
- 'sub',
78
- 'sup',
79
- 'code',
80
- 'pre',
81
- 'span',
82
- 'br',
83
- 'ul',
84
- 'ol',
85
- 'li',
86
- 'p',
87
- 'table',
88
- 'thead',
89
- 'tbody',
90
- 'tfoot',
91
- 'td',
92
- 'tr',
93
- 'th',
94
- 'br',
95
- ],
96
- allowedAttributes: {
97
- a: ['href', 'target', 'rel'],
98
- img: ['src', 'alt', 'width', 'height'],
99
- video: ['controls', 'autoplay', 'loop', 'muted', 'poster', 'width', 'height'],
100
- iframe: [
101
- 'src',
102
- 'width',
103
- 'height',
104
- 'frameborder',
105
- 'allow',
106
- 'allowfullscreen',
107
- 'referrerpolicy',
108
- ],
109
- source: ['src', 'type'],
110
- td: ['colspan', 'rowspan', 'scope', 'headers'],
111
- th: ['colspan', 'rowspan', 'scope', 'headers'],
112
- },
113
- allowedSchemes: ['https', 'http'],
114
- allowedSchemesByTag: {
115
- source: ['https', 'http'],
116
- iframe: ['https', 'http'],
117
- },
118
- allowProtocolRelative: false,
119
- transformTags: {
120
- iframe: sanitize_html_1.default.simpleTransform('iframe', {
121
- sandbox: '',
122
- referrerpolicy: 'strict-origin-when-cross-origin',
123
- allow: 'fullscreen; autoplay; encrypted-media',
124
- }),
125
- },
126
- });
127
- }
128
- const prepareFormFields = (context, fields) => {
129
- return fields.map((field) => {
130
- if (field.fieldType === 'html') {
131
- let { html } = field;
132
- if (!html)
133
- return field;
134
- for (const resolvable of (0, utilities_1.getResolvables)(html)) {
135
- html = html.replace(resolvable, context.evaluateExpression(resolvable));
136
- }
137
- field.html = sanitizeHtml(html);
138
- field.fieldLabel = field.elementName;
139
- }
140
- if (field.fieldType === 'hiddenField') {
141
- field.fieldLabel = field.fieldName;
142
- }
143
- return field;
144
- });
145
- };
146
- exports.prepareFormFields = prepareFormFields;
147
- function sanitizeCustomCss(css) {
148
- if (!css)
149
- return undefined;
150
- return (0, sanitize_html_1.default)(css, {
151
- allowedTags: [],
152
- allowedAttributes: {},
153
- });
154
- }
155
- function createDescriptionMetadata(description) {
156
- return description === ''
157
- ? 'n8n form'
158
- : description.replace(/^\s*\n+|<\/?[^>]+(>|$)/g, '').slice(0, 150);
159
- }
160
- function prepareFormData({ formHeader, formTitle, formDescription, formSubmittedHeader, formSubmittedText, completionHeader, redirectUrl, formFields, testRun, query, instanceId, useResponseData, appendAttribution = true, buttonLabel, customCss, }) {
161
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
162
- const utm_campaign = instanceId ? `&utm_campaign=${instanceId}` : '';
163
- const n8nWebsiteLink = `https://n8n.io/?utm_source=n8n-internal&utm_medium=form-trigger${utm_campaign}`;
164
- if (formSubmittedText === undefined) {
165
- formSubmittedText = 'Your response has been recorded';
166
- }
167
- const finalFormHeader = formHeader && typeof formHeader === 'string' && formHeader.trim().length > 0
168
- ? formHeader.trim()
169
- : undefined;
170
- const finalCompletionHeader = completionHeader && typeof completionHeader === 'string' && completionHeader.trim().length > 0
171
- ? sanitizeHtml(completionHeader.trim())
172
- : undefined;
173
- const formData = {
174
- testRun,
175
- formHeader: finalFormHeader,
176
- formTitle,
177
- formDescription,
178
- formDescriptionMetadata: createDescriptionMetadata(formDescription),
179
- formSubmittedHeader,
180
- formSubmittedText,
181
- completionHeader: finalCompletionHeader,
182
- n8nWebsiteLink,
183
- formFields: [],
184
- useResponseData,
185
- appendAttribution,
186
- buttonLabel,
187
- dangerousCustomCss: sanitizeCustomCss(customCss),
188
- };
189
- if (redirectUrl) {
190
- if (!redirectUrl.includes('://')) {
191
- redirectUrl = `http://${redirectUrl}`;
192
- }
193
- formData.redirectUrl = redirectUrl;
194
- }
195
- for (const [index, field] of formFields.entries()) {
196
- const { fieldType, requiredField, multiselect, placeholder } = field;
197
- const input = {
198
- id: `field-${index}`,
199
- errorId: `error-field-${index}`,
200
- label: field.fieldLabel,
201
- inputRequired: requiredField ? 'form-required' : '',
202
- defaultValue: (_a = query[field.fieldLabel]) !== null && _a !== void 0 ? _a : '',
203
- placeholder,
204
- };
205
- if (fieldType === 'dropdownSearchable') {
206
- input.isSearchableDropdown = true;
207
- const fieldOptions = (_c = (_b = field.fieldOptions) === null || _b === void 0 ? void 0 : _b.values) !== null && _c !== void 0 ? _c : [];
208
- input.searchableOptions = fieldOptions.map((e) => e.option);
209
- }
210
- else if (fieldType === 'dropdownMultiselect') {
211
- input.isSearchableMultiselect = true;
212
- const fieldOptions = (_e = (_d = field.fieldOptions) === null || _d === void 0 ? void 0 : _d.values) !== null && _e !== void 0 ? _e : [];
213
- input.searchableMultiselectOptions = fieldOptions.map((e) => e.option);
214
- }
215
- else if (fieldType === 'dropdown') {
216
- if (multiselect) {
217
- input.isMultiSelect = true;
218
- input.multiSelectOptions =
219
- (_g = (_f = field.fieldOptions) === null || _f === void 0 ? void 0 : _f.values.map((e, i) => ({
220
- id: `option${i}_${input.id}`,
221
- label: e.option,
222
- }))) !== null && _g !== void 0 ? _g : [];
223
- }
224
- else {
225
- input.isSelect = true;
226
- const fieldOptions = (_j = (_h = field.fieldOptions) === null || _h === void 0 ? void 0 : _h.values) !== null && _j !== void 0 ? _j : [];
227
- input.selectOptions = fieldOptions.map((e) => e.option);
228
- }
229
- }
230
- else if (multiselect || (fieldType && ['radio', 'checkbox'].includes(fieldType))) {
231
- input.isMultiSelect = true;
232
- input.multiSelectOptions =
233
- (_l = (_k = field.fieldOptions) === null || _k === void 0 ? void 0 : _k.values.map((e, i) => ({
234
- id: `option${i}_${input.id}`,
235
- label: e.option,
236
- }))) !== null && _l !== void 0 ? _l : [];
237
- if (fieldType === 'radio') {
238
- input.radioSelect = 'radio';
239
- }
240
- else if (field.limitSelection === 'exact') {
241
- input.exactSelectedOptions = field.numberOfSelections;
242
- }
243
- else if (field.limitSelection === 'range') {
244
- input.minSelectedOptions = field.minSelections;
245
- input.maxSelectedOptions = field.maxSelections;
246
- }
247
- }
248
- else if (fieldType === 'file') {
249
- input.isFileInput = true;
250
- input.acceptFileTypes = field.acceptFileTypes;
251
- input.multipleFiles = field.multipleFiles ? 'multiple' : '';
252
- input.maxFileSize = field.maxFileSize;
253
- }
254
- else if (fieldType === 'textarea') {
255
- input.isTextarea = true;
256
- }
257
- else if (fieldType === 'html') {
258
- input.isHtml = true;
259
- input.html = field.html;
260
- }
261
- else if (fieldType === 'hiddenField') {
262
- input.isHidden = true;
263
- input.hiddenName = field.fieldName;
264
- input.hiddenValue =
265
- input.defaultValue === '' ? field.fieldValue : input.defaultValue;
266
- }
267
- else {
268
- input.isInput = true;
269
- input.type = fieldType;
270
- }
271
- const fieldWithConditional = field;
272
- if ((_m = fieldWithConditional.conditionalVisibility) === null || _m === void 0 ? void 0 : _m.showWhen) {
273
- const { fieldLabel, values } = fieldWithConditional.conditionalVisibility.showWhen;
274
- if (fieldLabel && values) {
275
- const triggerFieldIndex = formFields.findIndex(f => f.fieldLabel === fieldLabel);
276
- if (triggerFieldIndex !== -1) {
277
- const triggerFieldId = `field-${triggerFieldIndex}`;
278
- const valueArray = values.split(',').map((v) => v.trim()).filter((v) => v);
279
- input.showWhen = {
280
- fieldId: triggerFieldId,
281
- fieldLabel,
282
- values: valueArray,
283
- };
284
- }
285
- }
286
- }
287
- formData.formFields.push(input);
288
- }
289
- return formData;
290
- }
291
- const validateResponseModeConfiguration = (context) => {
292
- const responseMode = context.getNodeParameter('responseMode', 'onReceived');
293
- const connectedNodes = context.getChildNodes(context.getNode().name);
294
- const nodeVersion = context.getNode().typeVersion;
295
- const isRespondToWebhookConnected = connectedNodes.some((node) => node.type === 'n8n-nodes-base.respondToWebhook');
296
- if (!isRespondToWebhookConnected && responseMode === 'responseNode') {
297
- throw new n8n_workflow_1.NodeOperationError(context.getNode(), new Error('No Respond to Webhook node found in the workflow'), {
298
- description: 'Insert a Respond to Webhook node to your workflow to respond to the form submission or choose another option for the “Respond When” parameter',
299
- });
300
- }
301
- if (isRespondToWebhookConnected && responseMode !== 'responseNode' && nodeVersion <= 2.1) {
302
- throw new n8n_workflow_1.WorkflowConfigurationError(context.getNode(), new Error('Unused Respond to Webhook node found in the workflow'), {
303
- description: 'Set the “Respond When” parameter to “Using Respond to Webhook Node” or remove the Respond to Webhook node',
304
- });
305
- }
306
- if (isRespondToWebhookConnected && nodeVersion > 2.1) {
307
- throw new n8n_workflow_1.NodeOperationError(context.getNode(), new Error('The "Respond to Webhook" node is not supported in workflows initiated by the "n8n Form Trigger"'), {
308
- description: 'To configure your response, add an "n8n Form" node and set the "Page Type" to "Form Ending"',
309
- });
310
- }
311
- };
312
- exports.validateResponseModeConfiguration = validateResponseModeConfiguration;
313
- function addFormResponseDataToReturnItem(returnItem, formFields, bodyData) {
314
- var _a, _b;
315
- for (const [index, field] of formFields.entries()) {
316
- const key = `field-${index}`;
317
- const name = (_a = field.fieldLabel) !== null && _a !== void 0 ? _a : field.fieldName;
318
- let value = (_b = bodyData[key]) !== null && _b !== void 0 ? _b : null;
319
- if (value === null) {
320
- returnItem.json[name] = null;
321
- continue;
322
- }
323
- if (field.fieldType === 'html') {
324
- if (field.elementName) {
325
- returnItem.json[field.elementName] = value;
326
- }
327
- continue;
328
- }
329
- if (field.fieldType === 'number') {
330
- value = Number(value);
331
- }
332
- if (field.fieldType === 'text') {
333
- value = String(value).trim();
334
- }
335
- if ((field.multiselect ||
336
- field.fieldType === 'checkbox' ||
337
- field.fieldType === 'radio' ||
338
- field.fieldType === 'dropdownMultiselect') &&
339
- typeof value === 'string') {
340
- value = (0, n8n_workflow_1.jsonParse)(value);
341
- if (field.fieldType === 'radio' && Array.isArray(value)) {
342
- value = value[0];
343
- }
344
- }
345
- if (field.fieldType === 'date' && value && field.formatDate !== '') {
346
- value = luxon_1.DateTime.fromFormat(String(value), 'yyyy-mm-dd').toFormat(field.formatDate);
347
- }
348
- if (field.fieldType === 'file' && field.multipleFiles && !Array.isArray(value)) {
349
- value = [value];
350
- }
351
- returnItem.json[name] = value;
352
- }
353
- }
354
- async function prepareFormReturnItem(context, formFields, mode, useWorkflowTimezone = false) {
355
- var _a, _b, _c;
356
- const req = context.getRequestObject();
357
- a.ok(req.contentType === 'multipart/form-data', 'Expected multipart/form-data');
358
- const bodyData = (_a = context.getBodyData().data) !== null && _a !== void 0 ? _a : {};
359
- const files = (_b = context.getBodyData().files) !== null && _b !== void 0 ? _b : {};
360
- const returnItem = {
361
- json: {},
362
- };
363
- if (files && Object.keys(files).length) {
364
- returnItem.binary = {};
365
- }
366
- for (const key of Object.keys(files)) {
367
- const processFiles = [];
368
- let multiFile = false;
369
- const filesInput = files[key];
370
- if (Array.isArray(filesInput)) {
371
- bodyData[key] = filesInput.map((file) => ({
372
- filename: file.originalFilename,
373
- mimetype: file.mimetype,
374
- size: file.size,
375
- }));
376
- processFiles.push(...filesInput);
377
- multiFile = true;
378
- }
379
- else {
380
- bodyData[key] = {
381
- filename: filesInput.originalFilename,
382
- mimetype: filesInput.mimetype,
383
- size: filesInput.size,
384
- };
385
- processFiles.push(filesInput);
386
- }
387
- const entryIndex = Number(key.replace(/field-/g, ''));
388
- const fieldLabel = isNaN(entryIndex) ? key : formFields[entryIndex].fieldLabel;
389
- let fileCount = 0;
390
- for (const file of processFiles) {
391
- let binaryPropertyName = fieldLabel.replace(/\W/g, '_');
392
- if (multiFile) {
393
- binaryPropertyName += `_${fileCount++}`;
394
- }
395
- returnItem.binary[binaryPropertyName] = await context.nodeHelpers.copyBinaryFile(file.filepath, (_c = file.originalFilename) !== null && _c !== void 0 ? _c : file.newFilename, file.mimetype);
396
- }
397
- }
398
- addFormResponseDataToReturnItem(returnItem, formFields, bodyData);
399
- const timezone = useWorkflowTimezone ? context.getTimezone() : 'UTC';
400
- returnItem.json.submittedAt = luxon_1.DateTime.now().setZone(timezone).toISO();
401
- returnItem.json.formMode = mode;
402
- if (Object.keys(context.getRequestObject().query || {}).length) {
403
- returnItem.json.formQueryParameters = context.getRequestObject().query;
404
- }
405
- return returnItem;
406
- }
407
- function renderForm({ context, res, formHeader, formTitle, formDescription, formFields, responseMode, mode, formSubmittedText, formSubmittedHeader, completionHeader, redirectUrl, appendAttribution, buttonLabel, customCss, }) {
408
- formDescription = (formDescription || '').replace(/\\n/g, '\n').replace(/<br>/g, '\n');
409
- const instanceId = context.getInstanceId();
410
- const useResponseData = responseMode === 'responseNode';
411
- let query = {};
412
- if (context.getNode().type === n8n_workflow_1.FORM_TRIGGER_NODE_TYPE) {
413
- query = context.getRequestObject().query;
414
- }
415
- else if (context.getNode().type === n8n_workflow_1.FORM_NODE_TYPE) {
416
- const parentNodes = context.getParentNodes(context.getNode().name);
417
- const trigger = parentNodes.find((node) => node.type === n8n_workflow_1.FORM_TRIGGER_NODE_TYPE);
418
- try {
419
- const triggerQueryParameters = context.evaluateExpression(`{{ $('${trigger === null || trigger === void 0 ? void 0 : trigger.name}').first().json.formQueryParameters }}`);
420
- if (triggerQueryParameters) {
421
- query = triggerQueryParameters;
422
- }
423
- }
424
- catch (error) { }
425
- }
426
- formFields = (0, exports.prepareFormFields)(context, formFields);
427
- let data;
428
- try {
429
- data = prepareFormData({
430
- formHeader,
431
- formTitle,
432
- formDescription,
433
- formSubmittedText,
434
- formSubmittedHeader,
435
- completionHeader,
436
- redirectUrl,
437
- formFields,
438
- testRun: mode === 'test',
439
- query,
440
- instanceId,
441
- useResponseData,
442
- appendAttribution,
443
- buttonLabel,
444
- customCss,
445
- });
446
- }
447
- catch (error) {
448
- throw error;
449
- }
450
- const html = (0, templateRenderer_1.renderTemplate)('form-trigger', data);
451
- res.setHeader('Content-Type', 'text/html');
452
- res.send(html);
453
- }
454
- const isFormConnected = (nodes) => {
455
- const result = nodes.some((n) => {
456
- var _a;
457
- const isFormNode = n.type === n8n_workflow_1.FORM_NODE_TYPE;
458
- const isWaitNodeWithForm = n.type === n8n_workflow_1.WAIT_NODE_TYPE && ((_a = n.parameters) === null || _a === void 0 ? void 0 : _a.resume) === 'form';
459
- const matches = isFormNode || isWaitNodeWithForm;
460
- return matches;
461
- });
462
- return result;
463
- };
464
- exports.isFormConnected = isFormConnected;
465
- async function formWebhook(context, authProperty = interfaces_1.FORM_TRIGGER_AUTHENTICATION_PROPERTY) {
466
- const node = context.getNode();
467
- const options = context.getNodeParameter('options', {});
468
- const res = context.getResponseObject();
469
- const req = context.getRequestObject();
470
- try {
471
- if (options.ignoreBots && (0, isbot_1.isbot)(req.headers['user-agent'])) {
472
- throw new utilities_1.WebhookAuthorizationError(403);
473
- }
474
- if (node.typeVersion > 1) {
475
- await (0, utilities_1.validateWebhookAuthentication)(context, authProperty);
476
- }
477
- }
478
- catch (error) {
479
- if (error instanceof utilities_1.WebhookAuthorizationError) {
480
- console.log('error instanceof WebhookAuthorizationError');
481
- res.setHeader('WWW-Authenticate', 'Basic realm="Enter credentials"');
482
- res.status(401).send();
483
- return { noWebhookResponse: true };
484
- }
485
- throw error;
486
- }
487
- const mode = context.getMode() === 'manual' ? 'test' : 'production';
488
- const formFields = context.getNodeParameter('formFields.values', []);
489
- const method = context.getRequestObject().method;
490
- (0, exports.validateResponseModeConfiguration)(context);
491
- if (method === 'GET') {
492
- const formHeaderRaw = context.getNodeParameter('formHeader', '');
493
- let formHeader;
494
- if (formHeaderRaw && formHeaderRaw.trim()) {
495
- formHeader = sanitizeHtml(formHeaderRaw);
496
- if (!formHeader.trim()) {
497
- formHeader = undefined;
498
- }
499
- }
500
- else {
501
- formHeader = undefined;
502
- }
503
- const formTitle = context.getNodeParameter('formTitle', '');
504
- const formDescription = sanitizeHtml(context.getNodeParameter('formDescription', ''));
505
- let responseMode = context.getNodeParameter('responseMode', '');
506
- let formSubmittedText;
507
- let redirectUrl;
508
- let appendAttribution = true;
509
- let completionHeader;
510
- let completionTitle;
511
- if (options.respondWithOptions) {
512
- const values = options.respondWithOptions.values;
513
- if (values.respondWith === 'text') {
514
- formSubmittedText = values.formSubmittedText;
515
- completionHeader = values.completionHeader;
516
- completionTitle = values.completionTitle;
517
- }
518
- if (values.respondWith === 'redirect') {
519
- redirectUrl = values.redirectUrl;
520
- }
521
- }
522
- else {
523
- formSubmittedText = options.formSubmittedText;
524
- }
525
- if (options.appendAttribution === false) {
526
- appendAttribution = false;
527
- }
528
- let buttonLabel = 'Submit';
529
- if (options.buttonLabel) {
530
- buttonLabel = options.buttonLabel;
531
- }
532
- const connectedNodes = context.getChildNodes(context.getNode().name, {
533
- includeNodeParameters: true,
534
- });
535
- const hasNextPage = (0, exports.isFormConnected)(connectedNodes);
536
- if (hasNextPage) {
537
- redirectUrl = undefined;
538
- responseMode = 'responseNode';
539
- }
540
- renderForm({
541
- context,
542
- res,
543
- formHeader,
544
- formTitle,
545
- formDescription,
546
- formFields,
547
- responseMode,
548
- mode,
549
- formSubmittedText,
550
- formSubmittedHeader: completionTitle,
551
- completionHeader,
552
- redirectUrl,
553
- appendAttribution,
554
- buttonLabel,
555
- customCss: options.customCss,
556
- });
557
- return {
558
- noWebhookResponse: true,
559
- };
560
- }
561
- let { useWorkflowTimezone } = options;
562
- if (useWorkflowTimezone === undefined && node.typeVersion > 2) {
563
- useWorkflowTimezone = true;
564
- }
565
- const returnItem = await prepareFormReturnItem(context, formFields, mode, useWorkflowTimezone);
566
- return {
567
- webhookResponse: { status: 200 },
568
- workflowData: [[returnItem]],
569
- };
570
- }
571
- function resolveRawData(context, rawData) {
572
- const resolvables = (0, utilities_1.getResolvables)(rawData);
573
- let returnData = rawData;
574
- if (returnData.startsWith('=')) {
575
- returnData = returnData.replace(/^=+/, '');
576
- }
577
- else {
578
- return returnData;
579
- }
580
- if (resolvables.length) {
581
- for (const resolvable of resolvables) {
582
- const resolvedValue = context.evaluateExpression(`${resolvable}`);
583
- if (typeof resolvedValue === 'object' && resolvedValue !== null) {
584
- returnData = returnData.replace(resolvable, JSON.stringify(resolvedValue));
585
- }
586
- else {
587
- returnData = returnData.replace(resolvable, resolvedValue);
588
- }
589
- }
590
- }
591
- return returnData;
592
- }
593
- //# sourceMappingURL=utils.js.map
1
+ "use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(o,m,k,k2){void 0===k2&&(k2=k);var desc=Object.getOwnPropertyDescriptor(m,k);desc&&!("get"in desc?!m.__esModule:desc.writable||desc.configurable)||(desc={enumerable:!0,get:function(){return m[k]}}),Object.defineProperty(o,k2,desc)}:function(o,m,k,k2){void 0===k2&&(k2=k),o[k2]=m[k]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(o,v){Object.defineProperty(o,"default",{enumerable:!0,value:v})}:function(o,v){o.default=v}),__importStar=this&&this.__importStar||function(){var ownKeys=function(o){return ownKeys=Object.getOwnPropertyNames||function(o){var ar=[];for(var k in o)Object.prototype.hasOwnProperty.call(o,k)&&(ar[ar.length]=k);return ar},ownKeys(o)};return function(mod){if(mod&&mod.__esModule)return mod;var result={};if(null!=mod)for(var k=ownKeys(mod),i=0;i<k.length;i++)"default"!==k[i]&&__createBinding(result,mod,k[i]);return __setModuleDefault(result,mod),result}}(),__importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.isFormConnected=exports.validateResponseModeConfiguration=exports.prepareFormFields=void 0,exports.sanitizeHtml=sanitizeHtml,exports.sanitizeCustomCss=sanitizeCustomCss,exports.createDescriptionMetadata=createDescriptionMetadata,exports.prepareFormData=prepareFormData,exports.addFormResponseDataToReturnItem=addFormResponseDataToReturnItem,exports.prepareFormReturnItem=prepareFormReturnItem,exports.renderForm=renderForm,exports.formWebhook=formWebhook,exports.resolveRawData=resolveRawData;const isbot_1=require("isbot"),a=__importStar(require("node:assert")),luxon_1=require("luxon"),https=__importStar(require("https")),http=__importStar(require("http")),n8n_workflow_1=require("n8n-workflow"),sanitize_html_1=__importDefault(require("sanitize-html")),utilities_1=require("./utilities"),interfaces_1=require("../interfaces"),templateRenderer_1=require("./templateRenderer");function isFormTriggerNode(nodeType){return"CUSTOM.formTrigger"===nodeType||nodeType.includes(".formTrigger")||"formTrigger"===nodeType}function isFormNode(nodeType){return"CUSTOM.form"===nodeType||nodeType.includes(".form")||"form"===nodeType}function sanitizeHtml(text){return(0,sanitize_html_1.default)(text,{allowedTags:["b","div","i","iframe","img","video","source","em","strong","a","h1","h2","h3","h4","h5","h6","u","sub","sup","code","pre","span","br","ul","ol","li","p","table","thead","tbody","tfoot","td","tr","th","br"],allowedAttributes:{a:["href","target","rel"],img:["src","alt","width","height"],video:["controls","autoplay","loop","muted","poster","width","height"],iframe:["src","width","height","frameborder","allow","allowfullscreen","referrerpolicy"],source:["src","type"],td:["colspan","rowspan","scope","headers"],th:["colspan","rowspan","scope","headers"]},allowedSchemes:["https","http"],allowedSchemesByTag:{source:["https","http"],iframe:["https","http"]},allowProtocolRelative:!1,transformTags:{iframe:sanitize_html_1.default.simpleTransform("iframe",{sandbox:"",referrerpolicy:"strict-origin-when-cross-origin",allow:"fullscreen; autoplay; encrypted-media"})}})}const prepareFormFields=(context,fields)=>fields.map(field=>{if("html"===field.fieldType){let{html:html}=field;if(!html)return field;for(const resolvable of(0,utilities_1.getResolvables)(html))html=html.replace(resolvable,context.evaluateExpression(resolvable));field.html=sanitizeHtml(html),field.fieldLabel=field.elementName}return"hiddenField"===field.fieldType&&(field.fieldLabel=field.fieldName),field});function sanitizeCustomCss(css){if(css)return(0,sanitize_html_1.default)(css,{allowedTags:[],allowedAttributes:{}})}function createDescriptionMetadata(description){return""===description?"n8n form":description.replace(/^\s*\n+|<\/?[^>]+(>|$)/g,"").slice(0,150)}function prepareFormData({formHeader:formHeader,formTitle:formTitle,formDescription:formDescription,formSubmittedHeader:formSubmittedHeader,formSubmittedText:formSubmittedText,completionHeader:completionHeader,redirectUrl:redirectUrl,formFields:formFields,testRun:testRun,query:query,instanceId:instanceId,useResponseData:useResponseData,appendAttribution:appendAttribution=!0,buttonLabel:buttonLabel,customCss:customCss,enableProgressSaving:enableProgressSaving,saveProgressWebhookUrl:saveProgressWebhookUrl,loadProgressWebhookUrl:loadProgressWebhookUrl,progressQueryParam:progressQueryParam}){var _a,_b,_c,_d,_e,_f,_g,_h,_j,_k,_l,_m;const n8nWebsiteLink=`https://n8n.io/?utm_source=n8n-internal&utm_medium=form-trigger${instanceId?`&utm_campaign=${instanceId}`:""}`;void 0===formSubmittedText&&(formSubmittedText="Your response has been recorded");const finalFormHeader=formHeader&&"string"==typeof formHeader&&formHeader.trim().length>0?formHeader.trim():void 0,finalCompletionHeader=completionHeader&&"string"==typeof completionHeader&&completionHeader.trim().length>0?sanitizeHtml(completionHeader.trim()):void 0,formData={testRun:testRun,formHeader:finalFormHeader,formTitle:formTitle,formDescription:formDescription,formDescriptionMetadata:createDescriptionMetadata(formDescription),formSubmittedHeader:formSubmittedHeader,formSubmittedText:formSubmittedText,completionHeader:finalCompletionHeader,n8nWebsiteLink:n8nWebsiteLink,formFields:[],useResponseData:useResponseData,appendAttribution:appendAttribution,buttonLabel:buttonLabel,dangerousCustomCss:sanitizeCustomCss(customCss),enableProgressSaving:enableProgressSaving,saveProgressWebhookUrl:saveProgressWebhookUrl,loadProgressWebhookUrl:loadProgressWebhookUrl,progressQueryParam:progressQueryParam};redirectUrl&&(redirectUrl.includes("://")||(redirectUrl=`http://${redirectUrl}`),formData.redirectUrl=redirectUrl);for(const[index,field]of formFields.entries()){const{fieldType:fieldType,requiredField:requiredField,multiselect:multiselect,placeholder:placeholder}=field,input={id:`field-${index}`,errorId:`error-field-${index}`,label:field.fieldLabel,inputRequired:requiredField?"form-required":"",defaultValue:null!==(_a=query[field.fieldLabel])&&void 0!==_a?_a:"",placeholder:placeholder};if("dropdownSearchable"===fieldType){input.isSearchableDropdown=!0;const fieldOptions=null!==(_c=null===(_b=field.fieldOptions)||void 0===_b?void 0:_b.values)&&void 0!==_c?_c:[];input.searchableOptions=fieldOptions.map(e=>e.option)}else if("dropdownMultiselect"===fieldType){input.isSearchableMultiselect=!0;const fieldOptions=null!==(_e=null===(_d=field.fieldOptions)||void 0===_d?void 0:_d.values)&&void 0!==_e?_e:[];input.searchableMultiselectOptions=fieldOptions.map(e=>e.option)}else if("dropdown"===fieldType)if(multiselect)input.isMultiSelect=!0,input.multiSelectOptions=null!==(_g=null===(_f=field.fieldOptions)||void 0===_f?void 0:_f.values.map((e,i)=>({id:`option${i}_${input.id}`,label:e.option})))&&void 0!==_g?_g:[];else{input.isSelect=!0;const fieldOptions=null!==(_j=null===(_h=field.fieldOptions)||void 0===_h?void 0:_h.values)&&void 0!==_j?_j:[];input.selectOptions=fieldOptions.map(e=>e.option)}else multiselect||fieldType&&["radio","checkbox"].includes(fieldType)?(input.isMultiSelect=!0,input.multiSelectOptions=null!==(_l=null===(_k=field.fieldOptions)||void 0===_k?void 0:_k.values.map((e,i)=>({id:`option${i}_${input.id}`,label:e.option})))&&void 0!==_l?_l:[],"radio"===fieldType?input.radioSelect="radio":"exact"===field.limitSelection?input.exactSelectedOptions=field.numberOfSelections:"range"===field.limitSelection&&(input.minSelectedOptions=field.minSelections,input.maxSelectedOptions=field.maxSelections)):"file"===fieldType?(input.isFileInput=!0,input.acceptFileTypes=field.acceptFileTypes,input.multipleFiles=field.multipleFiles?"multiple":"",input.maxFileSize=field.maxFileSize):"textarea"===fieldType?input.isTextarea=!0:"html"===fieldType?(input.isHtml=!0,input.html=field.html):"hiddenField"===fieldType?(input.isHidden=!0,input.hiddenName=field.fieldName,input.hiddenValue=""===input.defaultValue?field.fieldValue:input.defaultValue):(input.isInput=!0,input.type=fieldType);const fieldWithConditional=field;if(null===(_m=fieldWithConditional.conditionalVisibility)||void 0===_m?void 0:_m.showWhen){const{fieldLabel:fieldLabel,values:values}=fieldWithConditional.conditionalVisibility.showWhen;if(fieldLabel&&values){const triggerFieldIndex=formFields.findIndex(f=>f.fieldLabel===fieldLabel);if(-1!==triggerFieldIndex){const triggerFieldId=`field-${triggerFieldIndex}`,valueArray=values.split(",").map(v=>v.trim()).filter(v=>v);input.showWhen={fieldId:triggerFieldId,fieldLabel:fieldLabel,values:valueArray}}}}formData.formFields.push(input)}return formData}exports.prepareFormFields=prepareFormFields;const validateResponseModeConfiguration=context=>{const responseMode=context.getNodeParameter("responseMode","onReceived"),connectedNodes=context.getChildNodes(context.getNode().name),nodeVersion=context.getNode().typeVersion,isRespondToWebhookConnected=connectedNodes.some(node=>"n8n-nodes-base.respondToWebhook"===node.type);if(!isRespondToWebhookConnected&&"responseNode"===responseMode)throw new n8n_workflow_1.NodeOperationError(context.getNode(),new Error("No Respond to Webhook node found in the workflow"),{description:"Insert a Respond to Webhook node to your workflow to respond to the form submission or choose another option for the “Respond When” parameter"});if(isRespondToWebhookConnected&&"responseNode"!==responseMode&&nodeVersion<=2.1)throw new n8n_workflow_1.WorkflowConfigurationError(context.getNode(),new Error("Unused Respond to Webhook node found in the workflow"),{description:"Set the “Respond When” parameter to “Using Respond to Webhook Node” or remove the Respond to Webhook node"});if(isRespondToWebhookConnected&&nodeVersion>2.1)throw new n8n_workflow_1.NodeOperationError(context.getNode(),new Error('The "Respond to Webhook" node is not supported in workflows initiated by the "n8n Form Trigger"'),{description:'To configure your response, add an "n8n Form" node and set the "Page Type" to "Form Ending"'})};function addFormResponseDataToReturnItem(returnItem,formFields,bodyData){var _a,_b;for(const[index,field]of formFields.entries()){const key=`field-${index}`,name=null!==(_a=field.fieldLabel)&&void 0!==_a?_a:field.fieldName;let value=null!==(_b=bodyData[key])&&void 0!==_b?_b:null;null!==value?"html"!==field.fieldType?("number"===field.fieldType&&(value=Number(value)),"text"===field.fieldType&&(value=String(value).trim()),!field.multiselect&&"checkbox"!==field.fieldType&&"radio"!==field.fieldType&&"dropdownMultiselect"!==field.fieldType||"string"!=typeof value||(value=(0,n8n_workflow_1.jsonParse)(value),"radio"===field.fieldType&&Array.isArray(value)&&(value=value[0])),"date"===field.fieldType&&value&&""!==field.formatDate&&(value=luxon_1.DateTime.fromFormat(String(value),"yyyy-mm-dd").toFormat(field.formatDate)),"file"===field.fieldType&&field.multipleFiles&&!Array.isArray(value)&&(value=[value]),returnItem.json[name]=value):field.elementName&&(returnItem.json[field.elementName]=value):returnItem.json[name]=null}}async function prepareFormReturnItem(context,formFields,mode,useWorkflowTimezone=!1){var _a,_b,_c;const req=context.getRequestObject();a.ok("multipart/form-data"===req.contentType,"Expected multipart/form-data");const bodyData=null!==(_a=context.getBodyData().data)&&void 0!==_a?_a:{},files=null!==(_b=context.getBodyData().files)&&void 0!==_b?_b:{},returnItem={json:{}};files&&Object.keys(files).length&&(returnItem.binary={});for(const key of Object.keys(files)){const processFiles=[];let multiFile=!1;const filesInput=files[key];Array.isArray(filesInput)?(bodyData[key]=filesInput.map(file=>({filename:file.originalFilename,mimetype:file.mimetype,size:file.size})),processFiles.push(...filesInput),multiFile=!0):(bodyData[key]={filename:filesInput.originalFilename,mimetype:filesInput.mimetype,size:filesInput.size},processFiles.push(filesInput));const entryIndex=Number(key.replace(/field-/g,"")),fieldLabel=isNaN(entryIndex)?key:formFields[entryIndex].fieldLabel;let fileCount=0;for(const file of processFiles){let binaryPropertyName=fieldLabel.replace(/\W/g,"_");multiFile&&(binaryPropertyName+="_"+fileCount++),returnItem.binary[binaryPropertyName]=await context.nodeHelpers.copyBinaryFile(file.filepath,null!==(_c=file.originalFilename)&&void 0!==_c?_c:file.newFilename,file.mimetype)}}addFormResponseDataToReturnItem(returnItem,formFields,bodyData);const timezone=useWorkflowTimezone?context.getTimezone():"UTC";return returnItem.json.submittedAt=luxon_1.DateTime.now().setZone(timezone).toISO(),returnItem.json.formMode=mode,Object.keys(context.getRequestObject().query||{}).length&&(returnItem.json.formQueryParameters=context.getRequestObject().query),returnItem}async function renderForm({context:context,res:res,formHeader:formHeader,formTitle:formTitle,formDescription:formDescription,formFields:formFields,responseMode:responseMode,mode:mode,formSubmittedText:formSubmittedText,formSubmittedHeader:formSubmittedHeader,completionHeader:completionHeader,redirectUrl:redirectUrl,appendAttribution:appendAttribution,buttonLabel:buttonLabel,customCss:customCss,enableProgressSaving:enableProgressSavingParam,progressQueryParam:progressQueryParamParam,saveProgressWebhookUrl:saveProgressWebhookUrlParam,loadProgressWebhookUrl:loadProgressWebhookUrlParam}){var _a;formDescription=(formDescription||"").replace(/\\n/g,"\n").replace(/<br>/g,"\n");const instanceId=context.getInstanceId(),useResponseData="responseNode"===responseMode;let query={};if(isFormTriggerNode(context.getNode().type)){query=context.getRequestObject().query;const progressSettings=null===(_a=context.getNodeParameter("options",{}).progressSavingOptions)||void 0===_a?void 0:_a.values,enableProgressSaving=!!progressSettings,progressQueryParam=(null==progressSettings?void 0:progressSettings.progressQueryParam)||"token",loadProgressWebhookUrl=(null==progressSettings?void 0:progressSettings.loadProgressWebhookUrl)||"",progressId=(null==progressSettings||progressSettings.saveProgressWebhookUrl,query[progressQueryParam]);if(enableProgressSaving&&progressId&&loadProgressWebhookUrl)try{const url=new URL(loadProgressWebhookUrl);url.searchParams.set(progressQueryParam,progressId);const requestUrl=url.toString(),savedData=await makeHttpGetRequest(requestUrl);savedData&&"object"==typeof savedData&&Object.keys(savedData).length>0&&(query={...query,...savedData})}catch(error){}}else if(isFormNode(context.getNode().type)){const trigger=context.getParentNodes(context.getNode().name).find(node=>isFormTriggerNode(node.type));try{const triggerQueryParameters=context.evaluateExpression(`{{ $('${null==trigger?void 0:trigger.name}').first().json.formQueryParameters }}`);triggerQueryParameters&&(query=triggerQueryParameters)}catch(error){}}formFields=(0,exports.prepareFormFields)(context,formFields);const enableProgressSaving=enableProgressSavingParam||!1,progressQueryParam=progressQueryParamParam||"token",saveProgressWebhookUrl=saveProgressWebhookUrlParam,loadProgressWebhookUrl=loadProgressWebhookUrlParam;let data;try{data=prepareFormData({formHeader:formHeader,formTitle:formTitle,formDescription:formDescription,formSubmittedText:formSubmittedText,formSubmittedHeader:formSubmittedHeader,completionHeader:completionHeader,redirectUrl:redirectUrl,formFields:formFields,testRun:"test"===mode,query:query,instanceId:instanceId,useResponseData:useResponseData,appendAttribution:appendAttribution,buttonLabel:buttonLabel,customCss:customCss,enableProgressSaving:enableProgressSaving,saveProgressWebhookUrl:saveProgressWebhookUrl,loadProgressWebhookUrl:loadProgressWebhookUrl,progressQueryParam:progressQueryParam})}catch(error){throw error}const html=(0,templateRenderer_1.renderTemplate)("form-trigger",data);res.setHeader("Content-Type","text/html"),res.send(html)}exports.validateResponseModeConfiguration=validateResponseModeConfiguration;const isFormConnected=nodes=>nodes.some(n=>{var _a;const isFormNodeType=isFormNode(n.type),isWaitNodeWithForm=n.type===n8n_workflow_1.WAIT_NODE_TYPE&&"form"===(null===(_a=n.parameters)||void 0===_a?void 0:_a.resume);return isFormNodeType||isWaitNodeWithForm});async function formWebhook(context,authProperty=interfaces_1.FORM_TRIGGER_AUTHENTICATION_PROPERTY){var _a;const node=context.getNode(),options=context.getNodeParameter("options",{}),progressSettings=null===(_a=options.progressSavingOptions)||void 0===_a?void 0:_a.values,res=context.getResponseObject(),req=context.getRequestObject();try{if(options.ignoreBots&&(0,isbot_1.isbot)(req.headers["user-agent"]))throw new utilities_1.WebhookAuthorizationError(403);node.typeVersion>1&&await(0,utilities_1.validateWebhookAuthentication)(context,authProperty)}catch(error){if(error instanceof utilities_1.WebhookAuthorizationError)return res.setHeader("WWW-Authenticate",'Basic realm="Enter credentials"'),res.status(401).send(),{noWebhookResponse:!0};throw error}const mode="manual"===context.getMode()?"test":"production",formFields=context.getNodeParameter("formFields.values",[]),method=context.getRequestObject().method;if((0,exports.validateResponseModeConfiguration)(context),"GET"===method){const formHeaderRaw=context.getNodeParameter("formHeader","");let formHeader;formHeaderRaw&&formHeaderRaw.trim()?(formHeader=sanitizeHtml(formHeaderRaw),formHeader.trim()||(formHeader=void 0)):formHeader=void 0;const formTitle=context.getNodeParameter("formTitle",""),formDescription=sanitizeHtml(context.getNodeParameter("formDescription",""));let formSubmittedText,redirectUrl,completionHeader,completionTitle,responseMode=context.getNodeParameter("responseMode",""),appendAttribution=!0;if(options.respondWithOptions){const values=options.respondWithOptions.values;"text"===values.respondWith&&(formSubmittedText=values.formSubmittedText,completionHeader=values.completionHeader,completionTitle=values.completionTitle),"redirect"===values.respondWith&&(redirectUrl=values.redirectUrl)}else formSubmittedText=options.formSubmittedText;!1===options.appendAttribution&&(appendAttribution=!1);let buttonLabel="Submit";options.buttonLabel&&(buttonLabel=options.buttonLabel);const connectedNodes=context.getChildNodes(context.getNode().name,{includeNodeParameters:!0});return(0,exports.isFormConnected)(connectedNodes)&&(redirectUrl=void 0,responseMode="responseNode"),renderForm({context:context,res:res,formHeader:formHeader,formTitle:formTitle,formDescription:formDescription,formFields:formFields,responseMode:responseMode,mode:mode,formSubmittedText:formSubmittedText,formSubmittedHeader:completionTitle,completionHeader:completionHeader,redirectUrl:redirectUrl,appendAttribution:appendAttribution,buttonLabel:buttonLabel,customCss:options.customCss,enableProgressSaving:!!progressSettings,progressQueryParam:(null==progressSettings?void 0:progressSettings.progressQueryParam)||"token",saveProgressWebhookUrl:null==progressSettings?void 0:progressSettings.saveProgressWebhookUrl,loadProgressWebhookUrl:null==progressSettings?void 0:progressSettings.loadProgressWebhookUrl}),{noWebhookResponse:!0}}let{useWorkflowTimezone:useWorkflowTimezone}=options;void 0===useWorkflowTimezone&&node.typeVersion>2&&(useWorkflowTimezone=!0);return{webhookResponse:{status:200},workflowData:[[await prepareFormReturnItem(context,formFields,mode,useWorkflowTimezone)]]}}async function makeHttpGetRequest(url){return new Promise((resolve,reject)=>{const urlObj=new URL(url),isHttps="https:"===urlObj.protocol,httpModule=isHttps?https:http,options={hostname:urlObj.hostname,port:urlObj.port||(isHttps?443:80),path:urlObj.pathname+urlObj.search,method:"GET",timeout:1e4},req=httpModule.request(options,res=>{let data="";res.on("data",chunk=>{data+=chunk}),res.on("end",()=>{if(res.statusCode&&res.statusCode>=200&&res.statusCode<300)try{const result=JSON.parse(data),savedData=result.formData||result;resolve(savedData)}catch(parseError){resolve(null)}else res.statusCode,resolve(null)})});req.on("error",error=>{reject(error)}),req.on("timeout",()=>{req.destroy(),reject(new Error("Request timeout"))}),req.end()})}function resolveRawData(context,rawData){const resolvables=(0,utilities_1.getResolvables)(rawData);let returnData=rawData;if(!returnData.startsWith("="))return returnData;if(returnData=returnData.replace(/^=+/,""),resolvables.length)for(const resolvable of resolvables){const resolvedValue=context.evaluateExpression(`${resolvable}`);returnData="object"==typeof resolvedValue&&null!==resolvedValue?returnData.replace(resolvable,JSON.stringify(resolvedValue)):returnData.replace(resolvable,resolvedValue)}return returnData}
2
+ //# sourceMappingURL=utils.js.map
3
+ exports.isFormConnected=isFormConnected;