import { Injectable, NotFoundException } from '@nestjs/common'; import { createHash, randomBytes } from 'node:crypto'; import { PrismaService } from '../../infrastructure/database/prisma.service'; import { DefaultUserService } from '../users/default-user.service'; import { DeviceHeartbeatRequestDto, DeviceHeartbeatResponseDto, RegisterDeviceRequestDto, RegisterDeviceResponseDto, } from './devices.dto'; @Injectable() export class DevicesService { constructor( private readonly prismaService: PrismaService, private readonly defaultUserService: DefaultUserService, ) {} async register( body: RegisterDeviceRequestDto, ): Promise { const bootstrapToken = randomBytes(24).toString('hex'); const installTokenHash = createHash('sha256') .update(bootstrapToken) .digest('hex'); const defaultUser = await this.defaultUserService.getOrCreateDefaultUser(); const device = await this.prismaService.device.create({ data: { userId: defaultUser.id, platform: body.platform, deviceName: body.deviceName, appVersion: body.appVersion, installTokenHash, lastSeenAt: new Date(), }, }); return { deviceId: device.id, bootstrapToken, serverTime: new Date().toISOString(), }; } async heartbeat( body: DeviceHeartbeatRequestDto, ): Promise { const existing = await this.prismaService.device.findUnique({ where: { id: body.deviceId }, }); if (!existing) { throw new NotFoundException('Device not found'); } await this.prismaService.device.update({ where: { id: body.deviceId }, data: { appVersion: body.appVersion, lastSeenAt: new Date(), }, }); return { ok: true, serverTime: new Date().toISOString(), }; } }