From c8d322a9ba02bfe6392b5164adcbcff18fab38ec Mon Sep 17 00:00:00 2001 From: Tomi Turtiainen <10324676+tomi@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:23:44 +0300 Subject: [PATCH] refactor(core): Reorganize webhook related components under src/webhooks (no-changelog) (#10296) --- packages/cli/src/AbstractServer.ts | 8 ++-- packages/cli/src/ActiveWorkflowManager.ts | 4 +- packages/cli/src/Interfaces.ts | 38 +------------------ packages/cli/src/WaitingForms.ts | 2 +- packages/cli/src/commands/webhook.ts | 4 +- packages/cli/src/commands/worker.ts | 2 +- .../main/handleCommandMessageMain.ts | 2 +- .../cli/src/{ => webhooks}/ActiveWebhooks.ts | 15 +++++--- .../cli/src/{ => webhooks}/TestWebhooks.ts | 22 ++++++----- .../cli/src/{ => webhooks}/WaitingWebhooks.ts | 20 ++++++---- .../cli/src/{ => webhooks}/WebhookHelpers.ts | 26 ++++++------- .../cli/src/{ => webhooks}/WebhookServer.ts | 0 .../__tests__/TestWebhooks.test.ts | 9 +++-- .../__tests__/WebhookHelpers.test.ts | 4 +- ...test-webhook-registrations.service.test.ts | 4 +- .../__tests__/waiting-webhooks.test.ts | 5 ++- .../__tests__/webhook.service.test.ts | 2 +- .../test-webhook-registrations.service.ts | 2 +- .../{services => webhooks}/webhook.service.ts | 0 packages/cli/src/webhooks/webhook.types.ts | 37 ++++++++++++++++++ .../workflows/workflowExecution.service.ts | 2 +- .../active-workflow-manager.test.ts | 4 +- .../cli/test/integration/webhooks.test.ts | 10 ++--- 23 files changed, 118 insertions(+), 104 deletions(-) rename packages/cli/src/{ => webhooks}/ActiveWebhooks.ts (91%) rename packages/cli/src/{ => webhooks}/TestWebhooks.ts (94%) rename packages/cli/src/{ => webhooks}/WaitingWebhooks.ts (88%) rename packages/cli/src/{ => webhooks}/WebhookHelpers.ts (97%) rename packages/cli/src/{ => webhooks}/WebhookServer.ts (100%) rename packages/cli/src/{ => webhooks}/__tests__/TestWebhooks.test.ts (93%) rename packages/cli/src/{ => webhooks}/__tests__/WebhookHelpers.test.ts (97%) rename packages/cli/src/{services => webhooks}/__tests__/test-webhook-registrations.service.test.ts (95%) rename packages/cli/src/{ => webhooks}/__tests__/waiting-webhooks.test.ts (90%) rename packages/cli/src/{services => webhooks}/__tests__/webhook.service.test.ts (99%) rename packages/cli/src/{services => webhooks}/test-webhook-registrations.service.ts (97%) rename packages/cli/src/{services => webhooks}/webhook.service.ts (100%) create mode 100644 packages/cli/src/webhooks/webhook.types.ts diff --git a/packages/cli/src/AbstractServer.ts b/packages/cli/src/AbstractServer.ts index ab150e2947..38cc327831 100644 --- a/packages/cli/src/AbstractServer.ts +++ b/packages/cli/src/AbstractServer.ts @@ -13,15 +13,15 @@ import { N8nInstanceType } from '@/Interfaces'; import { ExternalHooks } from '@/ExternalHooks'; import { send, sendErrorResponse } from '@/ResponseHelper'; import { rawBodyReader, bodyParser, corsMiddleware } from '@/middlewares'; -import { TestWebhooks } from '@/TestWebhooks'; import { WaitingForms } from '@/WaitingForms'; -import { WaitingWebhooks } from '@/WaitingWebhooks'; -import { webhookRequestHandler } from '@/WebhookHelpers'; +import { TestWebhooks } from '@/webhooks/TestWebhooks'; +import { WaitingWebhooks } from '@/webhooks/WaitingWebhooks'; +import { webhookRequestHandler } from '@/webhooks/WebhookHelpers'; +import { ActiveWebhooks } from '@/webhooks/ActiveWebhooks'; import { generateHostInstanceId } from './databases/utils/generators'; import { Logger } from '@/Logger'; import { ServiceUnavailableError } from './errors/response-errors/service-unavailable.error'; import { OnShutdown } from '@/decorators/OnShutdown'; -import { ActiveWebhooks } from '@/ActiveWebhooks'; import { GlobalConfig } from '@n8n/config'; @Service() diff --git a/packages/cli/src/ActiveWorkflowManager.ts b/packages/cli/src/ActiveWorkflowManager.ts index 1d5050e4d1..fac6e9d9fa 100644 --- a/packages/cli/src/ActiveWorkflowManager.ts +++ b/packages/cli/src/ActiveWorkflowManager.ts @@ -27,7 +27,7 @@ import { } from 'n8n-workflow'; import type { IWorkflowDb } from '@/Interfaces'; -import * as WebhookHelpers from '@/WebhookHelpers'; +import * as WebhookHelpers from '@/webhooks/WebhookHelpers'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; @@ -40,7 +40,7 @@ import { } from '@/constants'; import { NodeTypes } from '@/NodeTypes'; import { ExternalHooks } from '@/ExternalHooks'; -import { WebhookService } from './services/webhook.service'; +import { WebhookService } from '@/webhooks/webhook.service'; import { Logger } from './Logger'; import { WorkflowRepository } from '@db/repositories/workflow.repository'; import { OrchestrationService } from '@/services/orchestration.service'; diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index 8ddbd10fb2..9a1fdc367f 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -1,4 +1,4 @@ -import type { Application, Request, Response } from 'express'; +import type { Application } from 'express'; import type { ExecutionError, ICredentialDataDecryptedObject, @@ -22,7 +22,6 @@ import type { FeatureFlags, INodeProperties, IUserSettings, - IHttpRequestMethods, StartNodeData, } from 'n8n-workflow'; @@ -239,34 +238,6 @@ export interface IExternalHooksFunctions { }; } -export type WebhookCORSRequest = Request & { method: 'OPTIONS' }; - -export type WebhookRequest = Request<{ path: string }> & { - method: IHttpRequestMethods; - params: Record; -}; - -export type WaitingWebhookRequest = WebhookRequest & { - params: WebhookRequest['path'] & { suffix?: string }; -}; - -export interface WebhookAccessControlOptions { - allowedOrigins?: string; -} - -export interface IWebhookManager { - /** Gets all request methods associated with a webhook path*/ - getWebhookMethods?: (path: string) => Promise; - - /** Find the CORS options matching a path and method */ - findAccessControlOptions?: ( - path: string, - httpMethod: IHttpRequestMethods, - ) => Promise; - - executeWebhook(req: WebhookRequest, res: Response): Promise; -} - export interface IVersionNotificationSettings { enabled: boolean; endpoint: string; @@ -466,13 +437,6 @@ export interface IPushDataWorkerStatusPayload { version: string; } -export interface IResponseCallbackData { - data?: IDataObject | IDataObject[]; - headers?: object; - noWebhookResponse?: boolean; - responseCode?: number; -} - export interface INodesTypeData { [key: string]: { className: string; diff --git a/packages/cli/src/WaitingForms.ts b/packages/cli/src/WaitingForms.ts index 0625acd7e4..bf0ab7dedb 100644 --- a/packages/cli/src/WaitingForms.ts +++ b/packages/cli/src/WaitingForms.ts @@ -1,7 +1,7 @@ import { Service } from 'typedi'; import type { IExecutionResponse } from '@/Interfaces'; -import { WaitingWebhooks } from '@/WaitingWebhooks'; +import { WaitingWebhooks } from '@/webhooks/WaitingWebhooks'; @Service() export class WaitingForms extends WaitingWebhooks { diff --git a/packages/cli/src/commands/webhook.ts b/packages/cli/src/commands/webhook.ts index e76ac35817..2c8532ec76 100644 --- a/packages/cli/src/commands/webhook.ts +++ b/packages/cli/src/commands/webhook.ts @@ -4,7 +4,7 @@ import { ApplicationError } from 'n8n-workflow'; import config from '@/config'; import { ActiveExecutions } from '@/ActiveExecutions'; -import { WebhookServer } from '@/WebhookServer'; +import { WebhookServer } from '@/webhooks/WebhookServer'; import { Queue } from '@/Queue'; import { BaseCommand } from './BaseCommand'; @@ -86,7 +86,7 @@ export class Webhook extends BaseCommand { await this.initExternalHooks(); this.logger.debug('External hooks init complete'); await this.initExternalSecrets(); - this.logger.debug('External seecrets init complete'); + this.logger.debug('External secrets init complete'); } async run() { diff --git a/packages/cli/src/commands/worker.ts b/packages/cli/src/commands/worker.ts index 151ecfdf90..5681b41727 100644 --- a/packages/cli/src/commands/worker.ts +++ b/packages/cli/src/commands/worker.ts @@ -9,7 +9,7 @@ import { Workflow, sleep, ApplicationError } from 'n8n-workflow'; import * as Db from '@/Db'; import * as ResponseHelper from '@/ResponseHelper'; -import * as WebhookHelpers from '@/WebhookHelpers'; +import * as WebhookHelpers from '@/webhooks/WebhookHelpers'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; import config from '@/config'; import type { Job, JobId, JobResponse, WebhookResponse } from '@/Queue'; diff --git a/packages/cli/src/services/orchestration/main/handleCommandMessageMain.ts b/packages/cli/src/services/orchestration/main/handleCommandMessageMain.ts index 7945f59bc3..9a7b6b5640 100644 --- a/packages/cli/src/services/orchestration/main/handleCommandMessageMain.ts +++ b/packages/cli/src/services/orchestration/main/handleCommandMessageMain.ts @@ -7,7 +7,7 @@ import { License } from '@/License'; import { Logger } from '@/Logger'; import { ActiveWorkflowManager } from '@/ActiveWorkflowManager'; import { Push } from '@/push'; -import { TestWebhooks } from '@/TestWebhooks'; +import { TestWebhooks } from '@/webhooks/TestWebhooks'; import { OrchestrationService } from '@/services/orchestration.service'; import { WorkflowRepository } from '@/databases/repositories/workflow.repository'; import { CommunityPackagesService } from '@/services/communityPackages.service'; diff --git a/packages/cli/src/ActiveWebhooks.ts b/packages/cli/src/webhooks/ActiveWebhooks.ts similarity index 91% rename from packages/cli/src/ActiveWebhooks.ts rename to packages/cli/src/webhooks/ActiveWebhooks.ts index 43136e75d3..c18f949b88 100644 --- a/packages/cli/src/ActiveWebhooks.ts +++ b/packages/cli/src/webhooks/ActiveWebhooks.ts @@ -5,20 +5,25 @@ import type { INode, IWebhookData, IHttpRequestMethods } from 'n8n-workflow'; import { WorkflowRepository } from '@db/repositories/workflow.repository'; import type { - IResponseCallbackData, + IWebhookResponseCallbackData, IWebhookManager, WebhookAccessControlOptions, WebhookRequest, -} from '@/Interfaces'; +} from './webhook.types'; import { Logger } from '@/Logger'; import { NodeTypes } from '@/NodeTypes'; -import { WebhookService } from '@/services/webhook.service'; +import { WebhookService } from '@/webhooks/webhook.service'; import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; -import * as WebhookHelpers from '@/WebhookHelpers'; +import * as WebhookHelpers from '@/webhooks/WebhookHelpers'; import { WorkflowStaticDataService } from '@/workflows/workflowStaticData.service'; +/** + * Service for handling the execution of production webhooks, i.e. webhooks + * that belong to activated workflows and use the production URL + * (https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook/#webhook-urls) + */ @Service() export class ActiveWebhooks implements IWebhookManager { constructor( @@ -57,7 +62,7 @@ export class ActiveWebhooks implements IWebhookManager { async executeWebhook( request: WebhookRequest, response: Response, - ): Promise { + ): Promise { const httpMethod = request.method; const path = request.params.path; diff --git a/packages/cli/src/TestWebhooks.ts b/packages/cli/src/webhooks/TestWebhooks.ts similarity index 94% rename from packages/cli/src/TestWebhooks.ts rename to packages/cli/src/webhooks/TestWebhooks.ts index 827226ee54..8cf1b42929 100644 --- a/packages/cli/src/TestWebhooks.ts +++ b/packages/cli/src/webhooks/TestWebhooks.ts @@ -8,26 +8,30 @@ import type { IRunData, } from 'n8n-workflow'; import type { - IResponseCallbackData, + IWebhookResponseCallbackData, IWebhookManager, - IWorkflowDb, WebhookAccessControlOptions, WebhookRequest, -} from '@/Interfaces'; +} from './webhook.types'; import { Push } from '@/push'; import { NodeTypes } from '@/NodeTypes'; -import * as WebhookHelpers from '@/WebhookHelpers'; +import * as WebhookHelpers from '@/webhooks/WebhookHelpers'; import { TEST_WEBHOOK_TIMEOUT } from '@/constants'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; import { WorkflowMissingIdError } from '@/errors/workflow-missing-id.error'; import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error'; import * as NodeExecuteFunctions from 'n8n-core'; -import { removeTrailingSlash } from './utils'; -import type { TestWebhookRegistration } from '@/services/test-webhook-registrations.service'; -import { TestWebhookRegistrationsService } from '@/services/test-webhook-registrations.service'; +import { removeTrailingSlash } from '@/utils'; +import type { TestWebhookRegistration } from '@/webhooks/test-webhook-registrations.service'; +import { TestWebhookRegistrationsService } from '@/webhooks/test-webhook-registrations.service'; import { OrchestrationService } from '@/services/orchestration.service'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; +import type { IWorkflowDb } from '@/Interfaces'; +/** + * Service for handling the execution of webhooks of manual executions + * that use the [Test URL](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook/#webhook-urls). + */ @Service() export class TestWebhooks implements IWebhookManager { constructor( @@ -46,7 +50,7 @@ export class TestWebhooks implements IWebhookManager { async executeWebhook( request: WebhookRequest, response: express.Response, - ): Promise { + ): Promise { const httpMethod = request.method; let path = removeTrailingSlash(request.params.path); @@ -117,7 +121,7 @@ export class TestWebhooks implements IWebhookManager { undefined, // executionId request, response, - (error: Error | null, data: IResponseCallbackData) => { + (error: Error | null, data: IWebhookResponseCallbackData) => { if (error !== null) reject(error); else resolve(data); }, diff --git a/packages/cli/src/WaitingWebhooks.ts b/packages/cli/src/webhooks/WaitingWebhooks.ts similarity index 88% rename from packages/cli/src/WaitingWebhooks.ts rename to packages/cli/src/webhooks/WaitingWebhooks.ts index d795c948f1..367635c45e 100644 --- a/packages/cli/src/WaitingWebhooks.ts +++ b/packages/cli/src/webhooks/WaitingWebhooks.ts @@ -2,21 +2,25 @@ import { NodeHelpers, Workflow } from 'n8n-workflow'; import { Service } from 'typedi'; import type express from 'express'; -import * as WebhookHelpers from '@/WebhookHelpers'; +import * as WebhookHelpers from '@/webhooks/WebhookHelpers'; import { NodeTypes } from '@/NodeTypes'; import type { - IExecutionResponse, - IResponseCallbackData, + IWebhookResponseCallbackData, IWebhookManager, - IWorkflowDb, WaitingWebhookRequest, -} from '@/Interfaces'; +} from './webhook.types'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; import { ExecutionRepository } from '@db/repositories/execution.repository'; import { Logger } from '@/Logger'; -import { ConflictError } from './errors/response-errors/conflict.error'; -import { NotFoundError } from './errors/response-errors/not-found.error'; +import { ConflictError } from '@/errors/response-errors/conflict.error'; +import { NotFoundError } from '@/errors/response-errors/not-found.error'; +import type { IExecutionResponse, IWorkflowDb } from '@/Interfaces'; +/** + * Service for handling the execution of webhooks of Wait nodes that use the + * [Resume On Webhook Call](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.wait/#on-webhook-call) + * feature. + */ @Service() export class WaitingWebhooks implements IWebhookManager { protected includeForms = false; @@ -40,7 +44,7 @@ export class WaitingWebhooks implements IWebhookManager { async executeWebhook( req: WaitingWebhookRequest, res: express.Response, - ): Promise { + ): Promise { const { path: executionId, suffix } = req.params; this.logReceivedWebhook(req.method, executionId); diff --git a/packages/cli/src/WebhookHelpers.ts b/packages/cli/src/webhooks/WebhookHelpers.ts similarity index 97% rename from packages/cli/src/WebhookHelpers.ts rename to packages/cli/src/webhooks/WebhookHelpers.ts index eafec28133..8a98c74047 100644 --- a/packages/cli/src/WebhookHelpers.ts +++ b/packages/cli/src/webhooks/WebhookHelpers.ts @@ -43,27 +43,25 @@ import { } from 'n8n-workflow'; import type { - IExecutionDb, - IResponseCallbackData, + IWebhookResponseCallbackData, IWebhookManager, - IWorkflowDb, - IWorkflowExecutionDataProcess, WebhookCORSRequest, WebhookRequest, -} from '@/Interfaces'; +} from './webhook.types'; import * as ResponseHelper from '@/ResponseHelper'; import * as WorkflowHelpers from '@/WorkflowHelpers'; import { WorkflowRunner } from '@/WorkflowRunner'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; import { ActiveExecutions } from '@/ActiveExecutions'; import { WorkflowStatisticsService } from '@/services/workflow-statistics.service'; -import { OwnershipService } from './services/ownership.service'; -import { parseBody } from './middlewares'; -import { Logger } from './Logger'; -import { NotFoundError } from './errors/response-errors/not-found.error'; -import { InternalServerError } from './errors/response-errors/internal-server.error'; -import { UnprocessableRequestError } from './errors/response-errors/unprocessable.error'; -import type { Project } from './databases/entities/Project'; +import { OwnershipService } from '@/services/ownership.service'; +import { parseBody } from '@/middlewares'; +import { Logger } from '@/Logger'; +import { NotFoundError } from '@/errors/response-errors/not-found.error'; +import { InternalServerError } from '@/errors/response-errors/internal-server.error'; +import { UnprocessableRequestError } from '@/errors/response-errors/unprocessable.error'; +import type { Project } from '@/databases/entities/Project'; +import type { IExecutionDb, IWorkflowDb, IWorkflowExecutionDataProcess } from '@/Interfaces'; export const WEBHOOK_METHODS: IHttpRequestMethods[] = [ 'DELETE', @@ -137,7 +135,7 @@ export const webhookRequestHandler = return ResponseHelper.sendSuccessResponse(res, {}, true, 204); } - let response; + let response: IWebhookResponseCallbackData; try { response = await webhookManager.executeWebhook(req, res); } catch (error) { @@ -228,7 +226,7 @@ export async function executeWebhook( executionId: string | undefined, req: WebhookRequest, res: express.Response, - responseCallback: (error: Error | null, data: IResponseCallbackData) => void, + responseCallback: (error: Error | null, data: IWebhookResponseCallbackData) => void, destinationNode?: string, ): Promise { // Get the nodeType to know which responseMode is set diff --git a/packages/cli/src/WebhookServer.ts b/packages/cli/src/webhooks/WebhookServer.ts similarity index 100% rename from packages/cli/src/WebhookServer.ts rename to packages/cli/src/webhooks/WebhookServer.ts diff --git a/packages/cli/src/__tests__/TestWebhooks.test.ts b/packages/cli/src/webhooks/__tests__/TestWebhooks.test.ts similarity index 93% rename from packages/cli/src/__tests__/TestWebhooks.test.ts rename to packages/cli/src/webhooks/__tests__/TestWebhooks.test.ts index 6c7ae555b3..deb6930b96 100644 --- a/packages/cli/src/__tests__/TestWebhooks.test.ts +++ b/packages/cli/src/webhooks/__tests__/TestWebhooks.test.ts @@ -1,20 +1,21 @@ import { mock } from 'jest-mock-extended'; -import { TestWebhooks } from '@/TestWebhooks'; +import { TestWebhooks } from '@/webhooks/TestWebhooks'; import { WebhookNotFoundError } from '@/errors/response-errors/webhook-not-found.error'; import { v4 as uuid } from 'uuid'; import { generateNanoId } from '@/databases/utils/generators'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; -import * as WebhookHelpers from '@/WebhookHelpers'; +import * as WebhookHelpers from '@/webhooks/WebhookHelpers'; import type * as express from 'express'; -import type { IWorkflowDb, WebhookRequest } from '@/Interfaces'; +import type { IWorkflowDb } from '@/Interfaces'; import type { IWebhookData, IWorkflowExecuteAdditionalData, Workflow } from 'n8n-workflow'; import type { TestWebhookRegistrationsService, TestWebhookRegistration, -} from '@/services/test-webhook-registrations.service'; +} from '@/webhooks/test-webhook-registrations.service'; import * as AdditionalData from '@/WorkflowExecuteAdditionalData'; +import type { WebhookRequest } from '@/webhooks/webhook.types'; jest.mock('@/WorkflowExecuteAdditionalData'); diff --git a/packages/cli/src/__tests__/WebhookHelpers.test.ts b/packages/cli/src/webhooks/__tests__/WebhookHelpers.test.ts similarity index 97% rename from packages/cli/src/__tests__/WebhookHelpers.test.ts rename to packages/cli/src/webhooks/__tests__/WebhookHelpers.test.ts index 391d01b6fc..9f86fbc549 100644 --- a/packages/cli/src/__tests__/WebhookHelpers.test.ts +++ b/packages/cli/src/webhooks/__tests__/WebhookHelpers.test.ts @@ -3,8 +3,8 @@ import { mock } from 'jest-mock-extended'; import { randomString } from 'n8n-workflow'; import type { IHttpRequestMethods } from 'n8n-workflow'; -import type { IWebhookManager, WebhookCORSRequest, WebhookRequest } from '@/Interfaces'; -import { webhookRequestHandler } from '@/WebhookHelpers'; +import type { IWebhookManager, WebhookCORSRequest, WebhookRequest } from '@/webhooks/webhook.types'; +import { webhookRequestHandler } from '@/webhooks/WebhookHelpers'; describe('WebhookHelpers', () => { describe('webhookRequestHandler', () => { diff --git a/packages/cli/src/services/__tests__/test-webhook-registrations.service.test.ts b/packages/cli/src/webhooks/__tests__/test-webhook-registrations.service.test.ts similarity index 95% rename from packages/cli/src/services/__tests__/test-webhook-registrations.service.test.ts rename to packages/cli/src/webhooks/__tests__/test-webhook-registrations.service.test.ts index c93540938c..95502e3611 100644 --- a/packages/cli/src/services/__tests__/test-webhook-registrations.service.test.ts +++ b/packages/cli/src/webhooks/__tests__/test-webhook-registrations.service.test.ts @@ -1,7 +1,7 @@ import type { CacheService } from '@/services/cache/cache.service'; import type { OrchestrationService } from '@/services/orchestration.service'; -import type { TestWebhookRegistration } from '@/services/test-webhook-registrations.service'; -import { TestWebhookRegistrationsService } from '@/services/test-webhook-registrations.service'; +import type { TestWebhookRegistration } from '@/webhooks/test-webhook-registrations.service'; +import { TestWebhookRegistrationsService } from '@/webhooks/test-webhook-registrations.service'; import { mock } from 'jest-mock-extended'; describe('TestWebhookRegistrationsService', () => { diff --git a/packages/cli/src/__tests__/waiting-webhooks.test.ts b/packages/cli/src/webhooks/__tests__/waiting-webhooks.test.ts similarity index 90% rename from packages/cli/src/__tests__/waiting-webhooks.test.ts rename to packages/cli/src/webhooks/__tests__/waiting-webhooks.test.ts index 6748c72335..31f64eb198 100644 --- a/packages/cli/src/__tests__/waiting-webhooks.test.ts +++ b/packages/cli/src/webhooks/__tests__/waiting-webhooks.test.ts @@ -1,10 +1,11 @@ import { mock } from 'jest-mock-extended'; -import { WaitingWebhooks } from '@/WaitingWebhooks'; +import { WaitingWebhooks } from '@/webhooks/WaitingWebhooks'; import { ConflictError } from '@/errors/response-errors/conflict.error'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; -import type { IExecutionResponse, WaitingWebhookRequest } from '@/Interfaces'; +import type { IExecutionResponse } from '@/Interfaces'; import type express from 'express'; import type { ExecutionRepository } from '@/databases/repositories/execution.repository'; +import type { WaitingWebhookRequest } from '@/webhooks/webhook.types'; describe('WaitingWebhooks', () => { const executionRepository = mock(); diff --git a/packages/cli/src/services/__tests__/webhook.service.test.ts b/packages/cli/src/webhooks/__tests__/webhook.service.test.ts similarity index 99% rename from packages/cli/src/services/__tests__/webhook.service.test.ts rename to packages/cli/src/webhooks/__tests__/webhook.service.test.ts index 181bc60752..5a8e19e84c 100644 --- a/packages/cli/src/services/__tests__/webhook.service.test.ts +++ b/packages/cli/src/webhooks/__tests__/webhook.service.test.ts @@ -2,7 +2,7 @@ import { v4 as uuid } from 'uuid'; import config from '@/config'; import { WebhookRepository } from '@db/repositories/webhook.repository'; import { CacheService } from '@/services/cache/cache.service'; -import { WebhookService } from '@/services/webhook.service'; +import { WebhookService } from '@/webhooks/webhook.service'; import { WebhookEntity } from '@db/entities/WebhookEntity'; import { mockInstance } from '@test/mocking'; diff --git a/packages/cli/src/services/test-webhook-registrations.service.ts b/packages/cli/src/webhooks/test-webhook-registrations.service.ts similarity index 97% rename from packages/cli/src/services/test-webhook-registrations.service.ts rename to packages/cli/src/webhooks/test-webhook-registrations.service.ts index e2abae5605..94e7e7d826 100644 --- a/packages/cli/src/services/test-webhook-registrations.service.ts +++ b/packages/cli/src/webhooks/test-webhook-registrations.service.ts @@ -3,7 +3,7 @@ import { CacheService } from '@/services/cache/cache.service'; import type { IWebhookData } from 'n8n-workflow'; import type { IWorkflowDb } from '@/Interfaces'; import { TEST_WEBHOOK_TIMEOUT, TEST_WEBHOOK_TIMEOUT_BUFFER } from '@/constants'; -import { OrchestrationService } from './orchestration.service'; +import { OrchestrationService } from '@/services/orchestration.service'; export type TestWebhookRegistration = { pushRef?: string; diff --git a/packages/cli/src/services/webhook.service.ts b/packages/cli/src/webhooks/webhook.service.ts similarity index 100% rename from packages/cli/src/services/webhook.service.ts rename to packages/cli/src/webhooks/webhook.service.ts diff --git a/packages/cli/src/webhooks/webhook.types.ts b/packages/cli/src/webhooks/webhook.types.ts new file mode 100644 index 0000000000..7602ed1871 --- /dev/null +++ b/packages/cli/src/webhooks/webhook.types.ts @@ -0,0 +1,37 @@ +import type { Request, Response } from 'express'; +import type { IDataObject, IHttpRequestMethods } from 'n8n-workflow'; + +export type WebhookCORSRequest = Request & { method: 'OPTIONS' }; + +export type WebhookRequest = Request<{ path: string }> & { + method: IHttpRequestMethods; + params: Record; +}; + +export type WaitingWebhookRequest = WebhookRequest & { + params: WebhookRequest['path'] & { suffix?: string }; +}; + +export interface WebhookAccessControlOptions { + allowedOrigins?: string; +} + +export interface IWebhookManager { + /** Gets all request methods associated with a webhook path*/ + getWebhookMethods?: (path: string) => Promise; + + /** Find the CORS options matching a path and method */ + findAccessControlOptions?: ( + path: string, + httpMethod: IHttpRequestMethods, + ) => Promise; + + executeWebhook(req: WebhookRequest, res: Response): Promise; +} + +export interface IWebhookResponseCallbackData { + data?: IDataObject | IDataObject[]; + headers?: object; + noWebhookResponse?: boolean; + responseCode?: number; +} diff --git a/packages/cli/src/workflows/workflowExecution.service.ts b/packages/cli/src/workflows/workflowExecution.service.ts index 8ebe7aed0c..9ddce37d2f 100644 --- a/packages/cli/src/workflows/workflowExecution.service.ts +++ b/packages/cli/src/workflows/workflowExecution.service.ts @@ -30,7 +30,7 @@ import type { import { NodeTypes } from '@/NodeTypes'; import { WorkflowRunner } from '@/WorkflowRunner'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; -import { TestWebhooks } from '@/TestWebhooks'; +import { TestWebhooks } from '@/webhooks/TestWebhooks'; import { Logger } from '@/Logger'; import type { Project } from '@/databases/entities/Project'; import { GlobalConfig } from '@n8n/config'; diff --git a/packages/cli/test/integration/active-workflow-manager.test.ts b/packages/cli/test/integration/active-workflow-manager.test.ts index 03ce58e7ef..de586b643a 100644 --- a/packages/cli/test/integration/active-workflow-manager.test.ts +++ b/packages/cli/test/integration/active-workflow-manager.test.ts @@ -8,8 +8,8 @@ import { ActiveWorkflowManager } from '@/ActiveWorkflowManager'; import { ExternalHooks } from '@/ExternalHooks'; import { Push } from '@/push'; import { SecretsHelper } from '@/SecretsHelpers'; -import { WebhookService } from '@/services/webhook.service'; -import * as WebhookHelpers from '@/WebhookHelpers'; +import { WebhookService } from '@/webhooks/webhook.service'; +import * as WebhookHelpers from '@/webhooks/WebhookHelpers'; import * as AdditionalData from '@/WorkflowExecuteAdditionalData'; import type { WebhookEntity } from '@db/entities/WebhookEntity'; import { NodeTypes } from '@/NodeTypes'; diff --git a/packages/cli/test/integration/webhooks.test.ts b/packages/cli/test/integration/webhooks.test.ts index 9bd1977ed5..280edb370d 100644 --- a/packages/cli/test/integration/webhooks.test.ts +++ b/packages/cli/test/integration/webhooks.test.ts @@ -3,13 +3,13 @@ import { agent as testAgent } from 'supertest'; import { mock } from 'jest-mock-extended'; import { AbstractServer } from '@/AbstractServer'; -import { ActiveWebhooks } from '@/ActiveWebhooks'; +import { ActiveWebhooks } from '@/webhooks/ActiveWebhooks'; import { ExternalHooks } from '@/ExternalHooks'; import { InternalHooks } from '@/InternalHooks'; -import { TestWebhooks } from '@/TestWebhooks'; -import { WaitingWebhooks } from '@/WaitingWebhooks'; +import { TestWebhooks } from '@/webhooks/TestWebhooks'; +import { WaitingWebhooks } from '@/webhooks/WaitingWebhooks'; import { WaitingForms } from '@/WaitingForms'; -import type { IResponseCallbackData } from '@/Interfaces'; +import type { IWebhookResponseCallbackData } from '@/webhooks/webhook.types'; import { mockInstance } from '@test/mocking'; import { GlobalConfig } from '@n8n/config'; @@ -80,7 +80,7 @@ describe('WebhookServer', () => { } const mockResponse = (data = {}, headers = {}, status = 200) => { - const response = mock(); + const response = mock(); response.responseCode = status; response.data = data; response.headers = headers;