n8n-nodes-base 1.97.0 → 1.97.1

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.
@@ -41,7 +41,7 @@ var import_descriptions = require("./descriptions");
41
41
  var import_email_templates = require("./email-templates");
42
42
  var import_cssVariables = require("../../nodes/Form/cssVariables");
43
43
  var import_Form = require("../../nodes/Form/Form.node");
44
- var import_utils = require("../../nodes/Form/utils");
44
+ var import_utils = require("../../nodes/Form/utils/utils");
45
45
  var import_utilities = require("../utilities");
46
46
  const INPUT_FIELD_IDENTIFIER = "field-0";
47
47
  const limitWaitTimeOption = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../utils/sendAndWait/utils.ts"],"sourcesContent":["import isbot from 'isbot';\nimport {\n\tNodeOperationError,\n\tSEND_AND_WAIT_OPERATION,\n\ttryToParseJsonToFormFields,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\nimport type {\n\tINodeProperties,\n\tIExecuteFunctions,\n\tIWebhookFunctions,\n\tIDataObject,\n\tFormFieldsParameter,\n} from 'n8n-workflow';\n\nimport { limitWaitTimeProperties } from './descriptions';\nimport {\n\tACTION_RECORDED_PAGE,\n\tBUTTON_STYLE_PRIMARY,\n\tBUTTON_STYLE_SECONDARY,\n\tcreateEmailBodyWithN8nAttribution,\n\tcreateEmailBodyWithoutN8nAttribution,\n} from './email-templates';\nimport type { IEmail } from './interfaces';\nimport { cssVariables } from '../../nodes/Form/cssVariables';\nimport { formFieldsProperties } from '../../nodes/Form/Form.node';\nimport { prepareFormData, prepareFormReturnItem, resolveRawData } from '../../nodes/Form/utils';\nimport { escapeHtml } from '../utilities';\n\nexport type SendAndWaitConfig = {\n\ttitle: string;\n\tmessage: string;\n\turl: string;\n\toptions: Array<{ label: string; value: string; style: string }>;\n\tappendAttribution?: boolean;\n};\n\ntype FormResponseTypeOptions = {\n\tmessageButtonLabel?: string;\n\tresponseFormTitle?: string;\n\tresponseFormDescription?: string;\n\tresponseFormButtonLabel?: string;\n\tresponseFormCustomCss?: string;\n};\n\nconst INPUT_FIELD_IDENTIFIER = 'field-0';\n\nconst limitWaitTimeOption: INodeProperties = {\n\tdisplayName: 'Limit Wait Time',\n\tname: 'limitWaitTime',\n\ttype: 'fixedCollection',\n\tdescription:\n\t\t'Whether the workflow will automatically resume execution after the specified limit type',\n\tdefault: { values: { limitType: 'afterTimeInterval', resumeAmount: 45, resumeUnit: 'minutes' } },\n\toptions: [\n\t\t{\n\t\t\tdisplayName: 'Values',\n\t\t\tname: 'values',\n\t\t\tvalues: limitWaitTimeProperties,\n\t\t},\n\t],\n};\n\nconst appendAttributionOption: INodeProperties = {\n\tdisplayName: 'Append n8n Attribution',\n\tname: 'appendAttribution',\n\ttype: 'boolean',\n\tdefault: true,\n\tdescription:\n\t\t'Whether to include the phrase \"This message was sent automatically with n8n\" to the end of the message',\n};\n\n// Operation Properties ----------------------------------------------------------\nexport function getSendAndWaitProperties(\n\ttargetProperties: INodeProperties[],\n\tresource: string = 'message',\n\tadditionalProperties: INodeProperties[] = [],\n\toptions?: {\n\t\tnoButtonStyle?: boolean;\n\t\tdefaultApproveLabel?: string;\n\t\tdefaultDisapproveLabel?: string;\n\t},\n) {\n\tconst buttonStyle: INodeProperties = {\n\t\tdisplayName: 'Button Style',\n\t\tname: 'buttonStyle',\n\t\ttype: 'options',\n\t\tdefault: 'primary',\n\t\toptions: [\n\t\t\t{\n\t\t\t\tname: 'Primary',\n\t\t\t\tvalue: 'primary',\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'Secondary',\n\t\t\t\tvalue: 'secondary',\n\t\t\t},\n\t\t],\n\t};\n\tconst approvalOptionsValues = [\n\t\t{\n\t\t\tdisplayName: 'Type of Approval',\n\t\t\tname: 'approvalType',\n\t\t\ttype: 'options',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: 'single',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'Approve Only',\n\t\t\t\t\tvalue: 'single',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Approve and Disapprove',\n\t\t\t\t\tvalue: 'double',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Approve Button Label',\n\t\t\tname: 'approveLabel',\n\t\t\ttype: 'string',\n\t\t\tdefault: options?.defaultApproveLabel || 'Approve',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tapprovalType: ['single', 'double'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t...[\n\t\t\toptions?.noButtonStyle\n\t\t\t\t? ({} as INodeProperties)\n\t\t\t\t: {\n\t\t\t\t\t\t...buttonStyle,\n\t\t\t\t\t\tdisplayName: 'Approve Button Style',\n\t\t\t\t\t\tname: 'buttonApprovalStyle',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tapprovalType: ['single', 'double'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t],\n\t\t{\n\t\t\tdisplayName: 'Disapprove Button Label',\n\t\t\tname: 'disapproveLabel',\n\t\t\ttype: 'string',\n\t\t\tdefault: options?.defaultDisapproveLabel || 'Decline',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tapprovalType: ['double'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t...[\n\t\t\toptions?.noButtonStyle\n\t\t\t\t? ({} as INodeProperties)\n\t\t\t\t: {\n\t\t\t\t\t\t...buttonStyle,\n\t\t\t\t\t\tdisplayName: 'Disapprove Button Style',\n\t\t\t\t\t\tname: 'buttonDisapprovalStyle',\n\t\t\t\t\t\tdefault: 'secondary',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tapprovalType: ['double'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t],\n\t].filter((p) => Object.keys(p).length) as INodeProperties[];\n\n\tconst sendAndWait: INodeProperties[] = [\n\t\t...targetProperties,\n\t\t{\n\t\t\tdisplayName: 'Subject',\n\t\t\tname: 'subject',\n\t\t\ttype: 'string',\n\t\t\tdefault: '',\n\t\t\trequired: true,\n\t\t\tplaceholder: 'e.g. Approval required',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Message',\n\t\t\tname: 'message',\n\t\t\ttype: 'string',\n\t\t\tdefault: '',\n\t\t\trequired: true,\n\t\t\ttypeOptions: {\n\t\t\t\trows: 4,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Response Type',\n\t\t\tname: 'responseType',\n\t\t\ttype: 'options',\n\t\t\tdefault: 'approval',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'Approval',\n\t\t\t\t\tvalue: 'approval',\n\t\t\t\t\tdescription: 'User can approve/disapprove from within the message',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Free Text',\n\t\t\t\t\tvalue: 'freeText',\n\t\t\t\t\tdescription: 'User can submit a response via a form',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Custom Form',\n\t\t\t\t\tvalue: 'customForm',\n\t\t\t\t\tdescription: 'User can submit a response via a custom form',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t...updateDisplayOptions(\n\t\t\t{\n\t\t\t\tshow: {\n\t\t\t\t\tresponseType: ['customForm'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tformFieldsProperties,\n\t\t),\n\n\t\t{\n\t\t\tdisplayName: 'Approval Options',\n\t\t\tname: 'approvalOptions',\n\t\t\ttype: 'fixedCollection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Values',\n\t\t\t\t\tname: 'values',\n\t\t\t\t\tvalues: approvalOptionsValues,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tresponseType: ['approval'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Options',\n\t\t\tname: 'options',\n\t\t\ttype: 'collection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [limitWaitTimeOption, appendAttributionOption],\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tresponseType: ['approval'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Options',\n\t\t\tname: 'options',\n\t\t\ttype: 'collection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Message Button Label',\n\t\t\t\t\tname: 'messageButtonLabel',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: 'Respond',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Response Form Title',\n\t\t\t\t\tname: 'responseFormTitle',\n\t\t\t\t\tdescription: 'Title of the form that the user can access to provide their response',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Response Form Description',\n\t\t\t\t\tname: 'responseFormDescription',\n\t\t\t\t\tdescription: 'Description of the form that the user can access to provide their response',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Response Form Button Label',\n\t\t\t\t\tname: 'responseFormButtonLabel',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: 'Submit',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Response Form Custom Styling',\n\t\t\t\t\tname: 'responseFormCustomCss',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\trows: 10,\n\t\t\t\t\t\teditor: 'cssEditor',\n\t\t\t\t\t},\n\t\t\t\t\tdefault: cssVariables.trim(),\n\t\t\t\t\tdescription: 'Override default styling of the response form with CSS',\n\t\t\t\t},\n\t\t\t\tlimitWaitTimeOption,\n\t\t\t\tappendAttributionOption,\n\t\t\t],\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tresponseType: ['freeText', 'customForm'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t...additionalProperties,\n\t];\n\n\treturn updateDisplayOptions(\n\t\t{\n\t\t\tshow: {\n\t\t\t\tresource: [resource],\n\t\t\t\toperation: [SEND_AND_WAIT_OPERATION],\n\t\t\t},\n\t\t},\n\t\tsendAndWait,\n\t);\n}\n\n// Webhook Function --------------------------------------------------------------\nconst getFormResponseCustomizations = (context: IWebhookFunctions) => {\n\tconst message = context.getNodeParameter('message', '') as string;\n\tconst options = context.getNodeParameter('options', {}) as FormResponseTypeOptions;\n\n\tlet formTitle = '';\n\tif (options.responseFormTitle) {\n\t\tformTitle = options.responseFormTitle;\n\t}\n\n\tlet formDescription = message;\n\tif (options.responseFormDescription) {\n\t\tformDescription = options.responseFormDescription;\n\t}\n\tformDescription = formDescription.replace(/\\\\n/g, '\\n').replace(/<br>/g, '\\n');\n\n\tlet buttonLabel = 'Submit';\n\tif (options.responseFormButtonLabel) {\n\t\tbuttonLabel = options.responseFormButtonLabel;\n\t}\n\n\treturn {\n\t\tformTitle,\n\t\tformDescription,\n\t\tbuttonLabel,\n\t\tcustomCss: options.responseFormCustomCss,\n\t};\n};\n\nexport async function sendAndWaitWebhook(this: IWebhookFunctions) {\n\tconst method = this.getRequestObject().method;\n\tconst res = this.getResponseObject();\n\tconst req = this.getRequestObject();\n\n\tconst responseType = this.getNodeParameter('responseType', 'approval') as\n\t\t| 'approval'\n\t\t| 'freeText'\n\t\t| 'customForm';\n\n\tif (responseType === 'approval' && isbot(req.headers['user-agent'])) {\n\t\tres.send('');\n\t\treturn { noWebhookResponse: true };\n\t}\n\n\tif (responseType === 'freeText') {\n\t\tif (method === 'GET') {\n\t\t\tconst { formTitle, formDescription, buttonLabel, customCss } =\n\t\t\t\tgetFormResponseCustomizations(this);\n\n\t\t\tconst data = prepareFormData({\n\t\t\t\tformTitle,\n\t\t\t\tformDescription,\n\t\t\t\tformSubmittedHeader: 'Got it, thanks',\n\t\t\t\tformSubmittedText: 'This page can be closed now',\n\t\t\t\tbuttonLabel,\n\t\t\t\tredirectUrl: undefined,\n\t\t\t\tformFields: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfieldLabel: 'Response',\n\t\t\t\t\t\tfieldType: 'textarea',\n\t\t\t\t\t\trequiredField: true,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\ttestRun: false,\n\t\t\t\tquery: {},\n\t\t\t\tcustomCss,\n\t\t\t});\n\n\t\t\tres.render('form-trigger', data);\n\n\t\t\treturn {\n\t\t\t\tnoWebhookResponse: true,\n\t\t\t};\n\t\t}\n\t\tif (method === 'POST') {\n\t\t\tconst data = this.getBodyData().data as IDataObject;\n\n\t\t\treturn {\n\t\t\t\twebhookResponse: ACTION_RECORDED_PAGE,\n\t\t\t\tworkflowData: [[{ json: { data: { text: data[INPUT_FIELD_IDENTIFIER] } } }]],\n\t\t\t};\n\t\t}\n\t}\n\n\tif (responseType === 'customForm') {\n\t\tconst defineForm = this.getNodeParameter('defineForm', 'fields') as 'fields' | 'json';\n\t\tlet fields: FormFieldsParameter = [];\n\n\t\tif (defineForm === 'json') {\n\t\t\ttry {\n\t\t\t\tconst jsonOutput = this.getNodeParameter('jsonOutput', '', {\n\t\t\t\t\trawExpressions: true,\n\t\t\t\t}) as string;\n\n\t\t\t\tfields = tryToParseJsonToFormFields(resolveRawData(this, jsonOutput));\n\t\t\t} catch (error) {\n\t\t\t\tthrow new NodeOperationError(this.getNode(), error.message, {\n\t\t\t\t\tdescription: error.message,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tfields = this.getNodeParameter('formFields.values', []) as FormFieldsParameter;\n\t\t}\n\n\t\tif (method === 'GET') {\n\t\t\tconst { formTitle, formDescription, buttonLabel, customCss } =\n\t\t\t\tgetFormResponseCustomizations(this);\n\n\t\t\tconst data = prepareFormData({\n\t\t\t\tformTitle,\n\t\t\t\tformDescription,\n\t\t\t\tformSubmittedHeader: 'Got it, thanks',\n\t\t\t\tformSubmittedText: 'This page can be closed now',\n\t\t\t\tbuttonLabel,\n\t\t\t\tredirectUrl: undefined,\n\t\t\t\tformFields: fields,\n\t\t\t\ttestRun: false,\n\t\t\t\tquery: {},\n\t\t\t\tcustomCss,\n\t\t\t});\n\n\t\t\tres.render('form-trigger', data);\n\n\t\t\treturn {\n\t\t\t\tnoWebhookResponse: true,\n\t\t\t};\n\t\t}\n\t\tif (method === 'POST') {\n\t\t\tconst returnItem = await prepareFormReturnItem(this, fields, 'production', true);\n\t\t\tconst json = returnItem.json;\n\n\t\t\tdelete json.submittedAt;\n\t\t\tdelete json.formMode;\n\n\t\t\treturnItem.json = { data: json };\n\n\t\t\treturn {\n\t\t\t\twebhookResponse: ACTION_RECORDED_PAGE,\n\t\t\t\tworkflowData: [[returnItem]],\n\t\t\t};\n\t\t}\n\t}\n\n\tconst query = req.query as { approved: 'false' | 'true' };\n\tconst approved = query.approved === 'true';\n\treturn {\n\t\twebhookResponse: ACTION_RECORDED_PAGE,\n\t\tworkflowData: [[{ json: { data: { approved } } }]],\n\t};\n}\n\n// Send and Wait Config -----------------------------------------------------------\nexport function getSendAndWaitConfig(context: IExecuteFunctions): SendAndWaitConfig {\n\tconst message = escapeHtml((context.getNodeParameter('message', 0, '') as string).trim())\n\t\t.replace(/\\\\n/g, '\\n')\n\t\t.replace(/<br>/g, '\\n');\n\tconst subject = escapeHtml(context.getNodeParameter('subject', 0, '') as string);\n\tconst resumeUrl = context.evaluateExpression('{{ $execution?.resumeUrl }}', 0) as string;\n\tconst nodeId = context.evaluateExpression('{{ $nodeId }}', 0) as string;\n\tconst approvalOptions = context.getNodeParameter('approvalOptions.values', 0, {}) as {\n\t\tapprovalType?: 'single' | 'double';\n\t\tapproveLabel?: string;\n\t\tbuttonApprovalStyle?: string;\n\t\tdisapproveLabel?: string;\n\t\tbuttonDisapprovalStyle?: string;\n\t};\n\n\tconst options = context.getNodeParameter('options', 0, {});\n\n\tconst config: SendAndWaitConfig = {\n\t\ttitle: subject,\n\t\tmessage,\n\t\turl: `${resumeUrl}/${nodeId}`,\n\t\toptions: [],\n\t\tappendAttribution: options?.appendAttribution as boolean,\n\t};\n\n\tconst responseType = context.getNodeParameter('responseType', 0, 'approval') as string;\n\n\tif (responseType === 'freeText' || responseType === 'customForm') {\n\t\tconst label = context.getNodeParameter('options.messageButtonLabel', 0, 'Respond') as string;\n\t\tconfig.options.push({\n\t\t\tlabel,\n\t\t\tvalue: 'true',\n\t\t\tstyle: 'primary',\n\t\t});\n\t} else if (approvalOptions.approvalType === 'double') {\n\t\tconst approveLabel = escapeHtml(approvalOptions.approveLabel || 'Approve');\n\t\tconst buttonApprovalStyle = approvalOptions.buttonApprovalStyle || 'primary';\n\t\tconst disapproveLabel = escapeHtml(approvalOptions.disapproveLabel || 'Disapprove');\n\t\tconst buttonDisapprovalStyle = approvalOptions.buttonDisapprovalStyle || 'secondary';\n\n\t\tconfig.options.push({\n\t\t\tlabel: disapproveLabel,\n\t\t\tvalue: 'false',\n\t\t\tstyle: buttonDisapprovalStyle,\n\t\t});\n\t\tconfig.options.push({\n\t\t\tlabel: approveLabel,\n\t\t\tvalue: 'true',\n\t\t\tstyle: buttonApprovalStyle,\n\t\t});\n\t} else {\n\t\tconst label = escapeHtml(approvalOptions.approveLabel || 'Approve');\n\t\tconst style = approvalOptions.buttonApprovalStyle || 'primary';\n\t\tconfig.options.push({\n\t\t\tlabel,\n\t\t\tvalue: 'true',\n\t\t\tstyle,\n\t\t});\n\t}\n\n\treturn config;\n}\n\nexport function createButton(url: string, label: string, approved: string, style: string) {\n\tlet buttonStyle = BUTTON_STYLE_PRIMARY;\n\tif (style === 'secondary') {\n\t\tbuttonStyle = BUTTON_STYLE_SECONDARY;\n\t}\n\treturn `<a href=\"${url}?approved=${approved}\" target=\"_blank\" style=\"${buttonStyle}\">${label}</a>`;\n}\n\nexport function createEmail(context: IExecuteFunctions) {\n\tconst to = (context.getNodeParameter('sendTo', 0, '') as string).trim();\n\tconst config = getSendAndWaitConfig(context);\n\n\tif (to.indexOf('@') === -1 || (to.match(/@/g) || []).length > 1) {\n\t\tconst description = `The email address '${to}' in the 'To' field isn't valid or contains multiple addresses. Please provide only a single email address.`;\n\t\tthrow new NodeOperationError(context.getNode(), 'Invalid email address', {\n\t\t\tdescription,\n\t\t\titemIndex: 0,\n\t\t});\n\t}\n\n\tconst buttons: string[] = [];\n\tfor (const option of config.options) {\n\t\tbuttons.push(createButton(config.url, option.label, option.value, option.style));\n\t}\n\tlet emailBody: string;\n\tif (config.appendAttribution !== false) {\n\t\tconst instanceId = context.getInstanceId();\n\t\temailBody = createEmailBodyWithN8nAttribution(config.message, buttons.join('\\n'), instanceId);\n\t} else {\n\t\temailBody = createEmailBodyWithoutN8nAttribution(config.message, buttons.join('\\n'));\n\t}\n\n\tconst email: IEmail = {\n\t\tto,\n\t\tsubject: config.title,\n\t\tbody: '',\n\t\thtmlBody: emailBody,\n\t};\n\n\treturn email;\n}\n"],"mappings":"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","names":["isbot"]}
1
+ {"version":3,"sources":["../../../utils/sendAndWait/utils.ts"],"sourcesContent":["import isbot from 'isbot';\nimport {\n\tNodeOperationError,\n\tSEND_AND_WAIT_OPERATION,\n\ttryToParseJsonToFormFields,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\nimport type {\n\tINodeProperties,\n\tIExecuteFunctions,\n\tIWebhookFunctions,\n\tIDataObject,\n\tFormFieldsParameter,\n} from 'n8n-workflow';\n\nimport { limitWaitTimeProperties } from './descriptions';\nimport {\n\tACTION_RECORDED_PAGE,\n\tBUTTON_STYLE_PRIMARY,\n\tBUTTON_STYLE_SECONDARY,\n\tcreateEmailBodyWithN8nAttribution,\n\tcreateEmailBodyWithoutN8nAttribution,\n} from './email-templates';\nimport type { IEmail } from './interfaces';\nimport { cssVariables } from '../../nodes/Form/cssVariables';\nimport { formFieldsProperties } from '../../nodes/Form/Form.node';\nimport {\n\tprepareFormData,\n\tprepareFormReturnItem,\n\tresolveRawData,\n} from '../../nodes/Form/utils/utils';\nimport { escapeHtml } from '../utilities';\n\nexport type SendAndWaitConfig = {\n\ttitle: string;\n\tmessage: string;\n\turl: string;\n\toptions: Array<{ label: string; value: string; style: string }>;\n\tappendAttribution?: boolean;\n};\n\ntype FormResponseTypeOptions = {\n\tmessageButtonLabel?: string;\n\tresponseFormTitle?: string;\n\tresponseFormDescription?: string;\n\tresponseFormButtonLabel?: string;\n\tresponseFormCustomCss?: string;\n};\n\nconst INPUT_FIELD_IDENTIFIER = 'field-0';\n\nconst limitWaitTimeOption: INodeProperties = {\n\tdisplayName: 'Limit Wait Time',\n\tname: 'limitWaitTime',\n\ttype: 'fixedCollection',\n\tdescription:\n\t\t'Whether the workflow will automatically resume execution after the specified limit type',\n\tdefault: { values: { limitType: 'afterTimeInterval', resumeAmount: 45, resumeUnit: 'minutes' } },\n\toptions: [\n\t\t{\n\t\t\tdisplayName: 'Values',\n\t\t\tname: 'values',\n\t\t\tvalues: limitWaitTimeProperties,\n\t\t},\n\t],\n};\n\nconst appendAttributionOption: INodeProperties = {\n\tdisplayName: 'Append n8n Attribution',\n\tname: 'appendAttribution',\n\ttype: 'boolean',\n\tdefault: true,\n\tdescription:\n\t\t'Whether to include the phrase \"This message was sent automatically with n8n\" to the end of the message',\n};\n\n// Operation Properties ----------------------------------------------------------\nexport function getSendAndWaitProperties(\n\ttargetProperties: INodeProperties[],\n\tresource: string = 'message',\n\tadditionalProperties: INodeProperties[] = [],\n\toptions?: {\n\t\tnoButtonStyle?: boolean;\n\t\tdefaultApproveLabel?: string;\n\t\tdefaultDisapproveLabel?: string;\n\t},\n) {\n\tconst buttonStyle: INodeProperties = {\n\t\tdisplayName: 'Button Style',\n\t\tname: 'buttonStyle',\n\t\ttype: 'options',\n\t\tdefault: 'primary',\n\t\toptions: [\n\t\t\t{\n\t\t\t\tname: 'Primary',\n\t\t\t\tvalue: 'primary',\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'Secondary',\n\t\t\t\tvalue: 'secondary',\n\t\t\t},\n\t\t],\n\t};\n\tconst approvalOptionsValues = [\n\t\t{\n\t\t\tdisplayName: 'Type of Approval',\n\t\t\tname: 'approvalType',\n\t\t\ttype: 'options',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: 'single',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'Approve Only',\n\t\t\t\t\tvalue: 'single',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Approve and Disapprove',\n\t\t\t\t\tvalue: 'double',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Approve Button Label',\n\t\t\tname: 'approveLabel',\n\t\t\ttype: 'string',\n\t\t\tdefault: options?.defaultApproveLabel || 'Approve',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tapprovalType: ['single', 'double'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t...[\n\t\t\toptions?.noButtonStyle\n\t\t\t\t? ({} as INodeProperties)\n\t\t\t\t: {\n\t\t\t\t\t\t...buttonStyle,\n\t\t\t\t\t\tdisplayName: 'Approve Button Style',\n\t\t\t\t\t\tname: 'buttonApprovalStyle',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tapprovalType: ['single', 'double'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t],\n\t\t{\n\t\t\tdisplayName: 'Disapprove Button Label',\n\t\t\tname: 'disapproveLabel',\n\t\t\ttype: 'string',\n\t\t\tdefault: options?.defaultDisapproveLabel || 'Decline',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tapprovalType: ['double'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t...[\n\t\t\toptions?.noButtonStyle\n\t\t\t\t? ({} as INodeProperties)\n\t\t\t\t: {\n\t\t\t\t\t\t...buttonStyle,\n\t\t\t\t\t\tdisplayName: 'Disapprove Button Style',\n\t\t\t\t\t\tname: 'buttonDisapprovalStyle',\n\t\t\t\t\t\tdefault: 'secondary',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tapprovalType: ['double'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t],\n\t].filter((p) => Object.keys(p).length) as INodeProperties[];\n\n\tconst sendAndWait: INodeProperties[] = [\n\t\t...targetProperties,\n\t\t{\n\t\t\tdisplayName: 'Subject',\n\t\t\tname: 'subject',\n\t\t\ttype: 'string',\n\t\t\tdefault: '',\n\t\t\trequired: true,\n\t\t\tplaceholder: 'e.g. Approval required',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Message',\n\t\t\tname: 'message',\n\t\t\ttype: 'string',\n\t\t\tdefault: '',\n\t\t\trequired: true,\n\t\t\ttypeOptions: {\n\t\t\t\trows: 4,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Response Type',\n\t\t\tname: 'responseType',\n\t\t\ttype: 'options',\n\t\t\tdefault: 'approval',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'Approval',\n\t\t\t\t\tvalue: 'approval',\n\t\t\t\t\tdescription: 'User can approve/disapprove from within the message',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Free Text',\n\t\t\t\t\tvalue: 'freeText',\n\t\t\t\t\tdescription: 'User can submit a response via a form',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Custom Form',\n\t\t\t\t\tvalue: 'customForm',\n\t\t\t\t\tdescription: 'User can submit a response via a custom form',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t...updateDisplayOptions(\n\t\t\t{\n\t\t\t\tshow: {\n\t\t\t\t\tresponseType: ['customForm'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tformFieldsProperties,\n\t\t),\n\n\t\t{\n\t\t\tdisplayName: 'Approval Options',\n\t\t\tname: 'approvalOptions',\n\t\t\ttype: 'fixedCollection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Values',\n\t\t\t\t\tname: 'values',\n\t\t\t\t\tvalues: approvalOptionsValues,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tresponseType: ['approval'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Options',\n\t\t\tname: 'options',\n\t\t\ttype: 'collection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [limitWaitTimeOption, appendAttributionOption],\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tresponseType: ['approval'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Options',\n\t\t\tname: 'options',\n\t\t\ttype: 'collection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Message Button Label',\n\t\t\t\t\tname: 'messageButtonLabel',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: 'Respond',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Response Form Title',\n\t\t\t\t\tname: 'responseFormTitle',\n\t\t\t\t\tdescription: 'Title of the form that the user can access to provide their response',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Response Form Description',\n\t\t\t\t\tname: 'responseFormDescription',\n\t\t\t\t\tdescription: 'Description of the form that the user can access to provide their response',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Response Form Button Label',\n\t\t\t\t\tname: 'responseFormButtonLabel',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: 'Submit',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Response Form Custom Styling',\n\t\t\t\t\tname: 'responseFormCustomCss',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\trows: 10,\n\t\t\t\t\t\teditor: 'cssEditor',\n\t\t\t\t\t},\n\t\t\t\t\tdefault: cssVariables.trim(),\n\t\t\t\t\tdescription: 'Override default styling of the response form with CSS',\n\t\t\t\t},\n\t\t\t\tlimitWaitTimeOption,\n\t\t\t\tappendAttributionOption,\n\t\t\t],\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tresponseType: ['freeText', 'customForm'],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t...additionalProperties,\n\t];\n\n\treturn updateDisplayOptions(\n\t\t{\n\t\t\tshow: {\n\t\t\t\tresource: [resource],\n\t\t\t\toperation: [SEND_AND_WAIT_OPERATION],\n\t\t\t},\n\t\t},\n\t\tsendAndWait,\n\t);\n}\n\n// Webhook Function --------------------------------------------------------------\nconst getFormResponseCustomizations = (context: IWebhookFunctions) => {\n\tconst message = context.getNodeParameter('message', '') as string;\n\tconst options = context.getNodeParameter('options', {}) as FormResponseTypeOptions;\n\n\tlet formTitle = '';\n\tif (options.responseFormTitle) {\n\t\tformTitle = options.responseFormTitle;\n\t}\n\n\tlet formDescription = message;\n\tif (options.responseFormDescription) {\n\t\tformDescription = options.responseFormDescription;\n\t}\n\tformDescription = formDescription.replace(/\\\\n/g, '\\n').replace(/<br>/g, '\\n');\n\n\tlet buttonLabel = 'Submit';\n\tif (options.responseFormButtonLabel) {\n\t\tbuttonLabel = options.responseFormButtonLabel;\n\t}\n\n\treturn {\n\t\tformTitle,\n\t\tformDescription,\n\t\tbuttonLabel,\n\t\tcustomCss: options.responseFormCustomCss,\n\t};\n};\n\nexport async function sendAndWaitWebhook(this: IWebhookFunctions) {\n\tconst method = this.getRequestObject().method;\n\tconst res = this.getResponseObject();\n\tconst req = this.getRequestObject();\n\n\tconst responseType = this.getNodeParameter('responseType', 'approval') as\n\t\t| 'approval'\n\t\t| 'freeText'\n\t\t| 'customForm';\n\n\tif (responseType === 'approval' && isbot(req.headers['user-agent'])) {\n\t\tres.send('');\n\t\treturn { noWebhookResponse: true };\n\t}\n\n\tif (responseType === 'freeText') {\n\t\tif (method === 'GET') {\n\t\t\tconst { formTitle, formDescription, buttonLabel, customCss } =\n\t\t\t\tgetFormResponseCustomizations(this);\n\n\t\t\tconst data = prepareFormData({\n\t\t\t\tformTitle,\n\t\t\t\tformDescription,\n\t\t\t\tformSubmittedHeader: 'Got it, thanks',\n\t\t\t\tformSubmittedText: 'This page can be closed now',\n\t\t\t\tbuttonLabel,\n\t\t\t\tredirectUrl: undefined,\n\t\t\t\tformFields: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfieldLabel: 'Response',\n\t\t\t\t\t\tfieldType: 'textarea',\n\t\t\t\t\t\trequiredField: true,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\ttestRun: false,\n\t\t\t\tquery: {},\n\t\t\t\tcustomCss,\n\t\t\t});\n\n\t\t\tres.render('form-trigger', data);\n\n\t\t\treturn {\n\t\t\t\tnoWebhookResponse: true,\n\t\t\t};\n\t\t}\n\t\tif (method === 'POST') {\n\t\t\tconst data = this.getBodyData().data as IDataObject;\n\n\t\t\treturn {\n\t\t\t\twebhookResponse: ACTION_RECORDED_PAGE,\n\t\t\t\tworkflowData: [[{ json: { data: { text: data[INPUT_FIELD_IDENTIFIER] } } }]],\n\t\t\t};\n\t\t}\n\t}\n\n\tif (responseType === 'customForm') {\n\t\tconst defineForm = this.getNodeParameter('defineForm', 'fields') as 'fields' | 'json';\n\t\tlet fields: FormFieldsParameter = [];\n\n\t\tif (defineForm === 'json') {\n\t\t\ttry {\n\t\t\t\tconst jsonOutput = this.getNodeParameter('jsonOutput', '', {\n\t\t\t\t\trawExpressions: true,\n\t\t\t\t}) as string;\n\n\t\t\t\tfields = tryToParseJsonToFormFields(resolveRawData(this, jsonOutput));\n\t\t\t} catch (error) {\n\t\t\t\tthrow new NodeOperationError(this.getNode(), error.message, {\n\t\t\t\t\tdescription: error.message,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tfields = this.getNodeParameter('formFields.values', []) as FormFieldsParameter;\n\t\t}\n\n\t\tif (method === 'GET') {\n\t\t\tconst { formTitle, formDescription, buttonLabel, customCss } =\n\t\t\t\tgetFormResponseCustomizations(this);\n\n\t\t\tconst data = prepareFormData({\n\t\t\t\tformTitle,\n\t\t\t\tformDescription,\n\t\t\t\tformSubmittedHeader: 'Got it, thanks',\n\t\t\t\tformSubmittedText: 'This page can be closed now',\n\t\t\t\tbuttonLabel,\n\t\t\t\tredirectUrl: undefined,\n\t\t\t\tformFields: fields,\n\t\t\t\ttestRun: false,\n\t\t\t\tquery: {},\n\t\t\t\tcustomCss,\n\t\t\t});\n\n\t\t\tres.render('form-trigger', data);\n\n\t\t\treturn {\n\t\t\t\tnoWebhookResponse: true,\n\t\t\t};\n\t\t}\n\t\tif (method === 'POST') {\n\t\t\tconst returnItem = await prepareFormReturnItem(this, fields, 'production', true);\n\t\t\tconst json = returnItem.json;\n\n\t\t\tdelete json.submittedAt;\n\t\t\tdelete json.formMode;\n\n\t\t\treturnItem.json = { data: json };\n\n\t\t\treturn {\n\t\t\t\twebhookResponse: ACTION_RECORDED_PAGE,\n\t\t\t\tworkflowData: [[returnItem]],\n\t\t\t};\n\t\t}\n\t}\n\n\tconst query = req.query as { approved: 'false' | 'true' };\n\tconst approved = query.approved === 'true';\n\treturn {\n\t\twebhookResponse: ACTION_RECORDED_PAGE,\n\t\tworkflowData: [[{ json: { data: { approved } } }]],\n\t};\n}\n\n// Send and Wait Config -----------------------------------------------------------\nexport function getSendAndWaitConfig(context: IExecuteFunctions): SendAndWaitConfig {\n\tconst message = escapeHtml((context.getNodeParameter('message', 0, '') as string).trim())\n\t\t.replace(/\\\\n/g, '\\n')\n\t\t.replace(/<br>/g, '\\n');\n\tconst subject = escapeHtml(context.getNodeParameter('subject', 0, '') as string);\n\tconst resumeUrl = context.evaluateExpression('{{ $execution?.resumeUrl }}', 0) as string;\n\tconst nodeId = context.evaluateExpression('{{ $nodeId }}', 0) as string;\n\tconst approvalOptions = context.getNodeParameter('approvalOptions.values', 0, {}) as {\n\t\tapprovalType?: 'single' | 'double';\n\t\tapproveLabel?: string;\n\t\tbuttonApprovalStyle?: string;\n\t\tdisapproveLabel?: string;\n\t\tbuttonDisapprovalStyle?: string;\n\t};\n\n\tconst options = context.getNodeParameter('options', 0, {});\n\n\tconst config: SendAndWaitConfig = {\n\t\ttitle: subject,\n\t\tmessage,\n\t\turl: `${resumeUrl}/${nodeId}`,\n\t\toptions: [],\n\t\tappendAttribution: options?.appendAttribution as boolean,\n\t};\n\n\tconst responseType = context.getNodeParameter('responseType', 0, 'approval') as string;\n\n\tif (responseType === 'freeText' || responseType === 'customForm') {\n\t\tconst label = context.getNodeParameter('options.messageButtonLabel', 0, 'Respond') as string;\n\t\tconfig.options.push({\n\t\t\tlabel,\n\t\t\tvalue: 'true',\n\t\t\tstyle: 'primary',\n\t\t});\n\t} else if (approvalOptions.approvalType === 'double') {\n\t\tconst approveLabel = escapeHtml(approvalOptions.approveLabel || 'Approve');\n\t\tconst buttonApprovalStyle = approvalOptions.buttonApprovalStyle || 'primary';\n\t\tconst disapproveLabel = escapeHtml(approvalOptions.disapproveLabel || 'Disapprove');\n\t\tconst buttonDisapprovalStyle = approvalOptions.buttonDisapprovalStyle || 'secondary';\n\n\t\tconfig.options.push({\n\t\t\tlabel: disapproveLabel,\n\t\t\tvalue: 'false',\n\t\t\tstyle: buttonDisapprovalStyle,\n\t\t});\n\t\tconfig.options.push({\n\t\t\tlabel: approveLabel,\n\t\t\tvalue: 'true',\n\t\t\tstyle: buttonApprovalStyle,\n\t\t});\n\t} else {\n\t\tconst label = escapeHtml(approvalOptions.approveLabel || 'Approve');\n\t\tconst style = approvalOptions.buttonApprovalStyle || 'primary';\n\t\tconfig.options.push({\n\t\t\tlabel,\n\t\t\tvalue: 'true',\n\t\t\tstyle,\n\t\t});\n\t}\n\n\treturn config;\n}\n\nexport function createButton(url: string, label: string, approved: string, style: string) {\n\tlet buttonStyle = BUTTON_STYLE_PRIMARY;\n\tif (style === 'secondary') {\n\t\tbuttonStyle = BUTTON_STYLE_SECONDARY;\n\t}\n\treturn `<a href=\"${url}?approved=${approved}\" target=\"_blank\" style=\"${buttonStyle}\">${label}</a>`;\n}\n\nexport function createEmail(context: IExecuteFunctions) {\n\tconst to = (context.getNodeParameter('sendTo', 0, '') as string).trim();\n\tconst config = getSendAndWaitConfig(context);\n\n\tif (to.indexOf('@') === -1 || (to.match(/@/g) || []).length > 1) {\n\t\tconst description = `The email address '${to}' in the 'To' field isn't valid or contains multiple addresses. Please provide only a single email address.`;\n\t\tthrow new NodeOperationError(context.getNode(), 'Invalid email address', {\n\t\t\tdescription,\n\t\t\titemIndex: 0,\n\t\t});\n\t}\n\n\tconst buttons: string[] = [];\n\tfor (const option of config.options) {\n\t\tbuttons.push(createButton(config.url, option.label, option.value, option.style));\n\t}\n\tlet emailBody: string;\n\tif (config.appendAttribution !== false) {\n\t\tconst instanceId = context.getInstanceId();\n\t\temailBody = createEmailBodyWithN8nAttribution(config.message, buttons.join('\\n'), instanceId);\n\t} else {\n\t\temailBody = createEmailBodyWithoutN8nAttribution(config.message, buttons.join('\\n'));\n\t}\n\n\tconst email: IEmail = {\n\t\tto,\n\t\tsubject: config.title,\n\t\tbody: '',\n\t\thtmlBody: emailBody,\n\t};\n\n\treturn email;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAClB,0BAKO;AASP,0BAAwC;AACxC,6BAMO;AAEP,0BAA6B;AAC7B,kBAAqC;AACrC,mBAIO;AACP,uBAA2B;AAkB3B,MAAM,yBAAyB;AAE/B,MAAM,sBAAuC;AAAA,EAC5C,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aACC;AAAA,EACD,SAAS,EAAE,QAAQ,EAAE,WAAW,qBAAqB,cAAc,IAAI,YAAY,UAAU,EAAE;AAAA,EAC/F,SAAS;AAAA,IACR;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,QAAQ;AAAA,IACT;AAAA,EACD;AACD;AAEA,MAAM,0BAA2C;AAAA,EAChD,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aACC;AACF;AAGO,SAAS,yBACf,kBACA,WAAmB,WACnB,uBAA0C,CAAC,GAC3C,SAKC;AACD,QAAM,cAA+B;AAAA,IACpC,aAAa;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,MACR;AAAA,QACC,MAAM;AAAA,QACN,OAAO;AAAA,MACR;AAAA,MACA;AAAA,QACC,MAAM;AAAA,QACN,OAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AACA,QAAM,wBAAwB;AAAA,IAC7B;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,MACT,SAAS;AAAA,QACR;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,QACR;AAAA,QACA;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,QACR;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,SAAS,uBAAuB;AAAA,MACzC,gBAAgB;AAAA,QACf,MAAM;AAAA,UACL,cAAc,CAAC,UAAU,QAAQ;AAAA,QAClC;AAAA,MACD;AAAA,IACD;AAAA,IACA,GAAG;AAAA,MACF,SAAS,gBACL,CAAC,IACF;AAAA,QACA,GAAG;AAAA,QACH,aAAa;AAAA,QACb,MAAM;AAAA,QACN,gBAAgB;AAAA,UACf,MAAM;AAAA,YACL,cAAc,CAAC,UAAU,QAAQ;AAAA,UAClC;AAAA,QACD;AAAA,MACD;AAAA,IACH;AAAA,IACA;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,SAAS,0BAA0B;AAAA,MAC5C,gBAAgB;AAAA,QACf,MAAM;AAAA,UACL,cAAc,CAAC,QAAQ;AAAA,QACxB;AAAA,MACD;AAAA,IACD;AAAA,IACA,GAAG;AAAA,MACF,SAAS,gBACL,CAAC,IACF;AAAA,QACA,GAAG;AAAA,QACH,aAAa;AAAA,QACb,MAAM;AAAA,QACN,SAAS;AAAA,QACT,gBAAgB;AAAA,UACf,MAAM;AAAA,YACL,cAAc,CAAC,QAAQ;AAAA,UACxB;AAAA,QACD;AAAA,MACD;AAAA,IACH;AAAA,EACD,EAAE,OAAO,CAAC,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM;AAErC,QAAM,cAAiC;AAAA,IACtC,GAAG;AAAA,IACH;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa;AAAA,IACd;AAAA,IACA;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa;AAAA,QACZ,MAAM;AAAA,MACP;AAAA,IACD;AAAA,IACA;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,QACR;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,QACd;AAAA,QACA;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,QACd;AAAA,QACA;AAAA,UACC,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,QACd;AAAA,MACD;AAAA,IACD;AAAA,IACA,OAAG;AAAA,MACF;AAAA,QACC,MAAM;AAAA,UACL,cAAc,CAAC,YAAY;AAAA,QAC5B;AAAA,MACD;AAAA,MACA;AAAA,IACD;AAAA,IAEA;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS,CAAC;AAAA,MACV,SAAS;AAAA,QACR;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,QAAQ;AAAA,QACT;AAAA,MACD;AAAA,MACA,gBAAgB;AAAA,QACf,MAAM;AAAA,UACL,cAAc,CAAC,UAAU;AAAA,QAC1B;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS,CAAC;AAAA,MACV,SAAS,CAAC,qBAAqB,uBAAuB;AAAA,MACtD,gBAAgB;AAAA,QACf,MAAM;AAAA,UACL,cAAc,CAAC,UAAU;AAAA,QAC1B;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS,CAAC;AAAA,MACV,SAAS;AAAA,QACR;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,QACV;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,aAAa;AAAA,UACb,MAAM;AAAA,UACN,SAAS;AAAA,QACV;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,aAAa;AAAA,UACb,MAAM;AAAA,UACN,SAAS;AAAA,QACV;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,QACV;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,YACZ,MAAM;AAAA,YACN,QAAQ;AAAA,UACT;AAAA,UACA,SAAS,iCAAa,KAAK;AAAA,UAC3B,aAAa;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,MACA,gBAAgB;AAAA,QACf,MAAM;AAAA,UACL,cAAc,CAAC,YAAY,YAAY;AAAA,QACxC;AAAA,MACD;AAAA,IACD;AAAA,IACA,GAAG;AAAA,EACJ;AAEA,aAAO;AAAA,IACN;AAAA,MACC,MAAM;AAAA,QACL,UAAU,CAAC,QAAQ;AAAA,QACnB,WAAW,CAAC,2CAAuB;AAAA,MACpC;AAAA,IACD;AAAA,IACA;AAAA,EACD;AACD;AAGA,MAAM,gCAAgC,CAAC,YAA+B;AACrE,QAAM,UAAU,QAAQ,iBAAiB,WAAW,EAAE;AACtD,QAAM,UAAU,QAAQ,iBAAiB,WAAW,CAAC,CAAC;AAEtD,MAAI,YAAY;AAChB,MAAI,QAAQ,mBAAmB;AAC9B,gBAAY,QAAQ;AAAA,EACrB;AAEA,MAAI,kBAAkB;AACtB,MAAI,QAAQ,yBAAyB;AACpC,sBAAkB,QAAQ;AAAA,EAC3B;AACA,oBAAkB,gBAAgB,QAAQ,QAAQ,IAAI,EAAE,QAAQ,SAAS,IAAI;AAE7E,MAAI,cAAc;AAClB,MAAI,QAAQ,yBAAyB;AACpC,kBAAc,QAAQ;AAAA,EACvB;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,QAAQ;AAAA,EACpB;AACD;AAEA,eAAsB,qBAA4C;AACjE,QAAM,SAAS,KAAK,iBAAiB,EAAE;AACvC,QAAM,MAAM,KAAK,kBAAkB;AACnC,QAAM,MAAM,KAAK,iBAAiB;AAElC,QAAM,eAAe,KAAK,iBAAiB,gBAAgB,UAAU;AAKrE,MAAI,iBAAiB,kBAAc,aAAAA,SAAM,IAAI,QAAQ,YAAY,CAAC,GAAG;AACpE,QAAI,KAAK,EAAE;AACX,WAAO,EAAE,mBAAmB,KAAK;AAAA,EAClC;AAEA,MAAI,iBAAiB,YAAY;AAChC,QAAI,WAAW,OAAO;AACrB,YAAM,EAAE,WAAW,iBAAiB,aAAa,UAAU,IAC1D,8BAA8B,IAAI;AAEnC,YAAM,WAAO,8BAAgB;AAAA,QAC5B;AAAA,QACA;AAAA,QACA,qBAAqB;AAAA,QACrB,mBAAmB;AAAA,QACnB;AAAA,QACA,aAAa;AAAA,QACb,YAAY;AAAA,UACX;AAAA,YACC,YAAY;AAAA,YACZ,WAAW;AAAA,YACX,eAAe;AAAA,UAChB;AAAA,QACD;AAAA,QACA,SAAS;AAAA,QACT,OAAO,CAAC;AAAA,QACR;AAAA,MACD,CAAC;AAED,UAAI,OAAO,gBAAgB,IAAI;AAE/B,aAAO;AAAA,QACN,mBAAmB;AAAA,MACpB;AAAA,IACD;AACA,QAAI,WAAW,QAAQ;AACtB,YAAM,OAAO,KAAK,YAAY,EAAE;AAEhC,aAAO;AAAA,QACN,iBAAiB;AAAA,QACjB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,sBAAsB,EAAE,EAAE,EAAE,CAAC,CAAC;AAAA,MAC5E;AAAA,IACD;AAAA,EACD;AAEA,MAAI,iBAAiB,cAAc;AAClC,UAAM,aAAa,KAAK,iBAAiB,cAAc,QAAQ;AAC/D,QAAI,SAA8B,CAAC;AAEnC,QAAI,eAAe,QAAQ;AAC1B,UAAI;AACH,cAAM,aAAa,KAAK,iBAAiB,cAAc,IAAI;AAAA,UAC1D,gBAAgB;AAAA,QACjB,CAAC;AAED,qBAAS,oDAA2B,6BAAe,MAAM,UAAU,CAAC;AAAA,MACrE,SAAS,OAAO;AACf,cAAM,IAAI,uCAAmB,KAAK,QAAQ,GAAG,MAAM,SAAS;AAAA,UAC3D,aAAa,MAAM;AAAA,QACpB,CAAC;AAAA,MACF;AAAA,IACD,OAAO;AACN,eAAS,KAAK,iBAAiB,qBAAqB,CAAC,CAAC;AAAA,IACvD;AAEA,QAAI,WAAW,OAAO;AACrB,YAAM,EAAE,WAAW,iBAAiB,aAAa,UAAU,IAC1D,8BAA8B,IAAI;AAEnC,YAAM,WAAO,8BAAgB;AAAA,QAC5B;AAAA,QACA;AAAA,QACA,qBAAqB;AAAA,QACrB,mBAAmB;AAAA,QACnB;AAAA,QACA,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,OAAO,CAAC;AAAA,QACR;AAAA,MACD,CAAC;AAED,UAAI,OAAO,gBAAgB,IAAI;AAE/B,aAAO;AAAA,QACN,mBAAmB;AAAA,MACpB;AAAA,IACD;AACA,QAAI,WAAW,QAAQ;AACtB,YAAM,aAAa,UAAM,oCAAsB,MAAM,QAAQ,cAAc,IAAI;AAC/E,YAAM,OAAO,WAAW;AAExB,aAAO,KAAK;AACZ,aAAO,KAAK;AAEZ,iBAAW,OAAO,EAAE,MAAM,KAAK;AAE/B,aAAO;AAAA,QACN,iBAAiB;AAAA,QACjB,cAAc,CAAC,CAAC,UAAU,CAAC;AAAA,MAC5B;AAAA,IACD;AAAA,EACD;AAEA,QAAM,QAAQ,IAAI;AAClB,QAAM,WAAW,MAAM,aAAa;AACpC,SAAO;AAAA,IACN,iBAAiB;AAAA,IACjB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AAAA,EAClD;AACD;AAGO,SAAS,qBAAqB,SAA+C;AACnF,QAAM,cAAU,6BAAY,QAAQ,iBAAiB,WAAW,GAAG,EAAE,EAAa,KAAK,CAAC,EACtF,QAAQ,QAAQ,IAAI,EACpB,QAAQ,SAAS,IAAI;AACvB,QAAM,cAAU,6BAAW,QAAQ,iBAAiB,WAAW,GAAG,EAAE,CAAW;AAC/E,QAAM,YAAY,QAAQ,mBAAmB,+BAA+B,CAAC;AAC7E,QAAM,SAAS,QAAQ,mBAAmB,iBAAiB,CAAC;AAC5D,QAAM,kBAAkB,QAAQ,iBAAiB,0BAA0B,GAAG,CAAC,CAAC;AAQhF,QAAM,UAAU,QAAQ,iBAAiB,WAAW,GAAG,CAAC,CAAC;AAEzD,QAAM,SAA4B;AAAA,IACjC,OAAO;AAAA,IACP;AAAA,IACA,KAAK,GAAG,SAAS,IAAI,MAAM;AAAA,IAC3B,SAAS,CAAC;AAAA,IACV,mBAAmB,SAAS;AAAA,EAC7B;AAEA,QAAM,eAAe,QAAQ,iBAAiB,gBAAgB,GAAG,UAAU;AAE3E,MAAI,iBAAiB,cAAc,iBAAiB,cAAc;AACjE,UAAM,QAAQ,QAAQ,iBAAiB,8BAA8B,GAAG,SAAS;AACjF,WAAO,QAAQ,KAAK;AAAA,MACnB;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,IACR,CAAC;AAAA,EACF,WAAW,gBAAgB,iBAAiB,UAAU;AACrD,UAAM,mBAAe,6BAAW,gBAAgB,gBAAgB,SAAS;AACzE,UAAM,sBAAsB,gBAAgB,uBAAuB;AACnE,UAAM,sBAAkB,6BAAW,gBAAgB,mBAAmB,YAAY;AAClF,UAAM,yBAAyB,gBAAgB,0BAA0B;AAEzE,WAAO,QAAQ,KAAK;AAAA,MACnB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACR,CAAC;AACD,WAAO,QAAQ,KAAK;AAAA,MACnB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACR,CAAC;AAAA,EACF,OAAO;AACN,UAAM,YAAQ,6BAAW,gBAAgB,gBAAgB,SAAS;AAClE,UAAM,QAAQ,gBAAgB,uBAAuB;AACrD,WAAO,QAAQ,KAAK;AAAA,MACnB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,IACD,CAAC;AAAA,EACF;AAEA,SAAO;AACR;AAEO,SAAS,aAAa,KAAa,OAAe,UAAkB,OAAe;AACzF,MAAI,cAAc;AAClB,MAAI,UAAU,aAAa;AAC1B,kBAAc;AAAA,EACf;AACA,SAAO,YAAY,GAAG,aAAa,QAAQ,4BAA4B,WAAW,KAAK,KAAK;AAC7F;AAEO,SAAS,YAAY,SAA4B;AACvD,QAAM,KAAM,QAAQ,iBAAiB,UAAU,GAAG,EAAE,EAAa,KAAK;AACtE,QAAM,SAAS,qBAAqB,OAAO;AAE3C,MAAI,GAAG,QAAQ,GAAG,MAAM,OAAO,GAAG,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,GAAG;AAChE,UAAM,cAAc,sBAAsB,EAAE;AAC5C,UAAM,IAAI,uCAAmB,QAAQ,QAAQ,GAAG,yBAAyB;AAAA,MACxE;AAAA,MACA,WAAW;AAAA,IACZ,CAAC;AAAA,EACF;AAEA,QAAM,UAAoB,CAAC;AAC3B,aAAW,UAAU,OAAO,SAAS;AACpC,YAAQ,KAAK,aAAa,OAAO,KAAK,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,CAAC;AAAA,EAChF;AACA,MAAI;AACJ,MAAI,OAAO,sBAAsB,OAAO;AACvC,UAAM,aAAa,QAAQ,cAAc;AACzC,oBAAY,0DAAkC,OAAO,SAAS,QAAQ,KAAK,IAAI,GAAG,UAAU;AAAA,EAC7F,OAAO;AACN,oBAAY,6DAAqC,OAAO,SAAS,QAAQ,KAAK,IAAI,CAAC;AAAA,EACpF;AAEA,QAAM,QAAgB;AAAA,IACrB;AAAA,IACA,SAAS,OAAO;AAAA,IAChB,MAAM;AAAA,IACN,UAAU;AAAA,EACX;AAEA,SAAO;AACR;","names":["isbot"]}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "n8n-nodes-base",
3
- "version": "1.97.0",
3
+ "version": "1.97.1",
4
4
  "description": "Base nodes of n8n",
5
5
  "main": "index.js",
6
6
  "files": [
7
7
  "dist",
8
- "LICENSE.md",
9
- "LICENSE_EE.md"
8
+ "LICENSE_EE.md",
9
+ "LICENSE.md"
10
10
  ],
11
11
  "n8n": {
12
12
  "credentials": [
@@ -930,10 +930,10 @@
930
930
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz",
931
931
  "xml2js": "0.6.2",
932
932
  "xmlhttprequest-ssl": "3.1.0",
933
- "@n8n/config": "1.43.0",
934
- "@n8n/di": "0.6.0",
935
933
  "@n8n/imap": "0.10.0",
936
- "n8n-workflow": "1.96.0"
934
+ "@n8n/config": "1.43.0",
935
+ "n8n-workflow": "1.96.0",
936
+ "@n8n/di": "0.6.0"
937
937
  },
938
938
  "license": "SEE LICENSE IN LICENSE.md",
939
939
  "homepage": "https://n8n.io",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../nodes/Form/formCompletionUtils.ts"],"sourcesContent":["import { type Response } from 'express';\nimport {\n\ttype NodeTypeAndVersion,\n\ttype IWebhookFunctions,\n\ttype IWebhookResponseData,\n\ttype IBinaryData,\n\ttype IDataObject,\n\tOperationalError,\n} from 'n8n-workflow';\n\nimport { sanitizeCustomCss, sanitizeHtml } from './utils';\n\nconst getBinaryDataFromNode = (context: IWebhookFunctions, nodeName: string): IDataObject => {\n\treturn context.evaluateExpression(`{{ $('${nodeName}').first().binary }}`) as IDataObject;\n};\n\nexport const binaryResponse = async (\n\tcontext: IWebhookFunctions,\n): Promise<{ data: string | Buffer; fileName: string; type: string }> => {\n\tconst inputDataFieldName = context.getNodeParameter('inputDataFieldName', '') as string;\n\tconst parentNodes = context.getParentNodes(context.getNode().name);\n\tconst binaryNode = parentNodes\n\t\t.reverse()\n\t\t.find((node) => getBinaryDataFromNode(context, node?.name)?.hasOwnProperty(inputDataFieldName));\n\tif (!binaryNode) {\n\t\tthrow new OperationalError(`No binary data with field ${inputDataFieldName} found.`);\n\t}\n\tconst binaryData = getBinaryDataFromNode(context, binaryNode?.name)[\n\t\tinputDataFieldName\n\t] as IBinaryData;\n\n\treturn {\n\t\t// If a binaryData has an id, the following field is set:\n\t\t// N8N_DEFAULT_BINARY_DATA_MODE=filesystem\n\t\tdata: binaryData.id\n\t\t\t? await context.helpers.binaryToBuffer(await context.helpers.getBinaryStream(binaryData.id))\n\t\t\t: atob(binaryData.data),\n\t\tfileName: binaryData.fileName ?? 'file',\n\t\ttype: binaryData.mimeType,\n\t};\n};\n\nexport const renderFormCompletion = async (\n\tcontext: IWebhookFunctions,\n\tres: Response,\n\ttrigger: NodeTypeAndVersion,\n): Promise<IWebhookResponseData> => {\n\tconst completionTitle = context.getNodeParameter('completionTitle', '') as string;\n\tconst completionMessage = context.getNodeParameter('completionMessage', '') as string;\n\tconst redirectUrl = context.getNodeParameter('redirectUrl', '') as string;\n\tconst options = context.getNodeParameter('options', {}) as {\n\t\tformTitle: string;\n\t\tcustomCss?: string;\n\t};\n\tconst responseText = context.getNodeParameter('responseText', '') as string;\n\tconst binary =\n\t\tcontext.getNodeParameter('respondWith', '') === 'returnBinary'\n\t\t\t? await binaryResponse(context)\n\t\t\t: '';\n\n\tlet title = options.formTitle;\n\tif (!title) {\n\t\ttitle = context.evaluateExpression(`{{ $('${trigger?.name}').params.formTitle }}`) as string;\n\t}\n\tconst appendAttribution = context.evaluateExpression(\n\t\t`{{ $('${trigger?.name}').params.options?.appendAttribution === false ? false : true }}`,\n\t) as boolean;\n\n\tres.render('form-trigger-completion', {\n\t\ttitle: completionTitle,\n\t\tmessage: completionMessage,\n\t\tformTitle: title,\n\t\tappendAttribution,\n\t\tresponseText: sanitizeHtml(responseText),\n\t\tresponseBinary: encodeURIComponent(JSON.stringify(binary)),\n\t\tdangerousCustomCss: sanitizeCustomCss(options.customCss),\n\t\tredirectUrl,\n\t});\n\n\treturn { noWebhookResponse: true };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAOO;AAEP,mBAAgD;AAEhD,MAAM,wBAAwB,CAAC,SAA4B,aAAkC;AAC5F,SAAO,QAAQ,mBAAmB,SAAS,QAAQ,sBAAsB;AAC1E;AAEO,MAAM,iBAAiB,OAC7B,YACwE;AACxE,QAAM,qBAAqB,QAAQ,iBAAiB,sBAAsB,EAAE;AAC5E,QAAM,cAAc,QAAQ,eAAe,QAAQ,QAAQ,EAAE,IAAI;AACjE,QAAM,aAAa,YACjB,QAAQ,EACR,KAAK,CAAC,SAAS,sBAAsB,SAAS,MAAM,IAAI,GAAG,eAAe,kBAAkB,CAAC;AAC/F,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI,qCAAiB,6BAA6B,kBAAkB,SAAS;AAAA,EACpF;AACA,QAAM,aAAa,sBAAsB,SAAS,YAAY,IAAI,EACjE,kBACD;AAEA,SAAO;AAAA;AAAA;AAAA,IAGN,MAAM,WAAW,KACd,MAAM,QAAQ,QAAQ,eAAe,MAAM,QAAQ,QAAQ,gBAAgB,WAAW,EAAE,CAAC,IACzF,KAAK,WAAW,IAAI;AAAA,IACvB,UAAU,WAAW,YAAY;AAAA,IACjC,MAAM,WAAW;AAAA,EAClB;AACD;AAEO,MAAM,uBAAuB,OACnC,SACA,KACA,YACmC;AACnC,QAAM,kBAAkB,QAAQ,iBAAiB,mBAAmB,EAAE;AACtE,QAAM,oBAAoB,QAAQ,iBAAiB,qBAAqB,EAAE;AAC1E,QAAM,cAAc,QAAQ,iBAAiB,eAAe,EAAE;AAC9D,QAAM,UAAU,QAAQ,iBAAiB,WAAW,CAAC,CAAC;AAItD,QAAM,eAAe,QAAQ,iBAAiB,gBAAgB,EAAE;AAChE,QAAM,SACL,QAAQ,iBAAiB,eAAe,EAAE,MAAM,iBAC7C,MAAM,eAAe,OAAO,IAC5B;AAEJ,MAAI,QAAQ,QAAQ;AACpB,MAAI,CAAC,OAAO;AACX,YAAQ,QAAQ,mBAAmB,SAAS,SAAS,IAAI,wBAAwB;AAAA,EAClF;AACA,QAAM,oBAAoB,QAAQ;AAAA,IACjC,SAAS,SAAS,IAAI;AAAA,EACvB;AAEA,MAAI,OAAO,2BAA2B;AAAA,IACrC,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX;AAAA,IACA,kBAAc,2BAAa,YAAY;AAAA,IACvC,gBAAgB,mBAAmB,KAAK,UAAU,MAAM,CAAC;AAAA,IACzD,wBAAoB,gCAAkB,QAAQ,SAAS;AAAA,IACvD;AAAA,EACD,CAAC;AAED,SAAO,EAAE,mBAAmB,KAAK;AAClC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../nodes/Form/formNodeUtils.ts"],"sourcesContent":["import { type Response } from 'express';\nimport {\n\ttype NodeTypeAndVersion,\n\ttype IWebhookFunctions,\n\ttype FormFieldsParameter,\n\ttype IWebhookResponseData,\n} from 'n8n-workflow';\n\nimport { renderForm } from './utils';\n\nexport const renderFormNode = async (\n\tcontext: IWebhookFunctions,\n\tres: Response,\n\ttrigger: NodeTypeAndVersion,\n\tfields: FormFieldsParameter,\n\tmode: 'test' | 'production',\n): Promise<IWebhookResponseData> => {\n\tconst options = context.getNodeParameter('options', {}) as {\n\t\tformTitle: string;\n\t\tformDescription: string;\n\t\tbuttonLabel: string;\n\t\tcustomCss?: string;\n\t};\n\n\tlet title = options.formTitle;\n\tif (!title) {\n\t\ttitle = context.evaluateExpression(`{{ $('${trigger?.name}').params.formTitle }}`) as string;\n\t}\n\n\tlet buttonLabel = options.buttonLabel;\n\tif (!buttonLabel) {\n\t\tbuttonLabel =\n\t\t\t(context.evaluateExpression(\n\t\t\t\t`{{ $('${trigger?.name}').params.options?.buttonLabel }}`,\n\t\t\t) as string) || 'Submit';\n\t}\n\n\tconst appendAttribution = context.evaluateExpression(\n\t\t`{{ $('${trigger?.name}').params.options?.appendAttribution === false ? false : true }}`,\n\t) as boolean;\n\n\trenderForm({\n\t\tcontext,\n\t\tres,\n\t\tformTitle: title,\n\t\tformDescription: options.formDescription,\n\t\tformFields: fields,\n\t\tresponseMode: 'responseNode',\n\t\tmode,\n\t\tredirectUrl: undefined,\n\t\tappendAttribution,\n\t\tbuttonLabel,\n\t\tcustomCss: options.customCss,\n\t});\n\n\treturn {\n\t\tnoWebhookResponse: true,\n\t};\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,mBAA2B;AAEpB,MAAM,iBAAiB,OAC7B,SACA,KACA,SACA,QACA,SACmC;AACnC,QAAM,UAAU,QAAQ,iBAAiB,WAAW,CAAC,CAAC;AAOtD,MAAI,QAAQ,QAAQ;AACpB,MAAI,CAAC,OAAO;AACX,YAAQ,QAAQ,mBAAmB,SAAS,SAAS,IAAI,wBAAwB;AAAA,EAClF;AAEA,MAAI,cAAc,QAAQ;AAC1B,MAAI,CAAC,aAAa;AACjB,kBACE,QAAQ;AAAA,MACR,SAAS,SAAS,IAAI;AAAA,IACvB,KAAgB;AAAA,EAClB;AAEA,QAAM,oBAAoB,QAAQ;AAAA,IACjC,SAAS,SAAS,IAAI;AAAA,EACvB;AAEA,+BAAW;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,iBAAiB,QAAQ;AAAA,IACzB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,WAAW,QAAQ;AAAA,EACpB,CAAC;AAED,SAAO;AAAA,IACN,mBAAmB;AAAA,EACpB;AACD;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../nodes/Form/utils.ts"],"sourcesContent":["import type { Response } from 'express';\nimport isbot from 'isbot';\nimport { DateTime } from 'luxon';\nimport type {\n\tINodeExecutionData,\n\tMultiPartFormData,\n\tIDataObject,\n\tIWebhookFunctions,\n\tFormFieldsParameter,\n\tNodeTypeAndVersion,\n} from 'n8n-workflow';\nimport {\n\tFORM_NODE_TYPE,\n\tFORM_TRIGGER_NODE_TYPE,\n\tNodeOperationError,\n\tWAIT_NODE_TYPE,\n\tjsonParse,\n} from 'n8n-workflow';\nimport sanitize from 'sanitize-html';\n\nimport type { FormTriggerData, FormTriggerInput } from './interfaces';\nimport { FORM_TRIGGER_AUTHENTICATION_PROPERTY } from './interfaces';\nimport { getResolvables } from '../../utils/utilities';\nimport { WebhookAuthorizationError } from '../Webhook/error';\nimport { validateWebhookAuthentication } from '../Webhook/utils';\n\nexport function sanitizeHtml(text: string) {\n\treturn sanitize(text, {\n\t\tallowedTags: [\n\t\t\t'b',\n\t\t\t'div',\n\t\t\t'i',\n\t\t\t'iframe',\n\t\t\t'img',\n\t\t\t'video',\n\t\t\t'source',\n\t\t\t'em',\n\t\t\t'strong',\n\t\t\t'a',\n\t\t\t'h1',\n\t\t\t'h2',\n\t\t\t'h3',\n\t\t\t'h4',\n\t\t\t'h5',\n\t\t\t'h6',\n\t\t\t'u',\n\t\t\t'sub',\n\t\t\t'sup',\n\t\t\t'code',\n\t\t\t'pre',\n\t\t\t'span',\n\t\t\t'br',\n\t\t\t'ul',\n\t\t\t'ol',\n\t\t\t'li',\n\t\t\t'p',\n\t\t],\n\t\tallowedAttributes: {\n\t\t\ta: ['href', 'target', 'rel'],\n\t\t\timg: ['src', 'alt', 'width', 'height'],\n\t\t\tvideo: ['*'],\n\t\t\tiframe: ['*'],\n\t\t\tsource: ['*'],\n\t\t},\n\t\ttransformTags: {\n\t\t\tiframe: sanitize.simpleTransform('iframe', {\n\t\t\t\tsandbox: '',\n\t\t\t\treferrerpolicy: 'strict-origin-when-cross-origin',\n\t\t\t\tallow: 'fullscreen; autoplay; encrypted-media',\n\t\t\t}),\n\t\t},\n\t});\n}\n\nexport const prepareFormFields = (context: IWebhookFunctions, fields: FormFieldsParameter) => {\n\treturn fields.map((field) => {\n\t\tif (field.fieldType === 'html') {\n\t\t\tlet { html } = field;\n\n\t\t\tif (!html) return field;\n\n\t\t\tfor (const resolvable of getResolvables(html)) {\n\t\t\t\thtml = html.replace(resolvable, context.evaluateExpression(resolvable) as string);\n\t\t\t}\n\n\t\t\tfield.html = sanitizeHtml(html);\n\t\t}\n\n\t\tif (field.fieldType === 'hiddenField') {\n\t\t\tfield.fieldLabel = field.fieldName as string;\n\t\t}\n\n\t\treturn field;\n\t});\n};\n\nexport function sanitizeCustomCss(css: string | undefined): string | undefined {\n\tif (!css) return undefined;\n\n\t// Use sanitize-html with custom settings for CSS\n\treturn sanitize(css, {\n\t\tallowedTags: [], // No HTML tags allowed\n\t\tallowedAttributes: {}, // No attributes allowed\n\t\t// This ensures we're only keeping the text content\n\t\t// which should be the CSS, while removing any HTML/script tags\n\t});\n}\n\nexport function createDescriptionMetadata(description: string) {\n\treturn description === ''\n\t\t? 'n8n form'\n\t\t: description.replace(/^\\s*\\n+|<\\/?[^>]+(>|$)/g, '').slice(0, 150);\n}\n\nexport function prepareFormData({\n\tformTitle,\n\tformDescription,\n\tformSubmittedHeader,\n\tformSubmittedText,\n\tredirectUrl,\n\tformFields,\n\ttestRun,\n\tquery,\n\tinstanceId,\n\tuseResponseData,\n\tappendAttribution = true,\n\tbuttonLabel,\n\tcustomCss,\n}: {\n\tformTitle: string;\n\tformDescription: string;\n\tformSubmittedText: string | undefined;\n\tredirectUrl: string | undefined;\n\tformFields: FormFieldsParameter;\n\ttestRun: boolean;\n\tquery: IDataObject;\n\tinstanceId?: string;\n\tuseResponseData?: boolean;\n\tappendAttribution?: boolean;\n\tbuttonLabel?: string;\n\tformSubmittedHeader?: string;\n\tcustomCss?: string;\n}) {\n\tconst utm_campaign = instanceId ? `&utm_campaign=${instanceId}` : '';\n\tconst n8nWebsiteLink = `https://n8n.io/?utm_source=n8n-internal&utm_medium=form-trigger${utm_campaign}`;\n\n\tif (formSubmittedText === undefined) {\n\t\tformSubmittedText = 'Your response has been recorded';\n\t}\n\n\tconst formData: FormTriggerData = {\n\t\ttestRun,\n\t\tformTitle,\n\t\tformDescription,\n\t\tformDescriptionMetadata: createDescriptionMetadata(formDescription),\n\t\tformSubmittedHeader,\n\t\tformSubmittedText,\n\t\tn8nWebsiteLink,\n\t\tformFields: [],\n\t\tuseResponseData,\n\t\tappendAttribution,\n\t\tbuttonLabel,\n\t\tdangerousCustomCss: sanitizeCustomCss(customCss),\n\t};\n\n\tif (redirectUrl) {\n\t\tif (!redirectUrl.includes('://')) {\n\t\t\tredirectUrl = `http://${redirectUrl}`;\n\t\t}\n\t\tformData.redirectUrl = redirectUrl;\n\t}\n\n\tfor (const [index, field] of formFields.entries()) {\n\t\tconst { fieldType, requiredField, multiselect, placeholder } = field;\n\n\t\tconst input: IDataObject = {\n\t\t\tid: `field-${index}`,\n\t\t\terrorId: `error-field-${index}`,\n\t\t\tlabel: field.fieldLabel,\n\t\t\tinputRequired: requiredField ? 'form-required' : '',\n\t\t\tdefaultValue: query[field.fieldLabel] ?? '',\n\t\t\tplaceholder,\n\t\t};\n\n\t\tif (multiselect) {\n\t\t\tinput.isMultiSelect = true;\n\t\t\tinput.multiSelectOptions =\n\t\t\t\tfield.fieldOptions?.values.map((e, i) => ({\n\t\t\t\t\tid: `option${i}_${input.id}`,\n\t\t\t\t\tlabel: e.option,\n\t\t\t\t})) ?? [];\n\t\t} else if (fieldType === 'file') {\n\t\t\tinput.isFileInput = true;\n\t\t\tinput.acceptFileTypes = field.acceptFileTypes;\n\t\t\tinput.multipleFiles = field.multipleFiles ? 'multiple' : '';\n\t\t} else if (fieldType === 'dropdown') {\n\t\t\tinput.isSelect = true;\n\t\t\tconst fieldOptions = field.fieldOptions?.values ?? [];\n\t\t\tinput.selectOptions = fieldOptions.map((e) => e.option);\n\t\t} else if (fieldType === 'textarea') {\n\t\t\tinput.isTextarea = true;\n\t\t} else if (fieldType === 'html') {\n\t\t\tinput.isHtml = true;\n\t\t\tinput.html = field.html as string;\n\t\t} else if (fieldType === 'hiddenField') {\n\t\t\tinput.isHidden = true;\n\t\t\tinput.hiddenName = field.fieldName as string;\n\t\t\tinput.hiddenValue =\n\t\t\t\tinput.defaultValue === '' ? (field.fieldValue as string) : input.defaultValue;\n\t\t} else {\n\t\t\tinput.isInput = true;\n\t\t\tinput.type = fieldType as 'text' | 'number' | 'date' | 'email';\n\t\t}\n\n\t\tformData.formFields.push(input as FormTriggerInput);\n\t}\n\n\treturn formData;\n}\n\nexport const validateResponseModeConfiguration = (context: IWebhookFunctions) => {\n\tconst responseMode = context.getNodeParameter('responseMode', 'onReceived') as string;\n\tconst connectedNodes = context.getChildNodes(context.getNode().name);\n\tconst nodeVersion = context.getNode().typeVersion;\n\n\tconst isRespondToWebhookConnected = connectedNodes.some(\n\t\t(node) => node.type === 'n8n-nodes-base.respondToWebhook',\n\t);\n\n\tif (!isRespondToWebhookConnected && responseMode === 'responseNode') {\n\t\tthrow new NodeOperationError(\n\t\t\tcontext.getNode(),\n\t\t\tnew Error('No Respond to Webhook node found in the workflow'),\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t'Insert a Respond to Webhook node to your workflow to respond to the form submission or choose another option for the “Respond When” parameter',\n\t\t\t},\n\t\t);\n\t}\n\n\tif (isRespondToWebhookConnected && responseMode !== 'responseNode' && nodeVersion <= 2.1) {\n\t\tthrow new NodeOperationError(\n\t\t\tcontext.getNode(),\n\t\t\tnew Error(`${context.getNode().name} node not correctly configured`),\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t'Set the “Respond When” parameter to “Using Respond to Webhook Node” or remove the Respond to Webhook node',\n\t\t\t},\n\t\t);\n\t}\n\n\tif (isRespondToWebhookConnected && nodeVersion > 2.1) {\n\t\tthrow new NodeOperationError(\n\t\t\tcontext.getNode(),\n\t\t\tnew Error(\n\t\t\t\t'The \"Respond to Webhook\" node is not supported in workflows initiated by the \"n8n Form Trigger\"',\n\t\t\t),\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t'To configure your response, add an \"n8n Form\" node and set the \"Page Type\" to \"Form Ending\"',\n\t\t\t},\n\t\t);\n\t}\n};\n\nexport function addFormResponseDataToReturnItem(\n\treturnItem: INodeExecutionData,\n\tformFields: FormFieldsParameter,\n\tbodyData: IDataObject,\n) {\n\tfor (const [index, field] of formFields.entries()) {\n\t\tconst key = `field-${index}`;\n\t\tconst name = field.fieldLabel ?? field.fieldName;\n\t\tlet value = bodyData[key] ?? null;\n\n\t\tif (value === null) {\n\t\t\treturnItem.json[name] = null;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.fieldType === 'html') {\n\t\t\tif (field.elementName) {\n\t\t\t\treturnItem.json[field.elementName] = value;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.fieldType === 'number') {\n\t\t\tvalue = Number(value);\n\t\t}\n\t\tif (field.fieldType === 'text') {\n\t\t\tvalue = String(value).trim();\n\t\t}\n\t\tif (field.multiselect && typeof value === 'string') {\n\t\t\tvalue = jsonParse(value);\n\t\t}\n\t\tif (field.fieldType === 'date' && value && field.formatDate !== '') {\n\t\t\tvalue = DateTime.fromFormat(String(value), 'yyyy-mm-dd').toFormat(field.formatDate as string);\n\t\t}\n\t\tif (field.fieldType === 'file' && field.multipleFiles && !Array.isArray(value)) {\n\t\t\tvalue = [value];\n\t\t}\n\n\t\treturnItem.json[name] = value;\n\t}\n}\n\nexport async function prepareFormReturnItem(\n\tcontext: IWebhookFunctions,\n\tformFields: FormFieldsParameter,\n\tmode: 'test' | 'production',\n\tuseWorkflowTimezone: boolean = false,\n) {\n\tconst bodyData = (context.getBodyData().data as IDataObject) ?? {};\n\tconst files = (context.getBodyData().files as IDataObject) ?? {};\n\n\tconst returnItem: INodeExecutionData = {\n\t\tjson: {},\n\t};\n\tif (files && Object.keys(files).length) {\n\t\treturnItem.binary = {};\n\t}\n\n\tfor (const key of Object.keys(files)) {\n\t\tconst processFiles: MultiPartFormData.File[] = [];\n\t\tlet multiFile = false;\n\t\tconst filesInput = files[key] as MultiPartFormData.File[] | MultiPartFormData.File;\n\n\t\tif (Array.isArray(filesInput)) {\n\t\t\tbodyData[key] = filesInput.map((file) => ({\n\t\t\t\tfilename: file.originalFilename,\n\t\t\t\tmimetype: file.mimetype,\n\t\t\t\tsize: file.size,\n\t\t\t}));\n\t\t\tprocessFiles.push(...filesInput);\n\t\t\tmultiFile = true;\n\t\t} else {\n\t\t\tbodyData[key] = {\n\t\t\t\tfilename: filesInput.originalFilename,\n\t\t\t\tmimetype: filesInput.mimetype,\n\t\t\t\tsize: filesInput.size,\n\t\t\t};\n\t\t\tprocessFiles.push(filesInput);\n\t\t}\n\n\t\tconst entryIndex = Number(key.replace(/field-/g, ''));\n\t\tconst fieldLabel = isNaN(entryIndex) ? key : formFields[entryIndex].fieldLabel;\n\n\t\tlet fileCount = 0;\n\t\tfor (const file of processFiles) {\n\t\t\tlet binaryPropertyName = fieldLabel.replace(/\\W/g, '_');\n\n\t\t\tif (multiFile) {\n\t\t\t\tbinaryPropertyName += `_${fileCount++}`;\n\t\t\t}\n\n\t\t\treturnItem.binary![binaryPropertyName] = await context.nodeHelpers.copyBinaryFile(\n\t\t\t\tfile.filepath,\n\t\t\t\tfile.originalFilename ?? file.newFilename,\n\t\t\t\tfile.mimetype,\n\t\t\t);\n\t\t}\n\t}\n\n\taddFormResponseDataToReturnItem(returnItem, formFields, bodyData);\n\n\tconst timezone = useWorkflowTimezone ? context.getTimezone() : 'UTC';\n\treturnItem.json.submittedAt = DateTime.now().setZone(timezone).toISO();\n\n\treturnItem.json.formMode = mode;\n\n\tif (\n\t\tcontext.getNode().type === FORM_TRIGGER_NODE_TYPE &&\n\t\tObject.keys(context.getRequestObject().query || {}).length\n\t) {\n\t\treturnItem.json.formQueryParameters = context.getRequestObject().query;\n\t}\n\n\treturn returnItem;\n}\n\nexport function renderForm({\n\tcontext,\n\tres,\n\tformTitle,\n\tformDescription,\n\tformFields,\n\tresponseMode,\n\tmode,\n\tformSubmittedText,\n\tredirectUrl,\n\tappendAttribution,\n\tbuttonLabel,\n\tcustomCss,\n}: {\n\tcontext: IWebhookFunctions;\n\tres: Response;\n\tformTitle: string;\n\tformDescription: string;\n\tformFields: FormFieldsParameter;\n\tresponseMode: string;\n\tmode: 'test' | 'production';\n\tformSubmittedText?: string;\n\tredirectUrl?: string;\n\tappendAttribution?: boolean;\n\tbuttonLabel?: string;\n\tcustomCss?: string;\n}) {\n\tformDescription = (formDescription || '').replace(/\\\\n/g, '\\n').replace(/<br>/g, '\\n');\n\tconst instanceId = context.getInstanceId();\n\n\tconst useResponseData = responseMode === 'responseNode';\n\n\tlet query: IDataObject = {};\n\n\tif (context.getNode().type === FORM_TRIGGER_NODE_TYPE) {\n\t\tquery = context.getRequestObject().query as IDataObject;\n\t} else if (context.getNode().type === FORM_NODE_TYPE) {\n\t\tconst parentNodes = context.getParentNodes(context.getNode().name);\n\t\tconst trigger = parentNodes.find(\n\t\t\t(node) => node.type === FORM_TRIGGER_NODE_TYPE,\n\t\t) as NodeTypeAndVersion;\n\t\ttry {\n\t\t\tconst triggerQueryParameters = context.evaluateExpression(\n\t\t\t\t`{{ $('${trigger?.name}').first().json.formQueryParameters }}`,\n\t\t\t) as IDataObject;\n\n\t\t\tif (triggerQueryParameters) {\n\t\t\t\tquery = triggerQueryParameters;\n\t\t\t}\n\t\t} catch (error) {}\n\t}\n\n\tformFields = prepareFormFields(context, formFields);\n\n\tconst data = prepareFormData({\n\t\tformTitle,\n\t\tformDescription,\n\t\tformSubmittedText,\n\t\tredirectUrl,\n\t\tformFields,\n\t\ttestRun: mode === 'test',\n\t\tquery,\n\t\tinstanceId,\n\t\tuseResponseData,\n\t\tappendAttribution,\n\t\tbuttonLabel,\n\t\tcustomCss,\n\t});\n\n\tres.render('form-trigger', data);\n}\n\nexport const isFormConnected = (nodes: NodeTypeAndVersion[]) => {\n\treturn nodes.some(\n\t\t(n) =>\n\t\t\tn.type === FORM_NODE_TYPE || (n.type === WAIT_NODE_TYPE && n.parameters?.resume === 'form'),\n\t);\n};\n\nexport async function formWebhook(\n\tcontext: IWebhookFunctions,\n\tauthProperty = FORM_TRIGGER_AUTHENTICATION_PROPERTY,\n) {\n\tconst node = context.getNode();\n\tconst options = context.getNodeParameter('options', {}) as {\n\t\tignoreBots?: boolean;\n\t\trespondWithOptions?: {\n\t\t\tvalues: {\n\t\t\t\trespondWith: 'text' | 'redirect';\n\t\t\t\tformSubmittedText: string;\n\t\t\t\tredirectUrl: string;\n\t\t\t};\n\t\t};\n\t\tformSubmittedText?: string;\n\t\tuseWorkflowTimezone?: boolean;\n\t\tappendAttribution?: boolean;\n\t\tbuttonLabel?: string;\n\t\tcustomCss?: string;\n\t};\n\tconst res = context.getResponseObject();\n\tconst req = context.getRequestObject();\n\n\ttry {\n\t\tif (options.ignoreBots && isbot(req.headers['user-agent'])) {\n\t\t\tthrow new WebhookAuthorizationError(403);\n\t\t}\n\t\tif (node.typeVersion > 1) {\n\t\t\tawait validateWebhookAuthentication(context, authProperty);\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof WebhookAuthorizationError) {\n\t\t\tres.setHeader('WWW-Authenticate', 'Basic realm=\"Enter credentials\"');\n\t\t\tres.status(401).send();\n\t\t\treturn { noWebhookResponse: true };\n\t\t}\n\t\tthrow error;\n\t}\n\n\tconst mode = context.getMode() === 'manual' ? 'test' : 'production';\n\tconst formFields = context.getNodeParameter('formFields.values', []) as FormFieldsParameter;\n\n\tconst method = context.getRequestObject().method;\n\n\tvalidateResponseModeConfiguration(context);\n\n\t//Show the form on GET request\n\tif (method === 'GET') {\n\t\tconst formTitle = context.getNodeParameter('formTitle', '') as string;\n\t\tconst formDescription = sanitizeHtml(context.getNodeParameter('formDescription', '') as string);\n\t\tlet responseMode = context.getNodeParameter('responseMode', '') as string;\n\n\t\tlet formSubmittedText;\n\t\tlet redirectUrl;\n\t\tlet appendAttribution = true;\n\n\t\tif (options.respondWithOptions) {\n\t\t\tconst values = (options.respondWithOptions as IDataObject).values as IDataObject;\n\t\t\tif (values.respondWith === 'text') {\n\t\t\t\tformSubmittedText = values.formSubmittedText as string;\n\t\t\t}\n\t\t\tif (values.respondWith === 'redirect') {\n\t\t\t\tredirectUrl = values.redirectUrl as string;\n\t\t\t}\n\t\t} else {\n\t\t\tformSubmittedText = options.formSubmittedText as string;\n\t\t}\n\n\t\tif (options.appendAttribution === false) {\n\t\t\tappendAttribution = false;\n\t\t}\n\n\t\tlet buttonLabel = 'Submit';\n\n\t\tif (options.buttonLabel) {\n\t\t\tbuttonLabel = options.buttonLabel;\n\t\t}\n\n\t\tconst connectedNodes = context.getChildNodes(context.getNode().name, {\n\t\t\tincludeNodeParameters: true,\n\t\t});\n\t\tconst hasNextPage = isFormConnected(connectedNodes);\n\n\t\tif (hasNextPage) {\n\t\t\tredirectUrl = undefined;\n\t\t\tresponseMode = 'responseNode';\n\t\t}\n\n\t\trenderForm({\n\t\t\tcontext,\n\t\t\tres,\n\t\t\tformTitle,\n\t\t\tformDescription,\n\t\t\tformFields,\n\t\t\tresponseMode,\n\t\t\tmode,\n\t\t\tformSubmittedText,\n\t\t\tredirectUrl,\n\t\t\tappendAttribution,\n\t\t\tbuttonLabel,\n\t\t\tcustomCss: options.customCss,\n\t\t});\n\n\t\treturn {\n\t\t\tnoWebhookResponse: true,\n\t\t};\n\t}\n\n\tlet { useWorkflowTimezone } = options;\n\n\tif (useWorkflowTimezone === undefined && node.typeVersion > 2) {\n\t\tuseWorkflowTimezone = true;\n\t}\n\n\tconst returnItem = await prepareFormReturnItem(context, formFields, mode, useWorkflowTimezone);\n\n\treturn {\n\t\twebhookResponse: { status: 200 },\n\t\tworkflowData: [[returnItem]],\n\t};\n}\n\nexport function resolveRawData(context: IWebhookFunctions, rawData: string) {\n\tconst resolvables = getResolvables(rawData);\n\tlet returnData: string = rawData;\n\n\tif (returnData.startsWith('=')) {\n\t\treturnData = returnData.replace(/^=+/, '');\n\t} else {\n\t\treturn returnData;\n\t}\n\n\tif (resolvables.length) {\n\t\tfor (const resolvable of resolvables) {\n\t\t\tconst resolvedValue = context.evaluateExpression(`${resolvable}`);\n\n\t\t\tif (typeof resolvedValue === 'object' && resolvedValue !== null) {\n\t\t\t\treturnData = returnData.replace(resolvable, JSON.stringify(resolvedValue));\n\t\t\t} else {\n\t\t\t\treturnData = returnData.replace(resolvable, resolvedValue as string);\n\t\t\t}\n\t\t}\n\t}\n\treturn returnData;\n}\n"],"mappings":"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","names":["sanitize","isbot"]}