完善部分接口

This commit is contained in:
EL 2026-01-19 02:10:46 +08:00
parent 98cc1ffa92
commit 1352d62a5d
30 changed files with 1654 additions and 7 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
DATABASE_URL=postgres://postgres:lyh1234@192.168.0.180:5432/rbac

240
bun.lock
View File

@ -5,16 +5,92 @@
"": { "": {
"name": "api", "name": "api",
"dependencies": { "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": { "devDependencies": {
"@types/pg": "^8.16.0",
"bun-types": "latest", "bun-types": "latest",
"drizzle-kit": "^0.31.8",
"tsx": "^4.21.0",
}, },
}, },
}, },
"packages": { "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=="], "@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=="], "@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=="], "@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/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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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=="], "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
View 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!,
},
});

View File

@ -6,10 +6,22 @@
"dev": "bun run --watch src/index.ts" "dev": "bun run --watch src/index.ts"
}, },
"dependencies": { "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": { "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" "module": "src/index.js"
} }

93
seed.ts Normal file
View 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
View 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;
};

View 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
View 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
View 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];
};

View 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];
};

194
src/controllers/patient.ts Normal file
View File

@ -0,0 +1,194 @@
import { eq, inArray } 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 patients = await db.query.patientTable.findMany({
with: {
chiefDoctor: {
with: {
role: true,
},
},
},
where: (table, { inArray }) => inArray(table.chiefDoctorId, doctorIds),
orderBy: (table, { asc }) => asc(table.createdAt),
});
return patients;
}
// 组长可以看到本小组所有医生的患者
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 patients = await db.query.patientTable.findMany({
with: {
chiefDoctor: {
with: {
role: true,
},
},
},
where: (table, { inArray }) => inArray(table.chiefDoctorId, doctorIds),
orderBy: (table, { asc }) => asc(table.createdAt),
});
return patients;
}
// 普通医生只能看到自己的患者
const patients = await db.query.patientTable.findMany({
with: {
chiefDoctor: {
with: {
role: true,
},
},
},
where: (table, { eq }) => eq(table.chiefDoctorId, doctorId),
orderBy: (table, { asc }) => asc(table.createdAt),
});
return patients;
};
// 获取单个患者
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];
};

74
src/controllers/role.ts Normal file
View 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];
};

View File

@ -1,7 +1,16 @@
import { Elysia } from "elysia"; 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( const app = new Elysia({ prefix: "/api" }).use(router);
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
); app.use(cors());
app.listen(3000);
export type Api = typeof app;

View 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
View 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
View 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
View 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
View 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
View 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],
}),
}));

9
src/modules/patient.ts Normal file
View File

@ -0,0 +1,9 @@
import { uuid, varchar, timestamp } from "drizzle-orm/pg-core";
export const Patient = {
id: uuid().primaryKey().defaultRandom(), // 主键UUID
name: varchar().notNull(), // 患者姓名
chiefDoctorId: uuid().notNull(), // 主刀医生ID虚拟外键
createdAt: timestamp().notNull().defaultNow(), // 创建时间
updatedAt: timestamp().notNull().defaultNow(), // 更新时间
};

12
src/modules/role.ts Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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);

48
src/routes/patient.ts Normal file
View File

@ -0,0 +1,48 @@
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 }));

32
src/routes/role.ts Normal file
View 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
View 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.eyJ1c2VySWQiOiJiMzcwMzgwNi1jNDRjLTRkMTEtYWMzYy03NDAwYzViODYyNmEiLCJyb2xlSWQiOiIzOTA0YmQ0OC01MzdhLTQ0MzgtODE4Yi01NDJlYjcyNjA4YmUiLCJyb2xlQ29kZSI6IkdST1VQX0xFQURFUiIsImlhdCI6MTc2ODc1OTM1Mn0.IkoYXCQy44HFG2Y7dZWHGJAmieYEuCSqAZE0oG46z40",
},
});
console.log(res.data);