Implement backend API and database services in Docker setup

- Added a new `api` service for the NestJS backend, including health checks and dependencies on PostgreSQL, Redis, and MinIO.
- Introduced PostgreSQL and Redis services with health checks and configurations for data persistence.
- Added MinIO for S3-compatible object storage and a one-shot service to initialize required buckets.
- Updated the Nginx configuration to proxy requests to the new backend API and MinIO storage.
- Enhanced the Dockerfile to support the new API environment variables and configurations.
- Updated the `package.json` and `package-lock.json` to include new dependencies for QR code generation and other utilities.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Dorian
2026-02-12 20:14:39 +00:00
parent f19fd6feef
commit cdd24a5def
478 changed files with 55355 additions and 529 deletions

View File

@@ -0,0 +1,31 @@
import { Content } from 'src/contents/entities/content.entity';
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
ManyToOne,
PrimaryColumn,
} from 'typeorm';
@Entity('invites')
export class Invite {
@PrimaryColumn()
id: string;
@PrimaryColumn()
contentId: string;
@Column()
email: string;
@Column({ default: 0 })
share: number;
@CreateDateColumn({ type: 'timestamptz' })
createdAt: Date;
@ManyToOne(() => Content, (content) => content.invites)
@JoinColumn({ name: 'content_id' })
content: Content;
}

View File

@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Invite } from './entities/invite.entity';
import { InvitesService } from './invites.service';
@Module({
imports: [TypeOrmModule.forFeature([Invite])],
providers: [InvitesService],
exports: [InvitesService],
})
export class InvitesModule {}

View File

@@ -0,0 +1,64 @@
import { Inject, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Invite } from './entities/invite.entity';
import { Repository } from 'typeorm';
import { MailService } from 'src/mail/mail.service';
import { randomUUID } from 'node:crypto';
@Injectable()
export class InvitesService {
constructor(
@InjectRepository(Invite)
private invitesRepository: Repository<Invite>,
@Inject(MailService)
private mailService: MailService,
) {}
async getUserInvites(email: string) {
return this.invitesRepository.find({
where: { email },
});
}
async getFilmInvites(contentId: string, email?: string) {
return this.invitesRepository.find({
where: { contentId, email },
});
}
async sendInvite(email: string, contentId: string) {
const invite = await this.invitesRepository.save({
id: randomUUID(),
email,
contentId,
});
return invite;
}
async sendInvites(
invites: Array<{ email: string; share: number }>,
contentId: string,
) {
const parsedInvites = invites.map((invite) => ({
id: randomUUID(),
email: invite.email,
contentId,
share: invite.share,
}));
await this.invitesRepository.save(parsedInvites);
return true;
}
async removeInvite(email: string, contentId?: string) {
await this.invitesRepository.delete({
email,
contentId,
});
return true;
}
async updateInvite(email: string, contentId: string, share: number) {
await this.invitesRepository.update({ email, contentId }, { share });
return true;
}
}