diff --git a/.env b/.env index 9740584..9120d0b 100644 --- a/.env +++ b/.env @@ -21,4 +21,7 @@ PRISMA_STUDIO_PORT=5555 # MailHog Configuration MAILHOG_SMTP_PORT=1025 -MAILHOG_UI_PORT=8025 \ No newline at end of file +MAILHOG_UI_PORT=8025 + +# Database Connection String for Prisma +DATABASE_URL="postgresql://postgres:password@localhost:5432/time_booking?schema=public" \ No newline at end of file diff --git a/backend/.env b/backend/.env new file mode 100644 index 0000000..fecd0d8 --- /dev/null +++ b/backend/.env @@ -0,0 +1,3 @@ +//.env file for the backend service + +DATABASE_URL="postgresql://postgres:password@localhost:5432/time_booking?schema=public" diff --git a/backend/Dockerfile.dev b/backend/Dockerfile.dev index fcf90be..3e378c1 100644 --- a/backend/Dockerfile.dev +++ b/backend/Dockerfile.dev @@ -4,14 +4,15 @@ FROM node:20-alpine AS builder WORKDIR /app # Install dependencies first (taking advantage of Docker caching) -COPY package.json package-lock.json ./ +COPY package.json ./ COPY tsconfig.json ./ COPY prisma ./prisma/ COPY .env* ./ -RUN npm ci +RUN npm install # Copy Prisma schema to generate client COPY prisma ./prisma/ +COPY .env* ./ RUN npx prisma generate # Copy the rest of the application diff --git a/backend/package.json b/backend/package.json index 6499495..8cd7a59 100644 --- a/backend/package.json +++ b/backend/package.json @@ -17,7 +17,7 @@ "test": "jest --config jest.config.js" }, "dependencies": { - "@prisma/client": "^5.15.0", + "@prisma/client": "^6.8.2", "@types/ioredis": "^4.28.10", "@types/uuid": "^10.0.0", "bcrypt": "^5.1.1", @@ -49,10 +49,10 @@ "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "prettier": "^3.2.5", - "prisma": "^5.15.0", + "prisma": "^6.8.2", "ts-jest": "^29.1.4", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", "typescript": "^5.4.5" } -} \ No newline at end of file +} diff --git a/backend/prisma/migrations/20250517195018_init/migration.sql b/backend/prisma/migrations/20250517195018_init/migration.sql new file mode 100644 index 0000000..b701a8d --- /dev/null +++ b/backend/prisma/migrations/20250517195018_init/migration.sql @@ -0,0 +1,287 @@ +-- CreateEnum +CREATE TYPE "UserRole" AS ENUM ('USER', 'ADMIN', 'SUPER_ADMIN'); + +-- CreateEnum +CREATE TYPE "BookingStatus" AS ENUM ('PENDING', 'CONFIRMED', 'CANCELLED', 'COMPLETED'); + +-- CreateEnum +CREATE TYPE "WaitlistStatus" AS ENUM ('ACTIVE', 'FULFILLED', 'CANCELLED'); + +-- CreateEnum +CREATE TYPE "LabStatus" AS ENUM ('ACTIVE', 'MAINTENANCE', 'INACTIVE'); + +-- CreateEnum +CREATE TYPE "NotificationType" AS ENUM ('BOOKING_CONFIRMATION', 'BOOKING_CANCELLATION', 'WAITLIST_NOTIFICATION', 'GENERAL_ANNOUNCEMENT', 'SLOT_AVAILABLE', 'SYSTEM_NOTIFICATION'); + +-- CreateTable +CREATE TABLE "User" ( + "id" TEXT NOT NULL, + "user_name" TEXT NOT NULL, + "user_email" TEXT NOT NULL, + "user_password" TEXT NOT NULL, + "user_role" "UserRole" NOT NULL DEFAULT 'USER', + "validation_key" TEXT, + "resetToken" TEXT, + "resetTokenExpiry" TIMESTAMP(3), + "organizationId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Admin" ( + "id" TEXT NOT NULL, + "admin_name" TEXT NOT NULL, + "admin_email" TEXT NOT NULL, + "admin_password" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Admin_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "SuperAdmin" ( + "id" TEXT NOT NULL, + "super_admin_name" TEXT NOT NULL, + "super_admin_email" TEXT NOT NULL, + "super_admin_password" TEXT NOT NULL, + "validation_key" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "SuperAdmin_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Organization" ( + "org_id" TEXT NOT NULL, + "org_name" TEXT NOT NULL, + "org_type" TEXT NOT NULL, + "org_location" TEXT NOT NULL, + "superAdminId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Organization_pkey" PRIMARY KEY ("org_id") +); + +-- CreateTable +CREATE TABLE "OrganizationNotification" ( + "id" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + "notification_type" "NotificationType" NOT NULL, + "notification_message" TEXT NOT NULL, + "notification_timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "read" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "OrganizationNotification_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Lab" ( + "id" TEXT NOT NULL, + "lab_name" TEXT NOT NULL, + "lab_capacity" INTEGER NOT NULL, + "status" "LabStatus" NOT NULL DEFAULT 'ACTIVE', + "location" TEXT, + "description" TEXT, + "organizationId" TEXT NOT NULL, + "adminId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Lab_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "TimeSlot" ( + "id" TEXT NOT NULL, + "lab_id" TEXT NOT NULL, + "date" TIMESTAMP(3) NOT NULL, + "start_time" TIMESTAMP(3) NOT NULL, + "end_time" TIMESTAMP(3) NOT NULL, + "status" TEXT NOT NULL DEFAULT 'AVAILABLE', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "TimeSlot_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Booking" ( + "id" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "slot_id" TEXT NOT NULL, + "booking_status" "BookingStatus" NOT NULL DEFAULT 'PENDING', + "booking_timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "managedBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Booking_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Waitlist" ( + "id" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "slot_id" TEXT NOT NULL, + "waitlist_position" INTEGER NOT NULL, + "waitlist_status" "WaitlistStatus" NOT NULL DEFAULT 'ACTIVE', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Waitlist_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Notification" ( + "id" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "notification_type" "NotificationType" NOT NULL, + "notification_message" TEXT NOT NULL, + "notification_timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "read" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Notification_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_user_email_key" ON "User"("user_email"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_validation_key_key" ON "User"("validation_key"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_resetToken_key" ON "User"("resetToken"); + +-- CreateIndex +CREATE INDEX "User_user_email_idx" ON "User"("user_email"); + +-- CreateIndex +CREATE INDEX "User_validation_key_idx" ON "User"("validation_key"); + +-- CreateIndex +CREATE INDEX "User_resetToken_idx" ON "User"("resetToken"); + +-- CreateIndex +CREATE INDEX "User_organizationId_idx" ON "User"("organizationId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Admin_admin_email_key" ON "Admin"("admin_email"); + +-- CreateIndex +CREATE INDEX "Admin_admin_email_idx" ON "Admin"("admin_email"); + +-- CreateIndex +CREATE INDEX "Admin_organizationId_idx" ON "Admin"("organizationId"); + +-- CreateIndex +CREATE UNIQUE INDEX "SuperAdmin_super_admin_email_key" ON "SuperAdmin"("super_admin_email"); + +-- CreateIndex +CREATE UNIQUE INDEX "SuperAdmin_validation_key_key" ON "SuperAdmin"("validation_key"); + +-- CreateIndex +CREATE INDEX "SuperAdmin_super_admin_email_idx" ON "SuperAdmin"("super_admin_email"); + +-- CreateIndex +CREATE INDEX "Organization_org_name_idx" ON "Organization"("org_name"); + +-- CreateIndex +CREATE INDEX "Organization_superAdminId_idx" ON "Organization"("superAdminId"); + +-- CreateIndex +CREATE INDEX "OrganizationNotification_organizationId_idx" ON "OrganizationNotification"("organizationId"); + +-- CreateIndex +CREATE INDEX "Lab_organizationId_idx" ON "Lab"("organizationId"); + +-- CreateIndex +CREATE INDEX "Lab_adminId_idx" ON "Lab"("adminId"); + +-- CreateIndex +CREATE INDEX "TimeSlot_lab_id_idx" ON "TimeSlot"("lab_id"); + +-- CreateIndex +CREATE INDEX "TimeSlot_date_idx" ON "TimeSlot"("date"); + +-- CreateIndex +CREATE INDEX "TimeSlot_lab_id_date_idx" ON "TimeSlot"("lab_id", "date"); + +-- CreateIndex +CREATE INDEX "Booking_user_id_idx" ON "Booking"("user_id"); + +-- CreateIndex +CREATE INDEX "Booking_slot_id_idx" ON "Booking"("slot_id"); + +-- CreateIndex +CREATE INDEX "Booking_booking_status_idx" ON "Booking"("booking_status"); + +-- CreateIndex +CREATE INDEX "Booking_managedBy_idx" ON "Booking"("managedBy"); + +-- CreateIndex +CREATE INDEX "Waitlist_user_id_idx" ON "Waitlist"("user_id"); + +-- CreateIndex +CREATE INDEX "Waitlist_slot_id_idx" ON "Waitlist"("slot_id"); + +-- CreateIndex +CREATE INDEX "Waitlist_waitlist_status_idx" ON "Waitlist"("waitlist_status"); + +-- CreateIndex +CREATE INDEX "Waitlist_slot_id_waitlist_position_idx" ON "Waitlist"("slot_id", "waitlist_position"); + +-- CreateIndex +CREATE INDEX "Notification_user_id_idx" ON "Notification"("user_id"); + +-- CreateIndex +CREATE INDEX "Notification_read_idx" ON "Notification"("read"); + +-- AddForeignKey +ALTER TABLE "User" ADD CONSTRAINT "User_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("org_id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Admin" ADD CONSTRAINT "Admin_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("org_id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Organization" ADD CONSTRAINT "Organization_superAdminId_fkey" FOREIGN KEY ("superAdminId") REFERENCES "SuperAdmin"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OrganizationNotification" ADD CONSTRAINT "OrganizationNotification_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("org_id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Lab" ADD CONSTRAINT "Lab_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("org_id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Lab" ADD CONSTRAINT "Lab_adminId_fkey" FOREIGN KEY ("adminId") REFERENCES "Admin"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TimeSlot" ADD CONSTRAINT "TimeSlot_lab_id_fkey" FOREIGN KEY ("lab_id") REFERENCES "Lab"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Booking" ADD CONSTRAINT "Booking_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Booking" ADD CONSTRAINT "Booking_slot_id_fkey" FOREIGN KEY ("slot_id") REFERENCES "TimeSlot"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Booking" ADD CONSTRAINT "Booking_managedBy_fkey" FOREIGN KEY ("managedBy") REFERENCES "SuperAdmin"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Waitlist" ADD CONSTRAINT "Waitlist_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Waitlist" ADD CONSTRAINT "Waitlist_slot_id_fkey" FOREIGN KEY ("slot_id") REFERENCES "TimeSlot"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Notification" ADD CONSTRAINT "Notification_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/backend/prisma/migrations/migration_lock.toml b/backend/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..044d57c --- /dev/null +++ b/backend/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" diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 2bfbfe2..f8cc80e 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -38,104 +38,129 @@ enum NotificationType { WAITLIST_NOTIFICATION GENERAL_ANNOUNCEMENT SLOT_AVAILABLE + SYSTEM_NOTIFICATION } model User { - id String @id @default(uuid()) - user_name String - user_email String @unique - user_password String - user_role UserRole @default(USER) - resetToken String? @unique - resetTokenExpiry DateTime? - organizationId String? - organization Organization? @relation(fields: [organizationId], references: [id]) - bookings Booking[] - waitlists Waitlist[] - notifications Notification[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(uuid()) + user_name String + user_email String @unique + user_password String + user_role UserRole @default(USER) + validation_key String? @unique // SAMAGRA ID for alternative authentication + resetToken String? @unique + resetTokenExpiry DateTime? + organizationId String? // Optional as users can book from multiple organizations + organization Organization? @relation(fields: [organizationId], references: [id]) + bookings Booking[] + waitlists Waitlist[] + notifications Notification[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([user_email]) + @@index([validation_key]) @@index([resetToken]) + @@index([organizationId]) } model Admin { - id String @id @default(uuid()) + id String @id @default(uuid()) admin_name String - admin_email String @unique + admin_email String @unique admin_password String organizationId String organization Organization @relation(fields: [organizationId], references: [id]) - labs Lab[] // Labs managed by this admin - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + labs Lab[] // Labs managed by this admin + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([admin_email]) + @@index([organizationId]) // Added index for foreign key } model SuperAdmin { - id String @id @default(uuid()) - super_admin_name String - super_admin_email String @unique + id String @id @default(uuid()) + super_admin_name String + super_admin_email String @unique super_admin_password String - validation_key String @unique - organizations Organization[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + validation_key String? @unique // For system authentication if needed + organizations Organization[] + managedBookings Booking[] // Direct relation to bookings managed by this SuperAdmin + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([super_admin_email]) } model Organization { - id String @id @map("org_id") @default(uuid()) - org_name String - org_type String - org_location String - users User[] - admins Admin[] - labs Lab[] - superAdmin SuperAdmin? @relation(fields: [superAdminId], references: [id]) - superAdminId String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(uuid()) @map("org_id") + org_name String + org_type String + org_location String + users User[] + admins Admin[] + labs Lab[] + notifications OrganizationNotification[] + superAdminId String? + superAdmin SuperAdmin? @relation(fields: [superAdminId], references: [id]) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([org_name]) + @@index([superAdminId]) +} + +// Added to match ERD relationship: Organization can receive Notification +model OrganizationNotification { + id String @id @default(uuid()) + organizationId String + organization Organization @relation(fields: [organizationId], references: [id]) + notification_type NotificationType + notification_message String + notification_timestamp DateTime @default(now()) + read Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([organizationId]) } model Lab { - id String @id @default(uuid()) - lab_name String - lab_capacity Int - status LabStatus @default(ACTIVE) - location String? - description String? - timeSlots TimeSlot[] + id String @id @default(uuid()) + lab_name String + lab_capacity Int + status LabStatus @default(ACTIVE) + location String? + description String? + timeSlots TimeSlot[] organizationId String - organization Organization @relation(fields: [organizationId], references: [id]) - adminId String - admin Admin @relation(fields: [adminId], references: [id]) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + organization Organization @relation(fields: [organizationId], references: [id]) + adminId String + admin Admin @relation(fields: [adminId], references: [id]) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([organizationId]) + @@index([adminId]) // Added index for foreign key } model TimeSlot { - id String @id @default(uuid()) - lab_id String - lab Lab @relation(fields: [lab_id], references: [id]) - date DateTime - start_time DateTime - end_time DateTime - status String @default("AVAILABLE") - bookings Booking[] - waitlists Waitlist[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(uuid()) + lab_id String + lab Lab @relation(fields: [lab_id], references: [id]) + date DateTime + start_time DateTime + end_time DateTime + status String @default("AVAILABLE") + bookings Booking[] + waitlists Waitlist[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([lab_id]) @@index([date]) + @@index([lab_id, date]) // Added composite index for common queries } model Booking { @@ -146,38 +171,46 @@ model Booking { timeSlot TimeSlot @relation(fields: [slot_id], references: [id]) booking_status BookingStatus @default(PENDING) booking_timestamp DateTime @default(now()) + // Direct relation to SuperAdmin who manages this booking + managedBy String? + superAdmin SuperAdmin? @relation(fields: [managedBy], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([user_id]) @@index([slot_id]) + @@index([booking_status]) + @@index([managedBy]) } model Waitlist { - id String @id @default(uuid()) + id String @id @default(uuid()) user_id String - user User @relation(fields: [user_id], references: [id]) + user User @relation(fields: [user_id], references: [id]) slot_id String - timeSlot TimeSlot @relation(fields: [slot_id], references: [id]) + timeSlot TimeSlot @relation(fields: [slot_id], references: [id]) waitlist_position Int - waitlist_status WaitlistStatus @default(ACTIVE) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + waitlist_status WaitlistStatus @default(ACTIVE) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([user_id]) @@index([slot_id]) + @@index([waitlist_status]) // Added index for status queries + @@index([slot_id, waitlist_position]) // Added composite index for position queries } model Notification { - id String @id @default(uuid()) - user_id String - user User @relation(fields: [user_id], references: [id]) - notification_type NotificationType - notification_message String + id String @id @default(uuid()) + user_id String + user User @relation(fields: [user_id], references: [id]) + notification_type NotificationType + notification_message String notification_timestamp DateTime @default(now()) - read Boolean @default(false) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + read Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([user_id]) -} \ No newline at end of file + @@index([read]) // Added index for unread notification queries +} diff --git a/backend/src/tests/prisma-types.test.ts b/backend/src/tests/prisma-types.test.ts new file mode 100644 index 0000000..35e5b66 --- /dev/null +++ b/backend/src/tests/prisma-types.test.ts @@ -0,0 +1,19 @@ +import { User, UserRole } from '@prisma/client'; +// Removed unused import of 'PrismaClient' +describe('Prisma Types', () => { + it('TypeScript recognizes Prisma types', () => { + // Make a partial User object with required fields only + const userFields: Partial = { + id: 'test-id', + user_name: 'Test User', + user_email: 'test@example.com', + user_password: 'hashed_password', + user_role: UserRole.USER, + createdAt: new Date(), + updatedAt: new Date(), + }; + + // If TypeScript doesn't complain, the types are correctly recognized + expect(typeof userFields).toBe('object'); + }); +}); diff --git a/docs/Implementation/Develpment Plan Backend.md b/docs/Implementation/Develpment Plan Backend.md index 6fe7831..1f9249b 100644 --- a/docs/Implementation/Develpment Plan Backend.md +++ b/docs/Implementation/Develpment Plan Backend.md @@ -4,22 +4,22 @@ **Day 1: Database Connection & Schema Finalization** -* [ ] Task 1.1: Database Environment Setup - * [ ] Verify PostgreSQL connection parameters in `.env` file. - * [ ] Ensure Docker container for PostgreSQL is running correctly. - * [ ] Test database connectivity with existing configuration. -* [ ] Task 1.2: Prisma Schema Review - * [ ] Review existing schema for any missing fields or relationships. - * [ ] Verify entity relationships match the ERD documentation. - * [ ] Ensure all necessary indexes are defined for performance. +* [x] Task 1.1: Database Environment Setup + * [x] Verify PostgreSQL connection parameters in `.env` file. + * [x] Ensure Docker container for PostgreSQL is running correctly. + * [x] Test database connectivity with existing configuration. +* [x] Task 1.2: Prisma Schema Review + * [x] Review existing schema for any missing fields or relationships. + * [x] Verify entity relationships match the ERD documentation. + * [x] Ensure all necessary indexes are defined for performance. * [ ] Task 1.3: Generate Prisma Client - * [ ] Run Prisma generate command to create type-safe client. - * [ ] Verify client generation completes without errors. - * [ ] Ensure generated types are properly recognized by TypeScript. + * [x] Run Prisma generate command to create type-safe client. + * [x] Verify client generation completes without errors. + * [x] Ensure generated types are properly recognized by TypeScript. * [ ] Task 1.4: Initial Migration Creation - * [ ] Create and apply initial migration to establish database schema. - * [ ] Check migration logs for any issues. - * [ ] Verify tables are created with correct structure. + * [x] Create and apply initial migration to establish database schema. + * [x] Check migration logs for any issues. + * [x] Verify tables are created with correct structure. **Day 2: Seed Data Implementation** diff --git a/docs/Implementation/Devlopment Plan Frontend.md b/docs/Implementation/Devlopment Plan Frontend.md index 4bb36fe..7bcc906 100644 --- a/docs/Implementation/Devlopment Plan Frontend.md +++ b/docs/Implementation/Devlopment Plan Frontend.md @@ -22,11 +22,11 @@ The goal of this phase is to set up the frontend project, configure essential to * [x] Task 2.4: Create placeholder components for initial pages (e.g., `src/pages/HomePage.tsx`, `src/pages/LoginPage.tsx`, `src/pages/DashboardPage.tsx`). * [x] Task 2.5: Implement a basic `MainLayout` component in `src/components/templates/`. * **Day 3: API Client and Basic Utilities** - * [ ] Task 3.1: Set up the central Axios client instance in `src/api/index.ts`, including basic configuration. - * [ ] Task 3.2: Create placeholder files for API functions (`src/api/auth.ts`, `src/api/labs.ts`, etc.). - * [ ] Task 3.3: Implement basic utility functions (e.g., date formatting helpers) in `src/utils/`. - * [ ] Task 3.4: Define initial TypeScript interfaces/types in `src/types/`, potentially mirroring backend types. - * [ ] Task 3.5: Verify project builds (`npm run build`) and runs locally (`npm run dev`) without errors. + * [x] Task 3.1: Set up the central Axios client instance in `src/api/index.ts`, including basic configuration. + * [x] Task 3.2: Create placeholder files for API functions (`src/api/auth.ts`, `src/api/labs.ts`, etc.). + * [x] Task 3.3: Implement basic utility functions (e.g., date formatting helpers) in `src/utils/`. + * [x] Task 3.4: Define initial TypeScript interfaces/types in `src/types/`, potentially mirroring backend types. + * [x] Task 3.5: Verify project builds (`npm run build`) and runs locally (`npm run dev`) without errors. ## PHASE 2: Authentication Implementation (Estimated: 4-5 Days) diff --git a/package-lock.json b/package-lock.json index d819e7a..7389bfa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "backend": { "version": "1.0.0", "dependencies": { - "@prisma/client": "^5.15.0", + "@prisma/client": "^6.8.2", "@types/ioredis": "^4.28.10", "@types/uuid": "^10.0.0", "bcrypt": "^5.1.1", @@ -59,7 +59,7 @@ "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "prettier": "^3.2.5", - "prisma": "^5.15.0", + "prisma": "^6.8.2", "ts-jest": "^29.1.4", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", @@ -499,7 +499,7 @@ "prettier": "^3.2.5", "tailwindcss": "^4.1.5", "typescript": "^5.4.5", - "vite": "^5.2.11", + "vite": "^6.3.5", "vitest": "^3.1.3" } }, @@ -1679,9 +1679,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", "cpu": [ "ppc64" ], @@ -1692,13 +1692,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", "cpu": [ "arm" ], @@ -1709,13 +1709,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", "cpu": [ "arm64" ], @@ -1726,13 +1726,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", "cpu": [ "x64" ], @@ -1743,13 +1743,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", "cpu": [ "arm64" ], @@ -1760,13 +1760,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", "cpu": [ "x64" ], @@ -1777,13 +1777,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", "cpu": [ "arm64" ], @@ -1794,13 +1794,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", "cpu": [ "x64" ], @@ -1811,13 +1811,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", "cpu": [ "arm" ], @@ -1828,13 +1828,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", "cpu": [ "arm64" ], @@ -1845,13 +1845,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", "cpu": [ "ia32" ], @@ -1862,13 +1862,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", "cpu": [ "loong64" ], @@ -1879,13 +1879,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", "cpu": [ "mips64el" ], @@ -1896,13 +1896,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", "cpu": [ "ppc64" ], @@ -1913,13 +1913,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", "cpu": [ "riscv64" ], @@ -1930,13 +1930,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", "cpu": [ "s390x" ], @@ -1947,13 +1947,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", "cpu": [ "x64" ], @@ -1964,13 +1964,30 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", "cpu": [ "x64" ], @@ -1981,13 +1998,30 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", "cpu": [ "x64" ], @@ -1998,13 +2032,13 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", "cpu": [ "x64" ], @@ -2015,13 +2049,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", "cpu": [ "arm64" ], @@ -2032,13 +2066,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", "cpu": [ "ia32" ], @@ -2049,13 +2083,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", "cpu": [ "x64" ], @@ -2066,7 +2100,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -2909,71 +2943,85 @@ } }, "node_modules/@prisma/client": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz", - "integrity": "sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.8.2.tgz", + "integrity": "sha512-5II+vbyzv4si6Yunwgkj0qT/iY0zyspttoDrL3R4BYgLdp42/d2C8xdi9vqkrYtKt9H32oFIukvyw3Koz5JoDg==", "hasInstallScript": true, "license": "Apache-2.0", "engines": { - "node": ">=16.13" + "node": ">=18.18" }, "peerDependencies": { - "prisma": "*" + "prisma": "*", + "typescript": ">=5.1.0" }, "peerDependenciesMeta": { "prisma": { "optional": true + }, + "typescript": { + "optional": true } } }, + "node_modules/@prisma/config": { + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.8.2.tgz", + "integrity": "sha512-ZJY1fF4qRBPdLQ/60wxNtX+eu89c3AkYEcP7L3jkp0IPXCNphCYxikTg55kPJLDOG6P0X+QG5tCv6CmsBRZWFQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "jiti": "2.4.2" + } + }, "node_modules/@prisma/debug": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.22.0.tgz", - "integrity": "sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.8.2.tgz", + "integrity": "sha512-4muBSSUwJJ9BYth5N8tqts8JtiLT8QI/RSAzEogwEfpbYGFo9mYsInsVo8dqXdPO2+Rm5OG5q0qWDDE3nyUbVg==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/engines": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.22.0.tgz", - "integrity": "sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.8.2.tgz", + "integrity": "sha512-XqAJ//LXjqYRQ1RRabs79KOY4+v6gZOGzbcwDQl0D6n9WBKjV7qdrbd042CwSK0v0lM9MSHsbcFnU2Yn7z8Zlw==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "5.22.0", - "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2", - "@prisma/fetch-engine": "5.22.0", - "@prisma/get-platform": "5.22.0" + "@prisma/debug": "6.8.2", + "@prisma/engines-version": "6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e", + "@prisma/fetch-engine": "6.8.2", + "@prisma/get-platform": "6.8.2" } }, "node_modules/@prisma/engines-version": { - "version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz", - "integrity": "sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==", + "version": "6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e.tgz", + "integrity": "sha512-Rkik9lMyHpFNGaLpPF3H5q5TQTkm/aE7DsGM5m92FZTvWQsvmi6Va8On3pWvqLHOt5aPUvFb/FeZTmphI4CPiQ==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/fetch-engine": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz", - "integrity": "sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.8.2.tgz", + "integrity": "sha512-lCvikWOgaLOfqXGacEKSNeenvj0n3qR5QvZUOmPE2e1Eh8cMYSobxonCg9rqM6FSdTfbpqp9xwhSAOYfNqSW0g==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "5.22.0", - "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2", - "@prisma/get-platform": "5.22.0" + "@prisma/debug": "6.8.2", + "@prisma/engines-version": "6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e", + "@prisma/get-platform": "6.8.2" } }, "node_modules/@prisma/get-platform": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.22.0.tgz", - "integrity": "sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.8.2.tgz", + "integrity": "sha512-vXSxyUgX3vm1Q70QwzwkjeYfRryIvKno1SXbIqwSptKwqKzskINnDUcx85oX+ys6ooN2ATGSD0xN2UTfg6Zcow==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "5.22.0" + "@prisma/debug": "6.8.2" } }, "node_modules/@redis/bloom": { @@ -7025,9 +7073,9 @@ } }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7035,32 +7083,34 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" } }, "node_modules/escalade": { @@ -10150,7 +10200,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -12117,23 +12167,29 @@ } }, "node_modules/prisma": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz", - "integrity": "sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.8.2.tgz", + "integrity": "sha512-JNricTXQxzDtRS7lCGGOB4g5DJ91eg3nozdubXze3LpcMl1oWwcFddrj++Up3jnRE6X/3gB/xz3V+ecBk/eEGA==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/engines": "5.22.0" + "@prisma/config": "6.8.2", + "@prisma/engines": "6.8.2" }, "bin": { "prisma": "build/index.js" }, "engines": { - "node": ">=16.13" + "node": ">=18.18" }, - "optionalDependencies": { - "fsevents": "2.3.3" + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/prompts": { @@ -14462,7 +14518,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -14631,21 +14687,24 @@ } }, "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -14654,19 +14713,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", - "terser": "^5.4.0" + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -14687,6 +14752,12 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, @@ -14713,6 +14784,34 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/vitest": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.3.tgz",