diff --git a/package.json b/package.json index 0f32e0ea56..3dd939d9d3 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "build:backend": "turbo run build:backend", "build:frontend": "turbo run build:frontend", "build:nodes": "turbo run build:nodes", - "typecheck": "turbo --filter=!n8n typecheck", + "typecheck": "turbo typecheck", "dev": "turbo run dev --parallel --env-mode=loose --filter=!n8n-design-system --filter=!@n8n/chat", "dev:ai": "turbo run dev --parallel --env-mode=loose --filter=@n8n/nodes-langchain --filter=n8n --filter=n8n-core", "clean": "turbo run clean --parallel", diff --git a/packages/cli/src/InternalHooks.ts b/packages/cli/src/InternalHooks.ts index dedfb46b0c..7912054085 100644 --- a/packages/cli/src/InternalHooks.ts +++ b/packages/cli/src/InternalHooks.ts @@ -41,6 +41,9 @@ export class InternalHooks { private readonly sharedWorkflowRepository: SharedWorkflowRepository, workflowStatisticsService: WorkflowStatisticsService, private readonly projectRelationRepository: ProjectRelationRepository, + // Can't use @ts-expect-error because only dev time tsconfig considers this as an error, but not build time + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - needed until we decouple telemetry private readonly _eventBus: MessageEventBus, // needed until we decouple telemetry ) { workflowStatisticsService.on('telemetry.onFirstProductionWorkflowSuccess', (metrics) => diff --git a/packages/cli/src/eventbus/MessageEventBusWriter/MessageEventBusLogWriterWorker.ts b/packages/cli/src/eventbus/MessageEventBusWriter/MessageEventBusLogWriterWorker.ts index 4686a1cf3c..69d2e8ce26 100644 --- a/packages/cli/src/eventbus/MessageEventBusWriter/MessageEventBusLogWriterWorker.ts +++ b/packages/cli/src/eventbus/MessageEventBusWriter/MessageEventBusLogWriterWorker.ts @@ -6,7 +6,6 @@ import type { MessageEventBusLogWriterOptions } from './MessageEventBusLogWriter let logFileBasePath = ''; let loggingPaused = true; let keepFiles = 10; -let fileStatTimer: NodeJS.Timer; let maxLogFileSizeInKB = 102400; function setLogFileBasePath(basePath: string) { @@ -117,7 +116,7 @@ if (!isMainThread) { if (logFileBasePath) { renameAndCreateLogs(); loggingPaused = false; - fileStatTimer = setInterval(async () => { + setInterval(async () => { await checkFileSize(buildLogFileNameWithCounter()); }, 5000); } diff --git a/packages/cli/src/middlewares/listQuery/index.ts b/packages/cli/src/middlewares/listQuery/index.ts index 0c8e2c7427..524dcb268e 100644 --- a/packages/cli/src/middlewares/listQuery/index.ts +++ b/packages/cli/src/middlewares/listQuery/index.ts @@ -1,8 +1,16 @@ import { filterListQueryMiddleware } from './filter'; import { selectListQueryMiddleware } from './select'; import { paginationListQueryMiddleware } from './pagination'; +import type { ListQuery } from '@/requests'; +import type { NextFunction, Response } from 'express'; -export const listQueryMiddleware = [ +export type ListQueryMiddleware = ( + req: ListQuery.Request, + res: Response, + next: NextFunction, +) => void; + +export const listQueryMiddleware: ListQueryMiddleware[] = [ filterListQueryMiddleware, selectListQueryMiddleware, paginationListQueryMiddleware, diff --git a/packages/cli/test/integration/eventbus.ee.test.ts b/packages/cli/test/integration/eventbus.ee.test.ts index a79c1388b3..f21822683b 100644 --- a/packages/cli/test/integration/eventbus.ee.test.ts +++ b/packages/cli/test/integration/eventbus.ee.test.ts @@ -200,7 +200,7 @@ test('should anonymize audit message to syslog ', async () => { 'message', async function handler005(msg: { command: string; data: any }) { if (msg.command === 'appendMessageToLog') { - const sent = await eventBus.getEventsAll(); + await eventBus.getEventsAll(); await confirmIdInAll(testAuditMessage.id); expect(mockedSyslogClientLog).toHaveBeenCalled(); eventBus.logWriter.worker?.removeListener('message', handler005); @@ -217,7 +217,7 @@ test('should anonymize audit message to syslog ', async () => { 'message', async function handler006(msg: { command: string; data: any }) { if (msg.command === 'appendMessageToLog') { - const sent = await eventBus.getEventsAll(); + await eventBus.getEventsAll(); await confirmIdInAll(testAuditMessage.id); expect(mockedSyslogClientLog).toHaveBeenCalled(); syslogDestination.disable(); diff --git a/packages/cli/test/integration/executions.controller.test.ts b/packages/cli/test/integration/executions.controller.test.ts index ef04dde99b..1e6d65a4f8 100644 --- a/packages/cli/test/integration/executions.controller.test.ts +++ b/packages/cli/test/integration/executions.controller.test.ts @@ -12,7 +12,10 @@ import { WaitTracker } from '@/WaitTracker'; import { createTeamProject, linkUserToProject } from './shared/db/projects'; mockInstance(WaitTracker); -mockInstance(ConcurrencyControlService, { isEnabled: false }); +mockInstance(ConcurrencyControlService, { + // @ts-expect-error Private property + isEnabled: false, +}); const testServer = setupTestServer({ endpointGroups: ['executions'] }); diff --git a/packages/cli/test/integration/project.service.integration.test.ts b/packages/cli/test/integration/project.service.integration.test.ts index 77d388c161..7fe55ade06 100644 --- a/packages/cli/test/integration/project.service.integration.test.ts +++ b/packages/cli/test/integration/project.service.integration.test.ts @@ -31,7 +31,6 @@ describe('ProjectService', () => { describe('when user has roles in projects where workflow is accessible', () => { it('should return roles and project IDs', async () => { const user = await createUser(); - const secondUser = await createUser(); // @TODO: Needed only to satisfy index in legacy column const firstProject = await createTeamProject('Project 1'); const secondProject = await createTeamProject('Project 2'); @@ -42,17 +41,15 @@ describe('ProjectService', () => { const workflow = await createWorkflow(); await sharedWorkflowRepository.insert({ - userId: user.id, // @TODO: Legacy column projectId: firstProject.id, workflowId: workflow.id, role: 'workflow:owner', }); await sharedWorkflowRepository.insert({ - userId: secondUser.id, // @TODO: Legacy column projectId: secondProject.id, workflowId: workflow.id, - role: 'workflow:user', + role: 'workflow:owner', }); const projectIds = await projectService.findProjectsWorkflowIsIn(workflow.id); @@ -63,9 +60,6 @@ describe('ProjectService', () => { describe('when user has no roles in projects where workflow is accessible', () => { it('should return project IDs but no roles', async () => { - const user = await createUser(); - const secondUser = await createUser(); // @TODO: Needed only to satisfy index in legacy column - const firstProject = await createTeamProject('Project 1'); const secondProject = await createTeamProject('Project 2'); @@ -74,17 +68,15 @@ describe('ProjectService', () => { const workflow = await createWorkflow(); await sharedWorkflowRepository.insert({ - userId: user.id, // @TODO: Legacy column projectId: firstProject.id, workflowId: workflow.id, role: 'workflow:owner', }); await sharedWorkflowRepository.insert({ - userId: secondUser.id, // @TODO: Legacy column projectId: secondProject.id, workflowId: workflow.id, - role: 'workflow:user', + role: 'workflow:owner', }); const projectIds = await projectService.findProjectsWorkflowIsIn(workflow.id); diff --git a/packages/cli/test/integration/pruning.service.test.ts b/packages/cli/test/integration/pruning.service.test.ts index a600b4aabd..09a43a5b5b 100644 --- a/packages/cli/test/integration/pruning.service.test.ts +++ b/packages/cli/test/integration/pruning.service.test.ts @@ -98,7 +98,6 @@ describe('softDeleteOnPruningCycle()', () => { }); test.each<[ExecutionStatus, Partial]>([ - ['warning', { startedAt: now, stoppedAt: now }], ['unknown', { startedAt: now, stoppedAt: now }], ['canceled', { startedAt: now, stoppedAt: now }], ['crashed', { startedAt: now, stoppedAt: now }], @@ -191,7 +190,6 @@ describe('softDeleteOnPruningCycle()', () => { }); test.each<[ExecutionStatus, Partial]>([ - ['warning', { startedAt: yesterday, stoppedAt: yesterday }], ['unknown', { startedAt: yesterday, stoppedAt: yesterday }], ['canceled', { startedAt: yesterday, stoppedAt: yesterday }], ['crashed', { startedAt: yesterday, stoppedAt: yesterday }], diff --git a/packages/cli/test/integration/security-audit/InstanceRiskReporter.test.ts b/packages/cli/test/integration/security-audit/InstanceRiskReporter.test.ts index 5d359e0dba..5f59206426 100644 --- a/packages/cli/test/integration/security-audit/InstanceRiskReporter.test.ts +++ b/packages/cli/test/integration/security-audit/InstanceRiskReporter.test.ts @@ -14,6 +14,7 @@ import config from '@/config'; import { generateNanoId } from '@db/utils/generators'; import { WorkflowRepository } from '@db/repositories/workflow.repository'; import Container from 'typedi'; +import { NodeConnectionType } from 'n8n-workflow'; let securityAuditService: SecurityAuditService; @@ -156,7 +157,7 @@ test('should not report webhooks validated by direct children', async () => { [ { node: 'My Node', - type: 'main', + type: NodeConnectionType.Main, index: 0, }, ], diff --git a/packages/cli/test/integration/shared/db/workflows.ts b/packages/cli/test/integration/shared/db/workflows.ts index f81ac044c3..dc5490f9f3 100644 --- a/packages/cli/test/integration/shared/db/workflows.ts +++ b/packages/cli/test/integration/shared/db/workflows.ts @@ -9,6 +9,7 @@ import { WorkflowRepository } from '@db/repositories/workflow.repository'; import type { SharedWorkflow, WorkflowSharingRole } from '@db/entities/SharedWorkflow'; import { ProjectRepository } from '@/databases/repositories/project.repository'; import { Project } from '@/databases/entities/Project'; +import { NodeConnectionType } from 'n8n-workflow'; export async function createManyWorkflows( amount: number, @@ -157,7 +158,7 @@ export async function createWorkflowWithTrigger( position: [780, 300], }, ], - connections: { Cron: { main: [[{ node: 'Set', type: 'main', index: 0 }]] } }, + connections: { Cron: { main: [[{ node: 'Set', type: NodeConnectionType.Main, index: 0 }]] } }, ...attributes, }, user, diff --git a/packages/cli/test/integration/shared/utils/index.ts b/packages/cli/test/integration/shared/utils/index.ts index 96efb06039..7abdb1a8e8 100644 --- a/packages/cli/test/integration/shared/utils/index.ts +++ b/packages/cli/test/integration/shared/utils/index.ts @@ -96,9 +96,10 @@ export async function initBinaryDataService(mode: 'default' | 'filesystem' = 'de * Extract the value (token) of the auth cookie in a response. */ export function getAuthToken(response: request.Response, authCookieName = AUTH_COOKIE_NAME) { - const cookies: string[] = response.headers['set-cookie']; + const cookiesHeader = response.headers['set-cookie']; + if (!cookiesHeader) return undefined; - if (!cookies) return undefined; + const cookies = Array.isArray(cookiesHeader) ? cookiesHeader : [cookiesHeader]; const authCookie = cookies.find((c) => c.startsWith(`${authCookieName}=`)); diff --git a/packages/cli/test/integration/workflows/workflow.service.ee.test.ts b/packages/cli/test/integration/workflows/workflow.service.ee.test.ts index 55287c5f22..6e3b00bd58 100644 --- a/packages/cli/test/integration/workflows/workflow.service.ee.test.ts +++ b/packages/cli/test/integration/workflows/workflow.service.ee.test.ts @@ -30,6 +30,8 @@ describe('EnterpriseWorkflowService', () => { Container.get(CredentialsRepository), mock(), mock(), + mock(), + mock(), ); }); diff --git a/packages/cli/test/integration/workflows/workflows.controller-with-active-workflow-manager.ee.test.ts b/packages/cli/test/integration/workflows/workflows.controller-with-active-workflow-manager.ee.test.ts index 607639b091..d32722c23d 100644 --- a/packages/cli/test/integration/workflows/workflows.controller-with-active-workflow-manager.ee.test.ts +++ b/packages/cli/test/integration/workflows/workflows.controller-with-active-workflow-manager.ee.test.ts @@ -11,7 +11,6 @@ import { Telemetry } from '@/telemetry'; mockInstance(Telemetry); let member: User; -let anotherMember: User; const testServer = utils.setupTestServer({ endpointGroups: ['workflows'], @@ -20,7 +19,6 @@ const testServer = utils.setupTestServer({ beforeAll(async () => { member = await createUser({ role: 'global:member' }); - anotherMember = await createUser({ role: 'global:member' }); await utils.initNodeTypes(); }); diff --git a/packages/cli/test/unit/ActiveExecutions.test.ts b/packages/cli/test/unit/ActiveExecutions.test.ts index b2454de87c..0cc70a10a4 100644 --- a/packages/cli/test/unit/ActiveExecutions.test.ts +++ b/packages/cli/test/unit/ActiveExecutions.test.ts @@ -20,7 +20,10 @@ const executionRepository = mock({ createNewExecution, }); -const concurrencyControl = mockInstance(ConcurrencyControlService, { isEnabled: false }); +const concurrencyControl = mockInstance(ConcurrencyControlService, { + // @ts-expect-error Private property + isEnabled: false, +}); describe('ActiveExecutions', () => { let activeExecutions: ActiveExecutions; diff --git a/packages/cli/test/unit/Telemetry.test.ts b/packages/cli/test/unit/Telemetry.test.ts index e055abb1fd..af8445c814 100644 --- a/packages/cli/test/unit/Telemetry.test.ts +++ b/packages/cli/test/unit/Telemetry.test.ts @@ -15,11 +15,6 @@ describe('Telemetry', () => { const spyTrack = jest.spyOn(Telemetry.prototype, 'track').mockName('track'); const mockRudderStack = mock(); - mockRudderStack.track.mockImplementation(function (_, cb) { - cb?.(); - - return this; - }); let telemetry: Telemetry; const instanceId = 'Telemetry unit test'; diff --git a/packages/cli/test/unit/services/orchestration.service.test.ts b/packages/cli/test/unit/services/orchestration.service.test.ts index 0cdd73f605..75c7c06e40 100644 --- a/packages/cli/test/unit/services/orchestration.service.test.ts +++ b/packages/cli/test/unit/services/orchestration.service.test.ts @@ -33,7 +33,7 @@ function setDefaultConfig() { config.set('generic.instanceType', 'main'); } -const workerRestartEventbusResponse: RedisServiceWorkerResponseObject = { +const workerRestartEventBusResponse: RedisServiceWorkerResponseObject = { senderId: 'test', workerId: 'test', command: 'restartEventBus', @@ -88,7 +88,7 @@ describe('Orchestration Service', () => { test('should handle worker responses', async () => { const response = await handleWorkerResponseMessageMain( - JSON.stringify(workerRestartEventbusResponse), + JSON.stringify(workerRestartEventBusResponse), ); expect(response.command).toEqual('restartEventBus'); }); @@ -108,7 +108,7 @@ describe('Orchestration Service', () => { test('should reject command messages from itself', async () => { const response = await handleCommandMessageMain( - JSON.stringify({ ...workerRestartEventbusResponse, senderId: queueModeId }), + JSON.stringify({ ...workerRestartEventBusResponse, senderId: queueModeId }), ); expect(response).toBeDefined(); expect(response!.command).toEqual('restartEventBus'); @@ -141,7 +141,7 @@ describe('Orchestration Service', () => { ); expect(helpers.debounceMessageReceiver).toHaveBeenCalledTimes(2); expect(res1!.payload).toBeUndefined(); - expect(res2!.payload!.result).toEqual('debounced'); + expect((res2!.payload as { result: string }).result).toEqual('debounced'); }); describe('shouldAddWebhooks', () => { diff --git a/packages/cli/test/unit/services/workflow-statistics.service.test.ts b/packages/cli/test/unit/services/workflow-statistics.service.test.ts index 9bd9864bb0..6d9baf49ea 100644 --- a/packages/cli/test/unit/services/workflow-statistics.service.test.ts +++ b/packages/cli/test/unit/services/workflow-statistics.service.test.ts @@ -118,7 +118,7 @@ describe('WorkflowStatisticsService', () => { }; const runData: IRun = { finished: false, - status: 'failed', + status: 'error', data: { resultData: { runData: {} } }, mode: 'internal' as WorkflowExecuteMode, startedAt: new Date(), @@ -206,7 +206,7 @@ describe('WorkflowStatisticsService', () => { test('should not send metrics for entries that already have the flag set', async () => { // Fetch data for workflow 2 which is set up to not be altered in the mocks - entityManager.insert.mockRejectedValueOnce(new QueryFailedError('', undefined, '')); + entityManager.insert.mockRejectedValueOnce(new QueryFailedError('', undefined, new Error())); const workflowId = '1'; const node = { id: 'abcde', diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json index 008f1cb70d..0efc932861 100644 --- a/packages/cli/tsconfig.json +++ b/packages/cli/tsconfig.json @@ -2,7 +2,6 @@ "extends": ["../../tsconfig.json", "../../tsconfig.backend.json"], "compilerOptions": { "rootDir": ".", - "preserveSymlinks": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "baseUrl": "src",