diff --git a/packages/cli/package.json b/packages/cli/package.json index 07143a0fff..d9e746f5b2 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -65,7 +65,6 @@ "@oclif/dev-cli": "^1.22.2", "@types/basic-auth": "^1.1.2", "@types/bcryptjs": "^2.4.2", - "@types/bull": "^3.3.10", "@types/compression": "1.0.1", "@types/connect-history-api-fallback": "^1.3.1", "@types/convict": "^4.2.1", @@ -108,14 +107,14 @@ "@oclif/core": "^1.16.4", "@oclif/errors": "^1.3.6", "@rudderstack/rudder-sdk-node": "1.0.6", - "@sentry/integrations": "^7.17.3", - "@sentry/node": "^7.17.3", + "@sentry/integrations": "^7.28.1", + "@sentry/node": "^7.28.1", "axios": "^0.21.1", "basic-auth": "^2.0.1", "bcryptjs": "^2.4.3", "body-parser": "^1.18.3", "body-parser-xml": "^2.0.3", - "bull": "^3.19.0", + "bull": "^4.10.2", "callsites": "^3.1.0", "change-case": "^4.1.1", "class-validator": "^0.13.1", @@ -135,7 +134,7 @@ "google-timezones-json": "^1.0.2", "handlebars": "4.7.7", "inquirer": "^7.0.1", - "ioredis": "^4.28.5", + "ioredis": "^5.2.4", "json-diff": "^0.5.4", "jsonschema": "^1.4.1", "jsonwebtoken": "^8.5.1", diff --git a/packages/cli/src/ErrorReporting.ts b/packages/cli/src/ErrorReporting.ts index 66ff5f0ba1..6c2bf95115 100644 --- a/packages/cli/src/ErrorReporting.ts +++ b/packages/cli/src/ErrorReporting.ts @@ -1,12 +1,10 @@ -import * as Sentry from '@sentry/node'; -import { RewriteFrames } from '@sentry/integrations'; import type { Application } from 'express'; import config from '@/config'; import { ErrorReporterProxy } from 'n8n-workflow'; let initialized = false; -export const initErrorHandling = () => { +export const initErrorHandling = async () => { if (initialized) return; if (!config.getEnv('diagnostics.enabled')) { @@ -20,7 +18,11 @@ export const initErrorHandling = () => { const dsn = config.getEnv('diagnostics.config.sentry.dsn'); const { N8N_VERSION: release, ENVIRONMENT: environment } = process.env; - Sentry.init({ + const { init, captureException } = await import('@sentry/node'); + // eslint-disable-next-line @typescript-eslint/naming-convention + const { RewriteFrames } = await import('@sentry/integrations'); + + init({ dsn, release, environment, @@ -37,14 +39,16 @@ export const initErrorHandling = () => { }); ErrorReporterProxy.init({ - report: (error, options) => Sentry.captureException(error, options), + report: (error, options) => captureException(error, options), }); initialized = true; }; -export const setupErrorMiddleware = (app: Application) => { - const { requestHandler, errorHandler } = Sentry.Handlers; +export const setupErrorMiddleware = async (app: Application) => { + const { + Handlers: { requestHandler, errorHandler }, + } = await import('@sentry/node'); app.use(requestHandler()); app.use(errorHandler()); }; diff --git a/packages/cli/src/InternalHooksManager.ts b/packages/cli/src/InternalHooksManager.ts index d1e050c906..efde43d55f 100644 --- a/packages/cli/src/InternalHooksManager.ts +++ b/packages/cli/src/InternalHooksManager.ts @@ -13,10 +13,16 @@ export class InternalHooksManager { throw new Error('InternalHooks not initialized'); } - static init(instanceId: string, versionCli: string, nodeTypes: INodeTypes): InternalHooksClass { + static async init( + instanceId: string, + versionCli: string, + nodeTypes: INodeTypes, + ): Promise { if (!this.internalHooksInstance) { + const telemetry = new Telemetry(instanceId, versionCli); + await telemetry.init(); this.internalHooksInstance = new InternalHooksClass( - new Telemetry(instanceId, versionCli), + telemetry, instanceId, versionCli, nodeTypes, diff --git a/packages/cli/src/Queue.ts b/packages/cli/src/Queue.ts index f68c8c82b2..5c9f74c40c 100644 --- a/packages/cli/src/Queue.ts +++ b/packages/cli/src/Queue.ts @@ -1,4 +1,5 @@ -import Bull from 'bull'; +import type Bull from 'bull'; +import type { RedisOptions } from 'ioredis'; import { IExecuteResponsePromiseData } from 'n8n-workflow'; import config from '@/config'; import * as ActiveExecutions from '@/ActiveExecutions'; @@ -22,15 +23,17 @@ export interface WebhookResponse { } export class Queue { - private activeExecutions: ActiveExecutions.ActiveExecutions; - private jobQueue: JobQueue; - constructor() { - this.activeExecutions = ActiveExecutions.getInstance(); + constructor(private activeExecutions: ActiveExecutions.ActiveExecutions) {} + async init() { const prefix = config.getEnv('queue.bull.prefix'); - const redisOptions = config.getEnv('queue.bull.redis'); + const redisOptions: RedisOptions = config.getEnv('queue.bull.redis'); + + // eslint-disable-next-line @typescript-eslint/naming-convention + const { default: Bull } = await import('bull'); + // Disabling ready check is necessary as it allows worker to // quickly reconnect to Redis if Redis crashes or is unreachable // for some time. With it enabled, worker might take minutes to realize @@ -89,9 +92,10 @@ export class Queue { let activeQueueInstance: Queue | undefined; -export function getInstance(): Queue { +export async function getInstance(): Promise { if (activeQueueInstance === undefined) { - activeQueueInstance = new Queue(); + activeQueueInstance = new Queue(ActiveExecutions.getInstance()); + await activeQueueInstance.init(); } return activeQueueInstance; diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index d28f2e5718..12461cb052 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -270,7 +270,7 @@ class App { this.presetCredentialsLoaded = false; this.endpointPresetCredentials = config.getEnv('credentials.overwrite.endpoint'); - setupErrorMiddleware(this.app); + void setupErrorMiddleware(this.app); if (process.env.E2E_TESTS === 'true') { this.app.use('/e2e', require('./api/e2e.api').e2eController); @@ -1299,7 +1299,8 @@ class App { ResponseHelper.send( async (req: ExecutionRequest.GetAllCurrent): Promise => { if (config.getEnv('executions.mode') === 'queue') { - const currentJobs = await Queue.getInstance().getJobs(['active', 'waiting']); + const queue = await Queue.getInstance(); + const currentJobs = await queue.getJobs(['active', 'waiting']); const currentlyRunningQueueIds = currentJobs.map((job) => job.data.executionId); @@ -1428,14 +1429,15 @@ class App { } as IExecutionsStopData; } - const currentJobs = await Queue.getInstance().getJobs(['active', 'waiting']); + const queue = await Queue.getInstance(); + const currentJobs = await queue.getJobs(['active', 'waiting']); const job = currentJobs.find((job) => job.data.executionId.toString() === req.params.id); if (!job) { throw new Error(`Could not stop "${req.params.id}" as it is no longer in queue.`); } else { - await Queue.getInstance().stopJob(job); + await queue.stopJob(job); } const executionDb = (await Db.collections.Execution.findOne( diff --git a/packages/cli/src/WebhookServer.ts b/packages/cli/src/WebhookServer.ts index cedf2b4712..ab07338988 100644 --- a/packages/cli/src/WebhookServer.ts +++ b/packages/cli/src/WebhookServer.ts @@ -213,7 +213,7 @@ class App { this.presetCredentialsLoaded = false; this.endpointPresetCredentials = config.getEnv('credentials.overwrite.endpoint'); - setupErrorMiddleware(this.app); + void setupErrorMiddleware(this.app); } /** diff --git a/packages/cli/src/WorkflowRunner.ts b/packages/cli/src/WorkflowRunner.ts index 0568ab2fbe..bafd7d589a 100644 --- a/packages/cli/src/WorkflowRunner.ts +++ b/packages/cli/src/WorkflowRunner.ts @@ -62,19 +62,10 @@ export class WorkflowRunner { constructor() { this.push = Push.getInstance(); this.activeExecutions = ActiveExecutions.getInstance(); - - const executionsMode = config.getEnv('executions.mode'); - - if (executionsMode === 'queue') { - this.jobQueue = Queue.getInstance().getBullObjectInstance(); - } - - initErrorHandling(); } /** * The process did send a hook message so execute the appropriate hook - * */ processHookMessage(workflowHooks: WorkflowHooks, hookData: IProcessMessageDataHook) { // eslint-disable-next-line @typescript-eslint/no-floating-promises @@ -83,7 +74,6 @@ export class WorkflowRunner { /** * The process did error - * */ async processError( error: ExecutionError, @@ -133,13 +123,20 @@ export class WorkflowRunner { executionId?: string, responsePromise?: IDeferredPromise, ): Promise { - const executionsProcess = config.getEnv('executions.process'); const executionsMode = config.getEnv('executions.mode'); + const executionsProcess = config.getEnv('executions.process'); + + await initErrorHandling(); + + if (executionsMode === 'queue') { + const queue = await Queue.getInstance(); + this.jobQueue = queue.getBullObjectInstance(); + } if (executionsMode === 'queue' && data.executionMode !== 'manual') { // Do not run "manual" executions in bull because sending events to the // frontend would not be possible - executionId = await this.runBull( + executionId = await this.enqueueExecution( data, loadStaticData, realtime, @@ -378,7 +375,7 @@ export class WorkflowRunner { return executionId; } - async runBull( + async enqueueExecution( data: IWorkflowExecutionDataProcess, loadStaticData?: boolean, realtime?: boolean, @@ -444,7 +441,8 @@ export class WorkflowRunner { async (resolve, reject, onCancel) => { onCancel.shouldReject = false; onCancel(async () => { - await Queue.getInstance().stopJob(job); + const queue = await Queue.getInstance(); + await queue.stopJob(job); // We use "getWorkflowHooksWorkerExecuter" as "getWorkflowHooksWorkerMain" does not contain the // "workflowExecuteAfter" which we require. diff --git a/packages/cli/src/WorkflowRunnerProcess.ts b/packages/cli/src/WorkflowRunnerProcess.ts index 69e05af83d..f0c7098953 100644 --- a/packages/cli/src/WorkflowRunnerProcess.ts +++ b/packages/cli/src/WorkflowRunnerProcess.ts @@ -76,14 +76,12 @@ class WorkflowRunnerProcess { }, 30000); } - constructor() { - initErrorHandling(); - } - async runWorkflow(inputData: IWorkflowExecutionDataProcessWithExecution): Promise { process.once('SIGTERM', WorkflowRunnerProcess.stopProcess); process.once('SIGINT', WorkflowRunnerProcess.stopProcess); + await initErrorHandling(); + // eslint-disable-next-line no-multi-assign const logger = (this.logger = getLogger()); LoggerProxy.init(logger); @@ -114,7 +112,7 @@ class WorkflowRunnerProcess { const instanceId = (await UserSettings.prepareUserSettings()).instanceId ?? ''; const { cli } = await GenericHelpers.getVersions(); - InternalHooksManager.init(instanceId, cli, nodeTypes); + await InternalHooksManager.init(instanceId, cli, nodeTypes); const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig); diff --git a/packages/cli/src/commands/execute.ts b/packages/cli/src/commands/execute.ts index 8e1ad433e7..f993c69ea6 100644 --- a/packages/cli/src/commands/execute.ts +++ b/packages/cli/src/commands/execute.ts @@ -139,7 +139,7 @@ export class Execute extends Command { const instanceId = await UserSettings.getInstanceId(); const { cli } = await GenericHelpers.getVersions(); - InternalHooksManager.init(instanceId, cli, nodeTypes); + await InternalHooksManager.init(instanceId, cli, nodeTypes); if (!WorkflowHelpers.isWorkflowIdValid(workflowId)) { workflowId = undefined; diff --git a/packages/cli/src/commands/executeBatch.ts b/packages/cli/src/commands/executeBatch.ts index e89b49893e..5364dd9d16 100644 --- a/packages/cli/src/commands/executeBatch.ts +++ b/packages/cli/src/commands/executeBatch.ts @@ -327,7 +327,7 @@ export class ExecuteBatch extends Command { const instanceId = await UserSettings.getInstanceId(); const { cli } = await GenericHelpers.getVersions(); - InternalHooksManager.init(instanceId, cli, nodeTypes); + await InternalHooksManager.init(instanceId, cli, nodeTypes); // Send a shallow copy of allWorkflows so we still have all workflow data. const results = await this.runTests([...allWorkflows]); diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index 9ed95a2b9f..c7a7fb1884 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -12,7 +12,6 @@ import { createReadStream, createWriteStream, existsSync } from 'fs'; import localtunnel from 'localtunnel'; import { BinaryDataManager, TUNNEL_SUBDOMAIN_ENV, UserSettings } from 'n8n-core'; import { Command, flags } from '@oclif/command'; -import Redis from 'ioredis'; import stream from 'stream'; import replaceStream from 'replacestream'; import { promisify } from 'util'; @@ -225,7 +224,7 @@ export class Start extends Command { LoggerProxy.init(logger); logger.info('Initializing n8n process'); - initErrorHandling(); + await initErrorHandling(); await CrashJournal.init(); // eslint-disable-next-line @typescript-eslint/no-shadow @@ -394,6 +393,9 @@ export class Start extends Command { settings.db = redisDB; } + // eslint-disable-next-line @typescript-eslint/naming-convention + const { default: Redis } = await import('ioredis'); + // This connection is going to be our heartbeat // IORedis automatically pings redis and tries to reconnect // We will be using the retryStrategy above @@ -466,7 +468,7 @@ export class Start extends Command { const instanceId = await UserSettings.getInstanceId(); const { cli } = await GenericHelpers.getVersions(); - InternalHooksManager.init(instanceId, cli, nodeTypes); + await InternalHooksManager.init(instanceId, cli, nodeTypes); const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig, true); diff --git a/packages/cli/src/commands/webhook.ts b/packages/cli/src/commands/webhook.ts index 657cf3d4eb..d8f4a0f97d 100644 --- a/packages/cli/src/commands/webhook.ts +++ b/packages/cli/src/commands/webhook.ts @@ -6,7 +6,6 @@ /* eslint-disable @typescript-eslint/unbound-method */ import { BinaryDataManager, UserSettings } from 'n8n-core'; import { Command, flags } from '@oclif/command'; -import Redis from 'ioredis'; import { IDataObject, LoggerProxy, sleep } from 'n8n-workflow'; import config from '@/config'; @@ -93,7 +92,7 @@ export class Webhook extends Command { process.once('SIGTERM', Webhook.stopProcess); process.once('SIGINT', Webhook.stopProcess); - initErrorHandling(); + await initErrorHandling(); await CrashJournal.init(); // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-shadow @@ -153,7 +152,7 @@ export class Webhook extends Command { const instanceId = await UserSettings.getInstanceId(); const { cli } = await GenericHelpers.getVersions(); - InternalHooksManager.init(instanceId, cli, nodeTypes); + await InternalHooksManager.init(instanceId, cli, nodeTypes); const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig); @@ -203,6 +202,9 @@ export class Webhook extends Command { settings.db = redisDB; } + // eslint-disable-next-line @typescript-eslint/naming-convention + const { default: Redis } = await import('ioredis'); + // This connection is going to be our heartbeat // IORedis automatically pings redis and tries to reconnect // We will be using the retryStrategy above diff --git a/packages/cli/src/commands/worker.ts b/packages/cli/src/commands/worker.ts index b52ad95a06..2c465519bd 100644 --- a/packages/cli/src/commands/worker.ts +++ b/packages/cli/src/commands/worker.ts @@ -299,14 +299,15 @@ export class Worker extends Command { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const redisConnectionTimeoutLimit = config.getEnv('queue.bull.redis.timeoutThreshold'); - Worker.jobQueue = Queue.getInstance().getBullObjectInstance(); + const queue = await Queue.getInstance(); + Worker.jobQueue = queue.getBullObjectInstance(); // eslint-disable-next-line @typescript-eslint/no-floating-promises Worker.jobQueue.process(flags.concurrency, async (job) => this.runJob(job, nodeTypes)); const versions = await GenericHelpers.getVersions(); const instanceId = await UserSettings.getInstanceId(); - InternalHooksManager.init(instanceId, versions.cli, nodeTypes); + await InternalHooksManager.init(instanceId, versions.cli, nodeTypes); const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig); diff --git a/packages/cli/src/executions/executions.service.ts b/packages/cli/src/executions/executions.service.ts index 9a268fded5..b2d77b4072 100644 --- a/packages/cli/src/executions/executions.service.ts +++ b/packages/cli/src/executions/executions.service.ts @@ -180,7 +180,8 @@ export class ExecutionsService { const executingWorkflowIds: string[] = []; if (config.getEnv('executions.mode') === 'queue') { - const currentJobs = await Queue.getInstance().getJobs(['active', 'waiting']); + const queue = await Queue.getInstance(); + const currentJobs = await queue.getJobs(['active', 'waiting']); executingWorkflowIds.push(...currentJobs.map(({ data }) => data.executionId)); } diff --git a/packages/cli/src/telemetry/index.ts b/packages/cli/src/telemetry/index.ts index f48a6e9eb2..65b64d4ac4 100644 --- a/packages/cli/src/telemetry/index.ts +++ b/packages/cli/src/telemetry/index.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import RudderStack from '@rudderstack/rudder-sdk-node'; -import { PostHog } from 'posthog-node'; +import type RudderStack from '@rudderstack/rudder-sdk-node'; +import type { PostHog } from 'posthog-node'; import { ITelemetryTrackProperties, LoggerProxy } from 'n8n-workflow'; import config from '@/config'; import { IExecutionTrackProperties } from '@/Interfaces'; @@ -31,20 +31,14 @@ export class Telemetry { private postHog?: PostHog; - private instanceId: string; - - private versionCli: string; - private pulseIntervalReference: NodeJS.Timeout; private executionCountsBuffer: IExecutionsBuffer = {}; - constructor(instanceId: string, versionCli: string) { - this.instanceId = instanceId; - this.versionCli = versionCli; + constructor(private instanceId: string, private versionCli: string) {} + async init() { const enabled = config.getEnv('diagnostics.enabled'); - const logLevel = config.getEnv('logs.level'); if (enabled) { const conf = config.getEnv('diagnostics.config.backend'); const [key, url] = conf.split(';'); @@ -56,21 +50,20 @@ export class Telemetry { return; } - this.rudderStack = this.initRudderStack(key, url, logLevel); - this.postHog = this.initPostHog(); + const logLevel = config.getEnv('logs.level'); + + // eslint-disable-next-line @typescript-eslint/naming-convention + const { default: RudderStack } = await import('@rudderstack/rudder-sdk-node'); + this.rudderStack = new RudderStack(key, url, { logLevel }); + + // eslint-disable-next-line @typescript-eslint/naming-convention + const { PostHog } = await import('posthog-node'); + this.postHog = new PostHog(config.getEnv('diagnostics.config.posthog.apiKey')); this.startPulse(); } } - private initRudderStack(key: string, url: string, logLevel: string): RudderStack { - return new RudderStack(key, url, { logLevel }); - } - - private initPostHog(): PostHog { - return new PostHog(config.getEnv('diagnostics.config.posthog.apiKey')); - } - private startPulse() { this.pulseIntervalReference = setInterval(async () => { void this.pulse(); diff --git a/packages/cli/test/unit/Telemetry.test.ts b/packages/cli/test/unit/Telemetry.test.ts index b4c1c15bc4..e8a598930e 100644 --- a/packages/cli/test/unit/Telemetry.test.ts +++ b/packages/cli/test/unit/Telemetry.test.ts @@ -10,16 +10,6 @@ jest.mock('@/license/License.service', () => { }; }); -jest.mock('posthog-node'); - -jest.spyOn(Telemetry.prototype as any, 'initRudderStack').mockImplementation(() => { - return { - flush: () => {}, - identify: () => {}, - track: () => {}, - }; -}); - describe('Telemetry', () => { let startPulseSpy: jest.SpyInstance; const spyTrack = jest.spyOn(Telemetry.prototype, 'track').mockName('track'); @@ -49,6 +39,11 @@ describe('Telemetry', () => { beforeEach(() => { spyTrack.mockClear(); telemetry = new Telemetry(instanceId, n8nVersion); + (telemetry as any).rudderStack = { + flush: () => {}, + identify: () => {}, + track: () => {}, + }; }); afterEach(() => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d663f0f1ee..9f87421aea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -99,11 +99,10 @@ importers: '@oclif/dev-cli': ^1.22.2 '@oclif/errors': ^1.3.6 '@rudderstack/rudder-sdk-node': 1.0.6 - '@sentry/integrations': ^7.17.3 - '@sentry/node': ^7.17.3 + '@sentry/integrations': ^7.28.1 + '@sentry/node': ^7.28.1 '@types/basic-auth': ^1.1.2 '@types/bcryptjs': ^2.4.2 - '@types/bull': ^3.3.10 '@types/compression': 1.0.1 '@types/connect-history-api-fallback': ^1.3.1 '@types/convict': ^4.2.1 @@ -137,7 +136,7 @@ importers: bcryptjs: ^2.4.3 body-parser: ^1.18.3 body-parser-xml: ^2.0.3 - bull: ^3.19.0 + bull: ^4.10.2 callsites: ^3.1.0 change-case: ^4.1.1 class-validator: ^0.13.1 @@ -158,7 +157,7 @@ importers: google-timezones-json: ^1.0.2 handlebars: 4.7.7 inquirer: ^7.0.1 - ioredis: ^4.28.5 + ioredis: ^5.2.4 json-diff: ^0.5.4 jsonschema: ^1.4.1 jsonwebtoken: ^8.5.1 @@ -216,14 +215,14 @@ importers: '@oclif/core': 1.16.6 '@oclif/errors': 1.3.6 '@rudderstack/rudder-sdk-node': 1.0.6 - '@sentry/integrations': 7.18.0 - '@sentry/node': 7.18.0 + '@sentry/integrations': 7.28.1 + '@sentry/node': 7.28.1 axios: 0.21.4 basic-auth: 2.0.1 bcryptjs: 2.4.3 body-parser: 1.20.1 body-parser-xml: 2.0.3 - bull: 3.29.3 + bull: 4.10.2 callsites: 3.1.0 change-case: 4.1.2 class-validator: 0.13.2 @@ -243,7 +242,7 @@ importers: google-timezones-json: 1.0.2 handlebars: 4.7.7 inquirer: 7.3.3 - ioredis: 4.28.5 + ioredis: 5.2.4 json-diff: 0.5.5 jsonschema: 1.4.1 jsonwebtoken: 8.5.1 @@ -284,7 +283,7 @@ importers: sse-channel: 4.0.0 swagger-ui-express: 4.5.0_express@4.18.2 tslib: 1.14.1 - typeorm: 0.2.45_6spgkqhramqg35yodisibk43rm + typeorm: 0.2.45_b2izk5tn6tm5xb65gvog337urq uuid: 8.3.2 validator: 13.7.0 winston: 3.8.2 @@ -294,7 +293,6 @@ importers: '@oclif/dev-cli': 1.26.10 '@types/basic-auth': 1.1.3 '@types/bcryptjs': 2.4.2 - '@types/bull': 3.15.9 '@types/compression': 1.0.1 '@types/connect-history-api-fallback': 1.3.5 '@types/convict': 4.2.1 @@ -2890,6 +2888,10 @@ packages: xregexp: 2.0.0 dev: false + /@ioredis/commands/1.2.0: + resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} + dev: false + /@istanbuljs/load-nyc-config/1.1.0: resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} engines: {node: '>=8'} @@ -3337,6 +3339,48 @@ packages: resolution: {integrity: sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==} dev: true + /@msgpackr-extract/msgpackr-extract-darwin-arm64/2.2.0: + resolution: {integrity: sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ==} + cpu: [arm64] + os: [darwin] + dev: false + optional: true + + /@msgpackr-extract/msgpackr-extract-darwin-x64/2.2.0: + resolution: {integrity: sha512-vq0tT8sjZsy4JdSqmadWVw6f66UXqUCabLmUVHZwUFzMgtgoIIQjT4VVRHKvlof3P/dMCkbMJ5hB1oJ9OWHaaw==} + cpu: [x64] + os: [darwin] + dev: false + optional: true + + /@msgpackr-extract/msgpackr-extract-linux-arm/2.2.0: + resolution: {integrity: sha512-SaJ3Qq4lX9Syd2xEo9u3qPxi/OB+5JO/ngJKK97XDpa1C587H9EWYO6KD8995DAjSinWvdHKRrCOXVUC5fvGOg==} + cpu: [arm] + os: [linux] + dev: false + optional: true + + /@msgpackr-extract/msgpackr-extract-linux-arm64/2.2.0: + resolution: {integrity: sha512-hlxxLdRmPyq16QCutUtP8Tm6RDWcyaLsRssaHROatgnkOxdleMTgetf9JsdncL8vLh7FVy/RN9i3XR5dnb9cRA==} + cpu: [arm64] + os: [linux] + dev: false + optional: true + + /@msgpackr-extract/msgpackr-extract-linux-x64/2.2.0: + resolution: {integrity: sha512-94y5PJrSOqUNcFKmOl7z319FelCLAE0rz/jPCWS+UtdMZvpa4jrQd+cJPQCLp2Fes1yAW/YUQj/Di6YVT3c3Iw==} + cpu: [x64] + os: [linux] + dev: false + optional: true + + /@msgpackr-extract/msgpackr-extract-win32-x64/2.2.0: + resolution: {integrity: sha512-XrC0JzsqQSvOyM3t04FMLO6z5gCuhPE6k4FXuLK5xf52ZbdvcFe1yBmo7meCew9B8G2f0T9iu9t3kfTYRYROgA==} + cpu: [x64] + os: [win32] + dev: false + optional: true + /@n8n_io/license-sdk/1.8.0: resolution: {integrity: sha512-dSBD6EHTu6kWWz1ILxtCcaQqVZu+p/8J0eQ2ntx7Jk8BYSvn5Hh4Oz5M81ut9Pz+2uak+GnIuI6KeYUe1QBXIQ==} engines: {node: '>=14.0.0', npm: '>=7.10.0'} @@ -3706,32 +3750,32 @@ packages: selderee: 0.6.0 dev: false - /@sentry/core/7.18.0: - resolution: {integrity: sha512-erDEMGM+9Msvz/fQaKlYHD8vXDs/Mv5trZc6rlS/gnlaIPQQ8cALH7UdH2UO0eoCLH3/pEYTsa4Qh8AMz6Y86w==} + /@sentry/core/7.28.1: + resolution: {integrity: sha512-7wvnuvn/mrAfcugWoCG/3pqDIrUgH5t+HisMJMGw0h9Tc33KqrmqMDCQVvjlrr2pWrw/vuUCFdm8CbUHJ832oQ==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.18.0 - '@sentry/utils': 7.18.0 + '@sentry/types': 7.28.1 + '@sentry/utils': 7.28.1 tslib: 1.14.1 dev: false - /@sentry/integrations/7.18.0: - resolution: {integrity: sha512-vmJWfybbanfHoy47U8IU50FuEN3GwywP/jFvh7Owll9GuPP9B6spmndZwK+raTisDoDOp3201uC1Bfx0cjl4MQ==} + /@sentry/integrations/7.28.1: + resolution: {integrity: sha512-opeXVR1L9mZmZcpAs9kX+4JPY7pXhVupy17Sbz+43zd5CshYTveIcttGNPp+EPT3j7mMU+1TMAYZspKqJXtEBQ==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.18.0 - '@sentry/utils': 7.18.0 + '@sentry/types': 7.28.1 + '@sentry/utils': 7.28.1 localforage: 1.10.0 tslib: 1.14.1 dev: false - /@sentry/node/7.18.0: - resolution: {integrity: sha512-bc/cta6hnyqaGKECl2Ycffb7L6b+Xy4wzDR5j49FepCCYkXC3CcR/879AIf3sb0/TXP2QMIyfGN8TKlHigX6bA==} + /@sentry/node/7.28.1: + resolution: {integrity: sha512-n7AbpJqZJjWPpKNGc55mP7AdQ+XSomS9MZJuZ+Xt2AU52aVwGPI4z9aHUJFSDGaMHHiu/toyPnoUES+XZf6/hw==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.18.0 - '@sentry/types': 7.18.0 - '@sentry/utils': 7.18.0 + '@sentry/core': 7.28.1 + '@sentry/types': 7.28.1 + '@sentry/utils': 7.28.1 cookie: 0.4.2 https-proxy-agent: 5.0.1 lru_map: 0.3.3 @@ -3740,16 +3784,16 @@ packages: - supports-color dev: false - /@sentry/types/7.18.0: - resolution: {integrity: sha512-bOnyoK1S1chPJ+dAeWJo0srxZ9U48WE5dZFtvKeXoog6JNHY3nqAR/P/uxh9djB4bbwQRMdnGk1zm0bxhOOC6w==} + /@sentry/types/7.28.1: + resolution: {integrity: sha512-DvSplMVrVEmOzR2M161V5+B8Up3vR71xMqJOpWTzE9TqtFJRGPtqT/5OBsNJJw1+/j2ssMcnKwbEo9Q2EGeS6g==} engines: {node: '>=8'} dev: false - /@sentry/utils/7.18.0: - resolution: {integrity: sha512-nIIIF9FZ2rrw9OFIAfnSEK6TbHLii3ZtahVdcw6Jk9LscL2HMkgdmgroiNfFxhGYNqfWsaxVgMW+IdnkrHsqXQ==} + /@sentry/utils/7.28.1: + resolution: {integrity: sha512-75/jzLUO9HH09iC9TslNimGbxOP3jgn89P+q7uR+rp2fJfRExHVeKJZQdK0Ij4/SmE7TJ3Uh2r154N0INZEx1g==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.18.0 + '@sentry/types': 7.28.1 tslib: 1.14.1 dev: false @@ -5484,13 +5528,6 @@ packages: '@types/connect': 3.4.35 '@types/node': 16.11.65 - /@types/bull/3.15.9: - resolution: {integrity: sha512-MPUcyPPQauAmynoO3ezHAmCOhbB0pWmYyijr/5ctaCqhbKWsjW0YCod38ZcLzUBprosfZ9dPqfYIcfdKjk7RNQ==} - dependencies: - '@types/ioredis': 4.28.10 - '@types/redis': 2.8.32 - dev: true - /@types/caseless/0.12.2: resolution: {integrity: sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==} dev: true @@ -5689,12 +5726,6 @@ packages: rxjs: 6.6.7 dev: true - /@types/ioredis/4.28.10: - resolution: {integrity: sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==} - dependencies: - '@types/node': 16.11.65 - dev: true - /@types/is-function/1.0.1: resolution: {integrity: sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q==} dev: true @@ -8226,6 +8257,23 @@ packages: - supports-color dev: false + /bull/4.10.2: + resolution: {integrity: sha512-xa65xtWjQsLqYU/eNaXxq9VRG8xd6qNsQEjR7yjYuae05xKrzbVMVj2QgrYsTMmSs/vsqJjHqHSRRiW1+IkGXQ==} + engines: {node: '>=12'} + dependencies: + cron-parser: 4.7.0 + debuglog: 1.0.1 + get-port: 5.1.1 + ioredis: 5.2.4 + lodash: 4.17.21 + msgpackr: 1.8.1 + p-timeout: 3.2.0 + semver: 7.3.8 + uuid: 8.3.2 + transitivePeerDependencies: + - supports-color + dev: false + /busboy/1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -9551,6 +9599,13 @@ packages: moment-timezone: 0.5.37 dev: false + /cron-parser/4.7.0: + resolution: {integrity: sha512-BdAELR+MCT2ZWsIBhZKDuUqIUCBjHHulPJnm53OfdRLA4EWBjva3R+KM5NeidJuGsNXdEcZkjC7SCnkW5rAFSA==} + engines: {node: '>=12.0.0'} + dependencies: + luxon: 3.1.1 + dev: false + /cron/1.7.2: resolution: {integrity: sha512-+SaJ2OfeRvfQqwXQ2kgr0Y5pzBR/lijf5OpnnaruwWnmI799JfWr2jN2ItOV9s3A/+TFOt6mxvKzQq5F0Jp6VQ==} dependencies: @@ -13142,6 +13197,23 @@ packages: - supports-color dev: false + /ioredis/5.2.4: + resolution: {integrity: sha512-qIpuAEt32lZJQ0XyrloCRdlEdUUNGG9i0UOk6zgzK6igyudNWqEBxfH6OlbnOOoBBvr1WB02mm8fR55CnikRng==} + engines: {node: '>=12.22.0'} + dependencies: + '@ioredis/commands': 1.2.0 + cluster-key-slot: 1.1.1 + debug: 4.3.4 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + /ip-regex/2.1.0: resolution: {integrity: sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==} engines: {node: '>=4'} @@ -15211,6 +15283,11 @@ packages: engines: {node: '>=12'} dev: false + /luxon/3.1.1: + resolution: {integrity: sha512-Ah6DloGmvseB/pX1cAmjbFvyU/pKuwQMQqz7d0yvuDlVYLTs2WeDHQMpC8tGjm1da+BriHROW/OEIT/KfYg6xw==} + engines: {node: '>=12'} + dev: false + /lz-string/1.4.4: resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} hasBin: true @@ -15804,6 +15881,27 @@ packages: /ms/2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + /msgpackr-extract/2.2.0: + resolution: {integrity: sha512-0YcvWSv7ZOGl9Od6Y5iJ3XnPww8O7WLcpYMDwX+PAA/uXLDtyw94PJv9GLQV/nnp3cWlDhMoyKZIQLrx33sWog==} + hasBin: true + dependencies: + node-gyp-build-optional-packages: 5.0.3 + optionalDependencies: + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 2.2.0 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 2.2.0 + '@msgpackr-extract/msgpackr-extract-linux-arm': 2.2.0 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 2.2.0 + '@msgpackr-extract/msgpackr-extract-linux-x64': 2.2.0 + '@msgpackr-extract/msgpackr-extract-win32-x64': 2.2.0 + dev: false + optional: true + + /msgpackr/1.8.1: + resolution: {integrity: sha512-05fT4J8ZqjYlR4QcRDIhLCYKUOHXk7C/xa62GzMKj74l3up9k2QZ3LgFc6qWdsPHl91QA2WLWqWc8b8t7GLNNw==} + optionalDependencies: + msgpackr-extract: 2.2.0 + dev: false + /mssql/8.1.4: resolution: {integrity: sha512-nqkYYehETWVvFLB9zAGJV2kegOsdtLjUnkHA52aFhlE0ZIoOXC3BL8pLERwFicFypM4i3DX1hYeuM726EEIxjQ==} engines: {node: '>=10'} @@ -16007,6 +16105,12 @@ packages: dependencies: whatwg-url: 5.0.0 + /node-gyp-build-optional-packages/5.0.3: + resolution: {integrity: sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==} + hasBin: true + dev: false + optional: true + /node-gyp/8.4.1: resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} engines: {node: '>= 10.12.0'} @@ -20671,7 +20775,7 @@ packages: /typedarray/0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - /typeorm/0.2.45_6spgkqhramqg35yodisibk43rm: + /typeorm/0.2.45_b2izk5tn6tm5xb65gvog337urq: resolution: {integrity: sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==} hasBin: true peerDependencies: @@ -20730,7 +20834,7 @@ packages: debug: 4.3.4 dotenv: 8.6.0 glob: 7.2.3 - ioredis: 4.28.5 + ioredis: 5.2.4 js-yaml: 4.1.0 mkdirp: 1.0.4 mysql2: 2.3.3