ToolJet/server/src/modules/app/loader.ts
Midhun G S f68c8e1885
[Vulnerability] package upgrades (#14861)
* chore: update nestjs-otel to version 8.0.1 and add systeminformation override

* remove unused API metrics configuration from OpenTelemetry setup

* fixed ldap flaky case

* Update: Sendgrid package to 8.1.6 (#14833)

* updated sendgrid

* fix: update listBuckets function to use default options for ListBucketsCommand

---------

Co-authored-by: gsmithun4 <gsmithun4@gmail.com>

* Vulnerability Issues (#14834)

* Security Fixes

* set version

* utl harper db

* s3

* marketplace package-lock

* Remove package-lock.json files

* chore: update lerna to version 9.0.3 in package.json

* Implement code changes to enhance functionality and improve performance

* removing options from s3 bucket in markeplace

* supabase build type fixes

---------

Co-authored-by: Adish M <adish.madhu@gmail.com>
Co-authored-by: Yukti Goyal <yuktigoyal02@gmail.com>
Co-authored-by: Adish M <44204658+adishM98@users.noreply.github.com>
Co-authored-by: abhijeet760 <abhijeet@tooljet.com>
Co-authored-by: Rudhra Deep Biswas <98055396+rudeUltra@users.noreply.github.com>
Co-authored-by: Rudhra Deep Biswas <rudra21ultra@gmail.com>
2026-01-08 17:46:51 +05:30

173 lines
6.9 KiB
TypeScript

import { DynamicModule } from '@nestjs/common';
import { getImportPath } from './constants';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { ScheduleModule } from '@nestjs/schedule';
import { BullModule } from '@nestjs/bullmq';
import { ConfigModule } from '@nestjs/config';
import { getEnvVars } from '../../../scripts/database-config-utils';
import { LoggerModule } from 'nestjs-pino';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ormconfig, tooljetDbOrmconfig } from '../../../ormconfig';
import { RequestContextModule } from '@modules/request-context/module';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
import { GuardValidatorModule } from './validators/feature-guard.validator';
import { LoggingModule } from '@modules/logging/module';
import { TypeormLoggerService } from '@modules/logging/services/typeorm-logger.service';
import { OpenTelemetryModule } from 'nestjs-otel';
import { SentryModule } from '@sentry/nestjs/setup';
export class AppModuleLoader {
static async loadModules(configs: {
IS_GET_CONTEXT: boolean;
}): Promise<(DynamicModule | typeof GuardValidatorModule)[]> {
const getMainDBConnectionModule = (): DynamicModule => {
return process.env.DISABLE_CUSTOM_QUERY_LOGGING !== 'true'
? TypeOrmModule.forRootAsync({
inject: [TypeormLoggerService],
useFactory: (profilerLogger: TypeormLoggerService) => ({
...ormconfig,
logger: profilerLogger,
}),
})
: TypeOrmModule.forRoot(ormconfig);
};
// Static imports that are always loaded
const staticModules = [
EventEmitterModule.forRoot({
wildcard: false,
newListener: false,
removeListener: false,
maxListeners: process.env.NODE_ENV === 'test' ? 0 : 5,
verboseMemoryLeak: true,
ignoreErrors: false,
}),
ScheduleModule.forRoot(),
BullModule.forRoot({
connection: {
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT) || 6379,
...(process.env.REDIS_USERNAME && { username: process.env.REDIS_USERNAME }),
...(process.env.REDIS_PASSWORD && { password: process.env.REDIS_PASSWORD }),
...(process.env.REDIS_DB && { db: parseInt(process.env.REDIS_DB) }),
...(process.env.REDIS_TLS === 'true' && { tls: {} }),
},
}),
await ConfigModule.forRoot({
isGlobal: true,
envFilePath: [`../.env.${process.env.NODE_ENV}`, '../.env'],
load: [() => getEnvVars()],
}),
LoggerModule.forRoot({
pinoHttp: {
level: (() => {
const logLevel = {
production: 'info',
development: 'debug',
test: 'error',
};
return logLevel[process.env.NODE_ENV] || 'info';
})(),
autoLogging: {
ignore: (req) => {
if (req.url === '/api/health' || req.url === '/api/metrics') {
return true;
}
return false;
},
},
transport:
process.env.NODE_ENV !== 'production'
? {
target: 'pino-pretty',
options: {
colorize: true,
levelFirst: true,
translateTime: 'UTC:mm/dd/yyyy, h:MM:ss TT Z',
},
}
: undefined,
redact: {
paths: [
'req.headers.authorization',
'req.headers.cookie',
'res.headers.authorization',
'res.headers["set-cookie"]',
'req.headers["proxy-authorization"]',
'req.headers["www-authenticate"]',
'req.headers["authentication-info"]',
'req.headers["x-forwarded-for"]',
...(process.env.LOGGER_REDACT ? process.env.LOGGER_REDACT?.split(',') : []),
],
censor: '[REDACTED]',
},
customProps: (req, res) => {
const id = res?.['locals']?.tj_transactionId;
return id ? { transactionId: id } : {};
},
},
}),
getMainDBConnectionModule(),
TypeOrmModule.forRoot(tooljetDbOrmconfig),
RequestContextModule,
GuardValidatorModule,
LoggingModule.forRoot(),
];
// Add OpenTelemetry Module if enabled
if (process.env.ENABLE_OTEL === 'true') {
staticModules.push(
OpenTelemetryModule.forRoot({
metrics: {
hostMetrics: true,
},
})
);
}
if (process.env.SERVE_CLIENT !== 'false' && process.env.NODE_ENV === 'production') {
staticModules.unshift(
ServeStaticModule.forRoot({
// Have to remove trailing slash of SUB_PATH.
serveRoot: process.env.SUB_PATH === undefined ? '' : process.env.SUB_PATH.replace(/\/$/, ''),
rootPath: join(__dirname, '../../../../../', 'frontend/build'),
})
);
}
if (process.env.APM_VENDOR == 'sentry') {
staticModules.unshift(SentryModule.forRoot());
}
/**
* ███████████████████████████████████████████████████████████████████████████████
* █ █
* █ DYNAMIC MODULES █
* █ █
* █ Modules added here can be easily enabled with minimal code changes. █
* █ Not keeping the code on base directories. █
* █ █
* ███████████████████████████████████████████████████████████████████████████████
*/
const dynamicModules: DynamicModule[] = [];
if (!configs.IS_GET_CONTEXT) {
// Load dynamic modules only when not in migration context
try {
if (process.env.LOG_FILE_PATH) {
// Add log-to-file module if LOG_FILE_PATH is set
const { LogToFileModule } = await import(`${await getImportPath(configs.IS_GET_CONTEXT)}/log-to-file/module`);
dynamicModules.push(await LogToFileModule.register(configs));
}
const { AuditLogsModule } = await import(`${await getImportPath(configs.IS_GET_CONTEXT)}/audit-logs/module`);
dynamicModules.push(await AuditLogsModule.register(configs));
} catch (error) {
console.error('Error loading dynamic modules:', error);
}
}
return [...staticModules, ...dynamicModules];
}
}