| | import { ModuleRegistry } from '@n8n/backend-common'; |
| | import { DatabaseConfig, InstanceSettingsConfig } from '@n8n/config'; |
| | import { |
| | entities, |
| | subscribers, |
| | mysqlMigrations, |
| | postgresMigrations, |
| | sqliteMigrations, |
| | } from '@n8n/db'; |
| | import { Service } from '@n8n/di'; |
| | import type { DataSourceOptions, LoggerOptions } from '@n8n/typeorm'; |
| | import type { MysqlConnectionOptions } from '@n8n/typeorm/driver/mysql/MysqlConnectionOptions'; |
| | import type { PostgresConnectionOptions } from '@n8n/typeorm/driver/postgres/PostgresConnectionOptions'; |
| | import type { SqliteConnectionOptions } from '@n8n/typeorm/driver/sqlite/SqliteConnectionOptions'; |
| | import type { SqlitePooledConnectionOptions } from '@n8n/typeorm/driver/sqlite-pooled/SqlitePooledConnectionOptions'; |
| | import { UserError } from 'n8n-workflow'; |
| | import path from 'path'; |
| | import type { TlsOptions } from 'tls'; |
| |
|
| | @Service() |
| | export class DbConnectionOptions { |
| | constructor( |
| | private readonly config: DatabaseConfig, |
| | private readonly instanceSettingsConfig: InstanceSettingsConfig, |
| | private readonly moduleRegistry: ModuleRegistry, |
| | ) {} |
| |
|
| | getOverrides(dbType: 'postgresdb' | 'mysqldb') { |
| | const dbConfig = this.config[dbType]; |
| | return { |
| | database: dbConfig.database, |
| | host: dbConfig.host, |
| | port: dbConfig.port, |
| | username: dbConfig.user, |
| | password: dbConfig.password, |
| | }; |
| | } |
| |
|
| | getOptions(): DataSourceOptions { |
| | const { type: dbType } = this.config; |
| | switch (dbType) { |
| | case 'sqlite': |
| | return this.getSqliteConnectionOptions(); |
| | case 'postgresdb': |
| | return this.getPostgresConnectionOptions(); |
| | case 'mariadb': |
| | case 'mysqldb': |
| | return this.getMysqlConnectionOptions(dbType); |
| | default: |
| | throw new UserError('Database type currently not supported', { extra: { dbType } }); |
| | } |
| | } |
| |
|
| | private getCommonOptions() { |
| | const { tablePrefix: entityPrefix, logging: loggingConfig } = this.config; |
| |
|
| | let loggingOption: LoggerOptions = loggingConfig.enabled; |
| | if (loggingOption) { |
| | const optionsString = loggingConfig.options.replace(/\s+/g, ''); |
| | if (optionsString === 'all') { |
| | loggingOption = optionsString; |
| | } else { |
| | loggingOption = optionsString.split(',') as LoggerOptions; |
| | } |
| | } |
| |
|
| | return { |
| | entityPrefix, |
| | entities: [...Object.values(entities), ...this.moduleRegistry.entities], |
| | subscribers: Object.values(subscribers), |
| | migrationsTableName: `${entityPrefix}migrations`, |
| | migrationsRun: false, |
| | synchronize: false, |
| | maxQueryExecutionTime: loggingConfig.maxQueryExecutionTime, |
| | logging: loggingOption, |
| | }; |
| | } |
| |
|
| | private getSqliteConnectionOptions(): SqliteConnectionOptions | SqlitePooledConnectionOptions { |
| | const { sqlite: sqliteConfig } = this.config; |
| | const { n8nFolder } = this.instanceSettingsConfig; |
| |
|
| | const commonOptions = { |
| | ...this.getCommonOptions(), |
| | database: path.resolve(n8nFolder, sqliteConfig.database), |
| | migrations: sqliteMigrations, |
| | }; |
| |
|
| | if (sqliteConfig.poolSize > 0) { |
| | return { |
| | type: 'sqlite-pooled', |
| | poolSize: sqliteConfig.poolSize, |
| | enableWAL: true, |
| | acquireTimeout: 60_000, |
| | destroyTimeout: 5_000, |
| | ...commonOptions, |
| | }; |
| | } else { |
| | return { |
| | type: 'sqlite', |
| | enableWAL: sqliteConfig.enableWAL, |
| | ...commonOptions, |
| | }; |
| | } |
| | } |
| |
|
| | private getPostgresConnectionOptions(): PostgresConnectionOptions { |
| | const { postgresdb: postgresConfig } = this.config; |
| | const { |
| | ssl: { ca: sslCa, cert: sslCert, key: sslKey, rejectUnauthorized: sslRejectUnauthorized }, |
| | } = postgresConfig; |
| |
|
| | let ssl: TlsOptions | boolean = postgresConfig.ssl.enabled; |
| | if (sslCa !== '' || sslCert !== '' || sslKey !== '' || !sslRejectUnauthorized) { |
| | ssl = { |
| | ca: sslCa || undefined, |
| | cert: sslCert || undefined, |
| | key: sslKey || undefined, |
| | rejectUnauthorized: sslRejectUnauthorized, |
| | }; |
| | } |
| |
|
| | return { |
| | type: 'postgres', |
| | ...this.getCommonOptions(), |
| | ...this.getOverrides('postgresdb'), |
| | schema: postgresConfig.schema, |
| | poolSize: postgresConfig.poolSize, |
| | migrations: postgresMigrations, |
| | connectTimeoutMS: postgresConfig.connectionTimeoutMs, |
| | ssl, |
| | extra: { |
| | idleTimeoutMillis: postgresConfig.idleTimeoutMs, |
| | }, |
| | }; |
| | } |
| |
|
| | private getMysqlConnectionOptions(dbType: 'mariadb' | 'mysqldb'): MysqlConnectionOptions { |
| | return { |
| | type: dbType === 'mysqldb' ? 'mysql' : 'mariadb', |
| | ...this.getCommonOptions(), |
| | ...this.getOverrides('mysqldb'), |
| | migrations: mysqlMigrations, |
| | timezone: 'Z', |
| | }; |
| | } |
| | } |
| |
|