diff --git a/.env.example b/.env.example index 79b0a2c..ec5280d 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,11 @@ NEXT_PUBLIC_URL=http://localhost:3000 -# mongodb connection url -MONGODB_URI=mongodb://localhost:27017 +# postgres connection url +DB_URL= +DB_POOL_URL= # aws credentials -AWS_REGION= your aws region -AWS_ACCESS_KEY_ID= your access key id -AWS_SECRET_ACCESS_KEY= your secret access key -AWS_BUCKET_NAME= your s3 bucket name +AWS_REGION= +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_BUCKET_NAME= diff --git a/.gitignore b/.gitignore index 8067dd0..25f2207 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,7 @@ yarn-error.log* .pnpm-debug.log* # local env files -.env*.local +.env* # vercel .vercel diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 0000000..123989d --- /dev/null +++ b/drizzle.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'drizzle-kit'; + +export default defineConfig({ + schema: './src/lib/db/schema', + out: './src/lib/db/migrations', + dialect: 'postgresql', + dbCredentials: { + url: process.env.DB_URL + }, + verbose: true, + strict: true +}); diff --git a/env.d.ts b/env.d.ts index 3741f45..8f95026 100644 --- a/env.d.ts +++ b/env.d.ts @@ -2,7 +2,8 @@ namespace NodeJS { interface ProcessEnv { NEXT_PUBLIC_URL: string; - MONGODB_URI: string; + DB_URL: string; + DB_POOL_URL: string; AWS_REGION: string; AWS_ACCESS_KEY_ID: string; AWS_SECRET_ACCESS_KEY: string; diff --git a/package.json b/package.json index ca0a9dd..be31c08 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,9 @@ "dev": "next dev", "build": "next build", "start": "next start", + "db:generate": "drizzle-kit generate", + "db:migrate": "tsx --env-file=.env src/lib/db/migrate.ts", + "db:studio": "drizzle-kit studio", "lint": "next lint", "format:check": "prettier --check ./src", "format:fix": "prettier --write ./src --ignore-unknown", @@ -21,16 +24,19 @@ "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", + "drizzle-orm": "^0.31.4", "lucide-react": "^0.378.0", "mime-types": "^2.1.35", "mongoose": "^8.4.0", "next": "^14.1.2", + "pg": "^8.12.0", "react": "^18", "react-dom": "^18" }, "devDependencies": { "@types/mime-types": "^2.1.4", "@types/node": "^20", + "@types/pg": "^8.11.6", "@types/react": "^18", "@types/react-dom": "^18", "@typescript-eslint/eslint-plugin": "^6.2.1", @@ -38,6 +44,7 @@ "autoprefixer": "^10.4.14", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "drizzle-kit": "^0.22.8", "eslint": "^8", "eslint-config-next": "^14.1.2", "eslint-config-prettier": "^9.0.0", @@ -52,6 +59,7 @@ "tailwind-merge": "^2.3.0", "tailwindcss": "^3.3.3", "tailwindcss-animate": "^1.0.7", + "tsx": "^4.16.2", "typescript": "^5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4cf64a0..bb23025 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ dependencies: '@radix-ui/react-toast': specifier: ^1.1.5 version: 1.1.5(@types/react-dom@18.2.22)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) + drizzle-orm: + specifier: ^0.31.4 + version: 0.31.4(@types/pg@8.11.6)(@types/react@18.2.66)(pg@8.12.0)(react@18.2.0) lucide-react: specifier: ^0.378.0 version: 0.378.0(react@18.2.0) @@ -32,6 +35,9 @@ dependencies: next: specifier: ^14.1.2 version: 14.1.3(react-dom@18.2.0)(react@18.2.0) + pg: + specifier: ^8.12.0 + version: 8.12.0 react: specifier: ^18 version: 18.2.0 @@ -46,6 +52,9 @@ devDependencies: '@types/node': specifier: ^20 version: 20.11.28 + '@types/pg': + specifier: ^8.11.6 + version: 8.11.6 '@types/react': specifier: ^18 version: 18.2.66 @@ -67,6 +76,9 @@ devDependencies: clsx: specifier: ^2.1.1 version: 2.1.1 + drizzle-kit: + specifier: ^0.22.8 + version: 0.22.8 eslint: specifier: ^8 version: 8.57.0 @@ -109,6 +121,9 @@ devDependencies: tailwindcss-animate: specifier: ^1.0.7 version: 1.0.7(tailwindcss@3.4.1) + tsx: + specifier: ^4.16.2 + version: 4.16.2 typescript: specifier: ^5 version: 5.4.2 @@ -937,6 +952,842 @@ packages: dependencies: regenerator-runtime: 0.14.1 + /@esbuild-kit/core-utils@3.3.2: + resolution: + { + integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ== + } + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + dev: true + + /@esbuild-kit/esm-loader@2.6.5: + resolution: + { + integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA== + } + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.7.3 + dev: true + + /@esbuild/aix-ppc64@0.19.12: + resolution: + { + integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA== + } + engines: { node: '>=12' } + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/aix-ppc64@0.21.5: + resolution: + { + integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + } + engines: { node: '>=12' } + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.18.20: + resolution: + { + integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.19.12: + resolution: + { + integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.21.5: + resolution: + { + integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: + { + integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw== + } + engines: { node: '>=12' } + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.19.12: + resolution: + { + integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w== + } + engines: { node: '>=12' } + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.21.5: + resolution: + { + integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + } + engines: { node: '>=12' } + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: + { + integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg== + } + engines: { node: '>=12' } + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.19.12: + resolution: + { + integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew== + } + engines: { node: '>=12' } + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.21.5: + resolution: + { + integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + } + engines: { node: '>=12' } + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: + { + integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.19.12: + resolution: + { + integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.21.5: + resolution: + { + integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: + { + integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ== + } + engines: { node: '>=12' } + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.19.12: + resolution: + { + integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A== + } + engines: { node: '>=12' } + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.21.5: + resolution: + { + integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + } + engines: { node: '>=12' } + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: + { + integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.19.12: + resolution: + { + integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.21.5: + resolution: + { + integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: + { + integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ== + } + engines: { node: '>=12' } + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.19.12: + resolution: + { + integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg== + } + engines: { node: '>=12' } + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.21.5: + resolution: + { + integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + } + engines: { node: '>=12' } + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: + { + integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.19.12: + resolution: + { + integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.21.5: + resolution: + { + integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: + { + integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg== + } + engines: { node: '>=12' } + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.19.12: + resolution: + { + integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w== + } + engines: { node: '>=12' } + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.21.5: + resolution: + { + integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + } + engines: { node: '>=12' } + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: + { + integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA== + } + engines: { node: '>=12' } + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.19.12: + resolution: + { + integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA== + } + engines: { node: '>=12' } + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.21.5: + resolution: + { + integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + } + engines: { node: '>=12' } + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: + { + integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg== + } + engines: { node: '>=12' } + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.19.12: + resolution: + { + integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA== + } + engines: { node: '>=12' } + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.21.5: + resolution: + { + integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + } + engines: { node: '>=12' } + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: + { + integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ== + } + engines: { node: '>=12' } + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.19.12: + resolution: + { + integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w== + } + engines: { node: '>=12' } + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.21.5: + resolution: + { + integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + } + engines: { node: '>=12' } + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: + { + integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA== + } + engines: { node: '>=12' } + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.19.12: + resolution: + { + integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg== + } + engines: { node: '>=12' } + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.21.5: + resolution: + { + integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + } + engines: { node: '>=12' } + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.18.20: + resolution: + { + integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A== + } + engines: { node: '>=12' } + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.19.12: + resolution: + { + integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg== + } + engines: { node: '>=12' } + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.21.5: + resolution: + { + integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + } + engines: { node: '>=12' } + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.18.20: + resolution: + { + integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ== + } + engines: { node: '>=12' } + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.19.12: + resolution: + { + integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg== + } + engines: { node: '>=12' } + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.21.5: + resolution: + { + integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + } + engines: { node: '>=12' } + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.18.20: + resolution: + { + integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== + } + engines: { node: '>=12' } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.19.12: + resolution: + { + integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== + } + engines: { node: '>=12' } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.21.5: + resolution: + { + integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + } + engines: { node: '>=12' } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: + { + integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A== + } + engines: { node: '>=12' } + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.19.12: + resolution: + { + integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA== + } + engines: { node: '>=12' } + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.21.5: + resolution: + { + integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + } + engines: { node: '>=12' } + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: + { + integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg== + } + engines: { node: '>=12' } + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.19.12: + resolution: + { + integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw== + } + engines: { node: '>=12' } + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.21.5: + resolution: + { + integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + } + engines: { node: '>=12' } + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: + { + integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ== + } + engines: { node: '>=12' } + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.19.12: + resolution: + { + integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA== + } + engines: { node: '>=12' } + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.21.5: + resolution: + { + integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + } + engines: { node: '>=12' } + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.18.20: + resolution: + { + integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.19.12: + resolution: + { + integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.21.5: + resolution: + { + integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + } + engines: { node: '>=12' } + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.18.20: + resolution: + { + integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g== + } + engines: { node: '>=12' } + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.19.12: + resolution: + { + integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ== + } + engines: { node: '>=12' } + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.21.5: + resolution: + { + integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + } + engines: { node: '>=12' } + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.18.20: + resolution: + { + integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== + } + engines: { node: '>=12' } + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.19.12: + resolution: + { + integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA== + } + engines: { node: '>=12' } + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.21.5: + resolution: + { + integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + } + engines: { node: '>=12' } + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): resolution: { @@ -2342,7 +3193,16 @@ packages: } dependencies: undici-types: 5.26.5 - dev: true + + /@types/pg@8.11.6: + resolution: + { + integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ== + } + dependencies: + '@types/node': 20.11.28 + pg-protocol: 1.6.1 + pg-types: 4.0.2 /@types/prop-types@15.7.11: resolution: @@ -2956,6 +3816,13 @@ packages: engines: { node: '>=16.20.1' } dev: false + /buffer-from@1.1.2: + resolution: + { + integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + } + dev: true + /busboy@1.6.0: resolution: { @@ -3327,6 +4194,118 @@ packages: esutils: 2.0.3 dev: true + /drizzle-kit@0.22.8: + resolution: + { + integrity: sha512-VjI4wsJjk3hSqHSa3TwBf+uvH6M6pRHyxyoVbt935GUzP9tUR/BRZ+MhEJNgryqbzN2Za1KP0eJMTgKEPsalYQ== + } + hasBin: true + dependencies: + '@esbuild-kit/esm-loader': 2.6.5 + esbuild: 0.19.12 + esbuild-register: 3.5.0(esbuild@0.19.12) + transitivePeerDependencies: + - supports-color + dev: true + + /drizzle-orm@0.31.4(@types/pg@8.11.6)(@types/react@18.2.66)(pg@8.12.0)(react@18.2.0): + resolution: + { + integrity: sha512-VGD9SH9aStF2z4QOTnVlVX/WghV/EnuEzTmsH3fSVp2E4fFgc8jl3viQrS/XUJx1ekW4rVVLJMH42SfGQdjX3Q== + } + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=3' + '@electric-sql/pglite': '>=0.1.1' + '@libsql/client': '*' + '@neondatabase/serverless': '>=0.1' + '@op-engineering/op-sqlite': '>=2' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1' + '@prisma/client': '*' + '@tidbcloud/serverless': '*' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/react': '>=18' + '@types/sql.js': '*' + '@vercel/postgres': '>=0.8.0' + '@xata.io/client': '*' + better-sqlite3: '>=7' + bun-types: '*' + expo-sqlite: '>=13.2.0' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + prisma: '*' + react: '>=18' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + '@neondatabase/serverless': + optional: true + '@op-engineering/op-sqlite': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@prisma/client': + optional: true + '@tidbcloud/serverless': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/react': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + '@xata.io/client': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + react: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dependencies: + '@types/pg': 8.11.6 + '@types/react': 18.2.66 + pg: 8.12.0 + react: 18.2.0 + dev: false + /eastasianwidth@0.2.0: resolution: { @@ -3562,6 +4541,121 @@ packages: is-symbol: 1.0.4 dev: true + /esbuild-register@3.5.0(esbuild@0.19.12): + resolution: + { + integrity: sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A== + } + peerDependencies: + esbuild: '>=0.12 <1' + dependencies: + debug: 4.3.4 + esbuild: 0.19.12 + transitivePeerDependencies: + - supports-color + dev: true + + /esbuild@0.18.20: + resolution: + { + integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== + } + engines: { node: '>=12' } + hasBin: true + requiresBuild: true + 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 + dev: true + + /esbuild@0.19.12: + resolution: + { + integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg== + } + engines: { node: '>=12' } + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + dev: true + + /esbuild@0.21.5: + resolution: + { + integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + } + engines: { node: '>=12' } + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + dev: true + /escalade@3.1.2: resolution: { @@ -4167,6 +5261,15 @@ packages: resolve-pkg-maps: 1.0.0 dev: true + /get-tsconfig@4.7.5: + resolution: + { + integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== + } + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + /glob-parent@5.1.2: resolution: { @@ -5387,6 +6490,12 @@ packages: es-abstract: 1.22.5 dev: true + /obuf@1.1.2: + resolution: + { + integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + } + /once@1.4.0: resolution: { @@ -5519,6 +6628,112 @@ packages: engines: { node: '>=8' } dev: true + /pg-cloudflare@1.1.1: + resolution: + { + integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== + } + requiresBuild: true + dev: false + optional: true + + /pg-connection-string@2.6.4: + resolution: + { + integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA== + } + dev: false + + /pg-int8@1.0.1: + resolution: + { + integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + } + engines: { node: '>=4.0.0' } + + /pg-numeric@1.0.2: + resolution: + { + integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== + } + engines: { node: '>=4' } + + /pg-pool@3.6.2(pg@8.12.0): + resolution: + { + integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg== + } + peerDependencies: + pg: '>=8.0' + dependencies: + pg: 8.12.0 + dev: false + + /pg-protocol@1.6.1: + resolution: + { + integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg== + } + + /pg-types@2.2.0: + resolution: + { + integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + } + engines: { node: '>=4' } + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + dev: false + + /pg-types@4.0.2: + resolution: + { + integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng== + } + engines: { node: '>=10' } + dependencies: + pg-int8: 1.0.1 + pg-numeric: 1.0.2 + postgres-array: 3.0.2 + postgres-bytea: 3.0.0 + postgres-date: 2.1.0 + postgres-interval: 3.0.0 + postgres-range: 1.1.4 + + /pg@8.12.0: + resolution: + { + integrity: sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ== + } + engines: { node: '>= 8.0.0' } + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + dependencies: + pg-connection-string: 2.6.4 + pg-pool: 3.6.2(pg@8.12.0) + pg-protocol: 1.6.1 + pg-types: 2.2.0 + pgpass: 1.0.5 + optionalDependencies: + pg-cloudflare: 1.1.1 + dev: false + + /pgpass@1.0.5: + resolution: + { + integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== + } + dependencies: + split2: 4.2.0 + dev: false + /picocolors@1.0.0: resolution: { @@ -5669,6 +6884,76 @@ packages: source-map-js: 1.0.2 dev: true + /postgres-array@2.0.0: + resolution: + { + integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + } + engines: { node: '>=4' } + dev: false + + /postgres-array@3.0.2: + resolution: + { + integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog== + } + engines: { node: '>=12' } + + /postgres-bytea@1.0.0: + resolution: + { + integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== + } + engines: { node: '>=0.10.0' } + dev: false + + /postgres-bytea@3.0.0: + resolution: + { + integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw== + } + engines: { node: '>= 6' } + dependencies: + obuf: 1.1.2 + + /postgres-date@1.0.7: + resolution: + { + integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== + } + engines: { node: '>=0.10.0' } + dev: false + + /postgres-date@2.1.0: + resolution: + { + integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA== + } + engines: { node: '>=12' } + + /postgres-interval@1.2.0: + resolution: + { + integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + } + engines: { node: '>=0.10.0' } + dependencies: + xtend: 4.0.2 + dev: false + + /postgres-interval@3.0.0: + resolution: + { + integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== + } + engines: { node: '>=12' } + + /postgres-range@1.1.4: + resolution: + { + integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== + } + /prelude-ls@1.2.1: resolution: { @@ -6158,6 +7443,24 @@ packages: } engines: { node: '>=0.10.0' } + /source-map-support@0.5.21: + resolution: + { + integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + } + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: + { + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + } + engines: { node: '>=0.10.0' } + dev: true + /sparse-bitfield@3.0.3: resolution: { @@ -6167,6 +7470,14 @@ packages: memory-pager: 1.5.0 dev: false + /split2@4.2.0: + resolution: + { + integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + } + engines: { node: '>= 10.x' } + dev: false + /streamsearch@1.1.0: resolution: { @@ -6518,6 +7829,20 @@ packages: } dev: false + /tsx@4.16.2: + resolution: + { + integrity: sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ== + } + engines: { node: '>=18.0.0' } + hasBin: true + dependencies: + esbuild: 0.21.5 + get-tsconfig: 4.7.5 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /type-check@0.4.0: resolution: { @@ -6626,7 +7951,6 @@ packages: { integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== } - dev: true /update-browserslist-db@1.0.13(browserslist@4.23.0): resolution: @@ -6825,6 +8149,14 @@ packages: } dev: true + /xtend@4.0.2: + resolution: + { + integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + } + engines: { node: '>=0.4' } + dev: false + /yallist@4.0.0: resolution: { diff --git a/src/app/api/drop/route.ts b/src/app/api/drop/route.ts index 558473f..c9dbd92 100644 --- a/src/app/api/drop/route.ts +++ b/src/app/api/drop/route.ts @@ -1,15 +1,16 @@ -import crypto from 'crypto'; +import crypto from 'node:crypto'; import { NextResponse } from 'next/server'; +import { eq } from 'drizzle-orm'; -import FileModel from '@/lib/models/file'; -import { connectDB } from '@/lib/db'; +import db from '@/lib/db'; +import { files } from '@/lib/db/schema'; import { getObject, putObject } from '@/lib/storage'; import type { NextRequest } from 'next/server'; -import type { UploadAPIReqPayload } from '@/types'; +import type { PostAPIReqPayload } from '@/types'; async function POST(req: NextRequest) { - const body = (await req.json()) as UploadAPIReqPayload; + const body = (await req.json()) as PostAPIReqPayload; if (!body.name || !body.size || !body.type) { return NextResponse.json( @@ -23,27 +24,23 @@ async function POST(req: NextRequest) { return NextResponse.json({ error: 'File too large' }, { status: 413 }); } - const key = `${crypto.randomBytes(8).toString('hex')}-${body.name.replace(/\s+/g, '_')}`; - const newFile = new FileModel({ - name: body.name, - size: body.size, - type: body.type, - key - }); - try { - await connectDB(); + const key = `${crypto.randomBytes(8).toString('hex')}-${body.name.replace(/\s+/g, '_')}`; + + const [newFile] = await db + .insert(files) + .values({ + name: body.name, + size: body.size, + type: body.type, + key + }) + .returning({ id: files.id }); const uploadUrl = await putObject(key, body.type, body.size); - const savedFile = await newFile.save(); return NextResponse.json( - { - success: { - ...savedFile.toJSON(), - url: uploadUrl - } - }, + { success: { ...newFile, url: uploadUrl } }, { status: 201 } ); } catch (err) { @@ -66,18 +63,17 @@ async function GET(req: NextRequest) { } try { - await connectDB(); - - const file = await FileModel.findById(id); + const file = await db.query.files.findFirst({ + where: eq(files.id, id) + }); - if (!file || file.toJSON().expires.getTime() - Date.now() <= 0) { + if (!file || file.expiresAt.getTime() - Date.now() <= 0) { return NextResponse.json({ error: 'File not found' }, { status: 404 }); } - const data = file.toJSON(); - const downloadUrl = await getObject(data.key); + const downloadUrl = await getObject(file.key); - return NextResponse.json({ success: { ...data, url: downloadUrl } }); + return NextResponse.json({ success: { ...file, url: downloadUrl } }); } catch (err) { if (err instanceof Error) { return NextResponse.json({ error: err.message }, { status: 500 }); diff --git a/src/app/page.tsx b/src/app/page.tsx index 4c4e7c8..2fd34ba 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,6 +2,7 @@ import { useState } from 'react'; import { Check, Copy, File, Loader2, Share, Upload } from 'lucide-react'; + import { Button } from '@/components/ui/button'; import { AlertDialog, @@ -14,12 +15,13 @@ import { } from '@/components/ui/alert-dialog'; import { Input } from '@/components/ui/input'; import { useToast } from '@/hooks/use-toast'; -import type { UploadAPIRespData } from '@/types'; + +import type { PostAPIRespData } from '@/types'; export default function HomePage() { const [selectedFile, setSelectedFile] = useState(null); const [isLoading, setIsLoading] = useState(false); - const [respData, setRespData] = useState(); + const [respData, setRespData] = useState(); const [shareDialogOpen, setShareDialogOpen] = useState(false); const [copiedToClipboard, setCopiedToClipboard] = useState(false); @@ -45,7 +47,7 @@ export default function HomePage() { type: selectedFile.type }) }); - const data = (await uploadResp.json()) as UploadAPIRespData; + const data = (await uploadResp.json()) as PostAPIRespData; if (!uploadResp.ok) throw new Error(data.error); const s3Resp = await fetch(data.success.url, { @@ -78,7 +80,7 @@ export default function HomePage() { async function handleCopyToClipboard() { await navigator.clipboard.writeText( - `${process.env.NEXT_PUBLIC_URL}/s/${respData?._id}` + `${process.env.NEXT_PUBLIC_URL}/s/${respData?.id}` ); setCopiedToClipboard(true); setTimeout(() => setCopiedToClipboard(false), 2000); @@ -181,7 +183,7 @@ export default function HomePage() {
diff --git a/src/app/s/[id]/page.tsx b/src/app/s/[id]/page.tsx index 774b670..8ef7149 100644 --- a/src/app/s/[id]/page.tsx +++ b/src/app/s/[id]/page.tsx @@ -2,6 +2,7 @@ import { notFound } from 'next/navigation'; import { extension as mimeExtention } from 'mime-types'; import Link from 'next/link'; import { Download } from 'lucide-react'; + import { formatBytes } from '@/lib/utils'; import { Card, @@ -12,7 +13,8 @@ import { CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; -import type { DropAPIRespData } from '@/types'; + +import type { GetAPIRespData } from '@/types'; export const dynamic = 'force-dynamic'; @@ -28,7 +30,7 @@ export default async function DetailsPage({ params }: DetailsPageProps) { ); if (!resp.ok) return notFound(); - const { success: data } = (await resp.json()) as DropAPIRespData; + const { success: data } = (await resp.json()) as GetAPIRespData; return (
@@ -58,8 +60,8 @@ export default async function DetailsPage({ params }: DetailsPageProps) {
Expires: -