Configuring multiple databases
Some checks failed
Music Collection CI Workflow / deploy (push) Has been cancelled
Music Collection CI Workflow / test (./frontend) (push) Has been cancelled
Music Collection CI Workflow / build-and-push-images (./backend/Dockerfile, git.anatid.net/tabris/music-collection-backend, ./backend) (push) Has been cancelled
Music Collection CI Workflow / build-and-push-images (./frontend/Dockerfile, git.anatid.net/tabris/music-collection-frontend, ./frontend) (push) Has been cancelled
Music Collection CI Workflow / test (./backend) (push) Has been cancelled

This commit is contained in:
Phill Pover 2025-04-26 15:09:49 +01:00
parent 9c59b723cb
commit 513fd28d56
8 changed files with 1465 additions and 45 deletions

1411
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,12 +6,12 @@
"private": true, "private": true,
"license": "UNLICENSED", "license": "UNLICENSED",
"scripts": { "scripts": {
"build": "nest build", "build": "NODE_ENV=dev nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start", "start": "nest start",
"start:dev": "nest start --watch", "start:dev": "NODE_ENV=dev nest start --watch",
"start:debug": "nest start --debug --watch", "start:debug": "nest start --debug --watch",
"start:prod": "node dist/main", "start:prod": "NODE_ENV=prod node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest", "test": "jest",
"test:watch": "jest --watch", "test:watch": "jest --watch",
@ -30,9 +30,11 @@
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"crypto": "^1.0.1", "crypto": "^1.0.1",
"dotenv": "^16.5.0",
"pg": "^8.14.1", "pg": "^8.14.1",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"sqlite3": "^5.1.7",
"typeorm": "^0.3.21" "typeorm": "^0.3.21"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,10 +1,15 @@
export default () => ({ export default () => ({
port: parseInt(process.env.PORT!, 10) || 3000,
database: { database: {
host: process.env.POSTGRES_HOST || 'postgres', host: process.env.DB_HOST || 'postgres',
port: parseInt(process.env.POSTGRES_PORT!, 10) || 5432, port: parseInt(process.env.DB_PORT!, 10) || 5432,
name: process.env.DB_NAME || 'music-collection', name: process.env.DB_NAME || 'music-collection',
user: process.env.DB_USER || 'music-collection', user: process.env.DB_USER || 'music-collection',
password: process.env.DB_PASSWORD, password: process.env.DB_PASSWORD || 'password',
}, },
app: {
port: parseInt(process.env.PORT!, 10) || 5000,
hostname: process.env.HOSTNAME || 'localhost',
protocol: process.env.PROTOCOL || 'http',
frontend_url: process.env.FRONTEND_URL || 'http://localhost:5001',
}
}); });

View File

@ -0,0 +1,47 @@
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import { ConfigService } from '@nestjs/config';
const configService = new ConfigService();
const commonConf = {
SYNCRONIZE: true,
ENTITIES: [__dirname + '/../**/*.entity{.ts,.js}'],
MIGRATIONS_RUN: false,
};
let databaseConfig: TypeOrmModuleOptions = {
type: 'sqlite',
database: './target/sqlite-dev-db.sql',
logging: true,
synchronize: true,
entities: commonConf.ENTITIES,
migrationsRun: commonConf.MIGRATIONS_RUN,
};
if (process.env.NODE_ENV === 'prod') {
databaseConfig = {
type: 'postgres',
host: configService.get<string>('database.host'),
port: configService.get<number>('database.port'),
username: configService.get<string>('database.user'),
password: configService.get<string>('database.password'),
database: configService.get<string>('database.name'),
logging: false,
synchronize: commonConf.SYNCRONIZE,
entities: commonConf.ENTITIES,
migrationsRun: commonConf.MIGRATIONS_RUN,
};
}
if (process.env.NODE_ENV === 'test') {
databaseConfig = {
type: 'sqlite',
database: ':memory:',
logging: true,
synchronize: true,
entities: commonConf.ENTITIES,
migrationsRun: commonConf.MIGRATIONS_RUN,
};
}
export { databaseConfig };

View File

@ -1,27 +1,15 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import {TypeOrmModule, TypeOrmModuleOptions} from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config'; import { ConfigModule, ConfigService } from '@nestjs/config';
import configuration from '../config/configuration'; import configuration from '../config/configuration';
import { databaseConfig } from './database.config';
@Module({ @Module({
imports: [ imports: [
ConfigModule.forRoot({ ConfigModule.forRoot({
load: [configuration], load: [configuration],
}), }),
TypeOrmModule.forRootAsync({ TypeOrmModule.forRoot(databaseConfig),
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: 'postgres',
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.user'),
password: configService.get('database.password'),
database: configService.get('database.name'),
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
synchronize: true,
}),
inject: [ConfigService],
}),
], ],
}) })
export class DatabaseModule {} export class DatabaseModule {}

View File

@ -4,13 +4,15 @@ import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import { AlbumModule } from './album/album.module'; import { AlbumModule } from './album/album.module';
import { SongModule } from './song/song.module'; import { SongModule } from './song/song.module';
import { ConfigService } from '@nestjs/config';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule, { const app = await NestFactory.create(AppModule, {
logger: ['error', 'warn'], logger: ['error', 'warn'],
}); });
const configService = app.get<ConfigService>(ConfigService);
app.enableCors({ app.enableCors({
origin: ['https://music.anatid.net'], origin: [configService.get<string>('app.frontend_url')],
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true, credentials: true,
allowedHeaders: allowedHeaders:
@ -57,16 +59,16 @@ async function bootstrap() {
}, },
}), }),
); );
const config = new DocumentBuilder() const swaggerConfig = new DocumentBuilder()
.setTitle('Music Collection') .setTitle('Music Collection')
.setDescription('API for demo Music Collection app') .setDescription('API for demo Music Collection app')
.setVersion('1.0') .setVersion('1.0')
.addTag('album') .addTag('album')
.build(); .build();
const documentFactory = () => SwaggerModule.createDocument(app, config, { const documentFactory = () => SwaggerModule.createDocument(app, swaggerConfig, {
include: [AlbumModule, SongModule] include: [AlbumModule, SongModule]
}); });
SwaggerModule.setup('api', app, documentFactory); SwaggerModule.setup('api', app, documentFactory);
await app.listen(process.env.PORT ?? 3000); await app.listen(configService.get<number>('app.port') || 5000);
} }
bootstrap(); bootstrap();

Binary file not shown.

View File

@ -1,8 +1,9 @@
{ {
"compilerOptions": { "compilerOptions": {
"module": "commonjs", "module": "commonjs",
"declaration": true,
"removeComments": true, "removeComments": true,
"types": [ "node" ],
"declaration": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,