Explorar el Código

fix: device field null assertions + simulator dockerfile + UPLOAD_BASE_URL

- Add non-null assertions (!) for device.projectId/orgId/id/serialNo in captures service
  (Drizzle returns nullable types even for .notNull() columns)
- Fix simulator Dockerfile: correct COPY paths (apps/simulator/...)
- Set UPLOAD_BASE_URL default to 10.147.17.118:3001 for remote browser access
clawPi4Bot hace 2 meses
padre
commit
372220d73d

+ 21 - 21
apps/api-server/src/modules/captures/captures.service.ts

@@ -41,7 +41,7 @@ export class CapturesService {
     const validKey = await this.deviceRepo.verifyApiKey(device.apiKeyHash, apiKey)
     if (!validKey) throw new UnauthorizedException('Invalid API key')
     if (!device.projectId || !device.orgId) throw new BadRequestException('Device not assigned to a project')
-    return device
+    return device as Required<Pick<typeof device, 'id' | 'projectId' | 'orgId' | 'serialNo' | 'name'>>
   }
 
   async handleUpload(params: {
@@ -66,30 +66,30 @@ export class CapturesService {
     const dateStr = new Date(params.capturedAt).toISOString().slice(0, 10)
     const ext = path.extname(params.file.originalname) || '.jpg'
     const id = crypto.randomUUID().slice(0, 12)
-    const storagePath = path.join(this.uploadDir, device.projectId, dateStr)
+    const storagePath = path.join(this.uploadDir, device.projectId!, dateStr)
     fs.mkdirSync(storagePath, { recursive: true })
 
-    const fileKey = `${device.projectId}/${dateStr}/${id}${ext}`
+    const fileKey = `${device.projectId!}/${dateStr}/${id}${ext}`
     const destPath = path.join(this.uploadDir, fileKey)
     fs.renameSync(params.file.path, destPath)
 
     const capture = await this.repo.createCapture({
-      projectId: device.projectId,
+      projectId: device.projectId!,
       deviceId: params.deviceId,
       capturedAt: new Date(params.capturedAt),
       fileKey,
       checksum,
-      resolution: params.resolution ?? null,
+      resolution: params.resolution ?? undefined,
       fileSizeBytes: params.file.size,
-      exposureMs: params.exposureMs ?? null,
-      iso: params.iso ?? null,
-      aperture: params.aperture ?? null,
-      gpsLat: params.gpsLat ?? null,
-      gpsLng: params.gpsLng ?? null,
+      exposureMs: params.exposureMs ?? undefined,
+      iso: params.iso ?? undefined,
+      aperture: params.aperture ?? undefined,
+      gpsLat: params.gpsLat ?? undefined,
+      gpsLng: params.gpsLng ?? undefined,
       metadata: { originalFilename: params.file.originalname, uploadedAt: new Date().toISOString() },
     })
 
-    this.realtime.emitCaptureUploaded(params.deviceId, device.projectId, capture.id)
+    this.realtime.emitCaptureUploaded(params.deviceId, device.projectId!, capture.id)
 
     return {
       captureId: capture.id,
@@ -117,21 +117,21 @@ export class CapturesService {
     const device = await this.validateDeviceApiKey(params.deviceId, params.apiKey)
 
     const capture = await this.repo.createCapture({
-      projectId: device.projectId,
+      projectId: device.projectId!,
       deviceId: params.deviceId,
       capturedAt: new Date(params.capturedAt),
       fileKey: params.fileKey,
-      checksum: params.checksum ?? null,
-      resolution: params.resolution ?? null,
-      fileSizeBytes: params.fileSizeBytes ?? null,
-      exposureMs: params.exposureMs ?? null,
-      iso: params.iso ?? null,
-      aperture: params.aperture ?? null,
-      gpsLat: params.gpsLat ?? null,
-      gpsLng: params.gpsLng ?? null,
+      checksum: params.checksum ?? undefined,
+      resolution: params.resolution ?? undefined,
+      fileSizeBytes: params.fileSizeBytes ?? undefined,
+      exposureMs: params.exposureMs ?? undefined,
+      iso: params.iso ?? undefined,
+      aperture: params.aperture ?? undefined,
+      gpsLat: params.gpsLat ?? undefined,
+      gpsLng: params.gpsLng ?? undefined,
     })
 
-    this.realtime.emitCaptureUploaded(params.deviceId, device.projectId, capture.id)
+    this.realtime.emitCaptureUploaded(params.deviceId, device.projectId!, capture.id)
 
     return { captureId: capture.id, fileKey: params.fileKey }
   }

+ 2 - 2
apps/simulator/Dockerfile

@@ -8,10 +8,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 
 WORKDIR /app
 
-COPY requirements.txt ./
+COPY apps/simulator/requirements.txt ./
 RUN pip install --no-cache-dir -r requirements.txt
 
-COPY simulator/ ./simulator/
+COPY apps/simulator/simulator/ ./simulator/
 
 # Create config directory
 RUN mkdir -p /etc/timelapse

+ 1 - 1
docker-compose.yml

@@ -47,7 +47,7 @@ services:
       GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
       GOOGLE_CALLBACK_URL: ${GOOGLE_CALLBACK_URL:-http://localhost:3001/v1/auth/google/callback}
       UPLOAD_DIR: /uploads/captures
-      UPLOAD_BASE_URL: ${UPLOAD_BASE_URL:-http://localhost:3001}
+      UPLOAD_BASE_URL: ${UPLOAD_BASE_URL:-http://10.147.17.118:3001}
       SIM_INTERNAL_KEY: ${SIM_INTERNAL_KEY:-sim-internal-dev-key-123}
     ports:
       - '3001:3001'