import { Module, Global, Logger } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; import * as fs from 'fs'; import * as path from 'path'; import { UserEntity } from './entities/user.entity'; import { SettingEntity } from './entities/setting.entity'; import { CategoryEntity } from './entities/category.entity'; import { ChallengeEntity } from './entities/challenge.entity'; import { ChallengeFileEntity } from './entities/challenge-file.entity'; import { SolveEntity } from './entities/solve.entity'; import { RefreshTokenEntity } from './entities/refresh-token.entity'; import { BlogPostEntity } from './entities/blog-post.entity'; import { InitSchema1700000000000 } from './migrations/1700000000000-InitSchema'; import { SeedSystemData1700000000100 } from './migrations/1700000000100-SeedSystemData'; import { AddCategoryTimestampsAndUniqueAbbrev1700000000200 } from './migrations/1700000000200-AddCategoryTimestampsAndUniqueAbbrev'; import { UpdateSystemCategoryKeys1700000000300 } from './migrations/1700000000300-UpdateSystemCategoryKeys'; import { RepairCategorySchemaAndSystemCategories1700000000400 } from './migrations/1700000000400-RepairCategorySchemaAndSystemCategories'; import { UpgradeChallengeAdminSchema1700000000500 } from './migrations/1700000000500-UpgradeChallengeAdminSchema'; import { SeedSampleChallenges1700000000600 } from './migrations/1700000000600-SeedSampleChallenges'; import { DatabaseInitService } from './database-init.service'; const ENTITIES = [ UserEntity, SettingEntity, CategoryEntity, ChallengeEntity, ChallengeFileEntity, SolveEntity, RefreshTokenEntity, BlogPostEntity, ]; const MIGRATIONS = [ InitSchema1700000000000, SeedSystemData1700000000100, AddCategoryTimestampsAndUniqueAbbrev1700000000200, UpdateSystemCategoryKeys1700000000300, RepairCategorySchemaAndSystemCategories1700000000400, UpgradeChallengeAdminSchema1700000000500, SeedSampleChallenges1700000000600, ]; @Global() @Module({ imports: [ TypeOrmModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (config: ConfigService) => { const dbPath = config.get('DATABASE_PATH', './data/db.sqlite'); const isMemory = dbPath === ':memory:' || dbPath.startsWith('file:'); if (!isMemory) { const dir = path.dirname(dbPath); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); } return { type: 'better-sqlite3', database: dbPath, entities: ENTITIES, migrations: MIGRATIONS, migrationsRun: false, synchronize: false, logging: false, }; }, }), TypeOrmModule.forFeature(ENTITIES), ], providers: [DatabaseInitService], exports: [TypeOrmModule, DatabaseInitService], }) export class DatabaseModule { private readonly logger = new Logger(DatabaseModule.name); }