2023-02-10 05:59:20 -08:00
import { Command } from '@oclif/command' ;
2023-02-10 07:34:39 -08:00
import { ExitError } from '@oclif/errors' ;
2023-02-21 10:21:56 -08:00
import { Container } from 'typedi' ;
2023-02-10 05:59:20 -08:00
import type { INodeTypes } from 'n8n-workflow' ;
import { LoggerProxy , ErrorReporterProxy as ErrorReporter , sleep } from 'n8n-workflow' ;
import type { IUserSettings } from 'n8n-core' ;
import { BinaryDataManager , UserSettings } from 'n8n-core' ;
2023-01-27 05:56:56 -08:00
import { getLogger } from '@/Logger' ;
2023-02-10 05:59:20 -08:00
import config from '@/config' ;
2022-11-09 06:25:00 -08:00
import * as Db from '@/Db' ;
2023-02-10 05:59:20 -08:00
import * as CrashJournal from '@/CrashJournal' ;
2022-12-16 06:27:49 -08:00
import { inTest } from '@/constants' ;
2023-02-10 05:59:20 -08:00
import { CredentialTypes } from '@/CredentialTypes' ;
import { CredentialsOverwrites } from '@/CredentialsOverwrites' ;
import { initErrorHandling } from '@/ErrorReporting' ;
import { ExternalHooks } from '@/ExternalHooks' ;
import { NodeTypes } from '@/NodeTypes' ;
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials' ;
import type { IExternalHooksClass } from '@/Interfaces' ;
2023-02-21 10:21:56 -08:00
import { InternalHooks } from '@/InternalHooks' ;
2023-02-21 00:35:35 -08:00
import { PostHogClient } from '@/posthog' ;
2023-02-10 05:59:20 -08:00
export const UM_FIX_INSTRUCTION =
'Please fix the database by running ./packages/cli/bin/n8n user-management:reset' ;
2022-06-25 21:03:46 -07:00
export abstract class BaseCommand extends Command {
2023-02-10 05:59:20 -08:00
protected logger = LoggerProxy . init ( getLogger ( ) ) ;
protected externalHooks : IExternalHooksClass ;
2023-02-21 10:21:56 -08:00
protected loadNodesAndCredentials : LoadNodesAndCredentials ;
2023-02-10 05:59:20 -08:00
protected nodeTypes : INodeTypes ;
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected userSettings : IUserSettings ;
2022-06-25 21:03:46 -07:00
2023-03-10 10:05:51 -08:00
protected instanceId : string ;
2022-06-25 21:03:46 -07:00
async init ( ) : Promise < void > {
2023-02-10 05:59:20 -08:00
await initErrorHandling ( ) ;
2022-06-25 21:03:46 -07:00
2023-02-10 07:34:39 -08:00
process . once ( 'SIGTERM' , async ( ) = > this . stopProcess ( ) ) ;
process . once ( 'SIGINT' , async ( ) = > this . stopProcess ( ) ) ;
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
// Make sure the settings exist
this . userSettings = await UserSettings . prepareUserSettings ( ) ;
2022-06-25 21:03:46 -07:00
2023-02-21 10:21:56 -08:00
this . loadNodesAndCredentials = Container . get ( LoadNodesAndCredentials ) ;
2023-02-10 05:59:20 -08:00
await this . loadNodesAndCredentials . init ( ) ;
2023-02-21 10:21:56 -08:00
this . nodeTypes = Container . get ( NodeTypes ) ;
const credentialTypes = Container . get ( CredentialTypes ) ;
2023-02-10 05:59:20 -08:00
CredentialsOverwrites ( credentialTypes ) ;
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
await Db . init ( ) . catch ( async ( error : Error ) = >
this . exitWithCrash ( 'There was an error initializing DB' , error ) ,
) ;
2023-04-12 01:59:14 -07:00
2023-05-08 06:52:13 -07:00
if ( process . env . WEBHOOK_TUNNEL_URL ) {
LoggerProxy . warn (
'You are still using the WEBHOOK_TUNNEL_URL environment variable. It has been deprecated and will be removed in a future version of n8n. Please switch to using WEBHOOK_URL instead.' ,
) ;
}
2023-05-08 03:16:20 -07:00
const dbType = config . getEnv ( 'database.type' ) ;
if ( [ 'mysqldb' , 'mariadb' ] . includes ( dbType ) ) {
LoggerProxy . warn (
'Support for MySQL/MariaDB has been deprecated and will be removed with an upcoming version of n8n. Please migrate to PostgreSQL.' ,
) ;
}
2023-05-08 06:03:44 -07:00
if ( process . env . EXECUTIONS_PROCESS === 'own' ) {
LoggerProxy . warn (
'Own mode has been deprecated and will be removed in a future version of n8n. If you need the isolation and performance gains, please consider using queue mode.' ,
) ;
}
2023-05-08 03:16:20 -07:00
2023-04-12 01:59:14 -07:00
this . instanceId = this . userSettings . instanceId ? ? '' ;
await Container . get ( PostHogClient ) . init ( this . instanceId ) ;
await Container . get ( InternalHooks ) . init ( this . instanceId ) ;
2023-02-10 05:59:20 -08:00
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async stopProcess() {
// This needs to be overridden
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async initCrashJournal() {
await CrashJournal . init ( ) ;
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async exitSuccessFully() {
try {
await CrashJournal . cleanup ( ) ;
} finally {
process . exit ( ) ;
}
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async exitWithCrash ( message : string , error : unknown ) {
ErrorReporter . error ( new Error ( message , { cause : error } ) , { level : 'fatal' } ) ;
await sleep ( 2000 ) ;
process . exit ( 1 ) ;
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async initBinaryManager() {
const binaryDataConfig = config . getEnv ( 'binaryDataManager' ) ;
await BinaryDataManager . init ( binaryDataConfig , true ) ;
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async initExternalHooks() {
2023-02-21 10:21:56 -08:00
this . externalHooks = Container . get ( ExternalHooks ) ;
2023-02-10 05:59:20 -08:00
await this . externalHooks . init ( ) ;
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
async finally ( error : Error | undefined ) {
if ( inTest || this . id === 'start' ) return ;
2023-02-10 07:34:39 -08:00
if ( Db . isInitialized ) {
await sleep ( 100 ) ; // give any in-flight query some time to finish
2023-04-12 01:59:14 -07:00
await Db . getConnection ( ) . destroy ( ) ;
2023-02-10 07:34:39 -08:00
}
const exitCode = error instanceof ExitError ? error.oclif.exit : error ? 1 : 0 ;
this . exit ( exitCode ) ;
2022-06-25 21:03:46 -07:00
}
}