Compare commits
2 Commits
98cc1ffa92
...
6e144fc657
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e144fc657 | |||
| 1352d62a5d |
1
.env
Normal file
1
.env
Normal file
@ -0,0 +1 @@
|
||||
DATABASE_URL=postgres://postgres:lyh1234@192.168.0.180:5432/rbac
|
||||
240
bun.lock
240
bun.lock
@ -5,16 +5,92 @@
|
||||
"": {
|
||||
"name": "api",
|
||||
"dependencies": {
|
||||
"elysia": "latest",
|
||||
"@elysiajs/cors": "^1.4.1",
|
||||
"@elysiajs/eden": "^1.4.6",
|
||||
"@elysiajs/jwt": "^1.4.0",
|
||||
"@sinclair/typebox": "^0.34.47",
|
||||
"dotenv": "^17.2.3",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
"drizzle-typebox": "^0.3.3",
|
||||
"drizzle-zod": "^0.8.3",
|
||||
"elysia": "^1.4.22",
|
||||
"pg": "^8.17.1",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/pg": "^8.16.0",
|
||||
"bun-types": "latest",
|
||||
"drizzle-kit": "^0.31.8",
|
||||
"tsx": "^4.21.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@borewit/text-codec": ["@borewit/text-codec@0.2.1", "https://registry.npmmirror.com/@borewit/text-codec/-/text-codec-0.2.1.tgz", {}, "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw=="],
|
||||
|
||||
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "https://registry.npmmirror.com/@drizzle-team/brocli/-/brocli-0.10.2.tgz", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
|
||||
|
||||
"@elysiajs/cors": ["@elysiajs/cors@1.4.1", "https://registry.npmmirror.com/@elysiajs/cors/-/cors-1.4.1.tgz", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-lQfad+F3r4mNwsxRKbXyJB8Jg43oAOXjRwn7sKUL6bcOW3KjUqUimTS+woNpO97efpzjtDE0tEjGk9DTw8lqTQ=="],
|
||||
|
||||
"@elysiajs/eden": ["@elysiajs/eden@1.4.6", "https://registry.npmmirror.com/@elysiajs/eden/-/eden-1.4.6.tgz", { "peerDependencies": { "elysia": ">=1.4.19" } }, "sha512-Tsa4NwXEWg/u73vWiYZQ3L5/ecgZSxqiEjYwpS+4qBKXeTZqZKl2hcgHJSVBL+InEDMi35Xugct7qyAXE5oM4Q=="],
|
||||
|
||||
"@elysiajs/jwt": ["@elysiajs/jwt@1.4.0", "https://registry.npmmirror.com/@elysiajs/jwt/-/jwt-1.4.0.tgz", { "dependencies": { "jose": "^6.0.11" }, "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-Z0PvZhQxdDeKZ8HslXzDoXXD83NKExNPmoiAPki3nI2Xvh5wtUrBH+zWOD17yP14IbRo8fxGj3L25MRCAPsgPA=="],
|
||||
|
||||
"@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "https://registry.npmmirror.com/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
|
||||
|
||||
"@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "https://registry.npmmirror.com/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
|
||||
|
||||
"@sinclair/typebox": ["@sinclair/typebox@0.34.47", "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.34.47.tgz", {}, "sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw=="],
|
||||
|
||||
"@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "https://registry.npmmirror.com/@tokenizer/inflate/-/inflate-0.4.1.tgz", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="],
|
||||
@ -23,34 +99,196 @@
|
||||
|
||||
"@types/node": ["@types/node@25.0.9", "https://registry.npmmirror.com/@types/node/-/node-25.0.9.tgz", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw=="],
|
||||
|
||||
"@types/pg": ["@types/pg@8.16.0", "https://registry.npmmirror.com/@types/pg/-/pg-8.16.0.tgz", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ=="],
|
||||
|
||||
"buffer-from": ["buffer-from@1.1.2", "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.6", "https://registry.npmmirror.com/bun-types/-/bun-types-1.3.6.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="],
|
||||
|
||||
"cookie": ["cookie@1.1.1", "https://registry.npmmirror.com/cookie/-/cookie-1.1.1.tgz", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"dotenv": ["dotenv@17.2.3", "https://registry.npmmirror.com/dotenv/-/dotenv-17.2.3.tgz", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
|
||||
|
||||
"drizzle-kit": ["drizzle-kit@0.31.8", "https://registry.npmmirror.com/drizzle-kit/-/drizzle-kit-0.31.8.tgz", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-O9EC/miwdnRDY10qRxM8P3Pg8hXe3LyU4ZipReKOgTwn4OqANmftj8XJz1UPUAS6NMHf0E2htjsbQujUTkncCg=="],
|
||||
|
||||
"drizzle-orm": ["drizzle-orm@0.45.1", "https://registry.npmmirror.com/drizzle-orm/-/drizzle-orm-0.45.1.tgz", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-Te0FOdKIistGNPMq2jscdqngBRfBpC8uMFVwqjf6gtTVJHIQ/dosgV/CLBU2N4ZJBsXL5savCba9b0YJskKdcA=="],
|
||||
|
||||
"drizzle-typebox": ["drizzle-typebox@0.3.3", "https://registry.npmmirror.com/drizzle-typebox/-/drizzle-typebox-0.3.3.tgz", { "peerDependencies": { "@sinclair/typebox": ">=0.34.8", "drizzle-orm": ">=0.36.0" } }, "sha512-iJpW9K+BaP8+s/ImHxOFVjoZk9G5N/KXFTOpWcFdz9SugAOWv2fyGaH7FmqgdPo+bVNYQW0OOI3U9dkFIVY41w=="],
|
||||
|
||||
"drizzle-zod": ["drizzle-zod@0.8.3", "https://registry.npmmirror.com/drizzle-zod/-/drizzle-zod-0.8.3.tgz", { "peerDependencies": { "drizzle-orm": ">=0.36.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-66yVOuvGhKJnTdiqj1/Xaaz9/qzOdRJADpDa68enqS6g3t0kpNkwNYjUuaeXgZfO/UWuIM9HIhSlJ6C5ZraMww=="],
|
||||
|
||||
"elysia": ["elysia@1.4.22", "https://registry.npmmirror.com/elysia/-/elysia-1.4.22.tgz", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.6", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-Q90VCb1RVFxnFaRV0FDoSylESQQLWgLHFmWciQJdX9h3b2cSasji9KWEUvaJuy/L9ciAGg4RAhUVfsXHg5K2RQ=="],
|
||||
|
||||
"esbuild": ["esbuild@0.25.12", "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
|
||||
|
||||
"esbuild-register": ["esbuild-register@3.6.0", "https://registry.npmmirror.com/esbuild-register/-/esbuild-register-3.6.0.tgz", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
|
||||
|
||||
"exact-mirror": ["exact-mirror@0.2.6", "https://registry.npmmirror.com/exact-mirror/-/exact-mirror-0.2.6.tgz", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-7s059UIx9/tnOKSySzUk5cPGkoILhTE4p6ncf6uIPaQ+9aRBQzQjc9+q85l51+oZ+P6aBxh084pD0CzBQPcFUA=="],
|
||||
|
||||
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "https://registry.npmmirror.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
|
||||
|
||||
"file-type": ["file-type@21.3.0", "https://registry.npmmirror.com/file-type/-/file-type-21.3.0.tgz", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"get-tsconfig": ["get-tsconfig@4.13.0", "https://registry.npmmirror.com/get-tsconfig/-/get-tsconfig-4.13.0.tgz", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"jose": ["jose@6.1.3", "https://registry.npmmirror.com/jose/-/jose-6.1.3.tgz", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="],
|
||||
|
||||
"memoirist": ["memoirist@0.4.0", "https://registry.npmmirror.com/memoirist/-/memoirist-0.4.0.tgz", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"openapi-types": ["openapi-types@12.1.3", "https://registry.npmmirror.com/openapi-types/-/openapi-types-12.1.3.tgz", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
|
||||
|
||||
"pg": ["pg@8.17.1", "https://registry.npmmirror.com/pg/-/pg-8.17.1.tgz", { "dependencies": { "pg-connection-string": "^2.10.0", "pg-pool": "^3.11.0", "pg-protocol": "^1.11.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-EIR+jXdYNSMOrpRp7g6WgQr7SaZNZfS7IzZIO0oTNEeibq956JxeD15t3Jk3zZH0KH8DmOIx38qJfQenoE8bXQ=="],
|
||||
|
||||
"pg-cloudflare": ["pg-cloudflare@1.3.0", "https://registry.npmmirror.com/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="],
|
||||
|
||||
"pg-connection-string": ["pg-connection-string@2.10.0", "https://registry.npmmirror.com/pg-connection-string/-/pg-connection-string-2.10.0.tgz", {}, "sha512-ur/eoPKzDx2IjPaYyXS6Y8NSblxM7X64deV2ObV57vhjsWiwLvUD6meukAzogiOsu60GO8m/3Cb6FdJsWNjwXg=="],
|
||||
|
||||
"pg-int8": ["pg-int8@1.0.1", "https://registry.npmmirror.com/pg-int8/-/pg-int8-1.0.1.tgz", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
||||
|
||||
"pg-pool": ["pg-pool@3.11.0", "https://registry.npmmirror.com/pg-pool/-/pg-pool-3.11.0.tgz", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w=="],
|
||||
|
||||
"pg-protocol": ["pg-protocol@1.11.0", "https://registry.npmmirror.com/pg-protocol/-/pg-protocol-1.11.0.tgz", {}, "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g=="],
|
||||
|
||||
"pg-types": ["pg-types@2.2.0", "https://registry.npmmirror.com/pg-types/-/pg-types-2.2.0.tgz", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"pgpass": ["pgpass@1.0.5", "https://registry.npmmirror.com/pgpass/-/pgpass-1.0.5.tgz", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="],
|
||||
|
||||
"postgres-array": ["postgres-array@2.0.0", "https://registry.npmmirror.com/postgres-array/-/postgres-array-2.0.0.tgz", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"postgres-bytea": ["postgres-bytea@1.0.1", "https://registry.npmmirror.com/postgres-bytea/-/postgres-bytea-1.0.1.tgz", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
|
||||
"postgres-date": ["postgres-date@1.0.7", "https://registry.npmmirror.com/postgres-date/-/postgres-date-1.0.7.tgz", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"postgres-interval": ["postgres-interval@1.2.0", "https://registry.npmmirror.com/postgres-interval/-/postgres-interval-1.2.0.tgz", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "https://registry.npmmirror.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
|
||||
|
||||
"source-map": ["source-map@0.6.1", "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"source-map-support": ["source-map-support@0.5.21", "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
|
||||
|
||||
"split2": ["split2@4.2.0", "https://registry.npmmirror.com/split2/-/split2-4.2.0.tgz", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
||||
|
||||
"strtok3": ["strtok3@10.3.4", "https://registry.npmmirror.com/strtok3/-/strtok3-10.3.4.tgz", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
|
||||
|
||||
"token-types": ["token-types@6.1.2", "https://registry.npmmirror.com/token-types/-/token-types-6.1.2.tgz", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="],
|
||||
|
||||
"tsx": ["tsx@4.21.0", "https://registry.npmmirror.com/tsx/-/tsx-4.21.0.tgz", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
|
||||
|
||||
"uint8array-extras": ["uint8array-extras@1.5.0", "https://registry.npmmirror.com/uint8array-extras/-/uint8array-extras-1.5.0.tgz", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "https://registry.npmmirror.com/undici-types/-/undici-types-7.16.0.tgz", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"xtend": ["xtend@4.0.2", "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
|
||||
|
||||
"zod": ["zod@4.3.5", "https://registry.npmmirror.com/zod/-/zod-4.3.5.tgz", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "https://registry.npmmirror.com/esbuild/-/esbuild-0.18.20.tgz", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
||||
|
||||
"tsx/esbuild": ["esbuild@0.27.2", "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.2.tgz", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.2.tgz", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.2.tgz", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="],
|
||||
}
|
||||
}
|
||||
|
||||
11
drizzle.config.ts
Normal file
11
drizzle.config.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import "dotenv/config";
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
export default defineConfig({
|
||||
out: "./drizzle",
|
||||
schema: "./src/modules/index.ts",
|
||||
dialect: "postgresql",
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!,
|
||||
},
|
||||
});
|
||||
67
drizzle/0000_stormy_falcon.sql
Normal file
67
drizzle/0000_stormy_falcon.sql
Normal file
@ -0,0 +1,67 @@
|
||||
CREATE TABLE "department" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" varchar NOT NULL,
|
||||
"hospital" uuid NOT NULL,
|
||||
"description" varchar,
|
||||
"isActive" boolean DEFAULT true NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "doctor" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" varchar NOT NULL,
|
||||
"username" varchar NOT NULL,
|
||||
"password" varchar NOT NULL,
|
||||
"phone" varchar NOT NULL,
|
||||
"hospitalId" uuid NOT NULL,
|
||||
"departmentId" uuid,
|
||||
"groupId" uuid,
|
||||
"roleId" uuid NOT NULL,
|
||||
"isDoctor" boolean DEFAULT true NOT NULL,
|
||||
"isActive" boolean DEFAULT true NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "doctor_username_unique" UNIQUE("username")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "group" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" varchar NOT NULL,
|
||||
"departmentId" uuid NOT NULL,
|
||||
"description" varchar,
|
||||
"isActive" boolean DEFAULT true NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "hospital" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" varchar NOT NULL,
|
||||
"description" text,
|
||||
"isActive" boolean DEFAULT true NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "patient" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" varchar NOT NULL,
|
||||
"chiefDoctorId" uuid NOT NULL,
|
||||
"sharedWith" text,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "role" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" varchar NOT NULL,
|
||||
"code" varchar NOT NULL,
|
||||
"description" text,
|
||||
"permissions" text,
|
||||
"isActive" boolean DEFAULT true NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "role_name_unique" UNIQUE("name"),
|
||||
CONSTRAINT "role_code_unique" UNIQUE("code")
|
||||
);
|
||||
426
drizzle/meta/0000_snapshot.json
Normal file
426
drizzle/meta/0000_snapshot.json
Normal file
@ -0,0 +1,426 @@
|
||||
{
|
||||
"id": "89cec236-6382-4cab-b163-f1fbd0cfdddb",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"public.department": {
|
||||
"name": "department",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"hospital": {
|
||||
"name": "hospital",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"isActive": {
|
||||
"name": "isActive",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.doctor": {
|
||||
"name": "doctor",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"username": {
|
||||
"name": "username",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"password": {
|
||||
"name": "password",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"phone": {
|
||||
"name": "phone",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"hospitalId": {
|
||||
"name": "hospitalId",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"departmentId": {
|
||||
"name": "departmentId",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"groupId": {
|
||||
"name": "groupId",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"roleId": {
|
||||
"name": "roleId",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"isDoctor": {
|
||||
"name": "isDoctor",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"isActive": {
|
||||
"name": "isActive",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"doctor_username_unique": {
|
||||
"name": "doctor_username_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"username"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.group": {
|
||||
"name": "group",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"departmentId": {
|
||||
"name": "departmentId",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"isActive": {
|
||||
"name": "isActive",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.hospital": {
|
||||
"name": "hospital",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"isActive": {
|
||||
"name": "isActive",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.patient": {
|
||||
"name": "patient",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"chiefDoctorId": {
|
||||
"name": "chiefDoctorId",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"sharedWith": {
|
||||
"name": "sharedWith",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.role": {
|
||||
"name": "role",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"code": {
|
||||
"name": "code",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"permissions": {
|
||||
"name": "permissions",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"isActive": {
|
||||
"name": "isActive",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"role_name_unique": {
|
||||
"name": "role_name_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"role_code_unique": {
|
||||
"name": "role_code_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
"schemas": {},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
13
drizzle/meta/_journal.json
Normal file
13
drizzle/meta/_journal.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1768760286048,
|
||||
"tag": "0000_stormy_falcon",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
16
package.json
16
package.json
@ -6,10 +6,22 @@
|
||||
"dev": "bun run --watch src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"elysia": "latest"
|
||||
"@elysiajs/cors": "^1.4.1",
|
||||
"@elysiajs/eden": "^1.4.6",
|
||||
"@elysiajs/jwt": "^1.4.0",
|
||||
"@sinclair/typebox": "^0.34.47",
|
||||
"dotenv": "^17.2.3",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
"drizzle-typebox": "^0.3.3",
|
||||
"drizzle-zod": "^0.8.3",
|
||||
"elysia": "^1.4.22",
|
||||
"pg": "^8.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "latest"
|
||||
"@types/pg": "^8.16.0",
|
||||
"bun-types": "latest",
|
||||
"drizzle-kit": "^0.31.8",
|
||||
"tsx": "^4.21.0"
|
||||
},
|
||||
"module": "src/index.js"
|
||||
}
|
||||
|
||||
93
seed.ts
Normal file
93
seed.ts
Normal file
@ -0,0 +1,93 @@
|
||||
import { db } from "./src/index";
|
||||
import { roleTable } from "./src/modules";
|
||||
|
||||
const roles = [
|
||||
{
|
||||
name: "超级管理员",
|
||||
code: "ADMIN",
|
||||
description: "平台最高管理员,拥有所有权限",
|
||||
permissions: JSON.stringify([
|
||||
"view_all",
|
||||
"manage_all",
|
||||
"view_hospitals",
|
||||
"manage_hospitals",
|
||||
"view_departments",
|
||||
"manage_departments",
|
||||
"view_groups",
|
||||
"manage_groups",
|
||||
"view_doctors",
|
||||
"manage_doctors",
|
||||
"view_patients",
|
||||
"manage_patients",
|
||||
"view_roles",
|
||||
"manage_roles",
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "普通医生",
|
||||
code: "DOCTOR",
|
||||
description: "可以查看和管理自己的患者",
|
||||
permissions: JSON.stringify(["view_own_patients", "manage_own_patients"]),
|
||||
},
|
||||
{
|
||||
name: "组长",
|
||||
code: "GROUP_LEADER",
|
||||
description: "可以查看和管理小组内所有医生的患者",
|
||||
permissions: JSON.stringify([
|
||||
"view_own_patients",
|
||||
"manage_own_patients",
|
||||
"view_group_patients",
|
||||
"manage_group_patients",
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "科室主任",
|
||||
code: "DIRECTOR",
|
||||
description: "可以查看和管理科室内所有医生的患者",
|
||||
permissions: JSON.stringify([
|
||||
"view_own_patients",
|
||||
"manage_own_patients",
|
||||
"view_group_patients",
|
||||
"manage_group_patients",
|
||||
"view_department_patients",
|
||||
"manage_department_patients",
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "工程师",
|
||||
code: "ENGINEER",
|
||||
description: "可以接收和处理调压任务",
|
||||
permissions: JSON.stringify([
|
||||
"view_tasks",
|
||||
"accept_tasks",
|
||||
"cancel_tasks",
|
||||
"update_tasks",
|
||||
]),
|
||||
},
|
||||
];
|
||||
|
||||
async function seed() {
|
||||
console.log("开始插入角色数据...");
|
||||
|
||||
for (const role of roles) {
|
||||
try {
|
||||
const existing = await db.query.roleTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.code, role.code),
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
await db.insert(roleTable).values(role);
|
||||
console.log(`✓ 创建角色: ${role.name}`);
|
||||
} else {
|
||||
console.log(`- 角色已存在: ${role.name}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`✗ 创建角色失败: ${role.name}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("角色数据插入完成!");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
seed();
|
||||
60
src/controllers/auth.ts
Normal file
60
src/controllers/auth.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../index";
|
||||
import { doctorTable } from "../modules";
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
// 登录
|
||||
export const login = async ({
|
||||
body,
|
||||
}: {
|
||||
body: {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
}) => {
|
||||
const { username, password } = body;
|
||||
|
||||
// 查找医生
|
||||
const doctor = await db.query.doctorTable.findFirst({
|
||||
with: {
|
||||
role: true,
|
||||
hospital: true,
|
||||
},
|
||||
where: (table, { eq }) => eq(table.username, username),
|
||||
});
|
||||
|
||||
if (!doctor) {
|
||||
throw new Error("用户名或密码错误");
|
||||
}
|
||||
|
||||
// 验证密码(实际项目中应该使用加密密码)
|
||||
if (doctor.password !== password) {
|
||||
throw new Error("用户名或密码错误");
|
||||
}
|
||||
|
||||
if (!doctor.isActive) {
|
||||
throw new Error("账号已被禁用");
|
||||
}
|
||||
|
||||
// 返回医生信息(不包含密码)
|
||||
const { password: _, ...doctorWithoutPassword } = doctor;
|
||||
return doctorWithoutPassword;
|
||||
};
|
||||
|
||||
// 获取当前用户信息
|
||||
export const me = async ({ doctorId }: { doctorId: string }) => {
|
||||
const doctor = await db.query.doctorTable.findFirst({
|
||||
with: {
|
||||
role: true,
|
||||
hospital: true,
|
||||
},
|
||||
where: (table, { eq }) => eq(table.id, doctorId),
|
||||
});
|
||||
|
||||
if (!doctor) {
|
||||
throw new Error("用户不存在");
|
||||
}
|
||||
|
||||
const { password: _, ...doctorWithoutPassword } = doctor;
|
||||
return doctorWithoutPassword;
|
||||
};
|
||||
85
src/controllers/department.ts
Normal file
85
src/controllers/department.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../index";
|
||||
import { departmentTable } from "../modules";
|
||||
|
||||
// 获取科室列表
|
||||
export const list = async () => {
|
||||
const departments = await db.query.departmentTable.findMany({
|
||||
with: {
|
||||
hospital: true,
|
||||
},
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
return departments;
|
||||
};
|
||||
|
||||
// 获取单个科室
|
||||
export const one = async ({ params }: { params: { id: string } }) => {
|
||||
const department = await db.query.departmentTable.findFirst({
|
||||
with: {
|
||||
hospital: true,
|
||||
},
|
||||
where: (table, { eq }) => eq(table.id, params.id),
|
||||
});
|
||||
if (!department) {
|
||||
throw new Error("科室不存在");
|
||||
}
|
||||
return department;
|
||||
};
|
||||
|
||||
// 创建科室
|
||||
export const create = async ({
|
||||
body,
|
||||
}: {
|
||||
body: {
|
||||
name: string;
|
||||
hospital: string;
|
||||
description?: string;
|
||||
};
|
||||
}) => {
|
||||
// 判断医院是否存在
|
||||
const isHospital = await db.query.hospitalTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.hospital),
|
||||
});
|
||||
if (!isHospital) {
|
||||
throw new Error("所属医院不存在");
|
||||
}
|
||||
const department = await db.insert(departmentTable).values(body).returning();
|
||||
return department[0];
|
||||
};
|
||||
|
||||
// 更新科室
|
||||
export const update = async ({
|
||||
params,
|
||||
body,
|
||||
}: {
|
||||
params: { id: string };
|
||||
body: {
|
||||
name?: string;
|
||||
hospital?: string;
|
||||
description?: string;
|
||||
isActive?: boolean;
|
||||
};
|
||||
}) => {
|
||||
const department = await db
|
||||
.update(departmentTable)
|
||||
.set({ ...body, updatedAt: new Date() })
|
||||
.where(eq(departmentTable.id, params.id))
|
||||
.returning();
|
||||
if (!department) {
|
||||
throw new Error("科室不存在");
|
||||
}
|
||||
return department;
|
||||
};
|
||||
|
||||
// 删除科室
|
||||
export const remove = async ({ params }: { params: { id: string } }) => {
|
||||
const department = await db
|
||||
.delete(departmentTable)
|
||||
.where(eq(departmentTable.id, params.id))
|
||||
.returning();
|
||||
if (!department || department.length === 0) {
|
||||
throw new Error("科室不存在");
|
||||
}
|
||||
return department[0];
|
||||
};
|
||||
186
src/controllers/doctor.ts
Normal file
186
src/controllers/doctor.ts
Normal file
@ -0,0 +1,186 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../index";
|
||||
import { doctorTable } from "../modules";
|
||||
|
||||
// 获取医生列表
|
||||
export const list = async () => {
|
||||
const doctors = await db.query.doctorTable.findMany({
|
||||
with: {
|
||||
hospital: true,
|
||||
role: true,
|
||||
},
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
return doctors;
|
||||
};
|
||||
|
||||
// 获取单个医生
|
||||
export const one = async ({ params }: { params: { id: string } }) => {
|
||||
const doctor = await db.query.doctorTable.findFirst({
|
||||
with: {
|
||||
hospital: true,
|
||||
role: true,
|
||||
},
|
||||
where: (table, { eq }) => eq(table.id, params.id),
|
||||
});
|
||||
if (!doctor) {
|
||||
throw new Error("医生不存在");
|
||||
}
|
||||
return doctor;
|
||||
};
|
||||
|
||||
// 创建医生
|
||||
export const create = async ({
|
||||
body,
|
||||
}: {
|
||||
body: {
|
||||
name: string;
|
||||
username: string;
|
||||
password: string;
|
||||
phone: string;
|
||||
hospitalId?: string;
|
||||
departmentId?: string;
|
||||
groupId?: string;
|
||||
roleId?: string;
|
||||
isDoctor?: boolean;
|
||||
};
|
||||
}) => {
|
||||
// 验证医院是否存在(如果提供了医院ID)
|
||||
if (body.hospitalId) {
|
||||
const hospital = await db.query.hospitalTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.hospitalId!),
|
||||
});
|
||||
if (!hospital) {
|
||||
throw new Error("所属医院不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 验证科室是否存在(如果提供了科室ID)
|
||||
if (body.departmentId) {
|
||||
const department = await db.query.departmentTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.departmentId!),
|
||||
});
|
||||
if (!department) {
|
||||
throw new Error("所属科室不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 验证小组是否存在(如果提供了小组ID)
|
||||
if (body.groupId) {
|
||||
const group = await db.query.groupTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.groupId!),
|
||||
});
|
||||
if (!group) {
|
||||
throw new Error("所属小组不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 验证角色是否存在(如果提供了角色ID)
|
||||
if (body.roleId) {
|
||||
const role = await db.query.roleTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.roleId!),
|
||||
});
|
||||
if (!role) {
|
||||
throw new Error("角色不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 构建插入数据,只包含提供的字段
|
||||
const insertData: any = {
|
||||
name: body.name,
|
||||
username: body.username,
|
||||
password: body.password,
|
||||
phone: body.phone,
|
||||
};
|
||||
|
||||
if (body.hospitalId) insertData.hospitalId = body.hospitalId;
|
||||
if (body.departmentId) insertData.departmentId = body.departmentId;
|
||||
if (body.groupId) insertData.groupId = body.groupId;
|
||||
if (body.roleId) insertData.roleId = body.roleId;
|
||||
if (body.isDoctor !== undefined) insertData.isDoctor = body.isDoctor;
|
||||
|
||||
const doctor = await db.insert(doctorTable).values(insertData).returning();
|
||||
return doctor[0];
|
||||
};
|
||||
|
||||
// 更新医生
|
||||
export const update = async ({
|
||||
params,
|
||||
body,
|
||||
}: {
|
||||
params: { id: string };
|
||||
body: {
|
||||
name?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
phone?: string;
|
||||
hospitalId?: string;
|
||||
departmentId?: string;
|
||||
groupId?: string;
|
||||
roleId?: string;
|
||||
isDoctor?: boolean;
|
||||
isActive?: boolean;
|
||||
};
|
||||
}) => {
|
||||
// 如果要更新医院ID,验证医院是否存在
|
||||
if (body.hospitalId) {
|
||||
const hospital = await db.query.hospitalTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.hospitalId!),
|
||||
});
|
||||
if (!hospital) {
|
||||
throw new Error("所属医院不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果要更新科室ID,验证科室是否存在
|
||||
if (body.departmentId) {
|
||||
const department = await db.query.departmentTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.departmentId!),
|
||||
});
|
||||
if (!department) {
|
||||
throw new Error("所属科室不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果要更新小组ID,验证小组是否存在
|
||||
if (body.groupId) {
|
||||
const group = await db.query.groupTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.groupId!),
|
||||
});
|
||||
if (!group) {
|
||||
throw new Error("所属小组不存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果要更新角色ID,验证角色是否存在
|
||||
if (body.roleId) {
|
||||
const role = await db.query.roleTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.roleId!),
|
||||
});
|
||||
if (!role) {
|
||||
throw new Error("角色不存在");
|
||||
}
|
||||
}
|
||||
|
||||
const doctor = await db
|
||||
.update(doctorTable)
|
||||
.set({ ...body, updatedAt: new Date() })
|
||||
.where(eq(doctorTable.id, params.id))
|
||||
.returning();
|
||||
if (!doctor || doctor.length === 0) {
|
||||
throw new Error("医生不存在");
|
||||
}
|
||||
return doctor[0];
|
||||
};
|
||||
|
||||
// 删除医生
|
||||
export const remove = async ({ params }: { params: { id: string } }) => {
|
||||
const doctor = await db
|
||||
.delete(doctorTable)
|
||||
.where(eq(doctorTable.id, params.id))
|
||||
.returning();
|
||||
if (!doctor || doctor.length === 0) {
|
||||
throw new Error("医生不存在");
|
||||
}
|
||||
return doctor[0];
|
||||
};
|
||||
94
src/controllers/group.ts
Normal file
94
src/controllers/group.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../index";
|
||||
import { groupTable } from "../modules";
|
||||
|
||||
// 获取小组列表
|
||||
export const list = async () => {
|
||||
const groups = await db.query.groupTable.findMany({
|
||||
with: {
|
||||
department: true,
|
||||
},
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
return groups;
|
||||
};
|
||||
|
||||
// 获取单个小组
|
||||
export const one = async ({ params }: { params: { id: string } }) => {
|
||||
const group = await db.query.groupTable.findFirst({
|
||||
with: {
|
||||
department: true,
|
||||
},
|
||||
where: (table, { eq }) => eq(table.id, params.id),
|
||||
});
|
||||
if (!group) {
|
||||
throw new Error("小组不存在");
|
||||
}
|
||||
return group;
|
||||
};
|
||||
|
||||
// 创建小组
|
||||
export const create = async ({
|
||||
body,
|
||||
}: {
|
||||
body: {
|
||||
name: string;
|
||||
departmentId: string;
|
||||
description?: string;
|
||||
};
|
||||
}) => {
|
||||
// 判断科室是否存在
|
||||
const isDepartment = await db.query.departmentTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.departmentId),
|
||||
});
|
||||
if (!isDepartment) {
|
||||
throw new Error("所属科室不存在");
|
||||
}
|
||||
const group = await db.insert(groupTable).values(body).returning();
|
||||
return group[0];
|
||||
};
|
||||
|
||||
// 更新小组
|
||||
export const update = async ({
|
||||
params,
|
||||
body,
|
||||
}: {
|
||||
params: { id: string };
|
||||
body: {
|
||||
name?: string;
|
||||
departmentId?: string;
|
||||
description?: string;
|
||||
isActive?: boolean;
|
||||
};
|
||||
}) => {
|
||||
// 如果要更新科室ID,判断科室是否存在
|
||||
if (body.departmentId) {
|
||||
const isDepartment = await db.query.departmentTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.departmentId!),
|
||||
});
|
||||
if (!isDepartment) {
|
||||
throw new Error("所属科室不存在");
|
||||
}
|
||||
}
|
||||
const group = await db
|
||||
.update(groupTable)
|
||||
.set({ ...body, updatedAt: new Date() })
|
||||
.where(eq(groupTable.id, params.id))
|
||||
.returning();
|
||||
if (!group) {
|
||||
throw new Error("小组不存在");
|
||||
}
|
||||
return group;
|
||||
};
|
||||
|
||||
// 删除小组
|
||||
export const remove = async ({ params }: { params: { id: string } }) => {
|
||||
const group = await db
|
||||
.delete(groupTable)
|
||||
.where(eq(groupTable.id, params.id))
|
||||
.returning();
|
||||
if (!group || group.length === 0) {
|
||||
throw new Error("小组不存在");
|
||||
}
|
||||
return group[0];
|
||||
};
|
||||
74
src/controllers/hospital.ts
Normal file
74
src/controllers/hospital.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { asc, eq } from "drizzle-orm";
|
||||
import { db } from "../index";
|
||||
import { hospitalTable } from "../modules";
|
||||
|
||||
// 获取医院列表
|
||||
export const list = async () => {
|
||||
// const hospitals = await db
|
||||
// .select()
|
||||
// .from(hospitalTable)
|
||||
// .orderBy(hospitalTable.createdAt);
|
||||
const hospitals = await db.query.hospitalTable.findMany({
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
return hospitals;
|
||||
};
|
||||
|
||||
// 获取单个医院
|
||||
export const one = async ({ params }: { params: { id: string } }) => {
|
||||
const hospital = await db.query.hospitalTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, params.id),
|
||||
});
|
||||
if (!hospital) {
|
||||
throw new Error("医院不存在");
|
||||
}
|
||||
return hospital;
|
||||
};
|
||||
|
||||
// 创建医院
|
||||
export const create = async ({
|
||||
body,
|
||||
}: {
|
||||
body: {
|
||||
name: string;
|
||||
description?: string;
|
||||
};
|
||||
}) => {
|
||||
const hospital = await db.insert(hospitalTable).values(body).returning();
|
||||
return hospital[0];
|
||||
};
|
||||
|
||||
// 更新医院
|
||||
export const update = async ({
|
||||
params,
|
||||
body,
|
||||
}: {
|
||||
params: { id: string };
|
||||
body: {
|
||||
name?: string;
|
||||
description?: string;
|
||||
isActive?: boolean;
|
||||
};
|
||||
}) => {
|
||||
const hospital = await db
|
||||
.update(hospitalTable)
|
||||
.set({ ...body, updatedAt: new Date() })
|
||||
.where(eq(hospitalTable.id, params.id))
|
||||
.returning();
|
||||
if (!hospital) {
|
||||
throw new Error("医院不存在");
|
||||
}
|
||||
return hospital;
|
||||
};
|
||||
|
||||
// 删除医院
|
||||
export const remove = async ({ params }: { params: { id: string } }) => {
|
||||
const hospital = await db
|
||||
.delete(hospitalTable)
|
||||
.where(eq(hospitalTable.id, params.id))
|
||||
.returning();
|
||||
if (!hospital || hospital.length === 0) {
|
||||
throw new Error("医院不存在");
|
||||
}
|
||||
return hospital[0];
|
||||
};
|
||||
335
src/controllers/patient.ts
Normal file
335
src/controllers/patient.ts
Normal file
@ -0,0 +1,335 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../index";
|
||||
import { patientTable } from "../modules";
|
||||
|
||||
// 获取患者列表(带权限过滤)
|
||||
export const list = async ({ doctorId }: { doctorId?: string } = {}) => {
|
||||
if (!doctorId) {
|
||||
// 未登录,返回空
|
||||
return [];
|
||||
}
|
||||
|
||||
// 获取当前医生信息
|
||||
const currentDoctor = await db.query.doctorTable.findFirst({
|
||||
with: {
|
||||
role: true,
|
||||
hospital: true,
|
||||
},
|
||||
where: (table, { eq }) => eq(table.id, doctorId),
|
||||
});
|
||||
|
||||
if (!currentDoctor) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 调试日志
|
||||
console.log("当前医生信息:", {
|
||||
id: currentDoctor.id,
|
||||
name: currentDoctor.name,
|
||||
roleCode: currentDoctor.role?.code,
|
||||
roleName: currentDoctor.role?.name,
|
||||
departmentId: currentDoctor.departmentId,
|
||||
groupId: currentDoctor.groupId,
|
||||
});
|
||||
|
||||
// 超级管理员可以看到所有患者
|
||||
if (currentDoctor.role?.code === "ADMIN") {
|
||||
const patients = await db.query.patientTable.findMany({
|
||||
with: {
|
||||
chiefDoctor: {
|
||||
with: {
|
||||
role: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
return patients;
|
||||
}
|
||||
|
||||
// 科室主任可以看到本科室所有医生的患者 + 分享给自己的患者
|
||||
if (currentDoctor.role?.code === "DIRECTOR" && currentDoctor.departmentId) {
|
||||
// 获取本科室所有医生
|
||||
const departmentDoctors = await db.query.doctorTable.findMany({
|
||||
where: (table, { eq }) => eq(table.departmentId, currentDoctor.departmentId!),
|
||||
});
|
||||
const doctorIds = departmentDoctors.map((d) => d.id);
|
||||
|
||||
if (doctorIds.length === 0) return [];
|
||||
|
||||
// 获取本科室所有医生创建的患者
|
||||
const allPatients = await db.query.patientTable.findMany({
|
||||
with: {
|
||||
chiefDoctor: {
|
||||
with: {
|
||||
role: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
|
||||
// 过滤出本科室医生创建的患者 + 分享给自己的患者
|
||||
const filteredPatients = allPatients.filter((patient: any) => {
|
||||
// 本科室医生创建的患者
|
||||
if (doctorIds.includes(patient.chiefDoctorId)) return true;
|
||||
|
||||
// 分享给自己的患者
|
||||
if (patient.sharedWith) {
|
||||
try {
|
||||
const sharedWith = JSON.parse(patient.sharedWith);
|
||||
return sharedWith.includes(doctorId);
|
||||
} catch (error) {
|
||||
console.error("解析 sharedWith 失败:", patient.sharedWith, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
console.log("科室主任看到的患者数量:", {
|
||||
total: allPatients.length,
|
||||
filtered: filteredPatients.length,
|
||||
doctorId,
|
||||
departmentId: currentDoctor.departmentId,
|
||||
});
|
||||
|
||||
return filteredPatients;
|
||||
}
|
||||
|
||||
// 组长可以看到本小组所有医生的患者 + 分享给自己的患者
|
||||
if (currentDoctor.role?.code === "GROUP_LEADER" && currentDoctor.groupId) {
|
||||
// 获取本小组所有医生
|
||||
const groupDoctors = await db.query.doctorTable.findMany({
|
||||
where: (table, { eq }) => eq(table.groupId, currentDoctor.groupId!),
|
||||
});
|
||||
const doctorIds = groupDoctors.map((d) => d.id);
|
||||
|
||||
if (doctorIds.length === 0) return [];
|
||||
|
||||
// 获取本小组所有医生创建的患者
|
||||
const allPatients = await db.query.patientTable.findMany({
|
||||
with: {
|
||||
chiefDoctor: {
|
||||
with: {
|
||||
role: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
|
||||
// 过滤出本小组医生创建的患者 + 分享给自己的患者
|
||||
const filteredPatients = allPatients.filter((patient: any) => {
|
||||
// 本小组医生创建的患者
|
||||
if (doctorIds.includes(patient.chiefDoctorId)) return true;
|
||||
|
||||
// 分享给自己的患者
|
||||
if (patient.sharedWith) {
|
||||
try {
|
||||
const sharedWith = JSON.parse(patient.sharedWith);
|
||||
return sharedWith.includes(doctorId);
|
||||
} catch (error) {
|
||||
console.error("解析 sharedWith 失败:", patient.sharedWith, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
console.log("组长看到的患者数量:", {
|
||||
total: allPatients.length,
|
||||
filtered: filteredPatients.length,
|
||||
doctorId,
|
||||
groupId: currentDoctor.groupId,
|
||||
});
|
||||
|
||||
return filteredPatients;
|
||||
}
|
||||
|
||||
// 普通医生只能看到自己的患者 + 分享给自己的患者
|
||||
const allPatients = await db.query.patientTable.findMany({
|
||||
with: {
|
||||
chiefDoctor: {
|
||||
with: {
|
||||
role: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
|
||||
// 过滤出分享给自己的患者
|
||||
const filteredPatients = allPatients.filter((patient: any) => {
|
||||
// 自己创建的患者
|
||||
if (patient.chiefDoctorId === doctorId) return true;
|
||||
|
||||
// 分享给自己的患者
|
||||
if (patient.sharedWith) {
|
||||
try {
|
||||
const sharedWith = JSON.parse(patient.sharedWith);
|
||||
return sharedWith.includes(doctorId);
|
||||
} catch (error) {
|
||||
console.error("解析 sharedWith 失败:", patient.sharedWith, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
console.log("普通医生看到的患者数量:", {
|
||||
total: allPatients.length,
|
||||
filtered: filteredPatients.length,
|
||||
doctorId,
|
||||
});
|
||||
|
||||
return filteredPatients;
|
||||
};
|
||||
|
||||
// 获取单个患者
|
||||
export const one = async ({ params }: { params: { id: string } }) => {
|
||||
const patient = await db.query.patientTable.findFirst({
|
||||
with: {
|
||||
chiefDoctor: {
|
||||
with: {
|
||||
role: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
where: (table, { eq }) => eq(table.id, params.id),
|
||||
});
|
||||
if (!patient) {
|
||||
throw new Error("患者不存在");
|
||||
}
|
||||
return patient;
|
||||
};
|
||||
|
||||
// 创建患者
|
||||
export const create = async ({
|
||||
body,
|
||||
}: {
|
||||
body: {
|
||||
name: string;
|
||||
chiefDoctorId: string;
|
||||
};
|
||||
}) => {
|
||||
// 验证医生是否存在
|
||||
const doctor = await db.query.doctorTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.chiefDoctorId),
|
||||
});
|
||||
if (!doctor) {
|
||||
throw new Error("主刀医生不存在");
|
||||
}
|
||||
|
||||
const patient = await db.insert(patientTable).values(body).returning();
|
||||
return patient[0];
|
||||
};
|
||||
|
||||
// 更新患者
|
||||
export const update = async ({
|
||||
params,
|
||||
body,
|
||||
}: {
|
||||
params: { id: string };
|
||||
body: {
|
||||
name?: string;
|
||||
chiefDoctorId?: string;
|
||||
};
|
||||
}) => {
|
||||
// 如果要更新医生ID,验证医生是否存在
|
||||
if (body.chiefDoctorId) {
|
||||
const doctor = await db.query.doctorTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, body.chiefDoctorId!),
|
||||
});
|
||||
if (!doctor) {
|
||||
throw new Error("主刀医生不存在");
|
||||
}
|
||||
}
|
||||
|
||||
const patient = await db
|
||||
.update(patientTable)
|
||||
.set({ ...body, updatedAt: new Date() })
|
||||
.where(eq(patientTable.id, params.id))
|
||||
.returning();
|
||||
if (!patient || patient.length === 0) {
|
||||
throw new Error("患者不存在");
|
||||
}
|
||||
return patient[0];
|
||||
};
|
||||
|
||||
// 删除患者
|
||||
export const remove = async ({ params }: { params: { id: string } }) => {
|
||||
const patient = await db
|
||||
.delete(patientTable)
|
||||
.where(eq(patientTable.id, params.id))
|
||||
.returning();
|
||||
if (!patient || patient.length === 0) {
|
||||
throw new Error("患者不存在");
|
||||
}
|
||||
return patient[0];
|
||||
};
|
||||
|
||||
// 分享患者给其他医生
|
||||
export const share = async ({
|
||||
params,
|
||||
body,
|
||||
currentDoctorId,
|
||||
}: {
|
||||
params: { id: string };
|
||||
body: { sharedWith: string[] };
|
||||
currentDoctorId?: string;
|
||||
}) => {
|
||||
// 获取患者信息
|
||||
const patient = await db.query.patientTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, params.id),
|
||||
with: {
|
||||
chiefDoctor: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!patient) {
|
||||
throw new Error("患者不存在");
|
||||
}
|
||||
|
||||
// 验证权限:只有患者的主刀医生才能分享
|
||||
if (patient.chiefDoctorId !== currentDoctorId) {
|
||||
throw new Error("无权限分享此患者");
|
||||
}
|
||||
|
||||
// 验证:只能分享给同医院的医生
|
||||
const currentDoctor = await db.query.doctorTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, currentDoctorId!),
|
||||
});
|
||||
|
||||
if (!currentDoctor) {
|
||||
throw new Error("当前医生不存在");
|
||||
}
|
||||
|
||||
// 验证所有要分享的医生都在同一家医院
|
||||
if (body.sharedWith && body.sharedWith.length > 0) {
|
||||
const targetDoctors = await db.query.doctorTable.findMany({
|
||||
where: (table, { inArray }) => inArray(table.id, body.sharedWith),
|
||||
});
|
||||
|
||||
for (const targetDoctor of targetDoctors) {
|
||||
if (targetDoctor.hospitalId !== currentDoctor.hospitalId) {
|
||||
throw new Error(`只能分享给同医院的医生:${targetDoctor.name} 不在同一家医院`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将分享的医生ID列表转换为JSON字符串存储
|
||||
const updatedPatient = await db
|
||||
.update(patientTable)
|
||||
.set({
|
||||
sharedWith: JSON.stringify(body.sharedWith),
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(eq(patientTable.id, params.id))
|
||||
.returning();
|
||||
|
||||
return updatedPatient[0];
|
||||
};
|
||||
74
src/controllers/role.ts
Normal file
74
src/controllers/role.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../index";
|
||||
import { roleTable } from "../modules";
|
||||
|
||||
// 获取角色列表
|
||||
export const list = async () => {
|
||||
const roles = await db.query.roleTable.findMany({
|
||||
orderBy: (table, { asc }) => asc(table.createdAt),
|
||||
});
|
||||
return roles;
|
||||
};
|
||||
|
||||
// 获取单个角色
|
||||
export const one = async ({ params }: { params: { id: string } }) => {
|
||||
const role = await db.query.roleTable.findFirst({
|
||||
where: (table, { eq }) => eq(table.id, params.id),
|
||||
});
|
||||
if (!role) {
|
||||
throw new Error("角色不存在");
|
||||
}
|
||||
return role;
|
||||
};
|
||||
|
||||
// 创建角色
|
||||
export const create = async ({
|
||||
body,
|
||||
}: {
|
||||
body: {
|
||||
name: string;
|
||||
code: string;
|
||||
description?: string;
|
||||
permissions?: string;
|
||||
};
|
||||
}) => {
|
||||
const role = await db.insert(roleTable).values(body).returning();
|
||||
return role[0];
|
||||
};
|
||||
|
||||
// 更新角色
|
||||
export const update = async ({
|
||||
params,
|
||||
body,
|
||||
}: {
|
||||
params: { id: string };
|
||||
body: {
|
||||
name?: string;
|
||||
code?: string;
|
||||
description?: string;
|
||||
permissions?: string;
|
||||
isActive?: boolean;
|
||||
};
|
||||
}) => {
|
||||
const role = await db
|
||||
.update(roleTable)
|
||||
.set({ ...body, updatedAt: new Date() })
|
||||
.where(eq(roleTable.id, params.id))
|
||||
.returning();
|
||||
if (!role || role.length === 0) {
|
||||
throw new Error("角色不存在");
|
||||
}
|
||||
return role[0];
|
||||
};
|
||||
|
||||
// 删除角色
|
||||
export const remove = async ({ params }: { params: { id: string } }) => {
|
||||
const role = await db
|
||||
.delete(roleTable)
|
||||
.where(eq(roleTable.id, params.id))
|
||||
.returning();
|
||||
if (!role || role.length === 0) {
|
||||
throw new Error("角色不存在");
|
||||
}
|
||||
return role[0];
|
||||
};
|
||||
17
src/index.ts
17
src/index.ts
@ -1,7 +1,16 @@
|
||||
import { Elysia } from "elysia";
|
||||
import { router } from "./routes";
|
||||
import { drizzle } from "drizzle-orm/node-postgres";
|
||||
import { Pool } from "pg";
|
||||
import * as schema from "./modules";
|
||||
import cors from "@elysiajs/cors";
|
||||
|
||||
const app = new Elysia().get("/", () => "Hello Elysia").listen(3000);
|
||||
const pool = new Pool({ connectionString: process.env.DATABASE_URL! });
|
||||
export const db = drizzle(pool, { schema });
|
||||
|
||||
console.log(
|
||||
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
|
||||
);
|
||||
const app = new Elysia({ prefix: "/api" }).use(router);
|
||||
|
||||
app.use(cors());
|
||||
app.listen(3000);
|
||||
|
||||
export type Api = typeof app;
|
||||
|
||||
24
src/middleware/permission.ts
Normal file
24
src/middleware/permission.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../index";
|
||||
import { doctorTable } from "../modules";
|
||||
|
||||
// 获取当前请求的医生ID
|
||||
export const getDoctorId = async (token: string) => {
|
||||
// 这里应该验证JWT token,暂时简化处理
|
||||
// 实际应该从JWT payload中提取doctorId
|
||||
const jwt = (await import("@elysiajs/jwt")).jwt;
|
||||
|
||||
return token;
|
||||
};
|
||||
|
||||
// 检查医生权限
|
||||
export const checkPermission = (doctor: any, requiredPermission: string) => {
|
||||
if (!doctor.role) return false;
|
||||
|
||||
// 超级管理员拥有所有权限
|
||||
if (doctor.role.code === "ADMIN") return true;
|
||||
|
||||
// 解析角色权限
|
||||
const permissions = JSON.parse(doctor.role.permissions || "[]");
|
||||
return permissions.includes(requiredPermission);
|
||||
};
|
||||
11
src/modules/department.ts
Normal file
11
src/modules/department.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { uuid, varchar, timestamp, boolean } from "drizzle-orm/pg-core";
|
||||
|
||||
export const Department = {
|
||||
id: uuid().primaryKey().defaultRandom(), // 主键,UUID
|
||||
name: varchar().notNull(), // 科室名称
|
||||
hospital: uuid().notNull(), // 所属医院
|
||||
description: varchar(), // 科室描述
|
||||
isActive: boolean().notNull().default(true), // 是否启用
|
||||
createdAt: timestamp().notNull().defaultNow(), // 创建时间
|
||||
updatedAt: timestamp().notNull().defaultNow(), // 更新时间
|
||||
};
|
||||
18
src/modules/doctor.ts
Normal file
18
src/modules/doctor.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { uuid, varchar, timestamp, boolean } from "drizzle-orm/pg-core";
|
||||
|
||||
export const Doctor = {
|
||||
id: uuid().primaryKey().defaultRandom(), // 主键,UUID
|
||||
name: varchar().notNull(), // 医生姓名
|
||||
username: varchar().notNull().unique(), // 医生用户名,唯一标识
|
||||
password: varchar().notNull(), // 医生密码,建议加密存储
|
||||
// wechatOpenId: varchar().notNull().unique(), // 微信小程序的唯一标识
|
||||
phone: varchar().notNull(), // 手机号
|
||||
hospitalId: uuid().notNull(), // 所属医院ID(可选,如果有多医院场景)
|
||||
departmentId: uuid(), // 所属科室ID,虚拟外键
|
||||
groupId: uuid(), // 所属小组ID,虚拟外键
|
||||
roleId: uuid().notNull(), // 角色ID,虚拟外键
|
||||
isDoctor: boolean().notNull().default(true), // 是否为医生(false表示管理员)
|
||||
isActive: boolean().notNull().default(true), // 是否启用
|
||||
createdAt: timestamp().notNull().defaultNow(), // 创建时间
|
||||
updatedAt: timestamp().notNull().defaultNow(), // 更新时间
|
||||
};
|
||||
11
src/modules/group.ts
Normal file
11
src/modules/group.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { uuid, varchar, timestamp, boolean } from "drizzle-orm/pg-core";
|
||||
|
||||
export const Group = {
|
||||
id: uuid().primaryKey().defaultRandom(), // 主键,UUID
|
||||
name: varchar().notNull(), // 小组名称
|
||||
departmentId: uuid().notNull(), // 所属科室ID,虚拟外键
|
||||
description: varchar(), // 小组描述
|
||||
isActive: boolean().notNull().default(true), // 是否启用
|
||||
createdAt: timestamp().notNull().defaultNow(), // 创建时间
|
||||
updatedAt: timestamp().notNull().defaultNow(), // 更新时间
|
||||
};
|
||||
10
src/modules/hospital.ts
Normal file
10
src/modules/hospital.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { uuid, varchar, timestamp, boolean, text } from "drizzle-orm/pg-core";
|
||||
|
||||
export const Hospital = {
|
||||
id: uuid().primaryKey().defaultRandom(), // 主键,UUID
|
||||
name: varchar().notNull(), // 医院名称
|
||||
description: text(), // 医院描述
|
||||
isActive: boolean().notNull().default(true), // 是否启用
|
||||
createdAt: timestamp().notNull().defaultNow(), // 创建时间
|
||||
updatedAt: timestamp().notNull().defaultNow(), // 更新时间
|
||||
};
|
||||
58
src/modules/index.ts
Normal file
58
src/modules/index.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { pgTable } from "drizzle-orm/pg-core";
|
||||
import { Doctor } from "./doctor";
|
||||
import { Hospital } from "./hospital";
|
||||
import { Department } from "./department";
|
||||
import { Group } from "./group";
|
||||
import { Role } from "./role";
|
||||
import { Patient } from "./patient";
|
||||
import { relations } from "drizzle-orm";
|
||||
|
||||
export const hospitalTable = pgTable("hospital", Hospital);
|
||||
export const doctorTable = pgTable("doctor", Doctor);
|
||||
export const departmentTable = pgTable("department", Department);
|
||||
export const groupTable = pgTable("group", Group);
|
||||
export const roleTable = pgTable("role", Role);
|
||||
export const patientTable = pgTable("patient", Patient);
|
||||
|
||||
// 定义关联关系
|
||||
export const hospitalRelations = relations(hospitalTable, ({ many }) => ({
|
||||
departments: many(departmentTable),
|
||||
}));
|
||||
|
||||
export const departmentRelations = relations(departmentTable, ({ one, many }) => ({
|
||||
hospital: one(hospitalTable, {
|
||||
fields: [departmentTable.hospital],
|
||||
references: [hospitalTable.id],
|
||||
}),
|
||||
groups: many(groupTable),
|
||||
}));
|
||||
|
||||
export const groupRelations = relations(groupTable, ({ one }) => ({
|
||||
department: one(departmentTable, {
|
||||
fields: [groupTable.departmentId],
|
||||
references: [departmentTable.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const doctorRelations = relations(doctorTable, ({ one, many }) => ({
|
||||
hospital: one(hospitalTable, {
|
||||
fields: [doctorTable.hospitalId],
|
||||
references: [hospitalTable.id],
|
||||
}),
|
||||
role: one(roleTable, {
|
||||
fields: [doctorTable.roleId],
|
||||
references: [roleTable.id],
|
||||
}),
|
||||
patients: many(patientTable),
|
||||
}));
|
||||
|
||||
export const roleRelations = relations(roleTable, ({ many }) => ({
|
||||
doctors: many(doctorTable),
|
||||
}));
|
||||
|
||||
export const patientRelations = relations(patientTable, ({ one }) => ({
|
||||
chiefDoctor: one(doctorTable, {
|
||||
fields: [patientTable.chiefDoctorId],
|
||||
references: [doctorTable.id],
|
||||
}),
|
||||
}));
|
||||
10
src/modules/patient.ts
Normal file
10
src/modules/patient.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { uuid, varchar, timestamp, text } from "drizzle-orm/pg-core";
|
||||
|
||||
export const Patient = {
|
||||
id: uuid().primaryKey().defaultRandom(), // 主键,UUID
|
||||
name: varchar().notNull(), // 患者姓名
|
||||
chiefDoctorId: uuid().notNull(), // 主刀医生ID,虚拟外键
|
||||
sharedWith: text(), // 分享给其他医生的ID列表,JSON数组格式存储
|
||||
createdAt: timestamp().notNull().defaultNow(), // 创建时间
|
||||
updatedAt: timestamp().notNull().defaultNow(), // 更新时间
|
||||
};
|
||||
12
src/modules/role.ts
Normal file
12
src/modules/role.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { uuid, varchar, timestamp, text, boolean } from "drizzle-orm/pg-core";
|
||||
|
||||
export const Role = {
|
||||
id: uuid().primaryKey().defaultRandom(), // 主键,UUID
|
||||
name: varchar().notNull().unique(), // 角色名称(如:普通医生、组长、科室主任、工程师)
|
||||
code: varchar().notNull().unique(), // 角色代码(如:DOCTOR、GROUP_LEADER、DIRECTOR、ENGINEER)
|
||||
description: text(), // 角色描述
|
||||
permissions: text(), // 权限列表,JSON格式存储,如:["view_own_patients", "view_group_patients", "view_department_patients"]
|
||||
isActive: boolean().notNull().default(true), // 是否启用
|
||||
createdAt: timestamp().notNull().defaultNow(), // 创建时间
|
||||
updatedAt: timestamp().notNull().defaultNow(), // 更新时间
|
||||
};
|
||||
69
src/routes/auth.ts
Normal file
69
src/routes/auth.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { Elysia, t } from "elysia";
|
||||
import { jwt } from "@elysiajs/jwt";
|
||||
import * as authController from "../controllers/auth";
|
||||
|
||||
const authRoutes = new Elysia({ prefix: "/auth" })
|
||||
.post(
|
||||
"/login",
|
||||
async ({ body, set, jwt }) => {
|
||||
const doctor = await authController.login({ body });
|
||||
|
||||
// 生成JWT token
|
||||
const token = await jwt.sign({
|
||||
userId: doctor.id,
|
||||
roleId: doctor.roleId,
|
||||
roleCode: doctor.role?.code,
|
||||
});
|
||||
|
||||
return {
|
||||
token,
|
||||
doctor,
|
||||
};
|
||||
},
|
||||
{
|
||||
body: t.Object({
|
||||
username: t.String(),
|
||||
password: t.String(),
|
||||
}),
|
||||
}
|
||||
)
|
||||
.get(
|
||||
"/me",
|
||||
async ({ doctorId }) => {
|
||||
return await authController.me({ doctorId });
|
||||
},
|
||||
{
|
||||
beforeHandle: [
|
||||
async ({
|
||||
jwt,
|
||||
set,
|
||||
cookie: { auth },
|
||||
headers,
|
||||
}: any) => {
|
||||
// 尝试从 header 或 cookie 获取 token
|
||||
const token = headers.authorization?.replace("Bearer ", "") || auth;
|
||||
|
||||
if (!token) {
|
||||
set.status = 401;
|
||||
return { error: "未登录" };
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = await jwt.verify(token);
|
||||
if (!payload) {
|
||||
set.status = 401;
|
||||
return { error: "Token无效" };
|
||||
}
|
||||
|
||||
// 将用户信息注入到上下文
|
||||
return { doctorId: payload.userId };
|
||||
} catch (error) {
|
||||
set.status = 401;
|
||||
return { error: "Token无效" };
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
export default authRoutes;
|
||||
42
src/routes/department.ts
Normal file
42
src/routes/department.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import * as DepartmentController from "../controllers/department";
|
||||
|
||||
// 科室路由
|
||||
export const departmentRouter = new Elysia()
|
||||
.get("/department", DepartmentController.list) // 获取科室列表
|
||||
.get("/department/:id", DepartmentController.one) // 获取单个科室
|
||||
.post(
|
||||
"/department",
|
||||
async ({ body }) => DepartmentController.create({ body }),
|
||||
{
|
||||
body: t.Object({
|
||||
name: t.String(),
|
||||
hospital: t.String(),
|
||||
description: t.Optional(t.String()),
|
||||
}),
|
||||
}
|
||||
) // 创建科室
|
||||
.put(
|
||||
"/department/:id",
|
||||
async ({ params, body }) => DepartmentController.update({ params, body }),
|
||||
{
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
body: t.Object({
|
||||
name: t.Optional(t.String()),
|
||||
hospital: t.Optional(t.String()),
|
||||
description: t.Optional(t.String()),
|
||||
isActive: t.Optional(t.Boolean()),
|
||||
}),
|
||||
}
|
||||
) // 更新科室
|
||||
.delete(
|
||||
"/department/:id",
|
||||
async ({ params }) => DepartmentController.remove({ params }),
|
||||
{
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
}
|
||||
); // 删除科室
|
||||
58
src/routes/doctor.ts
Normal file
58
src/routes/doctor.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import * as DoctorController from "../controllers/doctor";
|
||||
|
||||
// 医生路由
|
||||
export const doctorRouter = new Elysia()
|
||||
.get("/doctor", DoctorController.list) // 获取医生列表
|
||||
.get("/doctor/:id", DoctorController.one, {
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
}) // 获取单个医生
|
||||
.post(
|
||||
"/doctor",
|
||||
async ({ body }) => DoctorController.create({ body }),
|
||||
{
|
||||
body: t.Object({
|
||||
name: t.String(),
|
||||
username: t.String(),
|
||||
password: t.String(),
|
||||
phone: t.String(),
|
||||
hospitalId: t.Optional(t.String()),
|
||||
departmentId: t.Optional(t.String()),
|
||||
groupId: t.Optional(t.String()),
|
||||
roleId: t.Optional(t.String()),
|
||||
isDoctor: t.Optional(t.Boolean()),
|
||||
}),
|
||||
}
|
||||
) // 创建医生
|
||||
.put(
|
||||
"/doctor/:id",
|
||||
async ({ params, body }) => DoctorController.update({ params, body }),
|
||||
{
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
body: t.Object({
|
||||
name: t.Optional(t.String()),
|
||||
username: t.Optional(t.String()),
|
||||
password: t.Optional(t.String()),
|
||||
phone: t.Optional(t.String()),
|
||||
hospitalId: t.Optional(t.String()),
|
||||
departmentId: t.Optional(t.String()),
|
||||
groupId: t.Optional(t.String()),
|
||||
roleId: t.Optional(t.String()),
|
||||
isDoctor: t.Optional(t.Boolean()),
|
||||
isActive: t.Optional(t.Boolean()),
|
||||
}),
|
||||
}
|
||||
) // 更新医生
|
||||
.delete(
|
||||
"/doctor/:id",
|
||||
async ({ params }) => DoctorController.remove({ params }),
|
||||
{
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
}
|
||||
); // 删除医生
|
||||
42
src/routes/group.ts
Normal file
42
src/routes/group.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import * as GroupController from "../controllers/group";
|
||||
|
||||
// 小组路由
|
||||
export const groupRouter = new Elysia()
|
||||
.get("/group", GroupController.list) // 获取小组列表
|
||||
.get("/group/:id", GroupController.one) // 获取单个小组
|
||||
.post(
|
||||
"/group",
|
||||
async ({ body }) => GroupController.create({ body }),
|
||||
{
|
||||
body: t.Object({
|
||||
name: t.String(),
|
||||
departmentId: t.String(),
|
||||
description: t.Optional(t.String()),
|
||||
}),
|
||||
}
|
||||
) // 创建小组
|
||||
.put(
|
||||
"/group/:id",
|
||||
async ({ params, body }) => GroupController.update({ params, body }),
|
||||
{
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
body: t.Object({
|
||||
name: t.Optional(t.String()),
|
||||
departmentId: t.Optional(t.String()),
|
||||
description: t.Optional(t.String()),
|
||||
isActive: t.Optional(t.Boolean()),
|
||||
}),
|
||||
}
|
||||
) // 更新小组
|
||||
.delete(
|
||||
"/group/:id",
|
||||
async ({ params }) => GroupController.remove({ params }),
|
||||
{
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
}
|
||||
); // 删除小组
|
||||
42
src/routes/hospital.ts
Normal file
42
src/routes/hospital.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import * as HospitalController from "../controllers/hospital";
|
||||
|
||||
// 医院路由
|
||||
export const hospitalRouter = new Elysia()
|
||||
.get("/hospital", HospitalController.list) // 获取医院列表
|
||||
.get("/hospital/:id", HospitalController.one) // 获取单个医院
|
||||
.post(
|
||||
"/hospital",
|
||||
async ({ body }) => HospitalController.create({ body }),
|
||||
{
|
||||
body: t.Object({
|
||||
name: t.String(),
|
||||
description: t.Optional(t.String()),
|
||||
}),
|
||||
}
|
||||
) // 创建医院
|
||||
.put(
|
||||
"/hospital/:id",
|
||||
async ({ params, body }) => HospitalController.update({ params, body }),
|
||||
{
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
body: t.Object({
|
||||
name: t.Optional(t.String()),
|
||||
description: t.Optional(t.String()),
|
||||
isActive: t.Optional(t.Boolean()),
|
||||
}),
|
||||
}
|
||||
) // 更新医院
|
||||
.delete(
|
||||
"/hospital/:id",
|
||||
async ({ params }) => HospitalController.remove({ params }),
|
||||
{
|
||||
params: t.Object({
|
||||
id: t.String(),
|
||||
}),
|
||||
}
|
||||
); // 删除医院
|
||||
|
||||
|
||||
17
src/routes/index.ts
Normal file
17
src/routes/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import Elysia from "elysia";
|
||||
import { doctorRouter } from "./doctor";
|
||||
import { hospitalRouter } from "./hospital";
|
||||
import { departmentRouter } from "./department";
|
||||
import { groupRouter } from "./group";
|
||||
import { roleRoutes } from "./role";
|
||||
import { patientRoutes } from "./patient";
|
||||
import authRoutes from "./auth";
|
||||
|
||||
export const router = new Elysia()
|
||||
.use(authRoutes)
|
||||
.use(doctorRouter)
|
||||
.use(hospitalRouter)
|
||||
.use(departmentRouter)
|
||||
.use(groupRouter)
|
||||
.use(roleRoutes)
|
||||
.use(patientRoutes);
|
||||
75
src/routes/patient.ts
Normal file
75
src/routes/patient.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { Elysia, t } from "elysia";
|
||||
import { jwt } from "@elysiajs/jwt";
|
||||
import * as patientController from "../controllers/patient";
|
||||
|
||||
export const patientRoutes = new Elysia({ prefix: "/patient" })
|
||||
.use(jwt({
|
||||
name: "jwt",
|
||||
secret: process.env.JWT_SECRET || "your-secret-key",
|
||||
}))
|
||||
.get("/", async ({ headers, jwt }) => {
|
||||
// 从 Authorization header 获取 token
|
||||
const authHeader = headers.authorization;
|
||||
const token = authHeader?.replace("Bearer ", "");
|
||||
|
||||
if (!token) {
|
||||
return patientController.list({});
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = await jwt.verify(token);
|
||||
if (payload && typeof payload === "object" && "userId" in payload) {
|
||||
return patientController.list({ doctorId: payload.userId as string });
|
||||
}
|
||||
} catch (error) {
|
||||
// Token无效,返回空列表
|
||||
return [];
|
||||
}
|
||||
|
||||
return patientController.list({});
|
||||
})
|
||||
.get("/:id", ({ params }) => patientController.one({ params }))
|
||||
.post("/", ({ body }) => patientController.create({ body }), {
|
||||
body: t.Object({
|
||||
name: t.String({ minLength: 1 }),
|
||||
chiefDoctorId: t.String(),
|
||||
}),
|
||||
})
|
||||
.put(
|
||||
"/:id",
|
||||
({ params, body }) => patientController.update({ params, body }),
|
||||
{
|
||||
body: t.Object({
|
||||
name: t.Optional(t.String({ minLength: 1 })),
|
||||
chiefDoctorId: t.Optional(t.String()),
|
||||
}),
|
||||
},
|
||||
)
|
||||
.delete("/:id", ({ params }) => patientController.remove({ params }))
|
||||
.post(
|
||||
"/:id/share",
|
||||
async ({ params, body, headers, jwt }) => {
|
||||
// 从 Authorization header 获取 token
|
||||
const authHeader = headers.authorization;
|
||||
const token = authHeader?.replace("Bearer ", "");
|
||||
|
||||
let currentDoctorId;
|
||||
if (token) {
|
||||
try {
|
||||
const payload = await jwt.verify(token);
|
||||
if (payload && typeof payload === "object" && "userId" in payload) {
|
||||
currentDoctorId = payload.userId as string;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error("无效的token");
|
||||
}
|
||||
}
|
||||
|
||||
return patientController.share({ params, body, currentDoctorId });
|
||||
},
|
||||
{
|
||||
body: t.Object({
|
||||
sharedWith: t.Array(t.String()),
|
||||
}),
|
||||
}
|
||||
);
|
||||
32
src/routes/role.ts
Normal file
32
src/routes/role.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { Elysia, t } from "elysia";
|
||||
import * as roleController from "../controllers/role";
|
||||
|
||||
export const roleRoutes = new Elysia({ prefix: "/role" })
|
||||
.get("/", () => roleController.list())
|
||||
.get("/:id", ({ params }) => roleController.one({ params }))
|
||||
.post(
|
||||
"/",
|
||||
({ body }) => roleController.create({ body }),
|
||||
{
|
||||
body: t.Object({
|
||||
name: t.String({ minLength: 1 }),
|
||||
code: t.String({ minLength: 1 }),
|
||||
description: t.Optional(t.String()),
|
||||
permissions: t.Optional(t.String()),
|
||||
}),
|
||||
}
|
||||
)
|
||||
.put(
|
||||
"/:id",
|
||||
({ params, body }) => roleController.update({ params, body }),
|
||||
{
|
||||
body: t.Object({
|
||||
name: t.Optional(t.String({ minLength: 1 })),
|
||||
code: t.Optional(t.String({ minLength: 1 })),
|
||||
description: t.Optional(t.String()),
|
||||
permissions: t.Optional(t.String()),
|
||||
isActive: t.Optional(t.Boolean()),
|
||||
}),
|
||||
}
|
||||
)
|
||||
.delete("/:id", ({ params }) => roleController.remove({ params }));
|
||||
13
test.ts
Normal file
13
test.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { treaty } from "@elysiajs/eden";
|
||||
import type { Api } from "./src";
|
||||
|
||||
const client = treaty<Api>("localhost:3000");
|
||||
|
||||
const res = await client.api.patient.get({
|
||||
headers: {
|
||||
Authorization:
|
||||
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI3MDE5OGMyZS1lM2EyLTRhZTUtOTdjMC01YWJlNGE0MmU3ZWQiLCJyb2xlSWQiOiI5MWU4MDE4Mi05MTcwLTRjMDEtYmYxNC1hNDQwM2FjZTAyMGIiLCJyb2xlQ29kZSI6IkRPQ1RPUiIsImlhdCI6MTc2ODc2MDY5MH0.TAjbfbP5nszzw9-keufpBcjbI45UnZm5hHJp5sHStRg",
|
||||
},
|
||||
});
|
||||
|
||||
console.log(res.data);
|
||||
Loading…
x
Reference in New Issue
Block a user