diff --git a/package-lock.json b/package-lock.json index 26c024f..a40eacc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -239,6 +239,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -586,7 +587,8 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.2.tgz", "integrity": "sha512-zfWWa+V2ViDCY/cmUfRqeWY1yLto+EpxjXnZzenB1TyxsTiXaTWeZFIZw6mac52BsuQm0RjCnisjBtdBaXOI6w==", - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/@electric-sql/pglite-socket": { "version": "0.0.6", @@ -4560,6 +4562,7 @@ "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "hoist-non-react-statics": "^3.3.0" }, @@ -4619,6 +4622,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz", "integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.19.2" } @@ -4683,6 +4687,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -4693,6 +4698,7 @@ "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -4843,6 +4849,7 @@ "integrity": "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.3", "@typescript-eslint/types": "8.46.3", @@ -5126,6 +5133,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5648,6 +5656,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", @@ -6696,7 +6705,8 @@ "version": "8.6.0", "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/embla-carousel-react": { "version": "8.6.0", @@ -7013,6 +7023,7 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -8220,6 +8231,7 @@ "resolved": "https://registry.npmjs.org/hono/-/hono-4.7.10.tgz", "integrity": "sha512-QkACju9MiN59CKSY5JsGZCYmPZkA6sIW6OFCUp7qDjZu6S6KHtJHhAc9Uy9mV9F8PJ1/HQ3ybZF2yjCa/73fvQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=16.9.0" } @@ -9998,6 +10010,7 @@ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz", "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==", "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=18" }, @@ -10030,6 +10043,7 @@ "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", "license": "MIT", + "peer": true, "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", @@ -10185,6 +10199,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -10402,6 +10417,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -11128,6 +11144,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -11219,6 +11236,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -11231,6 +11249,7 @@ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.66.0.tgz", "integrity": "sha512-xXBqsWGKrY46ZqaHDo+ZUYiMUgi8suYu5kdrS20EG8KiL7VRQitEbNjm+UcrDYrNi1YLyfpmAeGjCZYXLT9YBw==", "license": "MIT", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -11262,6 +11281,7 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", + "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -11521,7 +11541,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -12486,6 +12507,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz", "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", "license": "MIT", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -12766,6 +12788,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -13037,6 +13060,7 @@ "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" @@ -13212,6 +13236,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13489,6 +13514,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -13580,6 +13606,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -13891,6 +13918,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -13917,7 +13945,9 @@ "prisma-zod-generator": "^2.1.2" }, "devDependencies": { + "@types/bcrypt": "^5.0.2", "@types/node": "^22.15.17", + "bcrypt": "^5.1.1", "prisma": "^7.0.0", "tsx": "^4.19.4", "typescript": "^5.8.2" diff --git a/packages/db/package.json b/packages/db/package.json index 3c2427f..41dcaa5 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -22,7 +22,9 @@ "prisma-zod-generator": "^2.1.2" }, "devDependencies": { + "@types/bcrypt": "^5.0.2", "@types/node": "^22.15.17", + "bcrypt": "^5.1.1", "prisma": "^7.0.0", "tsx": "^4.19.4", "typescript": "^5.8.2" diff --git a/packages/db/prisma/seed.ts b/packages/db/prisma/seed.ts index ac5a22f..0cf4485 100644 --- a/packages/db/prisma/seed.ts +++ b/packages/db/prisma/seed.ts @@ -1,32 +1,43 @@ +import dotenv from "dotenv"; +import path from "path"; +dotenv.config({ path: path.resolve(__dirname, ".env") }); + import { PrismaClient } from "../generated/prisma"; -const prisma = new PrismaClient(); +import { PrismaPg } from "@prisma/adapter-pg"; +import bcrypt from "bcrypt"; + +const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }); +const prisma = new PrismaClient({ adapter }); function formatTime(date: Date): string { return date.toTimeString().slice(0, 5); // "HH:MM" } async function main() { - // Create multiple users - const users = await prisma.user.createMany({ - data: [ - { username: "admin2", password: "123456" }, - { username: "bob", password: "123456" }, - ], + const hash = (pw: string) => bcrypt.hash(pw, 10); + + const adminUser = await prisma.user.upsert({ + where: { username: "admin" }, + update: {}, + create: { username: "admin", password: await hash("123456"), role: "ADMIN" }, + }); + + const aaaUser = await prisma.user.upsert({ + where: { username: "aaa" }, + update: {}, + create: { username: "aaa", password: await hash("aaa"), role: "USER" }, }); const createdUsers = await prisma.user.findMany(); - // Creatin staff await prisma.staff.createMany({ data: [ { name: "Dr. Kai Gao", role: "Doctor" }, { name: "Dr. Jane Smith", role: "Doctor" }, ], + skipDuplicates: true, }); - const staffMembers = await prisma.staff.findMany(); - - // Create multiple patients const patients = await prisma.patient.createMany({ data: [ { @@ -54,33 +65,39 @@ async function main() { userId: createdUsers[1].id, }, ], + skipDuplicates: true, }); const createdPatients = await prisma.patient.findMany(); - // Create multiple appointments - await prisma.appointment.createMany({ - data: [ - { - patientId: createdPatients[0].id, - userId: createdUsers[0].id, - title: "Initial Consultation", - date: new Date("2025-06-01"), - startTime: formatTime(new Date("2025-06-01T10:00:00")), - endTime: formatTime(new Date("2025-06-01T10:30:00")), - type: "consultation", - }, - { - patientId: createdPatients[1].id, - userId: createdUsers[1].id, - title: "Follow-up", - date: new Date("2025-06-02"), - startTime: formatTime(new Date("2025-06-01T10:00:00")), - endTime: formatTime(new Date("2025-06-01T10:30:00")), - type: "checkup", - }, - ], - }); + const staffMembers = await prisma.staff.findMany(); + if (createdPatients.length >= 2 && createdUsers.length >= 2 && staffMembers.length >= 1) { + await prisma.appointment.createMany({ + data: [ + { + patientId: createdPatients[0].id, + userId: createdUsers[0].id, + staffId: staffMembers[0].id, + title: "Initial Consultation", + date: new Date("2025-06-01"), + startTime: formatTime(new Date("2025-06-01T10:00:00")), + endTime: formatTime(new Date("2025-06-01T10:30:00")), + type: "consultation", + }, + { + patientId: createdPatients[1].id, + userId: createdUsers[1].id, + staffId: staffMembers[0].id, + title: "Follow-up", + date: new Date("2025-06-02"), + startTime: formatTime(new Date("2025-06-01T10:00:00")), + endTime: formatTime(new Date("2025-06-01T10:30:00")), + type: "checkup", + }, + ], + skipDuplicates: true, + }); + } } main()