Merge branch 'main' into ppr-static
This commit is contained in:
commit
f023a57b7f
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -39,6 +39,7 @@
|
|||||||
"skippable",
|
"skippable",
|
||||||
"sonner",
|
"sonner",
|
||||||
"Streamable",
|
"Streamable",
|
||||||
|
"Supabase",
|
||||||
"thephotoblog",
|
"thephotoblog",
|
||||||
"trpc",
|
"trpc",
|
||||||
"unnest",
|
"unnest",
|
||||||
|
|||||||
22
README.md
22
README.md
@ -29,19 +29,19 @@ Installation
|
|||||||
1. Click [Deploy](https://vercel.com/new/clone?demo-title=Photo+Blog&demo-description=Store+photos+with+original+camera+data&demo-url=https%3A%2F%2Fphotos.sambecker.com&demo-image=https%3A%2F%2Fphotos.sambecker.com%2Ftemplate-image-tight&project-name=Photo+Blog&repository-name=exif-photo-blog&repository-url=https%3A%2F%2Fgithub.com%2Fsambecker%2Fexif-photo-blog&from=templates&skippable-integrations=1&teamCreateStatus=hidden&stores=%5B%7B%22type%22%3A%22postgres%22%7D%2C%7B%22type%22%3A%22blob%22%7D%5D)
|
1. Click [Deploy](https://vercel.com/new/clone?demo-title=Photo+Blog&demo-description=Store+photos+with+original+camera+data&demo-url=https%3A%2F%2Fphotos.sambecker.com&demo-image=https%3A%2F%2Fphotos.sambecker.com%2Ftemplate-image-tight&project-name=Photo+Blog&repository-name=exif-photo-blog&repository-url=https%3A%2F%2Fgithub.com%2Fsambecker%2Fexif-photo-blog&from=templates&skippable-integrations=1&teamCreateStatus=hidden&stores=%5B%7B%22type%22%3A%22postgres%22%7D%2C%7B%22type%22%3A%22blob%22%7D%5D)
|
||||||
2. Add required storage ([Vercel Postgres](https://vercel.com/docs/storage/vercel-postgres/quickstart#create-a-postgres-database) + [Vercel Blob](https://vercel.com/docs/storage/vercel-blob/quickstart#create-a-blob-store)) as part of template installation
|
2. Add required storage ([Vercel Postgres](https://vercel.com/docs/storage/vercel-postgres/quickstart#create-a-postgres-database) + [Vercel Blob](https://vercel.com/docs/storage/vercel-blob/quickstart#create-a-blob-store)) as part of template installation
|
||||||
3. Configure environment variables from project settings:
|
3. Configure environment variables from project settings:
|
||||||
- `NEXT_PUBLIC_SITE_TITLE` (e.g., My Photos)
|
- `NEXT_PUBLIC_SITE_TITLE` (e.g., My Photos)
|
||||||
- `NEXT_PUBLIC_SITE_DOMAIN` (e.g., photos.domain.com)
|
- `NEXT_PUBLIC_SITE_DOMAIN` (e.g., photos.domain.com)
|
||||||
- `NEXT_PUBLIC_SITE_DESCRIPTION` (optional—mainly used for OG meta)
|
- `NEXT_PUBLIC_SITE_DESCRIPTION` (optional—mainly used for OG meta)
|
||||||
|
|
||||||
### 2. Setup Auth
|
### 2. Setup Auth
|
||||||
|
|
||||||
1. [Generate auth secret](https://generate-secret.vercel.app/32) and add to environment variables:
|
1. [Generate auth secret](https://generate-secret.vercel.app/32) and add to environment variables:
|
||||||
- `AUTH_SECRET`
|
- `AUTH_SECRET`
|
||||||
2. Add admin user to environment variables:
|
2. Add admin user to environment variables:
|
||||||
- `ADMIN_EMAIL`
|
- `ADMIN_EMAIL`
|
||||||
- `ADMIN_PASSWORD`
|
- `ADMIN_PASSWORD`
|
||||||
3. Trigger redeploy
|
3. Trigger redeploy
|
||||||
- Visit project on Vercel, navigate to "Deployments" tab, click ••• button next to most recent deployment, and select "Redeploy"
|
- Visit project on Vercel, navigate to "Deployments" tab, click ••• button next to most recent deployment, and select "Redeploy"
|
||||||
|
|
||||||
### 3. Upload your first photo 🎉
|
### 3. Upload your first photo 🎉
|
||||||
1. Visit `/admin`
|
1. Visit `/admin`
|
||||||
@ -105,6 +105,14 @@ Application behavior can be changed by configuring the following environment var
|
|||||||
- `NEXT_PUBLIC_GRID_ASPECT_RATIO = 1.5` sets aspect ratio for grid tiles (defaults to `1`—setting to `0` removes the constraint)
|
- `NEXT_PUBLIC_GRID_ASPECT_RATIO = 1.5` sets aspect ratio for grid tiles (defaults to `1`—setting to `0` removes the constraint)
|
||||||
- `NEXT_PUBLIC_OG_TEXT_ALIGNMENT = BOTTOM` keeps OG image text bottom aligned (default is top)
|
- `NEXT_PUBLIC_OG_TEXT_ALIGNMENT = BOTTOM` keeps OG image text bottom aligned (default is top)
|
||||||
|
|
||||||
|
## Alternate database providers (experimental)
|
||||||
|
|
||||||
|
Vercel Postgres can be switched to another Postgres-compatible, pooling provider by updating `POSTGRES_URL`. Some providers only work when SSL is disabled, which can configured by setting `DISABLE_POSTGRES_SSL = 1`.
|
||||||
|
|
||||||
|
### Supabase
|
||||||
|
1. Ensure connection string is set to "Transaction Mode" via port `6543`
|
||||||
|
2. Disable SSL by setting `DISABLE_POSTGRES_SSL = 1`
|
||||||
|
|
||||||
## Alternate storage providers
|
## Alternate storage providers
|
||||||
|
|
||||||
Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). If you have multiple adapters, you can set one as preferred by storing "aws-s3," "cloudflare-r2," or "vercel-blob" in `NEXT_PUBLIC_STORAGE_PREFERENCE`.
|
Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). If you have multiple adapters, you can set one as preferred by storing "aws-s3," "cloudflare-r2," or "vercel-blob" in `NEXT_PUBLIC_STORAGE_PREFERENCE`.
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
"@testing-library/react": "^15.0.5",
|
"@testing-library/react": "^15.0.5",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/node": "^20.12.7",
|
"@types/node": "^20.12.7",
|
||||||
|
"@types/pg": "^8.11.5",
|
||||||
"@types/react": "18.3.1",
|
"@types/react": "18.3.1",
|
||||||
"@types/react-dom": "18.3.0",
|
"@types/react-dom": "18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.7.1",
|
"@typescript-eslint/eslint-plugin": "^7.7.1",
|
||||||
@ -27,7 +28,6 @@
|
|||||||
"@vercel/analytics": "^1.2.2",
|
"@vercel/analytics": "^1.2.2",
|
||||||
"@vercel/blob": "^0.23.2",
|
"@vercel/blob": "^0.23.2",
|
||||||
"@vercel/kv": "^1.0.1",
|
"@vercel/kv": "^1.0.1",
|
||||||
"@vercel/postgres": "^0.8.0",
|
|
||||||
"@vercel/speed-insights": "^1.0.10",
|
"@vercel/speed-insights": "^1.0.10",
|
||||||
"ai": "^3.0.34",
|
"ai": "^3.0.34",
|
||||||
"autoprefixer": "10.4.19",
|
"autoprefixer": "10.4.19",
|
||||||
@ -42,10 +42,11 @@
|
|||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.7",
|
||||||
"next": "14.3.0-canary.29",
|
"next": "14.3.0-canary.37",
|
||||||
"next-auth": "5.0.0-beta.15",
|
"next-auth": "5.0.0-beta.15",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
"openai": "^4.38.5",
|
"openai": "^4.38.5",
|
||||||
|
"pg": "^8.11.5",
|
||||||
"postcss": "8.4.38",
|
"postcss": "8.4.38",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
|
|||||||
273
pnpm-lock.yaml
generated
273
pnpm-lock.yaml
generated
@ -38,6 +38,9 @@ importers:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^20.12.7
|
specifier: ^20.12.7
|
||||||
version: 20.12.7
|
version: 20.12.7
|
||||||
|
'@types/pg':
|
||||||
|
specifier: ^8.11.5
|
||||||
|
version: 8.11.5
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.3.1
|
specifier: 18.3.1
|
||||||
version: 18.3.1
|
version: 18.3.1
|
||||||
@ -55,19 +58,16 @@ importers:
|
|||||||
version: 1.1.3
|
version: 1.1.3
|
||||||
'@vercel/analytics':
|
'@vercel/analytics':
|
||||||
specifier: ^1.2.2
|
specifier: ^1.2.2
|
||||||
version: 1.2.2(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
version: 1.2.2(next@14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||||
'@vercel/blob':
|
'@vercel/blob':
|
||||||
specifier: ^0.23.2
|
specifier: ^0.23.2
|
||||||
version: 0.23.2
|
version: 0.23.2
|
||||||
'@vercel/kv':
|
'@vercel/kv':
|
||||||
specifier: ^1.0.1
|
specifier: ^1.0.1
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
'@vercel/postgres':
|
|
||||||
specifier: ^0.8.0
|
|
||||||
version: 0.8.0
|
|
||||||
'@vercel/speed-insights':
|
'@vercel/speed-insights':
|
||||||
specifier: ^1.0.10
|
specifier: ^1.0.10
|
||||||
version: 1.0.10(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))
|
version: 1.0.10(next@14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))
|
||||||
ai:
|
ai:
|
||||||
specifier: ^3.0.34
|
specifier: ^3.0.34
|
||||||
version: 3.0.34(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))(zod@3.23.4)
|
version: 3.0.34(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))(zod@3.23.4)
|
||||||
@ -108,17 +108,20 @@ importers:
|
|||||||
specifier: ^5.0.7
|
specifier: ^5.0.7
|
||||||
version: 5.0.7
|
version: 5.0.7
|
||||||
next:
|
next:
|
||||||
specifier: 14.3.0-canary.29
|
specifier: 14.3.0-canary.37
|
||||||
version: 14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
next-auth:
|
next-auth:
|
||||||
specifier: 5.0.0-beta.15
|
specifier: 5.0.0-beta.15
|
||||||
version: 5.0.0-beta.15(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
version: 5.0.0-beta.15(next@14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||||
next-themes:
|
next-themes:
|
||||||
specifier: ^0.3.0
|
specifier: ^0.3.0
|
||||||
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
openai:
|
openai:
|
||||||
specifier: ^4.38.5
|
specifier: ^4.38.5
|
||||||
version: 4.38.5
|
version: 4.38.5
|
||||||
|
pg:
|
||||||
|
specifier: ^8.11.5
|
||||||
|
version: 8.11.5
|
||||||
postcss:
|
postcss:
|
||||||
specifier: 8.4.38
|
specifier: 8.4.38
|
||||||
version: 8.4.38
|
version: 8.4.38
|
||||||
@ -800,68 +803,65 @@ packages:
|
|||||||
'@jridgewell/trace-mapping@0.3.25':
|
'@jridgewell/trace-mapping@0.3.25':
|
||||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||||
|
|
||||||
'@neondatabase/serverless@0.7.2':
|
|
||||||
resolution: {integrity: sha512-wU3WA2uTyNO7wjPs3Mg0G01jztAxUxzd9/mskMmtPwPTjf7JKWi9AW5/puOGXLxmZ9PVgRFeBVRVYq5nBPhsCg==}
|
|
||||||
|
|
||||||
'@next/bundle-analyzer@14.2.3':
|
'@next/bundle-analyzer@14.2.3':
|
||||||
resolution: {integrity: sha512-Z88hbbngMs7njZKI8kTJIlpdLKYfMSLwnsqYe54AP4aLmgL70/Ynx/J201DQ+q2Lr6FxFw1uCeLGImDrHOl2ZA==}
|
resolution: {integrity: sha512-Z88hbbngMs7njZKI8kTJIlpdLKYfMSLwnsqYe54AP4aLmgL70/Ynx/J201DQ+q2Lr6FxFw1uCeLGImDrHOl2ZA==}
|
||||||
|
|
||||||
'@next/env@14.3.0-canary.29':
|
'@next/env@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-h5It2nnx97Y+VjVIEP+gLrQ/byTN34bAtHhdQui1fkdlsaBD/B7sjt6BITSJK4zk1IPztdoPHHaI8sMONVbeeg==}
|
resolution: {integrity: sha512-pZMCjC6cG4MEemm3mG+Ac1qzUgAABrqCnB71hjgPXe1adacL/wK7YliSUtoyC9Eurw4Pm0mBi4SCg0z6ymbMVg==}
|
||||||
|
|
||||||
'@next/eslint-plugin-next@14.2.3':
|
'@next/eslint-plugin-next@14.2.3':
|
||||||
resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==}
|
resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==}
|
||||||
|
|
||||||
'@next/swc-darwin-arm64@14.3.0-canary.29':
|
'@next/swc-darwin-arm64@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-ePqJ/d/7dYgdf+7YefmAdW08m5jysGw6PtB309fZbpm0BIUTLfSdShJKG+t6Ivft2jzYIwcfp3LoFHotG8XZTg==}
|
resolution: {integrity: sha512-AMH81oibPiLqhDpSuTinVwO27mvGtXCgq7puAhuFhVTTGfATBh/flwed7utC+/K6bC8dkd5QsRMV4+sxySdLeA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@next/swc-darwin-x64@14.3.0-canary.29':
|
'@next/swc-darwin-x64@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-H/Ese4aLROI3V65DpzKDUUEPtyQir+oNAdrZM1PPFPTRDRMpHz2LvbdcsxQ/aeIkYfRAc+foj5unnFjpIdyFIg==}
|
resolution: {integrity: sha512-fsFpGflXJyEXwD5k9fjMHOie6hj641hKAn4em8e3ohagH8nnb7OpC2QAtxv9WCkdSnH2Lv3OcLqsL4quieMKmg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@next/swc-linux-arm64-gnu@14.3.0-canary.29':
|
'@next/swc-linux-arm64-gnu@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-hW1DOdQAw4oOV6rAwBZh4R1i24xYwjoXgAKHbz5BlVq9QFEW5Zku0srzSl4eDPG2VEgZWcFCkmMamqR+gZheJA==}
|
resolution: {integrity: sha512-+PtZuhB5WwMICXMfmtK6Ax3S+CZkgj2++M/G/8wJfifghoeesVQgmVlFLgVtjApE2wQXwYJture3LlqteeM7vw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-arm64-musl@14.3.0-canary.29':
|
'@next/swc-linux-arm64-musl@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-tn2OT3NUyd/B2q5jnwtbM2pta/r+eizQFgM8ZMxhGHsl0Md3qmCE8TqR6PjiTTipcrG7KP7qElxwWkyYiEGYIg==}
|
resolution: {integrity: sha512-tgvJKQq68cGyrsIjm0X5jkGOlHMvJwRfUf7UAHTHcqtbwXF/SLLDkQHlCtnPXgaBYEEIH6GG9loo3+v/nzLzQg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-x64-gnu@14.3.0-canary.29':
|
'@next/swc-linux-x64-gnu@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-S2EfPr1qbU2y/+dJPdnr3aJIOxS0vsYz+VDAccUdbmXhzM3RSdsaE0okZWztih8AmKiiCS69MFWo6hUKnlOL4A==}
|
resolution: {integrity: sha512-tmQmL6WJ6DUFOLcIy8BFHwTzjJKLK7xp35OWdoOV/GibL4T9OSDkMAtKxRALvFsQ71LsIF+O69qDrvZ+35i+rA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-x64-musl@14.3.0-canary.29':
|
'@next/swc-linux-x64-musl@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-DfTjNpx1Szk82LEHRq1u57tSjGBrg3+kgIfM5/O0OUdU+6ESEOdaLlf7YrD1gIu3k4lDfn37b4S7R/BmPme0tg==}
|
resolution: {integrity: sha512-kXs2JVLdL1MWkFKMfVavlRJl9+Ep0xFLyrrJrxxyxBFp2qNXYqKXjEXXqYpKv0btnSHf7Tokt89TZztRxoaJlw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-win32-arm64-msvc@14.3.0-canary.29':
|
'@next/swc-win32-arm64-msvc@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-C9Igll3rnPoRFgUUFCJMOQkmAFEDiQnVPO2tfxRyleXQP9jpSYY55PYpHGFOp6L0iNy8zc/PuznmR3pcS3E2fQ==}
|
resolution: {integrity: sha512-HU18Co5cE7Hgrjwac6CzdtxErJJ1KHVBoVegMpH6BWBjWASv05vM9yK6fJyRsWG1mJu152Ozr0TgpXBOAkA7UQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@next/swc-win32-ia32-msvc@14.3.0-canary.29':
|
'@next/swc-win32-ia32-msvc@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-5ItF8rCzPMFhG9mlcPl5YpccUyhj3G5ElkjacRJYnqok2GQVmXtu6Ot5+LEGT86TCpizzTx+NkkY/lBSu28RRw==}
|
resolution: {integrity: sha512-sSq2frpcGuriFymNBFyppV7Vli8q6+jEyYBbqJo9QHXj5swvTksirnws9vwPM0PALfM6HPMgA1YkEW3DITWq9Q==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@next/swc-win32-x64-msvc@14.3.0-canary.29':
|
'@next/swc-win32-x64-msvc@14.3.0-canary.37':
|
||||||
resolution: {integrity: sha512-Bjd22hlcK4Kf4/jqPz6GyRiZ+h2Oa/h64RnZFrAvFJJfpBBMIQlihYLoS6HRwdS+bAXPrlf6cOz4TLVdFnum4w==}
|
resolution: {integrity: sha512-Qs4JJYMRG7wq/BTDHoNIz8kmbEk4O08dswfgCH3nKbDKCYJ1z/UYedksNrydRFmVyHmYMLyqtxlbUXgPwI02yA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@ -1467,8 +1467,8 @@ packages:
|
|||||||
'@types/node@20.12.7':
|
'@types/node@20.12.7':
|
||||||
resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==}
|
resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==}
|
||||||
|
|
||||||
'@types/pg@8.6.6':
|
'@types/pg@8.11.5':
|
||||||
resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==}
|
resolution: {integrity: sha512-2xMjVviMxneZHDHX5p5S6tsRRs7TpDHeeK7kTTMe/kAC/mRRNjWHjZg0rkiY+e17jXSZV3zJYDxXV8Cy72/Vuw==}
|
||||||
|
|
||||||
'@types/prop-types@15.7.12':
|
'@types/prop-types@15.7.12':
|
||||||
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
|
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
|
||||||
@ -1618,10 +1618,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-uTKddsqVYS2GRAM/QMNNXCTuw9N742mLoGRXoNDcyECaxEXvIHG0dEY+ZnYISV4Vz534VwJO+64fd9XeSggSKw==}
|
resolution: {integrity: sha512-uTKddsqVYS2GRAM/QMNNXCTuw9N742mLoGRXoNDcyECaxEXvIHG0dEY+ZnYISV4Vz534VwJO+64fd9XeSggSKw==}
|
||||||
engines: {node: '>=14.6'}
|
engines: {node: '>=14.6'}
|
||||||
|
|
||||||
'@vercel/postgres@0.8.0':
|
|
||||||
resolution: {integrity: sha512-/QUV9ExwaNdKooRjOQqvrKNVnRvsaXeukPNI5DB1ovUTesglfR/fparw7ngo1KUWWKIVpEj2TRrA+ObRHRdaLg==}
|
|
||||||
engines: {node: '>=14.6'}
|
|
||||||
|
|
||||||
'@vercel/speed-insights@1.0.10':
|
'@vercel/speed-insights@1.0.10':
|
||||||
resolution: {integrity: sha512-4uzdKB0RW6Ff2FkzshzjZ+RlJfLPxgm/00i0XXgxfMPhwnnsk92YgtqsxT9OcPLdJUyVU1DqFlSWWjIQMPkh0g==}
|
resolution: {integrity: sha512-4uzdKB0RW6Ff2FkzshzjZ+RlJfLPxgm/00i0XXgxfMPhwnnsk92YgtqsxT9OcPLdJUyVU1DqFlSWWjIQMPkh0g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -3260,8 +3256,8 @@ packages:
|
|||||||
react: ^16.8 || ^17 || ^18
|
react: ^16.8 || ^17 || ^18
|
||||||
react-dom: ^16.8 || ^17 || ^18
|
react-dom: ^16.8 || ^17 || ^18
|
||||||
|
|
||||||
next@14.3.0-canary.29:
|
next@14.3.0-canary.37:
|
||||||
resolution: {integrity: sha512-+4mx9dCIVBcW5jMs67jQ2ZCnb3VQ6AQPNBW6t8j17T+9Mp+h0c1XLzrCbfRETpDfdE0nfID2ilUYpQY/8oairg==}
|
resolution: {integrity: sha512-tWIT0Lep3IS+O3RELN4RUWqNHsQeqWJgf43riJgV3mJoWdRSlX610xyif63ZGwaz8Qd6MbvuGbtNWDnWCBZf0w==}
|
||||||
engines: {node: '>=18.17.0'}
|
engines: {node: '>=18.17.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -3358,6 +3354,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==}
|
resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
obuf@1.1.2:
|
||||||
|
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
|
||||||
|
|
||||||
once@1.4.0:
|
once@1.4.0:
|
||||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||||
|
|
||||||
@ -3434,10 +3433,25 @@ packages:
|
|||||||
periscopic@3.1.0:
|
periscopic@3.1.0:
|
||||||
resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
|
resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
|
||||||
|
|
||||||
|
pg-cloudflare@1.1.1:
|
||||||
|
resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==}
|
||||||
|
|
||||||
|
pg-connection-string@2.6.4:
|
||||||
|
resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==}
|
||||||
|
|
||||||
pg-int8@1.0.1:
|
pg-int8@1.0.1:
|
||||||
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
|
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
|
||||||
engines: {node: '>=4.0.0'}
|
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:
|
||||||
|
resolution: {integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==}
|
||||||
|
peerDependencies:
|
||||||
|
pg: '>=8.0'
|
||||||
|
|
||||||
pg-protocol@1.6.1:
|
pg-protocol@1.6.1:
|
||||||
resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==}
|
resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==}
|
||||||
|
|
||||||
@ -3445,6 +3459,22 @@ packages:
|
|||||||
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
|
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
pg-types@4.0.2:
|
||||||
|
resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
pg@8.11.5:
|
||||||
|
resolution: {integrity: sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==}
|
||||||
|
engines: {node: '>= 8.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
pg-native: '>=3.0.1'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
pg-native:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
pgpass@1.0.5:
|
||||||
|
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
|
||||||
|
|
||||||
picocolors@1.0.0:
|
picocolors@1.0.0:
|
||||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||||
|
|
||||||
@ -3517,18 +3547,37 @@ packages:
|
|||||||
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
|
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
postgres-array@3.0.2:
|
||||||
|
resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
postgres-bytea@1.0.0:
|
postgres-bytea@1.0.0:
|
||||||
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
|
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
postgres-bytea@3.0.0:
|
||||||
|
resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
postgres-date@1.0.7:
|
postgres-date@1.0.7:
|
||||||
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
|
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
postgres-date@2.1.0:
|
||||||
|
resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
postgres-interval@1.2.0:
|
postgres-interval@1.2.0:
|
||||||
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
|
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
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==}
|
||||||
|
|
||||||
preact-render-to-string@5.2.3:
|
preact-render-to-string@5.2.3:
|
||||||
resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==}
|
resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -3821,6 +3870,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
split2@4.2.0:
|
||||||
|
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
||||||
|
engines: {node: '>= 10.x'}
|
||||||
|
|
||||||
sprintf-js@1.0.3:
|
sprintf-js@1.0.3:
|
||||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||||
|
|
||||||
@ -4242,18 +4295,6 @@ packages:
|
|||||||
utf-8-validate:
|
utf-8-validate:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
ws@8.14.2:
|
|
||||||
resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
bufferutil: ^4.0.1
|
|
||||||
utf-8-validate: '>=5.0.2'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
bufferutil:
|
|
||||||
optional: true
|
|
||||||
utf-8-validate:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
ws@8.16.0:
|
ws@8.16.0:
|
||||||
resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==}
|
resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
@ -5405,10 +5446,6 @@ snapshots:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
|
|
||||||
'@neondatabase/serverless@0.7.2':
|
|
||||||
dependencies:
|
|
||||||
'@types/pg': 8.6.6
|
|
||||||
|
|
||||||
'@next/bundle-analyzer@14.2.3(bufferutil@4.0.8)(utf-8-validate@6.0.3)':
|
'@next/bundle-analyzer@14.2.3(bufferutil@4.0.8)(utf-8-validate@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
webpack-bundle-analyzer: 4.10.1(bufferutil@4.0.8)(utf-8-validate@6.0.3)
|
webpack-bundle-analyzer: 4.10.1(bufferutil@4.0.8)(utf-8-validate@6.0.3)
|
||||||
@ -5416,37 +5453,37 @@ snapshots:
|
|||||||
- bufferutil
|
- bufferutil
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
|
||||||
'@next/env@14.3.0-canary.29': {}
|
'@next/env@14.3.0-canary.37': {}
|
||||||
|
|
||||||
'@next/eslint-plugin-next@14.2.3':
|
'@next/eslint-plugin-next@14.2.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
glob: 10.3.10
|
glob: 10.3.10
|
||||||
|
|
||||||
'@next/swc-darwin-arm64@14.3.0-canary.29':
|
'@next/swc-darwin-arm64@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-darwin-x64@14.3.0-canary.29':
|
'@next/swc-darwin-x64@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-arm64-gnu@14.3.0-canary.29':
|
'@next/swc-linux-arm64-gnu@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-arm64-musl@14.3.0-canary.29':
|
'@next/swc-linux-arm64-musl@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-x64-gnu@14.3.0-canary.29':
|
'@next/swc-linux-x64-gnu@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-x64-musl@14.3.0-canary.29':
|
'@next/swc-linux-x64-musl@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-arm64-msvc@14.3.0-canary.29':
|
'@next/swc-win32-arm64-msvc@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-ia32-msvc@14.3.0-canary.29':
|
'@next/swc-win32-ia32-msvc@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-x64-msvc@14.3.0-canary.29':
|
'@next/swc-win32-x64-msvc@14.3.0-canary.37':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
@ -6195,11 +6232,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 5.26.5
|
undici-types: 5.26.5
|
||||||
|
|
||||||
'@types/pg@8.6.6':
|
'@types/pg@8.11.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.12.7
|
'@types/node': 20.12.7
|
||||||
pg-protocol: 1.6.1
|
pg-protocol: 1.6.1
|
||||||
pg-types: 2.2.0
|
pg-types: 4.0.2
|
||||||
|
|
||||||
'@types/prop-types@15.7.12': {}
|
'@types/prop-types@15.7.12': {}
|
||||||
|
|
||||||
@ -6368,11 +6405,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
crypto-js: 4.2.0
|
crypto-js: 4.2.0
|
||||||
|
|
||||||
'@vercel/analytics@1.2.2(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
|
'@vercel/analytics@1.2.2(next@14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
server-only: 0.0.1
|
server-only: 0.0.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
next: 14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
next: 14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|
||||||
'@vercel/blob@0.23.2':
|
'@vercel/blob@0.23.2':
|
||||||
@ -6386,16 +6423,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@upstash/redis': 1.25.1
|
'@upstash/redis': 1.25.1
|
||||||
|
|
||||||
'@vercel/postgres@0.8.0':
|
'@vercel/speed-insights@1.0.10(next@14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))':
|
||||||
dependencies:
|
|
||||||
'@neondatabase/serverless': 0.7.2
|
|
||||||
bufferutil: 4.0.8
|
|
||||||
utf-8-validate: 6.0.3
|
|
||||||
ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3)
|
|
||||||
|
|
||||||
'@vercel/speed-insights@1.0.10(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))':
|
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
next: 14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
next: 14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
svelte: 4.2.15
|
svelte: 4.2.15
|
||||||
vue: 3.4.25(typescript@5.4.5)
|
vue: 3.4.25(typescript@5.4.5)
|
||||||
@ -6747,6 +6777,7 @@ snapshots:
|
|||||||
bufferutil@4.0.8:
|
bufferutil@4.0.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
node-gyp-build: 4.8.0
|
node-gyp-build: 4.8.0
|
||||||
|
optional: true
|
||||||
|
|
||||||
busboy@1.6.0:
|
busboy@1.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -8381,10 +8412,10 @@ snapshots:
|
|||||||
|
|
||||||
natural-compare@1.4.0: {}
|
natural-compare@1.4.0: {}
|
||||||
|
|
||||||
next-auth@5.0.0-beta.15(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
|
next-auth@5.0.0-beta.15(next@14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@auth/core': 0.28.0
|
'@auth/core': 0.28.0
|
||||||
next: 14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
next: 14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|
||||||
next-themes@0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
next-themes@0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
@ -8392,9 +8423,9 @@ snapshots:
|
|||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
next@14.3.0-canary.37(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/env': 14.3.0-canary.29
|
'@next/env': 14.3.0-canary.37
|
||||||
'@swc/helpers': 0.5.11
|
'@swc/helpers': 0.5.11
|
||||||
busboy: 1.6.0
|
busboy: 1.6.0
|
||||||
caniuse-lite: 1.0.30001612
|
caniuse-lite: 1.0.30001612
|
||||||
@ -8404,15 +8435,15 @@ snapshots:
|
|||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
styled-jsx: 5.1.1(@babel/core@7.24.4)(react@18.3.1)
|
styled-jsx: 5.1.1(@babel/core@7.24.4)(react@18.3.1)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@next/swc-darwin-arm64': 14.3.0-canary.29
|
'@next/swc-darwin-arm64': 14.3.0-canary.37
|
||||||
'@next/swc-darwin-x64': 14.3.0-canary.29
|
'@next/swc-darwin-x64': 14.3.0-canary.37
|
||||||
'@next/swc-linux-arm64-gnu': 14.3.0-canary.29
|
'@next/swc-linux-arm64-gnu': 14.3.0-canary.37
|
||||||
'@next/swc-linux-arm64-musl': 14.3.0-canary.29
|
'@next/swc-linux-arm64-musl': 14.3.0-canary.37
|
||||||
'@next/swc-linux-x64-gnu': 14.3.0-canary.29
|
'@next/swc-linux-x64-gnu': 14.3.0-canary.37
|
||||||
'@next/swc-linux-x64-musl': 14.3.0-canary.29
|
'@next/swc-linux-x64-musl': 14.3.0-canary.37
|
||||||
'@next/swc-win32-arm64-msvc': 14.3.0-canary.29
|
'@next/swc-win32-arm64-msvc': 14.3.0-canary.37
|
||||||
'@next/swc-win32-ia32-msvc': 14.3.0-canary.29
|
'@next/swc-win32-ia32-msvc': 14.3.0-canary.37
|
||||||
'@next/swc-win32-x64-msvc': 14.3.0-canary.29
|
'@next/swc-win32-x64-msvc': 14.3.0-canary.37
|
||||||
sharp: 0.33.3
|
sharp: 0.33.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
@ -8424,7 +8455,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
|
|
||||||
node-gyp-build@4.8.0: {}
|
node-gyp-build@4.8.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
node-int64@0.4.0: {}
|
node-int64@0.4.0: {}
|
||||||
|
|
||||||
@ -8488,6 +8520,8 @@ snapshots:
|
|||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
es-object-atoms: 1.0.0
|
es-object-atoms: 1.0.0
|
||||||
|
|
||||||
|
obuf@1.1.2: {}
|
||||||
|
|
||||||
once@1.4.0:
|
once@1.4.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
wrappy: 1.0.2
|
wrappy: 1.0.2
|
||||||
@ -8574,8 +8608,19 @@ snapshots:
|
|||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
is-reference: 3.0.2
|
is-reference: 3.0.2
|
||||||
|
|
||||||
|
pg-cloudflare@1.1.1:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
pg-connection-string@2.6.4: {}
|
||||||
|
|
||||||
pg-int8@1.0.1: {}
|
pg-int8@1.0.1: {}
|
||||||
|
|
||||||
|
pg-numeric@1.0.2: {}
|
||||||
|
|
||||||
|
pg-pool@3.6.2(pg@8.11.5):
|
||||||
|
dependencies:
|
||||||
|
pg: 8.11.5
|
||||||
|
|
||||||
pg-protocol@1.6.1: {}
|
pg-protocol@1.6.1: {}
|
||||||
|
|
||||||
pg-types@2.2.0:
|
pg-types@2.2.0:
|
||||||
@ -8586,6 +8631,30 @@ snapshots:
|
|||||||
postgres-date: 1.0.7
|
postgres-date: 1.0.7
|
||||||
postgres-interval: 1.2.0
|
postgres-interval: 1.2.0
|
||||||
|
|
||||||
|
pg-types@4.0.2:
|
||||||
|
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.11.5:
|
||||||
|
dependencies:
|
||||||
|
pg-connection-string: 2.6.4
|
||||||
|
pg-pool: 3.6.2(pg@8.11.5)
|
||||||
|
pg-protocol: 1.6.1
|
||||||
|
pg-types: 2.2.0
|
||||||
|
pgpass: 1.0.5
|
||||||
|
optionalDependencies:
|
||||||
|
pg-cloudflare: 1.1.1
|
||||||
|
|
||||||
|
pgpass@1.0.5:
|
||||||
|
dependencies:
|
||||||
|
split2: 4.2.0
|
||||||
|
|
||||||
picocolors@1.0.0: {}
|
picocolors@1.0.0: {}
|
||||||
|
|
||||||
picomatch@2.3.1: {}
|
picomatch@2.3.1: {}
|
||||||
@ -8645,14 +8714,26 @@ snapshots:
|
|||||||
|
|
||||||
postgres-array@2.0.0: {}
|
postgres-array@2.0.0: {}
|
||||||
|
|
||||||
|
postgres-array@3.0.2: {}
|
||||||
|
|
||||||
postgres-bytea@1.0.0: {}
|
postgres-bytea@1.0.0: {}
|
||||||
|
|
||||||
|
postgres-bytea@3.0.0:
|
||||||
|
dependencies:
|
||||||
|
obuf: 1.1.2
|
||||||
|
|
||||||
postgres-date@1.0.7: {}
|
postgres-date@1.0.7: {}
|
||||||
|
|
||||||
|
postgres-date@2.1.0: {}
|
||||||
|
|
||||||
postgres-interval@1.2.0:
|
postgres-interval@1.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
xtend: 4.0.2
|
xtend: 4.0.2
|
||||||
|
|
||||||
|
postgres-interval@3.0.0: {}
|
||||||
|
|
||||||
|
postgres-range@1.1.4: {}
|
||||||
|
|
||||||
preact-render-to-string@5.2.3(preact@10.11.3):
|
preact-render-to-string@5.2.3(preact@10.11.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
preact: 10.11.3
|
preact: 10.11.3
|
||||||
@ -8960,6 +9041,8 @@ snapshots:
|
|||||||
|
|
||||||
source-map@0.6.1: {}
|
source-map@0.6.1: {}
|
||||||
|
|
||||||
|
split2@4.2.0: {}
|
||||||
|
|
||||||
sprintf-js@1.0.3: {}
|
sprintf-js@1.0.3: {}
|
||||||
|
|
||||||
sswr@2.0.0(svelte@4.2.15):
|
sswr@2.0.0(svelte@4.2.15):
|
||||||
@ -9308,6 +9391,7 @@ snapshots:
|
|||||||
utf-8-validate@6.0.3:
|
utf-8-validate@6.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
node-gyp-build: 4.8.0
|
node-gyp-build: 4.8.0
|
||||||
|
optional: true
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
@ -9448,11 +9532,6 @@ snapshots:
|
|||||||
bufferutil: 4.0.8
|
bufferutil: 4.0.8
|
||||||
utf-8-validate: 6.0.3
|
utf-8-validate: 6.0.3
|
||||||
|
|
||||||
ws@8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3):
|
|
||||||
optionalDependencies:
|
|
||||||
bufferutil: 4.0.8
|
|
||||||
utf-8-validate: 6.0.3
|
|
||||||
|
|
||||||
ws@8.16.0(bufferutil@4.0.8)(utf-8-validate@6.0.3):
|
ws@8.16.0(bufferutil@4.0.8)(utf-8-validate@6.0.3):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
bufferutil: 4.0.8
|
bufferutil: 4.0.8
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { getPhotosCountIncludingHiddenCached } from '@/photo/cache';
|
|||||||
import StorageUrls from '@/admin/StorageUrls';
|
import StorageUrls from '@/admin/StorageUrls';
|
||||||
import { PRO_MODE_ENABLED } from '@/site/config';
|
import { PRO_MODE_ENABLED } from '@/site/config';
|
||||||
import { getStoragePhotoUrlsNoStore } from '@/services/storage/cache';
|
import { getStoragePhotoUrlsNoStore } from '@/services/storage/cache';
|
||||||
import { getPhotos } from '@/services/vercel-postgres';
|
import { getPhotos } from '@/photo/db';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { revalidatePath } from 'next/cache';
|
||||||
import AdminPhotoTable from '@/admin/AdminPhotoTable';
|
import AdminPhotoTable from '@/admin/AdminPhotoTable';
|
||||||
import AdminPhotoTableInfinite from
|
import AdminPhotoTableInfinite from
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { getPhotosCached } from '@/photo/cache';
|
|||||||
import TagForm from '@/tag/TagForm';
|
import TagForm from '@/tag/TagForm';
|
||||||
import { PATH_ADMIN, PATH_ADMIN_TAGS, pathForTag } from '@/site/paths';
|
import { PATH_ADMIN, PATH_ADMIN_TAGS, pathForTag } from '@/site/paths';
|
||||||
import PhotoLightbox from '@/photo/PhotoLightbox';
|
import PhotoLightbox from '@/photo/PhotoLightbox';
|
||||||
import { getPhotosTagMeta } from '@/services/vercel-postgres';
|
import { getPhotosTagMeta } from '@/photo/db';
|
||||||
import AdminTagBadge from '@/admin/AdminTagBadge';
|
import AdminTagBadge from '@/admin/AdminTagBadge';
|
||||||
|
|
||||||
const MAX_PHOTO_TO_SHOW = 6;
|
const MAX_PHOTO_TO_SHOW = 6;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { MAX_PHOTOS_TO_SHOW_OG } from '@/image-response';
|
|||||||
import { Metadata } from 'next/types';
|
import { Metadata } from 'next/types';
|
||||||
import PhotoGridSidebar from '@/photo/PhotoGridSidebar';
|
import PhotoGridSidebar from '@/photo/PhotoGridSidebar';
|
||||||
import { getPhotoSidebarData } from '@/photo/data';
|
import { getPhotoSidebarData } from '@/photo/data';
|
||||||
import { getPhotos } from '@/services/vercel-postgres';
|
import { getPhotos } from '@/photo/db';
|
||||||
import { cache } from 'react';
|
import { cache } from 'react';
|
||||||
import PhotoGridInfinite from '@/photo/PhotoGridInfinite';
|
import PhotoGridInfinite from '@/photo/PhotoGridInfinite';
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { Metadata } from 'next/types';
|
|||||||
import { MAX_PHOTOS_TO_SHOW_OG } from '@/image-response';
|
import { MAX_PHOTOS_TO_SHOW_OG } from '@/image-response';
|
||||||
import PhotosLarge from '@/photo/PhotosLarge';
|
import PhotosLarge from '@/photo/PhotosLarge';
|
||||||
import { cache } from 'react';
|
import { cache } from 'react';
|
||||||
import { getPhotos, getPhotosCount } from '@/services/vercel-postgres';
|
import { getPhotos, getPhotosCount } from '@/photo/db';
|
||||||
import PhotosLargeInfinite from '@/photo/PhotosLargeInfinite';
|
import PhotosLargeInfinite from '@/photo/PhotosLargeInfinite';
|
||||||
|
|
||||||
export const dynamic = 'force-static';
|
export const dynamic = 'force-static';
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
sqlRenamePhotoTagGlobally,
|
sqlRenamePhotoTagGlobally,
|
||||||
getPhoto,
|
getPhoto,
|
||||||
getPhotos,
|
getPhotos,
|
||||||
} from '@/services/vercel-postgres';
|
} from '@/photo/db';
|
||||||
import {
|
import {
|
||||||
PhotoFormData,
|
PhotoFormData,
|
||||||
convertFormDataToPhotoDbInsert,
|
convertFormDataToPhotoDbInsert,
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import {
|
|||||||
getPhotosDateRange,
|
getPhotosDateRange,
|
||||||
getPhotosNearId,
|
getPhotosNearId,
|
||||||
getPhotosMostRecentUpdate,
|
getPhotosMostRecentUpdate,
|
||||||
} from '@/services/vercel-postgres';
|
} from '@/photo/db';
|
||||||
import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo';
|
import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo';
|
||||||
import { createCameraKey } from '@/camera';
|
import { createCameraKey } from '@/camera';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
getUniqueCameras,
|
getUniqueCameras,
|
||||||
getUniqueFilmSimulations,
|
getUniqueFilmSimulations,
|
||||||
getUniqueTags,
|
getUniqueTags,
|
||||||
} from '@/services/vercel-postgres';
|
} from '@/photo/db';
|
||||||
import { SHOW_FILM_SIMULATIONS } from '@/site/config';
|
import { SHOW_FILM_SIMULATIONS } from '@/site/config';
|
||||||
import { sortTagsObject } from '@/tag';
|
import { sortTagsObject } from '@/tag';
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
import { db, sql } from '@vercel/postgres';
|
import {
|
||||||
|
sql,
|
||||||
|
query,
|
||||||
|
convertArrayToPostgresString,
|
||||||
|
} from '@/services/postgres';
|
||||||
import {
|
import {
|
||||||
PhotoDb,
|
PhotoDb,
|
||||||
PhotoDbInsert,
|
PhotoDbInsert,
|
||||||
@ -16,10 +20,6 @@ import { screenForPPR } from '@/utility/ppr';
|
|||||||
|
|
||||||
const PHOTO_DEFAULT_LIMIT = 100;
|
const PHOTO_DEFAULT_LIMIT = 100;
|
||||||
|
|
||||||
export const convertArrayToPostgresString = (array?: string[]) => array
|
|
||||||
? `{${array.join(',')}}`
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const sqlCreatePhotosTable = () =>
|
const sqlCreatePhotosTable = () =>
|
||||||
sql`
|
sql`
|
||||||
CREATE TABLE IF NOT EXISTS photos (
|
CREATE TABLE IF NOT EXISTS photos (
|
||||||
@ -353,7 +353,7 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => {
|
|||||||
sortBy = PRIORITY_ORDER_ENABLED ? 'priority' : 'takenAt',
|
sortBy = PRIORITY_ORDER_ENABLED ? 'priority' : 'takenAt',
|
||||||
limit = PHOTO_DEFAULT_LIMIT,
|
limit = PHOTO_DEFAULT_LIMIT,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
query,
|
query: queryOption,
|
||||||
tag,
|
tag,
|
||||||
camera,
|
camera,
|
||||||
simulation,
|
simulation,
|
||||||
@ -379,10 +379,10 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => {
|
|||||||
wheres.push(`taken_at <= $${valueIndex++}`);
|
wheres.push(`taken_at <= $${valueIndex++}`);
|
||||||
values.push(takenAfterInclusive.toISOString());
|
values.push(takenAfterInclusive.toISOString());
|
||||||
}
|
}
|
||||||
if (query) {
|
if (queryOption) {
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
wheres.push(`CONCAT(title, ' ', caption, ' ', semantic_description) ILIKE $${valueIndex++}`);
|
wheres.push(`CONCAT(title, ' ', caption, ' ', semantic_description) ILIKE $${valueIndex++}`);
|
||||||
values.push(`%${query.toLocaleLowerCase()}%`);
|
values.push(`%${queryOption.toLocaleLowerCase()}%`);
|
||||||
}
|
}
|
||||||
if (tag) {
|
if (tag) {
|
||||||
wheres.push(`$${valueIndex++}=ANY(tags)`);
|
wheres.push(`$${valueIndex++}=ANY(tags)`);
|
||||||
@ -420,7 +420,7 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => {
|
|||||||
values.push(limit, offset);
|
values.push(limit, offset);
|
||||||
|
|
||||||
return safelyQueryPhotos(async () => {
|
return safelyQueryPhotos(async () => {
|
||||||
return db.query(sql.join(' '), values);
|
return query(sql.join(' '), values);
|
||||||
}, sql.join(' '))
|
}, sql.join(' '))
|
||||||
.then(({ rows }) => rows.map(parsePhotoFromDb));
|
.then(({ rows }) => rows.map(parsePhotoFromDb));
|
||||||
};
|
};
|
||||||
@ -434,7 +434,7 @@ export const getPhotosNearId = async (
|
|||||||
: 'ORDER BY taken_at DESC';
|
: 'ORDER BY taken_at DESC';
|
||||||
|
|
||||||
return safelyQueryPhotos(async () => {
|
return safelyQueryPhotos(async () => {
|
||||||
return db.query(
|
return query(
|
||||||
`
|
`
|
||||||
WITH twi AS (
|
WITH twi AS (
|
||||||
SELECT *, row_number()
|
SELECT *, row_number()
|
||||||
54
src/services/postgres.ts
Normal file
54
src/services/postgres.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { POSTGRES_SSL_ENABLED } from '@/site/config';
|
||||||
|
import { Pool, QueryResult, QueryResultRow } from 'pg';
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
connectionString: process.env.POSTGRES_URL,
|
||||||
|
...POSTGRES_SSL_ENABLED && { ssl: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Primitive = string | number | boolean | undefined | null;
|
||||||
|
|
||||||
|
export const query = async <T extends QueryResultRow = any>(
|
||||||
|
queryString: string,
|
||||||
|
values: Primitive[],
|
||||||
|
) => {
|
||||||
|
const client = await pool.connect();
|
||||||
|
let response: QueryResult<T>;
|
||||||
|
try {
|
||||||
|
response = await client.query<T>(queryString, values);
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
client.release();
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sql = <T extends QueryResultRow>(
|
||||||
|
strings: TemplateStringsArray,
|
||||||
|
...values: Primitive[]
|
||||||
|
) => {
|
||||||
|
if (!isTemplateStringsArray(strings) || !Array.isArray(values)) {
|
||||||
|
throw new Error('Invalid template literal argument');
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = strings[0] ?? '';
|
||||||
|
|
||||||
|
for (let i = 1; i < strings.length; i++) {
|
||||||
|
result += `$${i}${strings[i] ?? ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query<T>(result, values);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const convertArrayToPostgresString = (array?: string[]) => array
|
||||||
|
? `{${array.join(',')}}`
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const isTemplateStringsArray = (
|
||||||
|
strings: unknown,
|
||||||
|
): strings is TemplateStringsArray => {
|
||||||
|
return (
|
||||||
|
Array.isArray(strings) && 'raw' in strings && Array.isArray(strings.raw)
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -23,6 +23,8 @@ import { labelForStorage } from '@/services/storage';
|
|||||||
import { HiSparkles } from 'react-icons/hi';
|
import { HiSparkles } from 'react-icons/hi';
|
||||||
|
|
||||||
export default function SiteChecklistClient({
|
export default function SiteChecklistClient({
|
||||||
|
hasDatabase,
|
||||||
|
isPostgresSSLEnabled,
|
||||||
hasVercelPostgres,
|
hasVercelPostgres,
|
||||||
hasVercelKV,
|
hasVercelKV,
|
||||||
hasStorageProvider,
|
hasStorageProvider,
|
||||||
@ -148,16 +150,28 @@ export default function SiteChecklistClient({
|
|||||||
>
|
>
|
||||||
<ChecklistRow
|
<ChecklistRow
|
||||||
title="Setup database"
|
title="Setup database"
|
||||||
status={hasVercelPostgres}
|
status={hasDatabase}
|
||||||
isPending={isPendingPage}
|
isPending={isPendingPage}
|
||||||
>
|
>
|
||||||
{renderLink(
|
{hasVercelPostgres
|
||||||
// eslint-disable-next-line max-len
|
? renderSubStatus('checked', 'Vercel Postgres: connected')
|
||||||
'https://vercel.com/docs/storage/vercel-postgres/quickstart#create-a-postgres-database',
|
: renderSubStatus('optional', <>
|
||||||
'Create Vercel Postgres store',
|
Vercel Postgres:
|
||||||
)}
|
{' '}
|
||||||
{' '}
|
{renderLink(
|
||||||
and connect to project
|
// eslint-disable-next-line max-len
|
||||||
|
'https://vercel.com/docs/storage/vercel-postgres/quickstart#create-a-postgres-database',
|
||||||
|
'create store',
|
||||||
|
)}
|
||||||
|
{' '}
|
||||||
|
and connect to project
|
||||||
|
</>)}
|
||||||
|
{hasDatabase && !hasVercelPostgres &&
|
||||||
|
renderSubStatus('checked', <>
|
||||||
|
Postgres-compatible: connected
|
||||||
|
{' '}
|
||||||
|
(SSL {isPostgresSSLEnabled ? 'enabled' : 'disabled'})
|
||||||
|
</>)}
|
||||||
</ChecklistRow>
|
</ChecklistRow>
|
||||||
<ChecklistRow
|
<ChecklistRow
|
||||||
title={!hasStorageProvider
|
title={!hasStorageProvider
|
||||||
@ -169,9 +183,9 @@ export default function SiteChecklistClient({
|
|||||||
status={hasStorageProvider}
|
status={hasStorageProvider}
|
||||||
isPending={isPendingPage}
|
isPending={isPendingPage}
|
||||||
>
|
>
|
||||||
{renderSubStatus(
|
{hasVercelBlobStorage
|
||||||
hasVercelBlobStorage ? 'checked' : 'optional',
|
? renderSubStatus('checked', 'Vercel Blob: connected')
|
||||||
<>
|
: renderSubStatus('optional', <>
|
||||||
{labelForStorage('vercel-blob')}:
|
{labelForStorage('vercel-blob')}:
|
||||||
{' '}
|
{' '}
|
||||||
{renderLink(
|
{renderLink(
|
||||||
@ -181,30 +195,28 @@ export default function SiteChecklistClient({
|
|||||||
)}
|
)}
|
||||||
{' '}
|
{' '}
|
||||||
and connect to project
|
and connect to project
|
||||||
</>,
|
</>
|
||||||
)}
|
)}
|
||||||
{renderSubStatus(
|
{hasCloudflareR2Storage
|
||||||
hasCloudflareR2Storage ? 'checked' : 'optional',
|
? renderSubStatus('checked', 'Cloudflare R2: connected')
|
||||||
<>
|
: renderSubStatus('optional', <>
|
||||||
{labelForStorage('cloudflare-r2')}:
|
{labelForStorage('cloudflare-r2')}:
|
||||||
{' '}
|
{' '}
|
||||||
{renderLink(
|
{renderLink(
|
||||||
'https://github.com/sambecker/exif-photo-blog#cloudflare-r2',
|
'https://github.com/sambecker/exif-photo-blog#cloudflare-r2',
|
||||||
'create/configure bucket',
|
'create/configure bucket',
|
||||||
)}
|
)}
|
||||||
</>
|
</>)}
|
||||||
)}
|
{hasAwsS3Storage
|
||||||
{renderSubStatus(
|
? renderSubStatus('checked', 'AWS S3: connected')
|
||||||
hasAwsS3Storage ? 'checked' : 'optional',
|
: renderSubStatus('optional', <>
|
||||||
<>
|
|
||||||
{labelForStorage('aws-s3')}:
|
{labelForStorage('aws-s3')}:
|
||||||
{' '}
|
{' '}
|
||||||
{renderLink(
|
{renderLink(
|
||||||
'https://github.com/sambecker/exif-photo-blog#aws-s3',
|
'https://github.com/sambecker/exif-photo-blog#aws-s3',
|
||||||
'create/configure bucket',
|
'create/configure bucket',
|
||||||
)}
|
)}
|
||||||
</>
|
</>)}
|
||||||
)}
|
|
||||||
</ChecklistRow>
|
</ChecklistRow>
|
||||||
</Checklist>
|
</Checklist>
|
||||||
<Checklist
|
<Checklist
|
||||||
|
|||||||
@ -49,10 +49,11 @@ export const SITE_DESCRIPTION =
|
|||||||
process.env.NEXT_PUBLIC_SITE_DESCRIPTION ||
|
process.env.NEXT_PUBLIC_SITE_DESCRIPTION ||
|
||||||
SITE_DOMAIN;
|
SITE_DOMAIN;
|
||||||
|
|
||||||
// STORAGE: VERCEL POSTGRES
|
// STORAGE: DATABASE
|
||||||
export const HAS_VERCEL_POSTGRES =
|
export const HAS_DATABASE =
|
||||||
(process.env.POSTGRES_HOST ?? '').length > 0;
|
(process.env.POSTGRES_URL ?? '').length > 0;
|
||||||
|
export const POSTGRES_SSL_ENABLED =
|
||||||
|
process.env.DISABLE_POSTGRES_SSL === '1' ? false : true;
|
||||||
// STORAGE: VERCEL KV
|
// STORAGE: VERCEL KV
|
||||||
export const HAS_VERCEL_KV =
|
export const HAS_VERCEL_KV =
|
||||||
(process.env.KV_URL ?? '').length > 0;
|
(process.env.KV_URL ?? '').length > 0;
|
||||||
@ -134,7 +135,10 @@ export const ADMIN_DEBUG_TOOLS_ENABLED = process.env.ADMIN_DEBUG_TOOLS === '1';
|
|||||||
export const HIGH_DENSITY_GRID = GRID_ASPECT_RATIO <= 1;
|
export const HIGH_DENSITY_GRID = GRID_ASPECT_RATIO <= 1;
|
||||||
|
|
||||||
export const CONFIG_CHECKLIST_STATUS = {
|
export const CONFIG_CHECKLIST_STATUS = {
|
||||||
hasVercelPostgres: HAS_VERCEL_POSTGRES,
|
hasDatabase: HAS_DATABASE,
|
||||||
|
isPostgresSSLEnabled: POSTGRES_SSL_ENABLED,
|
||||||
|
hasVercelPostgres: /\.vercel-storage\.com\//
|
||||||
|
.test(process.env.POSTGRES_URL ?? ''),
|
||||||
hasVercelKV: HAS_VERCEL_KV,
|
hasVercelKV: HAS_VERCEL_KV,
|
||||||
hasVercelBlobStorage: HAS_VERCEL_BLOB_STORAGE,
|
hasVercelBlobStorage: HAS_VERCEL_BLOB_STORAGE,
|
||||||
hasCloudflareR2Storage: HAS_CLOUDFLARE_R2_STORAGE,
|
hasCloudflareR2Storage: HAS_CLOUDFLARE_R2_STORAGE,
|
||||||
@ -177,7 +181,7 @@ export const CONFIG_CHECKLIST_STATUS = {
|
|||||||
export type ConfigChecklistStatus = typeof CONFIG_CHECKLIST_STATUS;
|
export type ConfigChecklistStatus = typeof CONFIG_CHECKLIST_STATUS;
|
||||||
|
|
||||||
export const IS_SITE_READY =
|
export const IS_SITE_READY =
|
||||||
CONFIG_CHECKLIST_STATUS.hasVercelPostgres &&
|
CONFIG_CHECKLIST_STATUS.hasDatabase &&
|
||||||
CONFIG_CHECKLIST_STATUS.hasStorageProvider &&
|
CONFIG_CHECKLIST_STATUS.hasStorageProvider &&
|
||||||
CONFIG_CHECKLIST_STATUS.hasAuthSecret &&
|
CONFIG_CHECKLIST_STATUS.hasAuthSecret &&
|
||||||
CONFIG_CHECKLIST_STATUS.hasAdminUser;
|
CONFIG_CHECKLIST_STATUS.hasAdminUser;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user