feat: bootstrap NestJS backend with auth, stations, users, health-check, now-playing

This commit is contained in:
nk
2026-06-02 13:54:00 +03:00
commit 8aadd62e3c
47 changed files with 13234 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
import {
WebSocketGateway,
WebSocketServer,
OnGatewayConnection,
OnGatewayDisconnect,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { Logger } from '@nestjs/common';
@WebSocketGateway({
cors: { origin: '*' },
namespace: 'now-playing',
})
export class NowPlayingGateway
implements OnGatewayConnection, OnGatewayDisconnect
{
@WebSocketServer()
server: Server;
private readonly logger = new Logger(NowPlayingGateway.name);
handleConnection(client: Socket) {
this.logger.log(`Client connected: ${client.id}`);
}
handleDisconnect(client: Socket) {
this.logger.log(`Client disconnected: ${client.id}`);
}
broadcastNowPlaying(stationId: string, data: any) {
this.server.emit('now-playing', { stationId, ...data });
}
broadcastToRoom(room: string, event: string, data: any) {
this.server.to(room).emit(event, data);
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { NowPlayingGateway } from './now-playing.gateway';
import { NowPlayingService } from './now-playing.service';
@Module({
providers: [NowPlayingGateway, NowPlayingService],
exports: [NowPlayingService],
})
export class NowPlayingModule {}

View File

@@ -0,0 +1,54 @@
import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { NowPlayingGateway } from './now-playing.gateway';
@Injectable()
export class NowPlayingService {
private readonly logger = new Logger(NowPlayingService.name);
constructor(
private readonly prisma: PrismaService,
private readonly gateway: NowPlayingGateway,
) {}
async updateNowPlaying(
stationId: string,
data: { song: string; artist: string; coverUrl?: string },
) {
const nowPlaying = await this.prisma.nowPlaying.upsert({
where: { stationId },
create: {
stationId,
song: data.song,
artist: data.artist,
coverUrl: data.coverUrl,
},
update: {
song: data.song,
artist: data.artist,
coverUrl: data.coverUrl,
},
});
this.gateway.broadcastNowPlaying(stationId, {
song: data.song,
artist: data.artist,
coverUrl: data.coverUrl,
updatedAt: nowPlaying.updatedAt,
});
return nowPlaying;
}
async getNowPlaying(stationId: string) {
return this.prisma.nowPlaying.findUnique({
where: { stationId },
});
}
async getAllNowPlaying() {
return this.prisma.nowPlaying.findMany({
include: { station: true },
});
}
}