From 14b6f8b97275e38ba4a4c1819e8e32b711de21ba Mon Sep 17 00:00:00 2001 From: Michael Kret <88898367+michael-radency@users.noreply.github.com> Date: Wed, 19 Feb 2025 13:47:19 +0200 Subject: [PATCH] feat(n8n Form Node): Limit wait time parameters (#13160) --- .../nodes/Discord/v2/actions/router.ts | 2 +- .../EmailSend/v2/sendAndWait.operation.ts | 2 +- packages/nodes-base/nodes/Form/Form.node.ts | 27 +++- .../nodes/Form/test/Form.node.test.ts | 4 + .../nodes/Google/Chat/GoogleChat.node.ts | 7 +- .../nodes/Google/Gmail/v2/GmailV2.node.ts | 2 +- .../Microsoft/Outlook/v2/actions/router.ts | 2 +- .../Microsoft/Teams/v2/actions/router.ts | 2 +- .../nodes-base/nodes/Slack/V2/SlackV2.node.ts | 7 +- .../nodes/Telegram/Telegram.node.ts | 7 +- packages/nodes-base/nodes/Wait/Wait.node.ts | 2 +- .../sendAndWait/configureWaitTillDate.util.ts | 64 +++++++++ .../utils/sendAndWait/descriptions.ts | 79 ++++++++++- .../utils/sendAndWait/test/util.test.ts | 74 +++++++++- .../nodes-base/utils/sendAndWait/utils.ts | 129 +----------------- 15 files changed, 261 insertions(+), 149 deletions(-) create mode 100644 packages/nodes-base/utils/sendAndWait/configureWaitTillDate.util.ts diff --git a/packages/nodes-base/nodes/Discord/v2/actions/router.ts b/packages/nodes-base/nodes/Discord/v2/actions/router.ts index 1e163be0e9..d0dd30037f 100644 --- a/packages/nodes-base/nodes/Discord/v2/actions/router.ts +++ b/packages/nodes-base/nodes/Discord/v2/actions/router.ts @@ -6,7 +6,7 @@ import * as member from './member'; import * as message from './message'; import type { Discord } from './node.type'; import * as webhook from './webhook'; -import { configureWaitTillDate } from '../../../../utils/sendAndWait/utils'; +import { configureWaitTillDate } from '../../../../utils/sendAndWait/configureWaitTillDate.util'; import { checkAccessToGuild } from '../helpers/utils'; import { discordApiRequest } from '../transport'; diff --git a/packages/nodes-base/nodes/EmailSend/v2/sendAndWait.operation.ts b/packages/nodes-base/nodes/EmailSend/v2/sendAndWait.operation.ts index 5962ec564d..401e85731c 100644 --- a/packages/nodes-base/nodes/EmailSend/v2/sendAndWait.operation.ts +++ b/packages/nodes-base/nodes/EmailSend/v2/sendAndWait.operation.ts @@ -7,9 +7,9 @@ import type { import { fromEmailProperty, toEmailProperty } from './descriptions'; import { configureTransport } from './utils'; +import { configureWaitTillDate } from '../../../utils/sendAndWait/configureWaitTillDate.util'; import { createEmailBody } from '../../../utils/sendAndWait/email-templates'; import { - configureWaitTillDate, createButton, getSendAndWaitConfig, getSendAndWaitProperties, diff --git a/packages/nodes-base/nodes/Form/Form.node.ts b/packages/nodes-base/nodes/Form/Form.node.ts index b9e1340f13..0607b155fa 100644 --- a/packages/nodes-base/nodes/Form/Form.node.ts +++ b/packages/nodes-base/nodes/Form/Form.node.ts @@ -16,14 +16,34 @@ import { FORM_TRIGGER_NODE_TYPE, tryToParseJsonToFormFields, NodeConnectionType, - WAIT_INDEFINITELY, } from 'n8n-workflow'; import { renderFormCompletion } from './formCompletionUtils'; import { renderFormNode } from './formNodeUtils'; +import { configureWaitTillDate } from '../../utils/sendAndWait/configureWaitTillDate.util'; +import { limitWaitTimeProperties } from '../../utils/sendAndWait/descriptions'; import { formDescription, formFields, formTitle } from '../Form/common.descriptions'; import { prepareFormReturnItem, resolveRawData } from '../Form/utils'; +const waitTimeProperties: INodeProperties[] = [ + { + displayName: 'Limit Wait Time', + name: 'limitWaitTime', + type: 'boolean', + default: false, + description: + 'Whether to limit the time this node should wait for a user response before execution resumes', + }, + ...updateDisplayOptions( + { + show: { + limitWaitTime: [true], + }, + }, + limitWaitTimeProperties, + ), +]; + export const formFieldsProperties: INodeProperties[] = [ { displayName: 'Define Form', @@ -71,6 +91,7 @@ const pageProperties = updateDisplayOptions( }, [ ...formFieldsProperties, + ...waitTimeProperties, { displayName: 'Options', name: 'options', @@ -177,6 +198,7 @@ const completionProperties = updateDisplayOptions( placeholder: 'e.g. Thanks for filling the form', description: 'The text to display on the page. Use HTML to show a customized web page.', }, + ...waitTimeProperties, { displayName: 'Options', name: 'options', @@ -359,7 +381,8 @@ export class Form extends Node { ); } - await context.putExecutionToWait(WAIT_INDEFINITELY); + const waitTill = configureWaitTillDate(context, 'root'); + await context.putExecutionToWait(waitTill); return [context.getInputData()]; } diff --git a/packages/nodes-base/nodes/Form/test/Form.node.test.ts b/packages/nodes-base/nodes/Form/test/Form.node.test.ts index 5065df20c9..61753ab9dc 100644 --- a/packages/nodes-base/nodes/Form/test/Form.node.test.ts +++ b/packages/nodes-base/nodes/Form/test/Form.node.test.ts @@ -11,6 +11,10 @@ import type { import { Form } from '../Form.node'; +jest.mock('../../../utils/sendAndWait/configureWaitTillDate.util', () => ({ + configureWaitTillDate: jest.fn(), // Mocked function +})); + describe('Form Node', () => { let form: Form; let mockExecuteFunctions: MockProxy; diff --git a/packages/nodes-base/nodes/Google/Chat/GoogleChat.node.ts b/packages/nodes-base/nodes/Google/Chat/GoogleChat.node.ts index 20665bdfee..184b0bbf93 100644 --- a/packages/nodes-base/nodes/Google/Chat/GoogleChat.node.ts +++ b/packages/nodes-base/nodes/Google/Chat/GoogleChat.node.ts @@ -37,12 +37,9 @@ import { validateJSON, } from './GenericFunctions'; import type { IMessage, IMessageUi } from './MessageInterface'; +import { configureWaitTillDate } from '../../../utils/sendAndWait/configureWaitTillDate.util'; import { sendAndWaitWebhooksDescription } from '../../../utils/sendAndWait/descriptions'; -import { - configureWaitTillDate, - getSendAndWaitProperties, - sendAndWaitWebhook, -} from '../../../utils/sendAndWait/utils'; +import { getSendAndWaitProperties, sendAndWaitWebhook } from '../../../utils/sendAndWait/utils'; export class GoogleChat implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Google/Gmail/v2/GmailV2.node.ts b/packages/nodes-base/nodes/Google/Gmail/v2/GmailV2.node.ts index 7c55c11eff..84261684a2 100644 --- a/packages/nodes-base/nodes/Google/Gmail/v2/GmailV2.node.ts +++ b/packages/nodes-base/nodes/Google/Gmail/v2/GmailV2.node.ts @@ -13,10 +13,10 @@ import { labelFields, labelOperations } from './LabelDescription'; import { getGmailAliases, getLabels, getThreadMessages } from './loadOptions'; import { messageFields, messageOperations } from './MessageDescription'; import { threadFields, threadOperations } from './ThreadDescription'; +import { configureWaitTillDate } from '../../../../utils/sendAndWait/configureWaitTillDate.util'; import { sendAndWaitWebhooksDescription } from '../../../../utils/sendAndWait/descriptions'; import type { IEmail } from '../../../../utils/sendAndWait/interfaces'; import { - configureWaitTillDate, createEmail, getSendAndWaitProperties, sendAndWaitWebhook, diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/router.ts b/packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/router.ts index 8a05975e56..edaf04d01d 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/router.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/router.ts @@ -10,7 +10,7 @@ import * as folderMessage from './folderMessage'; import * as message from './message'; import * as messageAttachment from './messageAttachment'; import type { MicrosoftOutlook } from './node.type'; -import { configureWaitTillDate } from '../../../../../utils/sendAndWait/utils'; +import { configureWaitTillDate } from '../../../../../utils/sendAndWait/configureWaitTillDate.util'; export async function router(this: IExecuteFunctions) { const items = this.getInputData(); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/v2/actions/router.ts b/packages/nodes-base/nodes/Microsoft/Teams/v2/actions/router.ts index 28c0028f3e..d7154f14a2 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/v2/actions/router.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/v2/actions/router.ts @@ -11,7 +11,7 @@ import * as channelMessage from './channelMessage'; import * as chatMessage from './chatMessage'; import type { MicrosoftTeamsType } from './node.type'; import * as task from './task'; -import { configureWaitTillDate } from '../../../../../utils/sendAndWait/utils'; +import { configureWaitTillDate } from '../../../../../utils/sendAndWait/configureWaitTillDate.util'; export async function router(this: IExecuteFunctions): Promise { const items = this.getInputData(); diff --git a/packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts b/packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts index 15d8e7bfbd..a9bda51c71 100644 --- a/packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts +++ b/packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts @@ -41,12 +41,9 @@ import { reactionFields, reactionOperations } from './ReactionDescription'; import { starFields, starOperations } from './StarDescription'; import { userFields, userOperations } from './UserDescription'; import { userGroupFields, userGroupOperations } from './UserGroupDescription'; +import { configureWaitTillDate } from '../../../utils/sendAndWait/configureWaitTillDate.util'; import { sendAndWaitWebhooksDescription } from '../../../utils/sendAndWait/descriptions'; -import { - configureWaitTillDate, - getSendAndWaitProperties, - sendAndWaitWebhook, -} from '../../../utils/sendAndWait/utils'; +import { getSendAndWaitProperties, sendAndWaitWebhook } from '../../../utils/sendAndWait/utils'; export class SlackV2 implements INodeType { description: INodeTypeDescription; diff --git a/packages/nodes-base/nodes/Telegram/Telegram.node.ts b/packages/nodes-base/nodes/Telegram/Telegram.node.ts index 0a96b9c7a1..fb9b37d816 100644 --- a/packages/nodes-base/nodes/Telegram/Telegram.node.ts +++ b/packages/nodes-base/nodes/Telegram/Telegram.node.ts @@ -21,12 +21,9 @@ import { getPropertyName, } from './GenericFunctions'; import { appendAttributionOption } from '../../utils/descriptions'; +import { configureWaitTillDate } from '../../utils/sendAndWait/configureWaitTillDate.util'; import { sendAndWaitWebhooksDescription } from '../../utils/sendAndWait/descriptions'; -import { - configureWaitTillDate, - getSendAndWaitProperties, - sendAndWaitWebhook, -} from '../../utils/sendAndWait/utils'; +import { getSendAndWaitProperties, sendAndWaitWebhook } from '../../utils/sendAndWait/utils'; export class Telegram implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Wait/Wait.node.ts b/packages/nodes-base/nodes/Wait/Wait.node.ts index 45922270c2..62fa6e3e69 100644 --- a/packages/nodes-base/nodes/Wait/Wait.node.ts +++ b/packages/nodes-base/nodes/Wait/Wait.node.ts @@ -77,7 +77,7 @@ const waitTimeProperties: INodeProperties[] = [ type: 'boolean', default: false, description: - 'Whether the workflow will automatically resume execution after the specified limit type', + 'Whether to limit the time this node should wait for a user response before execution resumes', displayOptions: { show: { resume: ['webhook', 'form'], diff --git a/packages/nodes-base/utils/sendAndWait/configureWaitTillDate.util.ts b/packages/nodes-base/utils/sendAndWait/configureWaitTillDate.util.ts new file mode 100644 index 0000000000..02bf2e113b --- /dev/null +++ b/packages/nodes-base/utils/sendAndWait/configureWaitTillDate.util.ts @@ -0,0 +1,64 @@ +import { ApplicationError, NodeOperationError, WAIT_INDEFINITELY } from 'n8n-workflow'; +import type { IExecuteFunctions, IDataObject } from 'n8n-workflow'; + +export function configureWaitTillDate( + context: IExecuteFunctions, + location: 'options' | 'root' = 'options', +) { + let waitTill = WAIT_INDEFINITELY; + let limitOptions: IDataObject = {}; + + if (location === 'options') { + limitOptions = context.getNodeParameter('options.limitWaitTime.values', 0, {}) as { + limitType?: string; + resumeAmount?: number; + resumeUnit?: string; + maxDateAndTime?: string; + }; + } else { + const limitWaitTime = context.getNodeParameter('limitWaitTime', 0, false); + if (limitWaitTime) { + limitOptions.limitType = context.getNodeParameter('limitType', 0, 'afterTimeInterval'); + + if (limitOptions.limitType === 'afterTimeInterval') { + limitOptions.resumeAmount = context.getNodeParameter('resumeAmount', 0, 1) as number; + limitOptions.resumeUnit = context.getNodeParameter('resumeUnit', 0, 'hours'); + } else { + limitOptions.maxDateAndTime = context.getNodeParameter('maxDateAndTime', 0, ''); + } + } + } + + if (Object.keys(limitOptions).length) { + try { + if (limitOptions.limitType === 'afterTimeInterval') { + let waitAmount = limitOptions.resumeAmount as number; + + if (limitOptions.resumeUnit === 'minutes') { + waitAmount *= 60; + } + if (limitOptions.resumeUnit === 'hours') { + waitAmount *= 60 * 60; + } + if (limitOptions.resumeUnit === 'days') { + waitAmount *= 60 * 60 * 24; + } + + waitAmount *= 1000; + waitTill = new Date(new Date().getTime() + waitAmount); + } else { + waitTill = new Date(limitOptions.maxDateAndTime as string); + } + + if (isNaN(waitTill.getTime())) { + throw new ApplicationError('Invalid date format'); + } + } catch (error) { + throw new NodeOperationError(context.getNode(), 'Could not configure Limit Wait Time', { + description: error.message, + }); + } + } + + return waitTill; +} diff --git a/packages/nodes-base/utils/sendAndWait/descriptions.ts b/packages/nodes-base/utils/sendAndWait/descriptions.ts index 1549a6cc98..d2a5eda469 100644 --- a/packages/nodes-base/utils/sendAndWait/descriptions.ts +++ b/packages/nodes-base/utils/sendAndWait/descriptions.ts @@ -1,4 +1,4 @@ -import type { IWebhookDescription } from 'n8n-workflow'; +import type { INodeProperties, IWebhookDescription } from 'n8n-workflow'; export const sendAndWaitWebhooksDescription: IWebhookDescription[] = [ { @@ -20,3 +20,80 @@ export const sendAndWaitWebhooksDescription: IWebhookDescription[] = [ isFullPath: true, }, ]; + +export const limitWaitTimeProperties: INodeProperties[] = [ + { + displayName: 'Limit Type', + name: 'limitType', + type: 'options', + default: 'afterTimeInterval', + description: + 'Sets the condition for the execution to resume. Can be a specified date or after some time.', + options: [ + { + name: 'After Time Interval', + description: 'Waits for a certain amount of time', + value: 'afterTimeInterval', + }, + { + name: 'At Specified Time', + description: 'Waits until the set date and time to continue', + value: 'atSpecifiedTime', + }, + ], + }, + { + displayName: 'Amount', + name: 'resumeAmount', + type: 'number', + displayOptions: { + show: { + limitType: ['afterTimeInterval'], + }, + }, + typeOptions: { + minValue: 0, + numberPrecision: 2, + }, + default: 1, + description: 'The time to wait', + }, + { + displayName: 'Unit', + name: 'resumeUnit', + type: 'options', + displayOptions: { + show: { + limitType: ['afterTimeInterval'], + }, + }, + options: [ + { + name: 'Minutes', + value: 'minutes', + }, + { + name: 'Hours', + value: 'hours', + }, + { + name: 'Days', + value: 'days', + }, + ], + default: 'hours', + description: 'Unit of the interval value', + }, + { + displayName: 'Max Date and Time', + name: 'maxDateAndTime', + type: 'dateTime', + displayOptions: { + show: { + limitType: ['atSpecifiedTime'], + }, + }, + default: '', + description: 'Continue execution after the specified date and time', + }, +]; diff --git a/packages/nodes-base/utils/sendAndWait/test/util.test.ts b/packages/nodes-base/utils/sendAndWait/test/util.test.ts index c04c0fb4cb..5739757d1a 100644 --- a/packages/nodes-base/utils/sendAndWait/test/util.test.ts +++ b/packages/nodes-base/utils/sendAndWait/test/util.test.ts @@ -2,12 +2,12 @@ import { type MockProxy, mock } from 'jest-mock-extended'; import type { IExecuteFunctions, INodeProperties, IWebhookFunctions } from 'n8n-workflow'; import { NodeOperationError, WAIT_INDEFINITELY } from 'n8n-workflow'; +import { configureWaitTillDate } from '../configureWaitTillDate.util'; import { getSendAndWaitProperties, getSendAndWaitConfig, createEmail, sendAndWaitWebhook, - configureWaitTillDate, } from '../utils'; describe('Send and Wait utils tests', () => { @@ -466,4 +466,76 @@ describe('configureWaitTillDate', () => { 'Could not configure Limit Wait Time', ); }); + + it('should return WAIT_INDEFINITELY when limitWaitTime is false', () => { + mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(false); + const result = configureWaitTillDate(mockExecuteFunctions, 'root'); + expect(result).toBe(WAIT_INDEFINITELY); + }); + + it('should calculate minutes correctly in root location', () => { + mockExecuteFunctions.getNodeParameter + .mockReturnValueOnce(true) // limitWaitTime + .mockReturnValueOnce('afterTimeInterval') // limitType + .mockReturnValueOnce(15) // resumeAmount + .mockReturnValueOnce('minutes'); // resumeUnit + + const result = configureWaitTillDate(mockExecuteFunctions, 'root'); + const expectedDate = new Date(new Date().getTime() + 15 * 60 * 1000); + expect(result.getTime()).toBeCloseTo(expectedDate.getTime(), -2); + }); + + it('should calculate hours correctly in root location', () => { + mockExecuteFunctions.getNodeParameter + .mockReturnValueOnce(true) + .mockReturnValueOnce('afterTimeInterval') + .mockReturnValueOnce(3) + .mockReturnValueOnce('hours'); + + const result = configureWaitTillDate(mockExecuteFunctions, 'root'); + const expectedDate = new Date(new Date().getTime() + 3 * 60 * 60 * 1000); + expect(result.getTime()).toBeCloseTo(expectedDate.getTime(), -2); + }); + + it('should calculate days correctly in root location', () => { + mockExecuteFunctions.getNodeParameter + .mockReturnValueOnce(true) + .mockReturnValueOnce('afterTimeInterval') + .mockReturnValueOnce(5) + .mockReturnValueOnce('days'); + + const result = configureWaitTillDate(mockExecuteFunctions, 'root'); + const expectedDate = new Date(new Date().getTime() + 5 * 24 * 60 * 60 * 1000); + expect(result.getTime()).toBeCloseTo(expectedDate.getTime(), -2); + }); + + it('should handle maxDateAndTime in root location', () => { + const maxDateAndTime = '2024-12-31T23:59:59Z'; + mockExecuteFunctions.getNodeParameter + .mockReturnValueOnce(true) + .mockReturnValueOnce('maxDateAndTime') + .mockReturnValueOnce(maxDateAndTime); + + const result = configureWaitTillDate(mockExecuteFunctions, 'root'); + expect(result).toEqual(new Date(maxDateAndTime)); + }); + + it('should throw error for invalid date in root location', () => { + mockExecuteFunctions.getNodeParameter + .mockReturnValueOnce(true) + .mockReturnValueOnce('maxDateAndTime') + .mockReturnValueOnce('not-a-valid-date'); + + expect(() => configureWaitTillDate(mockExecuteFunctions, 'root')).toThrow(NodeOperationError); + }); + + it('should throw error for invalid resumeAmount in root location', () => { + mockExecuteFunctions.getNodeParameter + .mockReturnValueOnce(true) + .mockReturnValueOnce('afterTimeInterval') + .mockReturnValueOnce('not-a-number') + .mockReturnValueOnce('minutes'); + + expect(() => configureWaitTillDate(mockExecuteFunctions, 'root')).toThrow(NodeOperationError); + }); }); diff --git a/packages/nodes-base/utils/sendAndWait/utils.ts b/packages/nodes-base/utils/sendAndWait/utils.ts index 218ca3c216..96a4114d63 100644 --- a/packages/nodes-base/utils/sendAndWait/utils.ts +++ b/packages/nodes-base/utils/sendAndWait/utils.ts @@ -1,10 +1,8 @@ import { - ApplicationError, NodeOperationError, SEND_AND_WAIT_OPERATION, tryToParseJsonToFormFields, updateDisplayOptions, - WAIT_INDEFINITELY, } from 'n8n-workflow'; import type { INodeProperties, @@ -14,6 +12,7 @@ import type { FormFieldsParameter, } from 'n8n-workflow'; +import { limitWaitTimeProperties } from './descriptions'; import { ACTION_RECORDED_PAGE, BUTTON_STYLE_PRIMARY, @@ -41,7 +40,7 @@ type FormResponseTypeOptions = { const INPUT_FIELD_IDENTIFIER = 'field-0'; -const limitWaitTimeProperties: INodeProperties = { +const limitWaitTimeOption: INodeProperties = { displayName: 'Limit Wait Time', name: 'limitWaitTime', type: 'fixedCollection', @@ -52,82 +51,7 @@ const limitWaitTimeProperties: INodeProperties = { { displayName: 'Values', name: 'values', - values: [ - { - displayName: 'Limit Type', - name: 'limitType', - type: 'options', - default: 'afterTimeInterval', - description: - 'Sets the condition for the execution to resume. Can be a specified date or after some time.', - options: [ - { - name: 'After Time Interval', - description: 'Waits for a certain amount of time', - value: 'afterTimeInterval', - }, - { - name: 'At Specified Time', - description: 'Waits until the set date and time to continue', - value: 'atSpecifiedTime', - }, - ], - }, - { - displayName: 'Amount', - name: 'resumeAmount', - type: 'number', - displayOptions: { - show: { - limitType: ['afterTimeInterval'], - }, - }, - typeOptions: { - minValue: 0, - numberPrecision: 2, - }, - default: 1, - description: 'The time to wait', - }, - { - displayName: 'Unit', - name: 'resumeUnit', - type: 'options', - displayOptions: { - show: { - limitType: ['afterTimeInterval'], - }, - }, - options: [ - { - name: 'Minutes', - value: 'minutes', - }, - { - name: 'Hours', - value: 'hours', - }, - { - name: 'Days', - value: 'days', - }, - ], - default: 'hours', - description: 'Unit of the interval value', - }, - { - displayName: 'Max Date and Time', - name: 'maxDateAndTime', - type: 'dateTime', - displayOptions: { - show: { - limitType: ['atSpecifiedTime'], - }, - }, - default: '', - description: 'Continue execution after the specified date and time', - }, - ], + values: limitWaitTimeProperties, }, ], }; @@ -307,7 +231,7 @@ export function getSendAndWaitProperties( type: 'collection', placeholder: 'Add option', default: {}, - options: [limitWaitTimeProperties], + options: [limitWaitTimeOption], displayOptions: { show: { responseType: ['approval'], @@ -347,7 +271,7 @@ export function getSendAndWaitProperties( type: 'string', default: 'Submit', }, - limitWaitTimeProperties, + limitWaitTimeOption, ], displayOptions: { show: { @@ -605,46 +529,3 @@ export function createEmail(context: IExecuteFunctions) { return email; } - -export function configureWaitTillDate(context: IExecuteFunctions) { - let waitTill = WAIT_INDEFINITELY; - const limitWaitTime = context.getNodeParameter('options.limitWaitTime.values', 0, {}) as { - limitType?: string; - resumeAmount?: number; - resumeUnit?: string; - maxDateAndTime?: string; - }; - - if (Object.keys(limitWaitTime).length) { - try { - if (limitWaitTime.limitType === 'afterTimeInterval') { - let waitAmount = limitWaitTime.resumeAmount as number; - - if (limitWaitTime.resumeUnit === 'minutes') { - waitAmount *= 60; - } - if (limitWaitTime.resumeUnit === 'hours') { - waitAmount *= 60 * 60; - } - if (limitWaitTime.resumeUnit === 'days') { - waitAmount *= 60 * 60 * 24; - } - - waitAmount *= 1000; - waitTill = new Date(new Date().getTime() + waitAmount); - } else { - waitTill = new Date(limitWaitTime.maxDateAndTime as string); - } - - if (isNaN(waitTill.getTime())) { - throw new ApplicationError('Invalid date format'); - } - } catch (error) { - throw new NodeOperationError(context.getNode(), 'Could not configure Limit Wait Time', { - description: error.message, - }); - } - } - - return waitTill; -}