diff --git a/docker-compose.yml b/docker-compose.yml index d0d34a8..c06dc5e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,8 @@ services: POSTGRES_DB: ${POSTGRES_DB} volumes: - postgres-data:/var/lib/postgresql/data + ports: + - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 5s diff --git a/web/package.json b/web/package.json index cf74d8b..3ee904a 100644 --- a/web/package.json +++ b/web/package.json @@ -6,7 +6,10 @@ "dev": "next dev", "build": "next build", "start": "next start", - "test": "vitest run" + "test": "vitest run", + "postinstall": "prisma generate", + "db:migrate": "prisma migrate deploy", + "db:dev": "prisma migrate dev" }, "dependencies": { "next": "15.5.20", diff --git a/web/prisma/migrations/20260710144250_init_request_job/migration.sql b/web/prisma/migrations/20260710144250_init_request_job/migration.sql new file mode 100644 index 0000000..d5da5af --- /dev/null +++ b/web/prisma/migrations/20260710144250_init_request_job/migration.sql @@ -0,0 +1,37 @@ +-- CreateEnum +CREATE TYPE "RequestStatus" AS ENUM ('pending', 'completed', 'needs_attention'); + +-- CreateEnum +CREATE TYPE "JobState" AS ENUM ('requested', 'matching', 'matched', 'downloading', 'tagging', 'imported', 'needs_attention'); + +-- CreateTable +CREATE TABLE "Request" ( + "id" TEXT NOT NULL, + "artist" TEXT NOT NULL, + "album" TEXT NOT NULL, + "status" "RequestStatus" NOT NULL DEFAULT 'pending', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Request_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Job" ( + "id" TEXT NOT NULL, + "requestId" TEXT NOT NULL, + "state" "JobState" NOT NULL DEFAULT 'requested', + "currentStage" TEXT NOT NULL DEFAULT 'intake', + "attempts" INTEGER NOT NULL DEFAULT 0, + "error" TEXT, + "claimedAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Job_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Job_requestId_key" ON "Job"("requestId"); + +-- AddForeignKey +ALTER TABLE "Job" ADD CONSTRAINT "Job_requestId_fkey" FOREIGN KEY ("requestId") REFERENCES "Request"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/web/prisma/migrations/migration_lock.toml b/web/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..648c57f --- /dev/null +++ b/web/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" \ No newline at end of file diff --git a/web/prisma/schema.prisma b/web/prisma/schema.prisma new file mode 100644 index 0000000..58e42cc --- /dev/null +++ b/web/prisma/schema.prisma @@ -0,0 +1,46 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +enum RequestStatus { + pending + completed + needs_attention +} + +enum JobState { + requested + matching + matched + downloading + tagging + imported + needs_attention +} + +model Request { + id String @id @default(cuid()) + artist String + album String + status RequestStatus @default(pending) + createdAt DateTime @default(now()) + job Job? +} + +model Job { + id String @id @default(cuid()) + request Request @relation(fields: [requestId], references: [id], onDelete: Cascade) + requestId String @unique + state JobState @default(requested) + currentStage String @default("intake") + attempts Int @default(0) + error String? + claimedAt DateTime? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} diff --git a/web/src/lib/db.ts b/web/src/lib/db.ts new file mode 100644 index 0000000..f501add --- /dev/null +++ b/web/src/lib/db.ts @@ -0,0 +1,7 @@ +import { PrismaClient } from "@prisma/client"; + +const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient }; + +export const prisma = globalForPrisma.prisma ?? new PrismaClient(); + +if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;