From ff56cda08b9f942ee7750dac8e26dfbdfd398e06 Mon Sep 17 00:00:00 2001 From: Phill Pover Date: Mon, 7 Apr 2025 12:18:42 +0100 Subject: [PATCH] Adding README.md --- README.md | 92 +++++++++++++++++++++++++++++++++++++++++++++ backend/src/main.ts | 14 +++---- 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e69de29..feb4585 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,92 @@ +# Music Collection +Music Collection is a demo app with a frontend written in NextJS, and the backend API written using NestJS. + +## Frontend +The frontend app can be accessed at [https://music.anatid.net/album](https://music.anatid.net/album), showing a list of Albums added through the app. +Clicking on the (+) symbol will allow the user to add an Album with the attributes of Album Title, Artist and Genre. +Each Album listed also has controls for editing and deleting. (TODO: Add dialog to warn of deletion). +Clicking on the Album Title will allow the user to view the full track list, showing each Songs Title, Duration and Track number. The user can also add, edit or delete each Song. (TODO: Add dialog to warn of deletion). +Messages from the API are returned to the user via a Toast style pop-up. +(TODO: Authentication, User Accounts) + +## Backend +The backend API can be accessed at [https://api.anatid.net/album](https://api.anatid.net/album) and [https://api.anatid.net/song](https://api.anatid.net/song), showing the GET requests of the API in the browser. + +Swagger Docs are available at [https://api.anatid.net/api](https://api.anatid.net/api) showing all endpoints for GET, POST, PUT and DELETE. + +## Docker + +The frontend and backend are built as Docker Images, running with Docker Compose behind a Swag based reverse proxy to enable SSL provided by LetsEncrypt, with the API suppored by a Postgres database for persistence. + +services: + music-collection-frontend: + image: git.anatid.net/tabris/music-collection-frontend:main + restart: unless-stopped + depends_on: + - music-collection-backend + networks: + - frontend + + music-collection-backend: + image: git.anatid.net/tabris/music-collection-backend:main + restart: unless-stopped + environment: + - DB_NAME=${MUSIC_DB_NAME} + - DB_USER=${MUSIC_DB_USER} + - DB_PASSWORD=${MUSIC_DB_PASSWORD} + - POSTGRES_HOST=${POSTGRES_HOST} + - POSTGRES_PORT=${POSTGRES_PORT} + - PORT=3000 + depends_on: + - postgres + networks: + - frontend + - database + + postgres: + image: postgres:17.4 + restart: unless-stopped + environment: + - PUID=${POSTGRES_PUID} + - PGID=${POSTGRES_GUID} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + volumes: + - ./data/postgres/data:/var/lib/postgresql/data:rw + - ./data/git/anatid-config/init/create-multiple-postgresql-databases.sh:/docker-entrypoint-initdb.d/create-multiple-postgresql-databases.sh:ro + networks: + - database + + swag: + image: lscr.io/linuxserver/swag:3.2.0 + cap_add: + - NET_ADMIN + environment: + - PUID=${SWAG_PUID} + - PGID=${SWAG_GUID} + - TZ=Europe/London + - URL=${SWAG_DOMAIN} + - SUBDOMAINS=${SWAG_SUBDOMAINS} + - VALIDATION=${SWAG_VALIDATION} + - DNSPLUGIN=${SWAG_DNS_PLUGIN} + volumes: + - ./data/swag/config:/config:rw + - ./data/git/anatid-web/user:/config/www/user:rw + ports: + - 80:80 + - 443:443 + networks: + web: + frontend: + aliases: + - api.anatid.net + - anatid.net + restart: unless-stopped +networks: + web: + external: true + driver: bridge + database: + external: false + frontend: + external: false diff --git a/backend/src/main.ts b/backend/src/main.ts index 4f8782f..9d8094d 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -1,11 +1,9 @@ import { NestFactory } from '@nestjs/core'; -import { - BadRequestException, - ValidationError, - ValidationPipe, -} from '@nestjs/common'; +import { BadRequestException, ValidationError, ValidationPipe } from '@nestjs/common'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { AppModule } from './app.module'; +import { AlbumModule } from './album/album.module'; +import { SongModule } from './song/song.module'; async function bootstrap() { const app = await NestFactory.create(AppModule, { @@ -27,7 +25,7 @@ async function bootstrap() { validationErrors: ValidationError[], parentProperty = '', ): Array<{ property: string; errors: string[] }> => { - const errors: Array<{ property: string; errors: string[] }> = []; + const errors : Array<{ property: string; errors: string[] }> = []; const getValidationErrorsRecursively = ( validationErrors: ValidationError[], parentProperty = '', @@ -65,7 +63,9 @@ async function bootstrap() { .setVersion('1.0') .addTag('album') .build(); - const documentFactory = () => SwaggerModule.createDocument(app, config); + const documentFactory = () => SwaggerModule.createDocument(app, config, { + include: [AlbumModule, SongModule] + }); SwaggerModule.setup('api', app, documentFactory); await app.listen(process.env.PORT ?? 3000); }