diff --git a/README.md b/README.md index e6b2d455..a4a2b907 100644 --- a/README.md +++ b/README.md @@ -96,27 +96,34 @@ _⚠️ READ BEFORE PROCEEDING_ Application behavior can be changed by configuring the following environment variables: -#### Site meta +#### Content - `NEXT_PUBLIC_SITE_TITLE` (seen in browser tab) - `NEXT_PUBLIC_SITE_DESCRIPTION` (seen in nav, beneath title) - `NEXT_PUBLIC_SITE_ABOUT` (seen in grid sidebar—accepts rich formatting tags: ``, ``, ``, ``, ``, `
`) -#### Site behavior +#### Performance +> ⚠️ Enabling may result in increased project usage +- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTOS = 1` enables static optimization for photo pages (`p/[photoId]`), i.e., renders pages at build time +- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_OG_IMAGES = 1` enables static optimization for OG images, i.e., renders images at build time +- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORIES = 1` enables static optimization for photo categories (`tag/[tag]`, `shot-on/[make]/[model]`, etc.), i.e., renders pages at build time +- `NEXT_PUBLIC_PRESERVE_ORIGINAL_UPLOADS = 1` prevents photo uploads being compressed before storing +- `NEXT_PUBLIC_BLUR_DISABLED = 1` prevents image blur data being stored and displayed (potentially useful for limiting Postgres usage) + +#### Display +- `NEXT_PUBLIC_HIDE_EXIF_DATA = 1` hides EXIF data in photo details and OG images (potentially useful for portfolios, which don't focus on photography) +- `NEXT_PUBLIC_HIDE_TAKEN_AT_TIME = 1` hides taken at time from photo meta +- `NEXT_PUBLIC_HIDE_SOCIAL = 1` removes X button from share modal +- `NEXT_PUBLIC_HIDE_FILM_SIMULATIONS = 1` prevents Fujifilm simulations showing up in `/grid` sidebar and CMD-K search results +- `NEXT_PUBLIC_HIDE_REPO_LINK = 1` removes footer link to repo + +#### Settings - `NEXT_PUBLIC_GRID_HOMEPAGE = 1` shows grid layout on homepage - `NEXT_PUBLIC_DEFAULT_THEME = light | dark` sets preferred initial theme (defaults to `system` when not configured) -- `NEXT_PUBLIC_PRO_MODE = 1` enables higher quality image storage (results in increased storage usage) -- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PAGES = 1` enables static optimization for pages, i.e., renders pages at build time (results in increased project usage)—⚠️ _Experimental_ -- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_OG_IMAGES = 1` enables static optimization for OG images, i.e., renders images at build time (results in increased project usage)—⚠️ _Experimental_ - `NEXT_PUBLIC_MATTE_PHOTOS = 1` constrains the size of each photo, and enables a surrounding border (potentially useful for photos with tall aspect ratios) -- `NEXT_PUBLIC_BLUR_DISABLED = 1` prevents image blur data being stored and displayed (potentially useful for limiting Postgres usage) - `NEXT_PUBLIC_GEO_PRIVACY = 1` disables collection/display of location-based data (⚠️ re-compresses uploaded images in order to remove GPS information) -- `NEXT_PUBLIC_HIDE_REPO_LINK = 1` removes footer link to repo - `NEXT_PUBLIC_ALLOW_PUBLIC_DOWNLOADS = 1` enables public photo downloads for all visitors (⚠️ may result in increased bandwidth usage) - `NEXT_PUBLIC_PUBLIC_API = 1` enables public API available at `/api` - `NEXT_PUBLIC_IGNORE_PRIORITY_ORDER = 1` prevents `priority_order` field affecting photo order -- `NEXT_PUBLIC_HIDE_SOCIAL = 1` removes X button from share modal -- `NEXT_PUBLIC_HIDE_FILM_SIMULATIONS = 1` prevents Fujifilm simulations showing up in `/grid` sidebar and CMD-K search results -- `NEXT_PUBLIC_HIDE_EXIF_DATA = 1` hides EXIF data in photo details and OG images (potentially useful for portfolios, which don't focus on photography) - `NEXT_PUBLIC_GRID_ASPECT_RATIO = 1.5` sets aspect ratio for grid tiles (defaults to `1`—setting to `0` removes the constraint) - `NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS = 1` ensures large thumbnails on photo grid views - `NEXT_PUBLIC_OG_TEXT_ALIGNMENT = BOTTOM` keeps OG image text bottom aligned (default is top) @@ -152,7 +159,7 @@ Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used a - Store public configuration: - `NEXT_PUBLIC_CLOUDFLARE_R2_BUCKET`: bucket name - `NEXT_PUBLIC_CLOUDFLARE_R2_ACCOUNT_ID`: account id (found on R2 overview page) - - `NEXT_PUBLIC_CLOUDFLARE_R2_PUBLIC_DOMAIN`: either "your-custom-domain.com" or "pub-jf90908...s0d9f8s0s9df.r2.dev" (_do not include "https://" in your domain_) + - `NEXT_PUBLIC_CLOUDFLARE_R2_PUBLIC_DOMAIN`: either "your-custom-domain.com" or "pub-jf90908...s0d9f8s0s9df.r2.dev" 2. Setup private credentials - Create API token by selecting "Manage R2 API Tokens," and clicking "Create API Token" - Select "Object Read & Write," choose "Apply to specific buckets only," and select the bucket created in Step 1 @@ -233,7 +240,7 @@ FAQ > As the template has evolved, EXIF fields (such as lenses) have been added, blur data is generated through a different method, and AI/privacy features have been added. In order to bring older photos up to date, either click the 'sync' button next to a photo or use the outdated photo page (`/admin/outdated`) to make batch updates. #### Why don’t my OG images load when I share a link? -> Many services such as iMessage, Slack, and X, require near-instant responses when unfurling link-based content. In order to guarantee sufficient responsiveness, consider rendering pages and image assets ahead of time by enabling static optimization by setting `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PAGES = 1` and `NEXT_PUBLIC_STATICALLY_OPTIMIZE_OG_IMAGES = 1`. Keep in mind that this will increase platform usage. +> Many services such as iMessage, Slack, and X, require near-instant responses when unfurling link-based content. In order to guarantee sufficient responsiveness, consider rendering pages and image assets ahead of time by enabling static optimization by setting `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTOS = 1` and `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_OG_IMAGES = 1`. Keep in mind that this will increase platform usage. #### Why do vertical images take up so much space? > By default, all photos are shown full-width, regardless of orientation. Enable matting to showcase horizontal and vertical photos at similar scales by setting `NEXT_PUBLIC_MATTE_PHOTOS = 1`. diff --git a/__tests__/date.test.ts b/__tests__/date.test.ts index 6257779e..a6ebadeb 100644 --- a/__tests__/date.test.ts +++ b/__tests__/date.test.ts @@ -1,6 +1,9 @@ +/* eslint-disable max-len */ import { convertTimestampToNaivePostgresString, convertTimestampWithOffsetToPostgresString, + validatePostgresDateString, + validateNaivePostgresDateString, } from '../src/utility/date'; describe('Date utility', () => { @@ -29,19 +32,34 @@ describe('Date utility', () => { expect(convertTimestampToNaivePostgresString(timestamp)) .toBe('2023-12-02 16:38:36'); }); + it('Malformed date string', () => { + const timestamp = '2024/01a/01 Z'; + expect(convertTimestampWithOffsetToPostgresString(timestamp)) + .toBe(convertTimestampWithOffsetToPostgresString( + new Date().toISOString(), + )); + }); + it('Empty string', () => { + const timestamp = ' '; + expect(convertTimestampWithOffsetToPostgresString(timestamp)) + .toBe(convertTimestampWithOffsetToPostgresString( + new Date().toISOString(), + )); + }); }); - it('Malformed date string', () => { - const timestamp = '2024/01a/01 Z'; - expect(convertTimestampWithOffsetToPostgresString(timestamp)) - .toBe(convertTimestampWithOffsetToPostgresString( - new Date().toISOString(), - )); - }); - it('Empty string', () => { - const timestamp = ' '; - expect(convertTimestampWithOffsetToPostgresString(timestamp)) - .toBe(convertTimestampWithOffsetToPostgresString( - new Date().toISOString(), - )); + describe('validates date strings', () => { + it('Correct', () => { + expect(validatePostgresDateString('2025-01-03T21:00:44.000Z')).toBe(true); + expect(validateNaivePostgresDateString('2025-01-03 16:00:44')).toBe(true); + }); + it('Incorrect', () => { + expect(validatePostgresDateString('2024-01-01')).toBe(false); + expect(validatePostgresDateString('2025-01-03 16:00:44')).toBe(false); + expect(validateNaivePostgresDateString('2024-01-01')).toBe(false); + expect(validatePostgresDateString('2025-01-03T21:00:44.000')).toBe(false); + expect(validateNaivePostgresDateString('2025-01-03T16:00:44')).toBe(false); + expect(validatePostgresDateString('2025-01-03T21:00:44.000ZZ')).toBe(false); + expect(validateNaivePostgresDateString('2025-01-03 16:00:44Z')).toBe(false); + }); }); }); diff --git a/__tests__/url.test.ts b/__tests__/url.test.ts index 4e900db7..c892a15c 100644 --- a/__tests__/url.test.ts +++ b/__tests__/url.test.ts @@ -1,5 +1,4 @@ -import { makeUrlAbsolute, shortenUrl } from '@/utility/url'; -import '@testing-library/jest-dom'; +import { makeUrlAbsolute, removeUrlProtocol, shortenUrl } from '@/utility/url'; const URL_LONG_1 = 'https://www.example.com/'; const URL_LONG_2 = 'https://www.example.com'; @@ -12,9 +11,10 @@ const URL_LONG_7 = 'https://example.com/final-path/'; const URL_SHORT_1 = 'example.com'; const URL_SHORT_2 = 'example.com/'; const URL_SHORT_3 = 'example.com/final-path'; +const URL_SHORT_4 = 'www.example.com'; -describe('String', () => { - it('url can be shortened', () => { +describe('URL', () => { + it('can be shortened', () => { expect(shortenUrl(URL_LONG_1)).toBe(URL_SHORT_1); expect(shortenUrl(URL_LONG_2)).toBe(URL_SHORT_1); expect(shortenUrl(URL_LONG_3)).toBe(URL_SHORT_1); @@ -23,7 +23,15 @@ describe('String', () => { expect(shortenUrl(URL_LONG_6)).toBe(URL_SHORT_3); expect(shortenUrl(URL_LONG_7)).toBe(URL_SHORT_3); }); - it('url can be made absolute', () => { + it('can have protocol removed', () => { + expect(removeUrlProtocol(URL_LONG_1)).toBe(URL_SHORT_4); + expect(removeUrlProtocol(URL_LONG_2)).toBe(URL_SHORT_4); + expect(removeUrlProtocol(URL_LONG_4)).toBe(URL_SHORT_1); + expect(removeUrlProtocol(URL_LONG_5)).toBe(URL_SHORT_1); + expect(removeUrlProtocol(URL_LONG_6)).toBe(URL_SHORT_3); + expect(removeUrlProtocol(URL_LONG_7)).toBe(URL_SHORT_3); + }); + it('can be made absolute', () => { expect(makeUrlAbsolute(URL_SHORT_1)).toBe(URL_LONG_5); expect(makeUrlAbsolute(URL_SHORT_2)).toBe(URL_LONG_5); }); diff --git a/eslint.config.mjs b/eslint.config.mjs index 9a536467..47a47718 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -14,6 +14,7 @@ const eslintConfig = [ rules: { '@next/next/no-img-element': 'off', '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-require-imports': 'off', 'no-unused-expressions': ['warn'], '@typescript-eslint/no-unused-vars': [ 'warn', { diff --git a/next.config.js b/next.config.ts similarity index 56% rename from next.config.js rename to next.config.ts index 893b3ae7..367c0ca6 100644 --- a/next.config.js +++ b/next.config.ts @@ -1,3 +1,7 @@ +import { removeUrlProtocol } from '@/utility/url'; +import type { NextConfig } from 'next'; +import { RemotePattern } from 'next/dist/shared/lib/image-config'; + const VERCEL_BLOB_STORE_ID = process.env.BLOB_READ_WRITE_TOKEN?.match( /^vercel_blob_rw_([a-z0-9]+)_[a-z0-9]+$/i, )?.[1].toLowerCase(); @@ -16,23 +20,30 @@ const HOSTNAME_AWS_S3 = ? `${process.env.NEXT_PUBLIC_AWS_S3_BUCKET}.s3.${process.env.NEXT_PUBLIC_AWS_S3_REGION}.amazonaws.com` : undefined; -const createRemotePattern = (hostname) => hostname - ? { +const generateRemotePattern = (hostname: string) => + ({ protocol: 'https', - hostname, + hostname: removeUrlProtocol(hostname)!, port: '', pathname: '/**', - } - : []; + } as const); -/** @type {import('next').NextConfig} */ -const nextConfig = { +const remotePatterns: RemotePattern[] = []; + +if (HOSTNAME_VERCEL_BLOB) { + remotePatterns.push(generateRemotePattern(HOSTNAME_VERCEL_BLOB)); +} +if (HOSTNAME_CLOUDFLARE_R2) { + remotePatterns.push(generateRemotePattern(HOSTNAME_CLOUDFLARE_R2)); +} +if (HOSTNAME_AWS_S3) { + remotePatterns.push(generateRemotePattern(HOSTNAME_AWS_S3)); +} + +const nextConfig: NextConfig = { images: { imageSizes: [200], - remotePatterns: [] - .concat(createRemotePattern(HOSTNAME_VERCEL_BLOB)) - .concat(createRemotePattern(HOSTNAME_CLOUDFLARE_R2)) - .concat(createRemotePattern(HOSTNAME_AWS_S3)), + remotePatterns, minimumCacheTTL: 31536000, }, }; diff --git a/package.json b/package.json index ec73a2d2..4f3cf89a 100644 --- a/package.json +++ b/package.json @@ -9,26 +9,26 @@ "analyze": "ANALYZE=true next build" }, "dependencies": { - "@ai-sdk/openai": "^1.0.18", - "@aws-sdk/client-s3": "3.726.1", - "@aws-sdk/s3-request-presigner": "3.726.1", - "@radix-ui/react-dialog": "^1.1.4", - "@radix-ui/react-dropdown-menu": "^2.1.4", + "@ai-sdk/openai": "^1.1.1", + "@aws-sdk/client-s3": "3.733.0", + "@aws-sdk/s3-request-presigner": "3.733.0", + "@radix-ui/react-dialog": "^1.1.5", + "@radix-ui/react-dropdown-menu": "^2.1.5", "@radix-ui/react-visually-hidden": "^1.1.1", "@upstash/ratelimit": "^2.0.5", "@vercel/analytics": "^1.4.1", - "@vercel/blob": "^0.27.0", + "@vercel/blob": "^0.27.1", "@vercel/kv": "^3.0.0", "@vercel/speed-insights": "^1.1.0", - "ai": "^4.0.33", + "ai": "^4.1.1", "camelcase-keys": "^9.1.3", "cmdk": "^1.0.4", "date-fns": "^4.1.0", "date-fns-tz": "^3.2.0", "exifr": "^7.1.3", - "framer-motion": "^11.17.0", + "framer-motion": "^12.0.1", "nanoid": "^5.0.9", - "next": "15.1.4", + "next": "15.1.6", "next-auth": "5.0.0-beta.25", "next-themes": "^0.4.4", "pg": "^8.13.1", @@ -37,31 +37,31 @@ "react-icons": "^5.4.0", "sanitize-html": "^2.14.0", "sharp": "^0.33.5", - "sonner": "^1.7.1", + "sonner": "^1.7.2", "swr": "^2.3.0", "ts-exif-parser": "^0.2.2", "use-debounce": "^10.0.4", "viewerjs": "^1.11.7" }, "devDependencies": { - "@next/bundle-analyzer": "15.1.4", + "@next/bundle-analyzer": "15.1.6", "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.10", "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.1.0", + "@testing-library/react": "^16.2.0", "@types/jest": "^29.5.14", - "@types/node": "^22.10.5", + "@types/node": "^22.10.7", "@types/pg": "^8.11.10", - "@types/react": "19.0.4", - "@types/react-dom": "19.0.2", + "@types/react": "19.0.7", + "@types/react-dom": "19.0.3", "@types/sanitize-html": "^2.13.0", "autoprefixer": "10.4.20", "clsx": "^2.1.1", "eslint": "9.18.0", - "eslint-config-next": "15.1.4", + "eslint-config-next": "15.1.6", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", - "postcss": "8.4.49", + "postcss": "8.5.1", "tailwindcss": "3.4.17", "typescript": "5.7.3" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47842bd8..890b8eb4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,47 +9,47 @@ importers: .: dependencies: '@ai-sdk/openai': - specifier: ^1.0.18 - version: 1.0.18(zod@3.23.8) + specifier: ^1.1.1 + version: 1.1.1(zod@3.23.8) '@aws-sdk/client-s3': - specifier: 3.726.1 - version: 3.726.1 + specifier: 3.733.0 + version: 3.733.0 '@aws-sdk/s3-request-presigner': - specifier: 3.726.1 - version: 3.726.1 + specifier: 3.733.0 + version: 3.733.0 '@radix-ui/react-dialog': - specifier: ^1.1.4 - version: 1.1.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^1.1.5 + version: 1.1.5(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@radix-ui/react-dropdown-menu': - specifier: ^2.1.4 - version: 2.1.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^2.1.5 + version: 2.1.5(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@radix-ui/react-visually-hidden': specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@upstash/ratelimit': specifier: ^2.0.5 version: 2.0.5(@upstash/redis@1.34.3) '@vercel/analytics': specifier: ^1.4.1 - version: 1.4.1(next@15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(svelte@4.2.17)(vue@3.4.27(typescript@5.7.3)) + version: 1.4.1(next@15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(svelte@4.2.17)(vue@3.4.27(typescript@5.7.3)) '@vercel/blob': - specifier: ^0.27.0 - version: 0.27.0 + specifier: ^0.27.1 + version: 0.27.1 '@vercel/kv': specifier: ^3.0.0 version: 3.0.0 '@vercel/speed-insights': specifier: ^1.1.0 - version: 1.1.0(next@15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(svelte@4.2.17)(vue@3.4.27(typescript@5.7.3)) + version: 1.1.0(next@15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(svelte@4.2.17)(vue@3.4.27(typescript@5.7.3)) ai: - specifier: ^4.0.33 - version: 4.0.33(react@19.0.0)(zod@3.23.8) + specifier: ^4.1.1 + version: 4.1.1(react@19.0.0)(zod@3.23.8) camelcase-keys: specifier: ^9.1.3 version: 9.1.3 cmdk: specifier: ^1.0.4 - version: 1.0.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 1.0.4(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) date-fns: specifier: ^4.1.0 version: 4.1.0 @@ -60,17 +60,17 @@ importers: specifier: ^7.1.3 version: 7.1.3 framer-motion: - specifier: ^11.17.0 - version: 11.17.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^12.0.1 + version: 12.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) nanoid: specifier: ^5.0.9 version: 5.0.9 next: - specifier: 15.1.4 - version: 15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: 15.1.6 + version: 15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) next-auth: specifier: 5.0.0-beta.25 - version: 5.0.0-beta.25(next@15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0) + version: 5.0.0-beta.25(next@15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0) next-themes: specifier: ^0.4.4 version: 0.4.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -93,8 +93,8 @@ importers: specifier: ^0.33.5 version: 0.33.5 sonner: - specifier: ^1.7.1 - version: 1.7.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^1.7.2 + version: 1.7.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) swr: specifier: ^2.3.0 version: 2.3.0(react@19.0.0) @@ -109,8 +109,8 @@ importers: version: 1.11.7 devDependencies: '@next/bundle-analyzer': - specifier: 15.1.4 - version: 15.1.4 + specifier: 15.1.6 + version: 15.1.6 '@tailwindcss/container-queries': specifier: ^0.1.1 version: 0.1.1(tailwindcss@3.4.17) @@ -121,29 +121,29 @@ importers: specifier: ^6.6.3 version: 6.6.3 '@testing-library/react': - specifier: ^16.1.0 - version: 16.1.0(@testing-library/dom@10.1.0)(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^16.2.0 + version: 16.2.0(@testing-library/dom@10.1.0)(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@types/jest': specifier: ^29.5.14 version: 29.5.14 '@types/node': - specifier: ^22.10.5 - version: 22.10.5 + specifier: ^22.10.7 + version: 22.10.7 '@types/pg': specifier: ^8.11.10 version: 8.11.10 '@types/react': - specifier: 19.0.4 - version: 19.0.4 + specifier: 19.0.7 + version: 19.0.7 '@types/react-dom': - specifier: 19.0.2 - version: 19.0.2(@types/react@19.0.4) + specifier: 19.0.3 + version: 19.0.3(@types/react@19.0.7) '@types/sanitize-html': specifier: ^2.13.0 version: 2.13.0 autoprefixer: specifier: 10.4.20 - version: 10.4.20(postcss@8.4.49) + version: 10.4.20(postcss@8.5.1) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -151,17 +151,17 @@ importers: specifier: 9.18.0 version: 9.18.0(jiti@1.21.7) eslint-config-next: - specifier: 15.1.4 - version: 15.1.4(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3) + specifier: 15.1.6 + version: 15.1.6(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@22.10.5) + version: 29.7.0(@types/node@22.10.7) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 postcss: - specifier: 8.4.49 - version: 8.4.49 + specifier: 8.5.1 + version: 8.5.1 tailwindcss: specifier: 3.4.17 version: 3.4.17 @@ -174,14 +174,14 @@ packages: '@adobe/css-tools@4.4.0': resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} - '@ai-sdk/openai@1.0.18': - resolution: {integrity: sha512-bienqSVHbUqUcskm2FTIf2X+c481e85EASFfa78YogLqctZQtqPFKJuG5E7i59664Y5G91+LkzIh+1agS13BlA==} + '@ai-sdk/openai@1.1.1': + resolution: {integrity: sha512-0tUlrjSMWYYQxiC/6d6n5C6nxUYSHzlt/FipJgzKQleMts3Br5+u2cM4nwOVtuS14J2MsBM/SK2DGL0lFctirA==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 - '@ai-sdk/provider-utils@2.0.7': - resolution: {integrity: sha512-4sfPlKEALHPXLmMFcPlYksst3sWBJXmCDZpIBJisRrmwGG6Nn3mq0N1Zu/nZaGcrWZoOY+HT2Wbxla1oTElYHQ==} + '@ai-sdk/provider-utils@2.1.1': + resolution: {integrity: sha512-+FRXSAdzPJFJN6TpyvyGWLo7WJuoBKI1g66UL+sli1HrxlldXSwxRPeb8tMMmNcyi3VKQogg2VsoJjlt4ort5w==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 @@ -189,12 +189,12 @@ packages: zod: optional: true - '@ai-sdk/provider@1.0.4': - resolution: {integrity: sha512-lJi5zwDosvvZER3e/pB8lj1MN3o3S7zJliQq56BRr4e9V3fcRyFtwP0JRxaRS5vHYX3OJ154VezVoQNrk0eaKw==} + '@ai-sdk/provider@1.0.5': + resolution: {integrity: sha512-KATFp9CNXtMEzs8KBwLYK2+rGkkeED6p1+4koQveszyscIavObXIRW7vjr0MoZ9HFIHOUlrcak+3s/Xt3UXmAg==} engines: {node: '>=18'} - '@ai-sdk/react@1.0.9': - resolution: {integrity: sha512-7mtkgVCSzp8J4x3qk5Vtlk1FiZTH7vWIZvIrA6ISbFDy+7mwm45rIDIymzCiofzr3c/Wioy41H2Ki3Nth55bgg==} + '@ai-sdk/react@1.1.1': + resolution: {integrity: sha512-7LX/YF8sis8UM7p8ftUcu0xySG86/TBddcB42w/+mWOXL6hjYzcuGD8G121TobHsnxVxbsBlF/ykps/GYVvLNg==} engines: {node: '>=18'} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc @@ -205,8 +205,8 @@ packages: zod: optional: true - '@ai-sdk/ui-utils@1.0.8': - resolution: {integrity: sha512-7ya/t28oMaFauHxSj4WGQCEV/iicZj9qP+O+tCakMIDq7oDCZMUNBLCQomoWs16CcYY4l0wo1S9hA4PAdFcOvA==} + '@ai-sdk/ui-utils@1.1.1': + resolution: {integrity: sha512-lkTxGoebnEgs8HtKeWut0AglXN7zpWQwYmun4yuhpiup7DxPWTmt3vGiYvqQTBOFAmyoea3uzIKjHwRHuayr2w==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 @@ -259,143 +259,131 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.726.1': - resolution: {integrity: sha512-UpOGcob87DiuS2d3fW6vDZg94g57mNiOSkzvR/6GOdvBSlUgk8LLwVzGASB71FdKMl1EGEr4MeD5uKH9JsG+dw==} + '@aws-sdk/client-s3@3.733.0': + resolution: {integrity: sha512-LmAbtNxrgbtB+YVt/HPPyKBgJWrvHOv5yNn98Ndlwm1mBgvI1N7+HQlI5ZWIKBCkwJtLtdS8ZVHzPtqnyWO+YA==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-sso-oidc@3.726.0': - resolution: {integrity: sha512-5JzTX9jwev7+y2Jkzjz0pd1wobB5JQfPOQF3N2DrJ5Pao0/k6uRYwE4NqB0p0HlGrMTDm7xNq7OSPPIPG575Jw==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@aws-sdk/client-sts': ^3.726.0 - - '@aws-sdk/client-sso@3.726.0': - resolution: {integrity: sha512-NM5pjv2qglEc4XN3nnDqtqGsSGv1k5YTmzDo3W3pObItHmpS8grSeNfX9zSH+aVl0Q8hE4ZIgvTPNZ+GzwVlqg==} + '@aws-sdk/client-sso@3.731.0': + resolution: {integrity: sha512-O4C/UYGgqMsBg21MMApFdgyh8BX568hQhbdoNFmRVTBoSnCZ3w+H4a1wBPX4Gyl0NX+ab6Xxo9rId8HiyPXJ0A==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-sts@3.726.1': - resolution: {integrity: sha512-qh9Q9Vu1hrM/wMBOBIaskwnE4GTFaZu26Q6WHwyWNfj7J8a40vBxpW16c2vYXHLBtwRKM1be8uRLkmDwghpiNw==} + '@aws-sdk/core@3.731.0': + resolution: {integrity: sha512-ithBN1VWASkvAIlozJmenqDvNnFddr/SZXAs58+jCnBHgy3tXLHABZGVNCjetZkHRqNdXEO1kirnoxaFeXMeDA==} engines: {node: '>=18.0.0'} - '@aws-sdk/core@3.723.0': - resolution: {integrity: sha512-UraXNmvqj3vScSsTkjMwQkhei30BhXlW5WxX6JacMKVtl95c7z0qOXquTWeTalYkFfulfdirUhvSZrl+hcyqTw==} + '@aws-sdk/credential-provider-env@3.731.0': + resolution: {integrity: sha512-h0WWZg4QMLgFVyIvQrC43zpVqsUWg1mPM1clpogP43B8+wEhDEQ4qWRzvFs3dQ4cqx/FLyDUZZF4cqgd94z7kw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-env@3.723.0': - resolution: {integrity: sha512-OuH2yULYUHTVDUotBoP/9AEUIJPn81GQ/YBtZLoo2QyezRJ2QiO/1epVtbJlhNZRwXrToLEDmQGA2QfC8c7pbA==} + '@aws-sdk/credential-provider-http@3.731.0': + resolution: {integrity: sha512-iRtrjtcYaWgbvtu2cvDhIsPWXZGvhy1Hgks4682MEBNTc9AUwlfvDrYz2EEnTtJJyrbOdEHVrYrzqD8qPyVLCg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-http@3.723.0': - resolution: {integrity: sha512-DTsKC6xo/kz/ZSs1IcdbQMTgiYbpGTGEd83kngFc1bzmw7AmK92DBZKNZpumf8R/UfSpTcj9zzUUmrWz1kD0eQ==} + '@aws-sdk/credential-provider-ini@3.731.1': + resolution: {integrity: sha512-0M0ejuqW8iHNcTH2ZXSY9m+I7Y06qVkj6k3vfQU9XaB//mTUCxxfGfqWAtgfr7Yi73egABTcPc0jyPdcvSW4Kw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-ini@3.726.0': - resolution: {integrity: sha512-seTtcKL2+gZX6yK1QRPr5mDJIBOatrpoyrO8D5b8plYtV/PDbDW3mtDJSWFHet29G61ZmlNElyXRqQCXn9WX+A==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@aws-sdk/client-sts': ^3.726.0 - - '@aws-sdk/credential-provider-node@3.726.0': - resolution: {integrity: sha512-jjsewBcw/uLi24x8JbnuDjJad4VA9ROCE94uVRbEnGmUEsds75FWOKp3fWZLQlmjLtzsIbJOZLALkZP86liPaw==} + '@aws-sdk/credential-provider-node@3.731.1': + resolution: {integrity: sha512-5c0ZiagMTPmWilXNffeXJCLoCEz97jilHr3QJWwf2GaTay4tzN+Ld71rpdfEenzUR7fuxEWFfVlwQbFOzFNYHg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-process@3.723.0': - resolution: {integrity: sha512-fgupvUjz1+jeoCBA7GMv0L6xEk92IN6VdF4YcFhsgRHlHvNgm7ayaoKQg7pz2JAAhG/3jPX6fp0ASNy+xOhmPA==} + '@aws-sdk/credential-provider-process@3.731.0': + resolution: {integrity: sha512-6yNMY6q3xHLbs2f2+C6GhvMrjTgtFBiPJJqKaPLsTIhlTRvh4sK8pGm3ITcma0jOxtPDIuoPfBAV8N8XVMBlZg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-sso@3.726.0': - resolution: {integrity: sha512-WxkN76WeB08j2yw7jUH9yCMPxmT9eBFd9ZA/aACG7yzOIlsz7gvG3P2FQ0tVg25GHM0E4PdU3p/ByTOawzcOAg==} + '@aws-sdk/credential-provider-sso@3.731.1': + resolution: {integrity: sha512-p1tp+rMUf5YNQLr8rVRmDgNtKGYLL0KCdq3K2hwwvFnx9MjReF1sA4lfm3xWsxBQM+j3QN9AvMQqBzDJ+NOSdw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-web-identity@3.723.0': - resolution: {integrity: sha512-tl7pojbFbr3qLcOE6xWaNCf1zEfZrIdSJtOPeSXfV/thFMMAvIjgf3YN6Zo1a6cxGee8zrV/C8PgOH33n+Ev/A==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@aws-sdk/client-sts': ^3.723.0 - - '@aws-sdk/middleware-bucket-endpoint@3.726.0': - resolution: {integrity: sha512-vpaP80rZqwu0C3ELayIcRIW84/nd1tadeoqllT+N9TDshuEvq4UJ+w47OBHB7RkHFJoc79lXXNYle0fdQdaE/A==} + '@aws-sdk/credential-provider-web-identity@3.731.1': + resolution: {integrity: sha512-+ynAvEGWDR5ZJFxgpwwzhvlQ3WQ7BleWXU6JwpIw3yFrD4eZEn85b8DZC1aEz7C9kb1HSV6B3gpqHqlyS6wj8g==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-expect-continue@3.723.0': - resolution: {integrity: sha512-w/O0EkIzkiqvGu7U8Ke7tue0V0HYM5dZQrz6nVU+R8T2LddWJ+njEIHU4Wh8aHPLQXdZA5NQumv0xLPdEutykw==} + '@aws-sdk/middleware-bucket-endpoint@3.731.0': + resolution: {integrity: sha512-G9vuGW5GWCbzGOwlGFJcOkfxhw1cB6vzcv75QTT0CmciLXK+Cio8O2pqMSTTF2kg9Y6iHVC2BlOtLRkJAVOxVQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.723.0': - resolution: {integrity: sha512-JY76mrUCLa0FHeMZp8X9+KK6uEuZaRZaQrlgq6zkXX/3udukH0T3YdFC+Y9uw5ddbiwZ5+KwgmlhnPpiXKfP4g==} + '@aws-sdk/middleware-expect-continue@3.731.0': + resolution: {integrity: sha512-oY4nsY/mb5O5eZCzIuWpyvzO45Bi6UBtE48IaJsoyVctagA1l8hB66aczH9M1NHNjvbS4Beu1agwh3Nyb1eJug==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-host-header@3.723.0': - resolution: {integrity: sha512-LLVzLvk299pd7v4jN9yOSaWDZDfH0SnBPb6q+FDPaOCMGBY8kuwQso7e/ozIKSmZHRMGO3IZrflasHM+rI+2YQ==} + '@aws-sdk/middleware-flexible-checksums@3.732.0': + resolution: {integrity: sha512-MIbF6cYWg5noRO1kRZNC0vewj6qzSYL/BGNlPxRQcqb6egUiGrhPEi8Y/qqweB7MlBHsqSO5YNPwH/Py8ToSVw==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-location-constraint@3.723.0': - resolution: {integrity: sha512-inp9tyrdRWjGOMu1rzli8i2gTo0P4X6L7nNRXNTKfyPNZcBimZ4H0H1B671JofSI5isaklVy5r4pvv2VjjLSHw==} + '@aws-sdk/middleware-host-header@3.731.0': + resolution: {integrity: sha512-ndAJsm5uWPPJRZowLKpB1zuL17qWlWVtCJP4I/ynBkq1PU1DijDXBul2UZaG6Mpvsgms1NXo/h9noHuK7T3v8w==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-logger@3.723.0': - resolution: {integrity: sha512-chASQfDG5NJ8s5smydOEnNK7N0gDMyuPbx7dYYcm1t/PKtnVfvWF+DHCTrRC2Ej76gLJVCVizlAJKM8v8Kg3cg==} + '@aws-sdk/middleware-location-constraint@3.731.0': + resolution: {integrity: sha512-1I2EjAFxrQksrzqdN7YYuY/q2YsjqeX4l7f9VOkdBjiZeDvVIEdM99IT5sISJB/r6CjNrYX5MhqGhE8i1VFchA==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-recursion-detection@3.723.0': - resolution: {integrity: sha512-7usZMtoynT9/jxL/rkuDOFQ0C2mhXl4yCm67Rg7GNTstl67u7w5WN1aIRImMeztaKlw8ExjoTyo6WTs1Kceh7A==} + '@aws-sdk/middleware-logger@3.731.0': + resolution: {integrity: sha512-IIZrOdjbY2vKzPJPrwE7FoFQCIPEL6UqURi8LEaiVyCag4p2fvaTN5pgKuQtGC2+iYd/HHcGT4qn2bAqF5Jmmw==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-sdk-s3@3.723.0': - resolution: {integrity: sha512-wfjOvNJVp8LDWhq4wO5jtSMb8Vgf4tNlR7QTEQfoYc6AGU3WlK5xyUQcpfcpwytEhQTN9u0cJLQpSyXDO+qSCw==} + '@aws-sdk/middleware-recursion-detection@3.731.0': + resolution: {integrity: sha512-y6FLASB1iKWuR5tUipMyo77bt0lEl3OnCrrd2xw/H24avq1HhJjjPR0HHhJE6QKJzF/FYXeV88tcyPSMe32VDw==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-ssec@3.723.0': - resolution: {integrity: sha512-Bs+8RAeSMik6ZYCGSDJzJieGsDDh2fRbh1HQG94T8kpwBXVxMYihm6e9Xp2cyl+w9fyyCnh0IdCKChP/DvrdhA==} + '@aws-sdk/middleware-sdk-s3@3.733.0': + resolution: {integrity: sha512-XX/sP61LugQZck6W8WQJpYQEeW/h7t0qgxfZEv9Qk9fWBxxdcR1j4zkmSD3Da5vgnBl8dJ3wdmI2k96qw6ONkQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-user-agent@3.726.0': - resolution: {integrity: sha512-hZvzuE5S0JmFie1r68K2wQvJbzyxJFdzltj9skgnnwdvLe8F/tz7MqLkm28uV0m4jeHk0LpiBo6eZaPkQiwsZQ==} + '@aws-sdk/middleware-ssec@3.731.0': + resolution: {integrity: sha512-1HP4lxGcQx4awXgxfL8t9faBK7TqEL7zkAZrm/YBbLrT9oQomxZOHKIOHvo5VVh4qmsNBdqnH2XUlSMY71gsww==} engines: {node: '>=18.0.0'} - '@aws-sdk/region-config-resolver@3.723.0': - resolution: {integrity: sha512-tGF/Cvch3uQjZIj34LY2mg8M2Dr4kYG8VU8Yd0dFnB1ybOEOveIK/9ypUo9ycZpB9oO6q01KRe5ijBaxNueUQg==} + '@aws-sdk/middleware-user-agent@3.731.0': + resolution: {integrity: sha512-Ngr2Gz0aec/uduoKaO3srN52SYkEHndYtFzkK/gDUyQwQzi4ha2eIisxPiuHEX6RvXT31V9ouqn/YtVkt0R76A==} engines: {node: '>=18.0.0'} - '@aws-sdk/s3-request-presigner@3.726.1': - resolution: {integrity: sha512-IoM/u1gaZiSHEZkkf+Hn6MvCFUtLJgJysApW6NFbM2GYt4hqGLX5jhbjo5KVxC3wFfAhAwK1deSOM0FriBrKrg==} + '@aws-sdk/nested-clients@3.731.1': + resolution: {integrity: sha512-/L8iVrulnXZl+kgmTn+oxRxNnhcSIbf+r12C06vGUq60w0YMidLvxJZN7vt8H9SnCAGCHqud2MS7ExCEvhc0gA==} engines: {node: '>=18.0.0'} - '@aws-sdk/signature-v4-multi-region@3.723.0': - resolution: {integrity: sha512-lJlVAa5Sl589qO8lwMLVUtnlF1Q7I+6k1Iomv2goY9d1bRl4q2N5Pit2qJVr2AMW0sceQXeh23i2a/CKOqVAdg==} + '@aws-sdk/region-config-resolver@3.731.0': + resolution: {integrity: sha512-XlDpRNkDVHF59f07JmkuAidEv//m3hT6/JL85h0l3+zrpaRWhf8n8lVUyAPNq35ZujK8AcorYM+93u7hdWsliQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/token-providers@3.723.0': - resolution: {integrity: sha512-hniWi1x4JHVwKElANh9afKIMUhAutHVBRD8zo6usr0PAoj+Waf220+1ULS74GXtLXAPCiNXl5Og+PHA7xT8ElQ==} + '@aws-sdk/s3-request-presigner@3.733.0': + resolution: {integrity: sha512-EcB4b2cR/2yGUZXS4S7swEDaodImh4b4ndBYOfcKaP0m5A3cJ2evVjncKFOPLZmnIXRlqRXN1r0bW82uKxXnrA==} engines: {node: '>=18.0.0'} - peerDependencies: - '@aws-sdk/client-sso-oidc': ^3.723.0 - '@aws-sdk/types@3.723.0': - resolution: {integrity: sha512-LmK3kwiMZG1y5g3LGihT9mNkeNOmwEyPk6HGcJqh0wOSV4QpWoKu2epyKE4MLQNUUlz2kOVbVbOrwmI6ZcteuA==} + '@aws-sdk/signature-v4-multi-region@3.733.0': + resolution: {integrity: sha512-gdN59yEDHSoEZqUJF4vnTl1OoiTfa8fyBWTbu4Ri1cYE20cFvoePHdz+eG6ipe7VZNwKf8j/ZQeOgO40jNbZKQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/token-providers@3.731.1': + resolution: {integrity: sha512-t34GOPwBZsX7zGHjiTXmMHGY3kHM7fLiQ60Jqk0On9P0ASHTDE5U75RgCXboE3u+qEv9wyKyaqMNyMWj9qQlFg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/types@3.731.0': + resolution: {integrity: sha512-NrdkJg6oOUbXR2r9WvHP408CLyvST8cJfp1/jP9pemtjvjPoh6NukbCtiSFdOOb1eryP02CnqQWItfJC1p2Y/Q==} engines: {node: '>=18.0.0'} '@aws-sdk/util-arn-parser@3.723.0': resolution: {integrity: sha512-ZhEfvUwNliOQROcAk34WJWVYTlTa4694kSVhDSjW6lE1bMataPnIN8A0ycukEzBXmd8ZSoBcQLn6lKGl7XIJ5w==} engines: {node: '>=18.0.0'} - '@aws-sdk/util-endpoints@3.726.0': - resolution: {integrity: sha512-sLd30ASsPMoPn3XBK50oe/bkpJ4N8Bpb7SbhoxcY3Lk+fSASaWxbbXE81nbvCnkxrZCvkPOiDHzJCp1E2im71A==} + '@aws-sdk/util-endpoints@3.731.0': + resolution: {integrity: sha512-riztxTAfncFS9yQWcBJffGgOgLoKSa63ph+rxWJxKl6BHAmWEvHICj1qDcVmnWfIcvJ5cClclY75l9qKaUH7rQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/util-format-url@3.723.0': - resolution: {integrity: sha512-70+xUrdcnencPlCdV9XkRqmgj0vLDb8vm4mcEsgabg5QQ3S80KM0GEuhBAIGMkBWwNQTzCgQy2s7xOUlJPbu+g==} + '@aws-sdk/util-format-url@3.731.0': + resolution: {integrity: sha512-wZHObjnYmiz8wFlUQ4/5dHsT7k0at+GvZM02LgvshcRJLnFjYdrzjelMKuNynd/NNK3gLgTsFTGuIgPpz9r4rA==} engines: {node: '>=18.0.0'} '@aws-sdk/util-locate-window@3.568.0': resolution: {integrity: sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==} engines: {node: '>=16.0.0'} - '@aws-sdk/util-user-agent-browser@3.723.0': - resolution: {integrity: sha512-Wh9I6j2jLhNFq6fmXydIpqD1WyQLyTfSxjW9B+PXSnPyk3jtQW8AKQur7p97rO8LAUzVI0bv8kb3ZzDEVbquIg==} + '@aws-sdk/util-user-agent-browser@3.731.0': + resolution: {integrity: sha512-EnYXxTkCNCjTTBjW/pelRPv4Thsi9jepoB6qQjPMA9/ixrZ71BhhQecz9kgqzZLR9BPCwb6hgJ/Yd702jqJ4aQ==} - '@aws-sdk/util-user-agent-node@3.726.0': - resolution: {integrity: sha512-iEj6KX9o6IQf23oziorveRqyzyclWai95oZHDJtYav3fvLJKStwSjygO4xSF7ycHcTYeCHSLO1FFOHgGVs4Viw==} + '@aws-sdk/util-user-agent-node@3.731.0': + resolution: {integrity: sha512-Rze78Ym5Bx7aWMvmZE2iL3JPo2INNCC5N9rLVx98Gg1G0ZaxclVRUvJrh1AojNlOFxU+otkxAe7FA3Foy2iLLQ==} engines: {node: '>=18.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -859,59 +847,59 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@next/bundle-analyzer@15.1.4': - resolution: {integrity: sha512-W8X96jOW0U5VjLVAkFr1P37kH2f/Ma9zzwgX2o3Omft92pI0XHpFG8Xa9YUT3NlhRJCe4ZKznr1VxhSrFNA+BA==} + '@next/bundle-analyzer@15.1.6': + resolution: {integrity: sha512-hGzQyDqJzFHcHNCyTqM3o05BpVq5tGnRODccZBVJDBf5Miv/26UJPMB0wh9L9j3ylgHC+0/v8BaBnBBek1rC6Q==} - '@next/env@15.1.4': - resolution: {integrity: sha512-2fZ5YZjedi5AGaeoaC0B20zGntEHRhi2SdWcu61i48BllODcAmmtj8n7YarSPt4DaTsJaBFdxQAVEVzgmx2Zpw==} + '@next/env@15.1.6': + resolution: {integrity: sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w==} - '@next/eslint-plugin-next@15.1.4': - resolution: {integrity: sha512-HwlEXwCK3sr6zmVGEvWBjW9tBFs1Oe6hTmTLoFQtpm4As5HCdu8jfSE0XJOp7uhfEGLniIx8yrGxEWwNnY0fmQ==} + '@next/eslint-plugin-next@15.1.6': + resolution: {integrity: sha512-+slMxhTgILUntZDGNgsKEYHUvpn72WP1YTlkmEhS51vnVd7S9jEEy0n9YAMcI21vUG4akTw9voWH02lrClt/yw==} - '@next/swc-darwin-arm64@15.1.4': - resolution: {integrity: sha512-wBEMBs+np+R5ozN1F8Y8d/Dycns2COhRnkxRc+rvnbXke5uZBHkUGFgWxfTXn5rx7OLijuUhyfB+gC/ap58dDw==} + '@next/swc-darwin-arm64@15.1.6': + resolution: {integrity: sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.1.4': - resolution: {integrity: sha512-7sgf5rM7Z81V9w48F02Zz6DgEJulavC0jadab4ZsJ+K2sxMNK0/BtF8J8J3CxnsJN3DGcIdC260wEKssKTukUw==} + '@next/swc-darwin-x64@15.1.6': + resolution: {integrity: sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.1.4': - resolution: {integrity: sha512-JaZlIMNaJenfd55kjaLWMfok+vWBlcRxqnRoZrhFQrhM1uAehP3R0+Aoe+bZOogqlZvAz53nY/k3ZyuKDtT2zQ==} + '@next/swc-linux-arm64-gnu@15.1.6': + resolution: {integrity: sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.1.4': - resolution: {integrity: sha512-7EBBjNoyTO2ipMDgCiORpwwOf5tIueFntKjcN3NK+GAQD7OzFJe84p7a2eQUeWdpzZvhVXuAtIen8QcH71ZCOQ==} + '@next/swc-linux-arm64-musl@15.1.6': + resolution: {integrity: sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.1.4': - resolution: {integrity: sha512-9TGEgOycqZFuADyFqwmK/9g6S0FYZ3tphR4ebcmCwhL8Y12FW8pIBKJvSwV+UBjMkokstGNH+9F8F031JZKpHw==} + '@next/swc-linux-x64-gnu@15.1.6': + resolution: {integrity: sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.1.4': - resolution: {integrity: sha512-0578bLRVDJOh+LdIoKvgNDz77+Bd85c5JrFgnlbI1SM3WmEQvsjxTA8ATu9Z9FCiIS/AliVAW2DV/BDwpXbtiQ==} + '@next/swc-linux-x64-musl@15.1.6': + resolution: {integrity: sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.1.4': - resolution: {integrity: sha512-JgFCiV4libQavwII+kncMCl30st0JVxpPOtzWcAI2jtum4HjYaclobKhj+JsRu5tFqMtA5CJIa0MvYyuu9xjjQ==} + '@next/swc-win32-arm64-msvc@15.1.6': + resolution: {integrity: sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.1.4': - resolution: {integrity: sha512-xxsJy9wzq7FR5SqPCUqdgSXiNXrMuidgckBa8nH9HtjjxsilgcN6VgXF6tZ3uEWuVEadotQJI8/9EQ6guTC4Yw==} + '@next/swc-win32-x64-msvc@15.1.6': + resolution: {integrity: sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -998,8 +986,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-dialog@1.1.4': - resolution: {integrity: sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==} + '@radix-ui/react-dialog@1.1.5': + resolution: {integrity: sha512-LaO3e5h/NOEL4OfXjxD43k9Dx+vn+8n+PCFt6uhX/BADFflllyv3WJG6rgvvSVBxpTch938Qq/LGc2MMxipXPw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1020,8 +1008,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-dismissable-layer@1.1.3': - resolution: {integrity: sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==} + '@radix-ui/react-dismissable-layer@1.1.4': + resolution: {integrity: sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1033,8 +1021,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.4': - resolution: {integrity: sha512-iXU1Ab5ecM+yEepGAWK8ZhMyKX4ubFdCNtol4sT9D0OVErG9PNElfx3TQhjw7n7BC5nFVz68/5//clWy+8TXzA==} + '@radix-ui/react-dropdown-menu@2.1.5': + resolution: {integrity: sha512-50ZmEFL1kOuLalPKHrLWvPFMons2fGx9TqQCWlPwDVpbAnaUJ1g4XNcKqFNMQymYU0kKWR4MDDi+9vUQBGFgcQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1077,8 +1065,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-menu@2.1.4': - resolution: {integrity: sha512-BnOgVoL6YYdHAG6DtXONaR29Eq4nvbi8rutrV/xlr3RQCMMb3yqP85Qiw/3NReozrSW+4dfLkK+rc1hb4wPU/A==} + '@radix-ui/react-menu@2.1.5': + resolution: {integrity: sha512-uH+3w5heoMJtqVCgYOtYVMECk1TOrkUn0OG0p5MqXC0W2ppcuVeESbou8PTHoqAjbdTEK19AGXBWcEtR5WpEQg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1507,8 +1495,8 @@ packages: resolution: {integrity: sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - '@testing-library/react@16.1.0': - resolution: {integrity: sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg==} + '@testing-library/react@16.2.0': + resolution: {integrity: sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==} engines: {node: '>=18'} peerDependencies: '@testing-library/dom': ^10.0.0 @@ -1574,19 +1562,19 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/node@22.10.5': - resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==} + '@types/node@22.10.7': + resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==} '@types/pg@8.11.10': resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==} - '@types/react-dom@19.0.2': - resolution: {integrity: sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==} + '@types/react-dom@19.0.3': + resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==} peerDependencies: '@types/react': ^19.0.0 - '@types/react@19.0.4': - resolution: {integrity: sha512-3O4QisJDYr1uTUMZHA2YswiQZRq+Pd8D+GdVFYikTutYsTz+QZgWkAPnP7rx9txoI6EXKcPiluMqWPFV3tT9Wg==} + '@types/react@19.0.7': + resolution: {integrity: sha512-MoFsEJKkAtZCrC1r6CM8U22GzhG7u2Wir8ons/aCKH6MBdD1ibV24zOSSkdZVUKqN5i396zG5VKLYZ3yaUZdLA==} '@types/sanitize-html@2.13.0': resolution: {integrity: sha512-X31WxbvW9TjIhZZNyNBZ/p5ax4ti7qsNDBDEnH4zAgmEh35YnFD1UiS6z9Cd34kKm0LslFW0KPmTQzu/oGtsqQ==} @@ -1691,8 +1679,8 @@ packages: vue-router: optional: true - '@vercel/blob@0.27.0': - resolution: {integrity: sha512-EkYMKRMlHkWRWCnh99adrIT7G6cgv1dWpj/S3Kqykha8cI3EAMSmvnzI1N+41MAZiLMm0CsoGToKgtzGTf5xKQ==} + '@vercel/blob@0.27.1': + resolution: {integrity: sha512-X5EG9W1cZW+Nbt/XdrJJSl5DzCXXn1JRP5nfFwkpFD03nB6uh6BldwX4syElHcciM4Pih8CS7Ri1mtLCJvxSHA==} engines: {node: '>=16.14'} '@vercel/kv@3.0.0': @@ -1781,8 +1769,8 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} - ai@4.0.33: - resolution: {integrity: sha512-mOvhPyVchGZvZuPn8Zj4J+93fZOlaBH1BtunvGmQ/8yFc5hGmid3c0XIdw5UNt3++0sXawKE3j7JUL5ZmiQdKg==} + ai@4.1.1: + resolution: {integrity: sha512-oZTzQfrvrXuXnAJhoCsGcLUxSMWWYKkqrk2LfCzcukvB8us7ZUnFBgs9drhXuFP3JkWVbeIZHXjDexZIZcbi8g==} engines: {node: '>=18'} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc @@ -1980,10 +1968,6 @@ packages: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - call-bind-apply-helpers@1.0.1: resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} engines: {node: '>= 0.4'} @@ -2386,8 +2370,8 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-config-next@15.1.4: - resolution: {integrity: sha512-u9+7lFmfhKNgGjhQ9tBeyCFsPJyq0SvGioMJBngPC7HXUpR0U+ckEwQR48s7TrRNHra1REm6evGL2ie38agALg==} + eslint-config-next@15.1.6: + resolution: {integrity: sha512-Wd1uy6y7nBbXUSg9QAuQ+xYEKli5CgUhLjz1QHW11jLDis5vK5XB3PemL6jEmy7HrdhaRFDz+GTZ/3FoH+EUjg==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 typescript: '>=3.3.1' @@ -2594,8 +2578,8 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@11.17.0: - resolution: {integrity: sha512-uTNLH9JPMD3ad14WBt3KYRTR+If4tGPLgKTKTIIPaEBMkvazs6EkWNcmCh65qA/tyinOqIbQiuCorXX0qQsNoQ==} + framer-motion@12.0.1: + resolution: {integrity: sha512-u6p0Qc4cY/AEQAtrC7qiYlXla39qnWoI4JXY7OCNBDXwJ5yRBD8HU+RhaOqqziw2m/b0BDh32f44W94+wXonMQ==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -3296,11 +3280,11 @@ packages: resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} engines: {node: '>=16 || 14 >=14.17'} - motion-dom@11.16.4: - resolution: {integrity: sha512-2wuCie206pCiP2K23uvwJeci4pMFfyQKpWI0Vy6HrCTDzDCer4TsYtT7IVnuGbDeoIV37UuZiUr6SZMHEc1Vww==} + motion-dom@12.0.0: + resolution: {integrity: sha512-CvYd15OeIR6kHgMdonCc1ihsaUG4MYh/wrkz8gZ3hBX/uamyZCXN9S9qJoYF03GqfTt7thTV/dxnHYX4+55vDg==} - motion-utils@11.16.0: - resolution: {integrity: sha512-ngdWPjg31rD4WGXFi0eZ00DQQqKKu04QExyv/ymlC+3k+WIgYVFbt6gS5JsFPbJODTF/r8XiE/X+SsoT9c0ocw==} + motion-utils@12.0.0: + resolution: {integrity: sha512-MNFiBKbbqnmvOjkPyOKgHUp3Q6oiokLkI1bEwm5QA28cxMZrv0CbbBGDNmhF6DIXsi1pCQBSs0dX8xjeER1tmA==} mrmime@2.0.0: resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} @@ -3315,11 +3299,6 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - nanoid@3.3.8: resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -3355,8 +3334,8 @@ packages: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - next@15.1.4: - resolution: {integrity: sha512-mTaq9dwaSuwwOrcu3ebjDYObekkxRnXpuVL21zotM8qE2W0HBOdVIdg2Li9QjMEZrj73LN96LcWcz62V19FjAg==} + next@15.1.6: + resolution: {integrity: sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -3625,8 +3604,8 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + postcss@8.5.1: + resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} engines: {node: ^10 || ^12 || >=14} postgres-array@2.0.0: @@ -3932,8 +3911,8 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - sonner@1.7.1: - resolution: {integrity: sha512-b6LHBfH32SoVasRFECrdY8p8s7hXPDn3OHUFbZZbiB1ctLS9Gdh6rpX2dVrpQA0kiL5jcRzDDldwwLkSKk3+QQ==} + sonner@1.7.2: + resolution: {integrity: sha512-zMbseqjrOzQD1a93lxahm+qMGxWovdMxBlkTbbnZdNqVLt4j+amF9PQxUCL32WfztOFt9t9ADYkejAL3jF9iNA==} peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc @@ -4408,39 +4387,39 @@ snapshots: '@adobe/css-tools@4.4.0': {} - '@ai-sdk/openai@1.0.18(zod@3.23.8)': + '@ai-sdk/openai@1.1.1(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 1.0.4 - '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) + '@ai-sdk/provider': 1.0.5 + '@ai-sdk/provider-utils': 2.1.1(zod@3.23.8) zod: 3.23.8 - '@ai-sdk/provider-utils@2.0.7(zod@3.23.8)': + '@ai-sdk/provider-utils@2.1.1(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 1.0.4 + '@ai-sdk/provider': 1.0.5 eventsource-parser: 3.0.0 nanoid: 3.3.8 secure-json-parse: 2.7.0 optionalDependencies: zod: 3.23.8 - '@ai-sdk/provider@1.0.4': + '@ai-sdk/provider@1.0.5': dependencies: json-schema: 0.4.0 - '@ai-sdk/react@1.0.9(react@19.0.0)(zod@3.23.8)': + '@ai-sdk/react@1.1.1(react@19.0.0)(zod@3.23.8)': dependencies: - '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) - '@ai-sdk/ui-utils': 1.0.8(zod@3.23.8) + '@ai-sdk/provider-utils': 2.1.1(zod@3.23.8) + '@ai-sdk/ui-utils': 1.1.1(zod@3.23.8) swr: 2.3.0(react@19.0.0) throttleit: 2.1.0 optionalDependencies: react: 19.0.0 zod: 3.23.8 - '@ai-sdk/ui-utils@1.0.8(zod@3.23.8)': + '@ai-sdk/ui-utils@1.1.1(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 1.0.4 - '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) + '@ai-sdk/provider': 1.0.5 + '@ai-sdk/provider-utils': 2.1.1(zod@3.23.8) zod-to-json-schema: 3.24.1(zod@3.23.8) optionalDependencies: zod: 3.23.8 @@ -4465,20 +4444,20 @@ snapshots: '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 tslib: 2.8.1 '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 tslib: 2.8.1 '@aws-crypto/sha1-browser@5.2.0': dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@aws-sdk/util-locate-window': 3.568.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -4488,7 +4467,7 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@aws-sdk/util-locate-window': 3.568.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -4496,7 +4475,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -4505,35 +4484,33 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-s3@3.726.1': + '@aws-sdk/client-s3@3.733.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.726.0(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/client-sts': 3.726.1 - '@aws-sdk/core': 3.723.0 - '@aws-sdk/credential-provider-node': 3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1))(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/middleware-bucket-endpoint': 3.726.0 - '@aws-sdk/middleware-expect-continue': 3.723.0 - '@aws-sdk/middleware-flexible-checksums': 3.723.0 - '@aws-sdk/middleware-host-header': 3.723.0 - '@aws-sdk/middleware-location-constraint': 3.723.0 - '@aws-sdk/middleware-logger': 3.723.0 - '@aws-sdk/middleware-recursion-detection': 3.723.0 - '@aws-sdk/middleware-sdk-s3': 3.723.0 - '@aws-sdk/middleware-ssec': 3.723.0 - '@aws-sdk/middleware-user-agent': 3.726.0 - '@aws-sdk/region-config-resolver': 3.723.0 - '@aws-sdk/signature-v4-multi-region': 3.723.0 - '@aws-sdk/types': 3.723.0 - '@aws-sdk/util-endpoints': 3.726.0 - '@aws-sdk/util-user-agent-browser': 3.723.0 - '@aws-sdk/util-user-agent-node': 3.726.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/credential-provider-node': 3.731.1 + '@aws-sdk/middleware-bucket-endpoint': 3.731.0 + '@aws-sdk/middleware-expect-continue': 3.731.0 + '@aws-sdk/middleware-flexible-checksums': 3.732.0 + '@aws-sdk/middleware-host-header': 3.731.0 + '@aws-sdk/middleware-location-constraint': 3.731.0 + '@aws-sdk/middleware-logger': 3.731.0 + '@aws-sdk/middleware-recursion-detection': 3.731.0 + '@aws-sdk/middleware-sdk-s3': 3.733.0 + '@aws-sdk/middleware-ssec': 3.731.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/region-config-resolver': 3.731.0 + '@aws-sdk/signature-v4-multi-region': 3.733.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@aws-sdk/util-user-agent-browser': 3.731.0 + '@aws-sdk/util-user-agent-node': 3.731.0 '@aws-sdk/xml-builder': 3.723.0 '@smithy/config-resolver': 4.0.1 '@smithy/core': 3.1.0 @@ -4572,22 +4549,20 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1)': + '@aws-sdk/client-sso@3.731.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sts': 3.726.1 - '@aws-sdk/core': 3.723.0 - '@aws-sdk/credential-provider-node': 3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1))(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/middleware-host-header': 3.723.0 - '@aws-sdk/middleware-logger': 3.723.0 - '@aws-sdk/middleware-recursion-detection': 3.723.0 - '@aws-sdk/middleware-user-agent': 3.726.0 - '@aws-sdk/region-config-resolver': 3.723.0 - '@aws-sdk/types': 3.723.0 - '@aws-sdk/util-endpoints': 3.726.0 - '@aws-sdk/util-user-agent-browser': 3.723.0 - '@aws-sdk/util-user-agent-node': 3.726.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/middleware-host-header': 3.731.0 + '@aws-sdk/middleware-logger': 3.731.0 + '@aws-sdk/middleware-recursion-detection': 3.731.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/region-config-resolver': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@aws-sdk/util-user-agent-browser': 3.731.0 + '@aws-sdk/util-user-agent-node': 3.731.0 '@smithy/config-resolver': 4.0.1 '@smithy/core': 3.1.0 '@smithy/fetch-http-handler': 5.0.1 @@ -4617,97 +4592,9 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.726.0': + '@aws-sdk/core@3.731.0': dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.723.0 - '@aws-sdk/middleware-host-header': 3.723.0 - '@aws-sdk/middleware-logger': 3.723.0 - '@aws-sdk/middleware-recursion-detection': 3.723.0 - '@aws-sdk/middleware-user-agent': 3.726.0 - '@aws-sdk/region-config-resolver': 3.723.0 - '@aws-sdk/types': 3.723.0 - '@aws-sdk/util-endpoints': 3.726.0 - '@aws-sdk/util-user-agent-browser': 3.723.0 - '@aws-sdk/util-user-agent-node': 3.726.0 - '@smithy/config-resolver': 4.0.1 - '@smithy/core': 3.1.0 - '@smithy/fetch-http-handler': 5.0.1 - '@smithy/hash-node': 4.0.1 - '@smithy/invalid-dependency': 4.0.1 - '@smithy/middleware-content-length': 4.0.1 - '@smithy/middleware-endpoint': 4.0.1 - '@smithy/middleware-retry': 4.0.1 - '@smithy/middleware-serde': 4.0.1 - '@smithy/middleware-stack': 4.0.1 - '@smithy/node-config-provider': 4.0.1 - '@smithy/node-http-handler': 4.0.1 - '@smithy/protocol-http': 5.0.1 - '@smithy/smithy-client': 4.1.0 - '@smithy/types': 4.1.0 - '@smithy/url-parser': 4.0.1 - '@smithy/util-base64': 4.0.0 - '@smithy/util-body-length-browser': 4.0.0 - '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.1 - '@smithy/util-defaults-mode-node': 4.0.1 - '@smithy/util-endpoints': 3.0.1 - '@smithy/util-middleware': 4.0.1 - '@smithy/util-retry': 4.0.1 - '@smithy/util-utf8': 4.0.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/client-sts@3.726.1': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.726.0(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/core': 3.723.0 - '@aws-sdk/credential-provider-node': 3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1))(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/middleware-host-header': 3.723.0 - '@aws-sdk/middleware-logger': 3.723.0 - '@aws-sdk/middleware-recursion-detection': 3.723.0 - '@aws-sdk/middleware-user-agent': 3.726.0 - '@aws-sdk/region-config-resolver': 3.723.0 - '@aws-sdk/types': 3.723.0 - '@aws-sdk/util-endpoints': 3.726.0 - '@aws-sdk/util-user-agent-browser': 3.723.0 - '@aws-sdk/util-user-agent-node': 3.726.0 - '@smithy/config-resolver': 4.0.1 - '@smithy/core': 3.1.0 - '@smithy/fetch-http-handler': 5.0.1 - '@smithy/hash-node': 4.0.1 - '@smithy/invalid-dependency': 4.0.1 - '@smithy/middleware-content-length': 4.0.1 - '@smithy/middleware-endpoint': 4.0.1 - '@smithy/middleware-retry': 4.0.1 - '@smithy/middleware-serde': 4.0.1 - '@smithy/middleware-stack': 4.0.1 - '@smithy/node-config-provider': 4.0.1 - '@smithy/node-http-handler': 4.0.1 - '@smithy/protocol-http': 5.0.1 - '@smithy/smithy-client': 4.1.0 - '@smithy/types': 4.1.0 - '@smithy/url-parser': 4.0.1 - '@smithy/util-base64': 4.0.0 - '@smithy/util-body-length-browser': 4.0.0 - '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.1 - '@smithy/util-defaults-mode-node': 4.0.1 - '@smithy/util-endpoints': 3.0.1 - '@smithy/util-middleware': 4.0.1 - '@smithy/util-retry': 4.0.1 - '@smithy/util-utf8': 4.0.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/core@3.723.0': - dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/core': 3.1.0 '@smithy/node-config-provider': 4.0.1 '@smithy/property-provider': 4.0.1 @@ -4719,18 +4606,18 @@ snapshots: fast-xml-parser: 4.4.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.723.0': + '@aws-sdk/credential-provider-env@3.731.0': dependencies: - '@aws-sdk/core': 3.723.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 '@smithy/property-provider': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.723.0': + '@aws-sdk/credential-provider-http@3.731.0': dependencies: - '@aws-sdk/core': 3.723.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 '@smithy/fetch-http-handler': 5.0.1 '@smithy/node-http-handler': 4.0.1 '@smithy/property-provider': 4.0.1 @@ -4740,79 +4627,77 @@ snapshots: '@smithy/util-stream': 4.0.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1))(@aws-sdk/client-sts@3.726.1)': + '@aws-sdk/credential-provider-ini@3.731.1': dependencies: - '@aws-sdk/client-sts': 3.726.1 - '@aws-sdk/core': 3.723.0 - '@aws-sdk/credential-provider-env': 3.723.0 - '@aws-sdk/credential-provider-http': 3.723.0 - '@aws-sdk/credential-provider-process': 3.723.0 - '@aws-sdk/credential-provider-sso': 3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1)) - '@aws-sdk/credential-provider-web-identity': 3.723.0(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/types': 3.723.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/credential-provider-env': 3.731.0 + '@aws-sdk/credential-provider-http': 3.731.0 + '@aws-sdk/credential-provider-process': 3.731.0 + '@aws-sdk/credential-provider-sso': 3.731.1 + '@aws-sdk/credential-provider-web-identity': 3.731.1 + '@aws-sdk/nested-clients': 3.731.1 + '@aws-sdk/types': 3.731.0 '@smithy/credential-provider-imds': 4.0.1 '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 transitivePeerDependencies: - - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-node@3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1))(@aws-sdk/client-sts@3.726.1)': + '@aws-sdk/credential-provider-node@3.731.1': dependencies: - '@aws-sdk/credential-provider-env': 3.723.0 - '@aws-sdk/credential-provider-http': 3.723.0 - '@aws-sdk/credential-provider-ini': 3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1))(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/credential-provider-process': 3.723.0 - '@aws-sdk/credential-provider-sso': 3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1)) - '@aws-sdk/credential-provider-web-identity': 3.723.0(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/types': 3.723.0 + '@aws-sdk/credential-provider-env': 3.731.0 + '@aws-sdk/credential-provider-http': 3.731.0 + '@aws-sdk/credential-provider-ini': 3.731.1 + '@aws-sdk/credential-provider-process': 3.731.0 + '@aws-sdk/credential-provider-sso': 3.731.1 + '@aws-sdk/credential-provider-web-identity': 3.731.1 + '@aws-sdk/types': 3.731.0 '@smithy/credential-provider-imds': 4.0.1 '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 transitivePeerDependencies: - - '@aws-sdk/client-sso-oidc' - - '@aws-sdk/client-sts' - aws-crt - '@aws-sdk/credential-provider-process@3.723.0': + '@aws-sdk/credential-provider-process@3.731.0': dependencies: - '@aws-sdk/core': 3.723.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.726.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1))': + '@aws-sdk/credential-provider-sso@3.731.1': dependencies: - '@aws-sdk/client-sso': 3.726.0 - '@aws-sdk/core': 3.723.0 - '@aws-sdk/token-providers': 3.723.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1)) - '@aws-sdk/types': 3.723.0 + '@aws-sdk/client-sso': 3.731.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/token-providers': 3.731.1 + '@aws-sdk/types': 3.731.0 '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 transitivePeerDependencies: - - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-web-identity@3.723.0(@aws-sdk/client-sts@3.726.1)': + '@aws-sdk/credential-provider-web-identity@3.731.1': dependencies: - '@aws-sdk/client-sts': 3.726.1 - '@aws-sdk/core': 3.723.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/nested-clients': 3.731.1 + '@aws-sdk/types': 3.731.0 '@smithy/property-provider': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt - '@aws-sdk/middleware-bucket-endpoint@3.726.0': + '@aws-sdk/middleware-bucket-endpoint@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@aws-sdk/util-arn-parser': 3.723.0 '@smithy/node-config-provider': 4.0.1 '@smithy/protocol-http': 5.0.1 @@ -4820,20 +4705,20 @@ snapshots: '@smithy/util-config-provider': 4.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-expect-continue@3.723.0': + '@aws-sdk/middleware-expect-continue@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.723.0': + '@aws-sdk/middleware-flexible-checksums@3.732.0': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.723.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 '@smithy/is-array-buffer': 4.0.0 '@smithy/node-config-provider': 4.0.1 '@smithy/protocol-http': 5.0.1 @@ -4843,36 +4728,36 @@ snapshots: '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.723.0': + '@aws-sdk/middleware-host-header@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/middleware-location-constraint@3.723.0': + '@aws-sdk/middleware-location-constraint@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/middleware-logger@3.723.0': + '@aws-sdk/middleware-logger@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.723.0': + '@aws-sdk/middleware-recursion-detection@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.723.0': + '@aws-sdk/middleware-sdk-s3@3.733.0': dependencies: - '@aws-sdk/core': 3.723.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 '@aws-sdk/util-arn-parser': 3.723.0 '@smithy/core': 3.1.0 '@smithy/node-config-provider': 4.0.1 @@ -4886,61 +4771,106 @@ snapshots: '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-ssec@3.723.0': + '@aws-sdk/middleware-ssec@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.726.0': + '@aws-sdk/middleware-user-agent@3.731.0': dependencies: - '@aws-sdk/core': 3.723.0 - '@aws-sdk/types': 3.723.0 - '@aws-sdk/util-endpoints': 3.726.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 '@smithy/core': 3.1.0 '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/region-config-resolver@3.723.0': + '@aws-sdk/nested-clients@3.731.1': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/middleware-host-header': 3.731.0 + '@aws-sdk/middleware-logger': 3.731.0 + '@aws-sdk/middleware-recursion-detection': 3.731.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/region-config-resolver': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@aws-sdk/util-user-agent-browser': 3.731.0 + '@aws-sdk/util-user-agent-node': 3.731.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.0 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.1 + '@smithy/middleware-retry': 4.0.1 + '@smithy/middleware-serde': 4.0.1 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.0 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.1 + '@smithy/util-defaults-mode-node': 4.0.1 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.731.0': + dependencies: + '@aws-sdk/types': 3.731.0 '@smithy/node-config-provider': 4.0.1 '@smithy/types': 4.1.0 '@smithy/util-config-provider': 4.0.0 '@smithy/util-middleware': 4.0.1 tslib: 2.8.1 - '@aws-sdk/s3-request-presigner@3.726.1': + '@aws-sdk/s3-request-presigner@3.733.0': dependencies: - '@aws-sdk/signature-v4-multi-region': 3.723.0 - '@aws-sdk/types': 3.723.0 - '@aws-sdk/util-format-url': 3.723.0 + '@aws-sdk/signature-v4-multi-region': 3.733.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-format-url': 3.731.0 '@smithy/middleware-endpoint': 4.0.1 '@smithy/protocol-http': 5.0.1 '@smithy/smithy-client': 4.1.0 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.723.0': + '@aws-sdk/signature-v4-multi-region@3.733.0': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.723.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/middleware-sdk-s3': 3.733.0 + '@aws-sdk/types': 3.731.0 '@smithy/protocol-http': 5.0.1 '@smithy/signature-v4': 5.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.723.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.726.1))': + '@aws-sdk/token-providers@3.731.1': dependencies: - '@aws-sdk/client-sso-oidc': 3.726.0(@aws-sdk/client-sts@3.726.1) - '@aws-sdk/types': 3.723.0 + '@aws-sdk/nested-clients': 3.731.1 + '@aws-sdk/types': 3.731.0 '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt - '@aws-sdk/types@3.723.0': + '@aws-sdk/types@3.731.0': dependencies: '@smithy/types': 4.1.0 tslib: 2.8.1 @@ -4949,16 +4879,16 @@ snapshots: dependencies: tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.726.0': + '@aws-sdk/util-endpoints@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/types': 4.1.0 '@smithy/util-endpoints': 3.0.1 tslib: 2.8.1 - '@aws-sdk/util-format-url@3.723.0': + '@aws-sdk/util-format-url@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/querystring-builder': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 @@ -4967,17 +4897,17 @@ snapshots: dependencies: tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.723.0': + '@aws-sdk/util-user-agent-browser@3.731.0': dependencies: - '@aws-sdk/types': 3.723.0 + '@aws-sdk/types': 3.731.0 '@smithy/types': 4.1.0 bowser: 2.11.0 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.726.0': + '@aws-sdk/util-user-agent-node@3.731.0': dependencies: - '@aws-sdk/middleware-user-agent': 3.726.0 - '@aws-sdk/types': 3.723.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/types': 3.731.0 '@smithy/node-config-provider': 4.0.1 '@smithy/types': 4.1.0 tslib: 2.8.1 @@ -5369,7 +5299,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -5382,14 +5312,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.10.5) + jest-config: 29.7.0(@types/node@22.10.7) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -5414,7 +5344,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -5432,7 +5362,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.10.5 + '@types/node': 22.10.7 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -5454,7 +5384,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.10.5 + '@types/node': 22.10.7 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -5524,7 +5454,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.10.5 + '@types/node': 22.10.7 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -5545,41 +5475,41 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@next/bundle-analyzer@15.1.4': + '@next/bundle-analyzer@15.1.6': dependencies: webpack-bundle-analyzer: 4.10.1 transitivePeerDependencies: - bufferutil - utf-8-validate - '@next/env@15.1.4': {} + '@next/env@15.1.6': {} - '@next/eslint-plugin-next@15.1.4': + '@next/eslint-plugin-next@15.1.6': dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@15.1.4': + '@next/swc-darwin-arm64@15.1.6': optional: true - '@next/swc-darwin-x64@15.1.4': + '@next/swc-darwin-x64@15.1.6': optional: true - '@next/swc-linux-arm64-gnu@15.1.4': + '@next/swc-linux-arm64-gnu@15.1.6': optional: true - '@next/swc-linux-arm64-musl@15.1.4': + '@next/swc-linux-arm64-musl@15.1.6': optional: true - '@next/swc-linux-x64-gnu@15.1.4': + '@next/swc-linux-x64-gnu@15.1.6': optional: true - '@next/swc-linux-x64-musl@15.1.4': + '@next/swc-linux-x64-musl@15.1.6': optional: true - '@next/swc-win32-arm64-msvc@15.1.4': + '@next/swc-win32-arm64-msvc@15.1.6': optional: true - '@next/swc-win32-x64-msvc@15.1.4': + '@next/swc-win32-x64-msvc@15.1.6': optional: true '@nodelib/fs.scandir@2.1.5': @@ -5605,286 +5535,286 @@ snapshots: '@radix-ui/primitive@1.1.1': {} - '@radix-ui/react-arrow@1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-arrow@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-collection@1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-collection@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.1(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-compose-refs@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-compose-refs@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.7)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-context@1.1.1(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-context@1.1.1(@types/react@19.0.7)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-dialog@1.1.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dialog@1.1.5(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.7)(react@19.0.0) aria-hidden: 1.2.4 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) - react-remove-scroll: 2.6.2(@types/react@19.0.4)(react@19.0.0) + react-remove-scroll: 2.6.2(@types/react@19.0.7)(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-direction@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-direction@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-dismissable-layer@1.1.3(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dismissable-layer@1.1.4(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-dropdown-menu@2.1.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dropdown-menu@2.1.5(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-menu': 2.1.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-menu': 2.1.5(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.7)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-id@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-id@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-menu@2.1.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-menu@2.1.5(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.7)(react@19.0.0) aria-hidden: 1.2.4 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) - react-remove-scroll: 2.6.2(@types/react@19.0.4)(react@19.0.0) + react-remove-scroll: 2.6.2(@types/react@19.0.7)(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-popper@1.2.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-popper@1.2.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@floating-ui/react-dom': 2.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-arrow': 1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-arrow': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.7)(react@19.0.0) '@radix-ui/rect': 1.1.0 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-portal@1.1.3(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-portal@1.1.3(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-presence@1.1.2(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-presence@1.1.2(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-primitive@2.0.0(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-primitive@2.0.0(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-slot': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-slot': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-primitive@2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-primitive@2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-slot': 1.1.1(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) - '@radix-ui/react-slot@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-slot@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-slot@1.1.1(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-slot@1.1.1(@types/react@19.0.7)(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-use-rect@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-use-rect@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: '@radix-ui/rect': 1.1.0 react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-use-size@1.1.0(@types/react@19.0.4)(react@19.0.0)': + '@radix-ui/react-use-size@1.1.0(@types/react@19.0.7)(react@19.0.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.4)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.7)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@radix-ui/react-visually-hidden@1.1.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-visually-hidden@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) '@radix-ui/rect@1.1.0': {} @@ -6269,15 +6199,15 @@ snapshots: lodash: 4.17.21 redent: 3.0.0 - '@testing-library/react@16.1.0(@testing-library/dom@10.1.0)(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@testing-library/react@16.2.0(@testing-library/dom@10.1.0)(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@babel/runtime': 7.24.5 '@testing-library/dom': 10.1.0 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 - '@types/react-dom': 19.0.2(@types/react@19.0.4) + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) '@tootallnate/once@2.0.0': {} @@ -6312,7 +6242,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.7 '@types/istanbul-lib-coverage@2.0.6': {} @@ -6331,7 +6261,7 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.7 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 @@ -6339,21 +6269,21 @@ snapshots: '@types/json5@0.0.29': {} - '@types/node@22.10.5': + '@types/node@22.10.7': dependencies: undici-types: 6.20.0 '@types/pg@8.11.10': dependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.7 pg-protocol: 1.6.1 pg-types: 4.0.2 - '@types/react-dom@19.0.2(@types/react@19.0.4)': + '@types/react-dom@19.0.3(@types/react@19.0.7)': dependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - '@types/react@19.0.4': + '@types/react@19.0.7': dependencies: csstype: 3.1.3 @@ -6465,17 +6395,16 @@ snapshots: dependencies: crypto-js: 4.2.0 - '@vercel/analytics@1.4.1(next@15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(svelte@4.2.17)(vue@3.4.27(typescript@5.7.3))': + '@vercel/analytics@1.4.1(next@15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(svelte@4.2.17)(vue@3.4.27(typescript@5.7.3))': optionalDependencies: - next: 15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + next: 15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 svelte: 4.2.17 vue: 3.4.27(typescript@5.7.3) - '@vercel/blob@0.27.0': + '@vercel/blob@0.27.1': dependencies: async-retry: 1.3.3 - bytes: 3.1.2 is-buffer: 2.0.5 is-node-process: 1.2.0 throttleit: 2.1.0 @@ -6485,9 +6414,9 @@ snapshots: dependencies: '@upstash/redis': 1.34.3 - '@vercel/speed-insights@1.1.0(next@15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(svelte@4.2.17)(vue@3.4.27(typescript@5.7.3))': + '@vercel/speed-insights@1.1.0(next@15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(svelte@4.2.17)(vue@3.4.27(typescript@5.7.3))': optionalDependencies: - next: 15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + next: 15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 svelte: 4.2.17 vue: 3.4.27(typescript@5.7.3) @@ -6516,7 +6445,7 @@ snapshots: '@vue/shared': 3.4.27 estree-walker: 2.0.2 magic-string: 0.30.10 - postcss: 8.4.49 + postcss: 8.5.1 source-map-js: 1.2.1 optional: true @@ -6577,15 +6506,14 @@ snapshots: transitivePeerDependencies: - supports-color - ai@4.0.33(react@19.0.0)(zod@3.23.8): + ai@4.1.1(react@19.0.0)(zod@3.23.8): dependencies: - '@ai-sdk/provider': 1.0.4 - '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) - '@ai-sdk/react': 1.0.9(react@19.0.0)(zod@3.23.8) - '@ai-sdk/ui-utils': 1.0.8(zod@3.23.8) + '@ai-sdk/provider': 1.0.5 + '@ai-sdk/provider-utils': 2.1.1(zod@3.23.8) + '@ai-sdk/react': 1.1.1(react@19.0.0)(zod@3.23.8) + '@ai-sdk/ui-utils': 1.1.1(zod@3.23.8) '@opentelemetry/api': 1.9.0 jsondiffpatch: 0.6.0 - zod-to-json-schema: 3.24.1(zod@3.23.8) optionalDependencies: react: 19.0.0 zod: 3.23.8 @@ -6714,14 +6642,14 @@ snapshots: asynckit@0.4.0: {} - autoprefixer@10.4.20(postcss@8.4.49): + autoprefixer@10.4.20(postcss@8.5.1): dependencies: browserslist: 4.23.3 caniuse-lite: 1.0.30001651 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 - postcss: 8.4.49 + postcss: 8.5.1 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -6831,8 +6759,6 @@ snapshots: dependencies: streamsearch: 1.1.0 - bytes@3.1.2: {} - call-bind-apply-helpers@1.0.1: dependencies: es-errors: 1.3.0 @@ -6915,11 +6841,11 @@ snapshots: clsx@2.1.1: {} - cmdk@1.0.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + cmdk@1.0.4(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: - '@radix-ui/react-dialog': 1.1.4(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.4)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.2(@types/react@19.0.4))(@types/react@19.0.4)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-dialog': 1.1.5(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.7)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) use-sync-external-store: 1.2.2(react@19.0.0) @@ -6976,13 +6902,13 @@ snapshots: cookie@0.7.1: {} - create-jest@29.7.0(@types/node@22.10.5): + create-jest@29.7.0(@types/node@22.10.7): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.10.5) + jest-config: 29.7.0(@types/node@22.10.7) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -7275,9 +7201,9 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-next@15.1.4(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3): + eslint-config-next@15.1.6(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3): dependencies: - '@next/eslint-plugin-next': 15.1.4 + '@next/eslint-plugin-next': 15.1.6 '@rushstack/eslint-patch': 1.10.3 '@typescript-eslint/eslint-plugin': 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3) '@typescript-eslint/parser': 8.19.0(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3) @@ -7588,10 +7514,10 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@11.17.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + framer-motion@12.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: - motion-dom: 11.16.4 - motion-utils: 11.16.0 + motion-dom: 12.0.0 + motion-utils: 12.0.0 tslib: 2.8.1 optionalDependencies: react: 19.0.0 @@ -7980,7 +7906,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -8000,16 +7926,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@22.10.5): + jest-cli@29.7.0(@types/node@22.10.7): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.10.5) + create-jest: 29.7.0(@types/node@22.10.7) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@22.10.5) + jest-config: 29.7.0(@types/node@22.10.7) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -8019,7 +7945,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@22.10.5): + jest-config@29.7.0(@types/node@22.10.7): dependencies: '@babel/core': 7.24.5 '@jest/test-sequencer': 29.7.0 @@ -8044,7 +7970,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.7 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -8074,7 +8000,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 22.10.5 + '@types/node': 22.10.7 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -8088,7 +8014,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -8098,7 +8024,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 22.10.5 + '@types/node': 22.10.7 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -8137,7 +8063,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -8172,7 +8098,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -8200,7 +8126,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -8246,7 +8172,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -8265,7 +8191,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.10.5 + '@types/node': 22.10.7 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -8274,17 +8200,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 22.10.5 + '@types/node': 22.10.7 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@22.10.5): + jest@29.7.0(@types/node@22.10.7): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@22.10.5) + jest-cli: 29.7.0(@types/node@22.10.7) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8478,11 +8404,11 @@ snapshots: minipass@7.1.1: {} - motion-dom@11.16.4: + motion-dom@12.0.0: dependencies: - motion-utils: 11.16.0 + motion-utils: 12.0.0 - motion-utils@11.16.0: {} + motion-utils@12.0.0: {} mrmime@2.0.0: {} @@ -8496,18 +8422,16 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nanoid@3.3.7: {} - nanoid@3.3.8: {} nanoid@5.0.9: {} natural-compare@1.4.0: {} - next-auth@5.0.0-beta.25(next@15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0): + next-auth@5.0.0-beta.25(next@15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0): dependencies: '@auth/core': 0.37.2 - next: 15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + next: 15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 next-themes@0.4.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0): @@ -8515,9 +8439,9 @@ snapshots: react: 19.0.0 react-dom: 19.0.0(react@19.0.0) - next@15.1.4(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + next@15.1.6(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: - '@next/env': 15.1.4 + '@next/env': 15.1.6 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 @@ -8527,14 +8451,14 @@ snapshots: react-dom: 19.0.0(react@19.0.0) styled-jsx: 5.1.6(@babel/core@7.24.5)(react@19.0.0) optionalDependencies: - '@next/swc-darwin-arm64': 15.1.4 - '@next/swc-darwin-x64': 15.1.4 - '@next/swc-linux-arm64-gnu': 15.1.4 - '@next/swc-linux-arm64-musl': 15.1.4 - '@next/swc-linux-x64-gnu': 15.1.4 - '@next/swc-linux-x64-musl': 15.1.4 - '@next/swc-win32-arm64-msvc': 15.1.4 - '@next/swc-win32-x64-msvc': 15.1.4 + '@next/swc-darwin-arm64': 15.1.6 + '@next/swc-darwin-x64': 15.1.6 + '@next/swc-linux-arm64-gnu': 15.1.6 + '@next/swc-linux-arm64-musl': 15.1.6 + '@next/swc-linux-x64-gnu': 15.1.6 + '@next/swc-linux-x64-musl': 15.1.6 + '@next/swc-win32-arm64-msvc': 15.1.6 + '@next/swc-win32-x64-msvc': 15.1.6 '@opentelemetry/api': 1.9.0 sharp: 0.33.5 transitivePeerDependencies: @@ -8742,28 +8666,28 @@ snapshots: possible-typed-array-names@1.0.0: {} - postcss-import@15.1.0(postcss@8.4.49): + postcss-import@15.1.0(postcss@8.5.1): dependencies: - postcss: 8.4.49 + postcss: 8.5.1 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - postcss-js@4.0.1(postcss@8.4.49): + postcss-js@4.0.1(postcss@8.5.1): dependencies: camelcase-css: 2.0.1 - postcss: 8.4.49 + postcss: 8.5.1 - postcss-load-config@4.0.2(postcss@8.4.49): + postcss-load-config@4.0.2(postcss@8.5.1): dependencies: lilconfig: 3.1.3 yaml: 2.4.2 optionalDependencies: - postcss: 8.4.49 + postcss: 8.5.1 - postcss-nested@6.2.0(postcss@8.4.49): + postcss-nested@6.2.0(postcss@8.5.1): dependencies: - postcss: 8.4.49 + postcss: 8.5.1 postcss-selector-parser: 6.1.2 postcss-selector-parser@6.1.2: @@ -8779,9 +8703,9 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.4.49: + postcss@8.5.1: dependencies: - nanoid: 3.3.7 + nanoid: 3.3.8 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -8868,32 +8792,32 @@ snapshots: react-is@18.3.1: {} - react-remove-scroll-bar@2.3.8(@types/react@19.0.4)(react@19.0.0): + react-remove-scroll-bar@2.3.8(@types/react@19.0.7)(react@19.0.0): dependencies: react: 19.0.0 - react-style-singleton: 2.2.3(@types/react@19.0.4)(react@19.0.0) + react-style-singleton: 2.2.3(@types/react@19.0.7)(react@19.0.0) tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - react-remove-scroll@2.6.2(@types/react@19.0.4)(react@19.0.0): + react-remove-scroll@2.6.2(@types/react@19.0.7)(react@19.0.0): dependencies: react: 19.0.0 - react-remove-scroll-bar: 2.3.8(@types/react@19.0.4)(react@19.0.0) - react-style-singleton: 2.2.3(@types/react@19.0.4)(react@19.0.0) + react-remove-scroll-bar: 2.3.8(@types/react@19.0.7)(react@19.0.0) + react-style-singleton: 2.2.3(@types/react@19.0.7)(react@19.0.0) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.0.4)(react@19.0.0) - use-sidecar: 1.1.2(@types/react@19.0.4)(react@19.0.0) + use-callback-ref: 1.3.3(@types/react@19.0.7)(react@19.0.0) + use-sidecar: 1.1.2(@types/react@19.0.7)(react@19.0.0) optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 - react-style-singleton@2.2.3(@types/react@19.0.4)(react@19.0.0): + react-style-singleton@2.2.3(@types/react@19.0.7)(react@19.0.0): dependencies: get-nonce: 1.0.1 react: 19.0.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 react@19.0.0: {} @@ -8989,7 +8913,7 @@ snapshots: htmlparser2: 8.0.2 is-plain-object: 5.0.0 parse-srcset: 1.0.2 - postcss: 8.4.49 + postcss: 8.5.1 sax@1.2.4: {} @@ -9101,7 +9025,7 @@ snapshots: slash@3.0.0: {} - sonner@1.7.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + sonner@1.7.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: react: 19.0.0 react-dom: 19.0.0(react@19.0.0) @@ -9286,11 +9210,11 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.1 - postcss: 8.4.49 - postcss-import: 15.1.0(postcss@8.4.49) - postcss-js: 4.0.1(postcss@8.4.49) - postcss-load-config: 4.0.2(postcss@8.4.49) - postcss-nested: 6.2.0(postcss@8.4.49) + postcss: 8.5.1 + postcss-import: 15.1.0(postcss@8.5.1) + postcss-js: 4.0.1(postcss@8.5.1) + postcss-load-config: 4.0.2(postcss@8.5.1) + postcss-nested: 6.2.0(postcss@8.5.1) postcss-selector-parser: 6.1.2 resolve: 1.22.8 sucrase: 3.35.0 @@ -9436,24 +9360,24 @@ snapshots: querystringify: 2.2.0 requires-port: 1.0.0 - use-callback-ref@1.3.3(@types/react@19.0.4)(react@19.0.0): + use-callback-ref@1.3.3(@types/react@19.0.7)(react@19.0.0): dependencies: react: 19.0.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 use-debounce@10.0.4(react@19.0.0): dependencies: react: 19.0.0 - use-sidecar@1.1.2(@types/react@19.0.4)(react@19.0.0): + use-sidecar@1.1.2(@types/react@19.0.7)(react@19.0.0): dependencies: detect-node-es: 1.1.0 react: 19.0.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.4 + '@types/react': 19.0.7 use-sync-external-store@1.2.2(react@19.0.0): dependencies: diff --git a/src/admin/AdminNavClient.tsx b/src/admin/AdminNavClient.tsx index 98c08c64..3acc5e8d 100644 --- a/src/admin/AdminNavClient.tsx +++ b/src/admin/AdminNavClient.tsx @@ -1,7 +1,10 @@ 'use client'; +import LinkWithLoader from '@/components/LinkWithLoader'; +import LinkWithStatus from '@/components/LinkWithStatus'; import Note from '@/components/Note'; import SiteGrid from '@/components/SiteGrid'; +import Spinner from '@/components/Spinner'; import { PATH_ADMIN_CONFIGURATION, checkPathPrefix, @@ -11,7 +14,6 @@ import { import { useAppState } from '@/state/AppState'; import { clsx } from 'clsx/lite'; import { differenceInMinutes } from 'date-fns'; -import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { useEffect, useMemo, useState } from 'react'; import { BiCog } from 'react-icons/bi'; @@ -60,40 +62,43 @@ export default function AdminNavClient({ contentMain={
{items.map(({ label, href, count }) => - {label} {count > 0 && ({count})} - )} + )}
- } > - +
{shouldShowBanner && }> diff --git a/src/admin/AdminPhotosClient.tsx b/src/admin/AdminPhotosClient.tsx index 1da58678..c105eb5d 100644 --- a/src/admin/AdminPhotosClient.tsx +++ b/src/admin/AdminPhotosClient.tsx @@ -3,7 +3,10 @@ import PhotoUpload from '@/photo/PhotoUpload'; import { clsx } from 'clsx/lite'; import SiteGrid from '@/components/SiteGrid'; -import { AI_TEXT_GENERATION_ENABLED, PRO_MODE_ENABLED } from '@/site/config'; +import { + AI_TEXT_GENERATION_ENABLED, + PRESERVE_ORIGINAL_UPLOADS, +} from '@/site/config'; import AdminPhotosTable from '@/admin/AdminPhotosTable'; import AdminPhotosTableInfinite from '@/admin/AdminPhotosTableInfinite'; import PathLoaderButton from '@/components/primitives/PathLoaderButton'; @@ -43,7 +46,7 @@ export default function AdminPhotosClient({
+ !isDataMissing + ? + : + {error ?? 'Unknown error'} + ); }; diff --git a/src/app/film/[simulation]/page.tsx b/src/app/film/[simulation]/page.tsx index b9332428..0199457c 100644 --- a/src/app/film/[simulation]/page.tsx +++ b/src/app/film/[simulation]/page.tsx @@ -1,13 +1,26 @@ import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo'; +import { getUniqueFilmSimulations } from '@/photo/db/query'; import { FilmSimulation, generateMetaForFilmSimulation } from '@/simulation'; import FilmSimulationOverview from '@/simulation/FilmSimulationOverview'; +import { IS_PRODUCTION } from '@/site/config'; import { getPhotosFilmSimulationDataCached } from '@/simulation/data'; +import { STATICALLY_OPTIMIZED_PHOTO_CATEGORIES } from '@/site/config'; import { Metadata } from 'next/types'; import { cache } from 'react'; const getPhotosFilmSimulationDataCachedCached = cache(getPhotosFilmSimulationDataCached); +export let generateStaticParams: + (() => Promise<{ simulation: FilmSimulation }[]>) | undefined = undefined; + +if (STATICALLY_OPTIMIZED_PHOTO_CATEGORIES && IS_PRODUCTION) { + generateStaticParams = async () => { + const simulations = await getUniqueFilmSimulations(); + return simulations.map(({ simulation }) => ({ simulation })); + }; +} + interface FilmSimulationProps { params: Promise<{ simulation: FilmSimulation }> } diff --git a/src/app/focal/[focal]/page.tsx b/src/app/focal/[focal]/page.tsx index 78747359..ed8d78a6 100644 --- a/src/app/focal/[focal]/page.tsx +++ b/src/app/focal/[focal]/page.tsx @@ -2,6 +2,9 @@ import { generateMetaForFocalLength, getFocalLengthFromString } from '@/focal'; import FocalLengthOverview from '@/focal/FocalLengthOverview'; import { getPhotosFocalLengthDataCached } from '@/focal/data'; import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo'; +import { IS_PRODUCTION } from '@/site/config'; +import { getUniqueFocalLengths } from '@/photo/db/query'; +import { STATICALLY_OPTIMIZED_PHOTO_CATEGORIES } from '@/site/config'; import { PATH_ROOT } from '@/site/paths'; import type { Metadata } from 'next'; import { redirect } from 'next/navigation'; @@ -13,6 +16,16 @@ const getPhotosFocalDataCachedCached = cache((focal: number) => limit: INFINITE_SCROLL_GRID_INITIAL, })); +export let generateStaticParams: + (() => Promise<{ focal: string }[]>) | undefined = undefined; + +if (STATICALLY_OPTIMIZED_PHOTO_CATEGORIES && IS_PRODUCTION) { + generateStaticParams = async () => { + const focalLengths = await getUniqueFocalLengths(); + return focalLengths.map(({ focal }) => ({ focal: focal.toString() })); + }; +} + interface FocalLengthProps { params: Promise<{ focal: string }> } diff --git a/src/app/p/[photoId]/image/route.tsx b/src/app/p/[photoId]/image/route.tsx index 27dca021..73bf45ac 100644 --- a/src/app/p/[photoId]/image/route.tsx +++ b/src/app/p/[photoId]/image/route.tsx @@ -4,7 +4,10 @@ import PhotoImageResponse from '@/image-response/PhotoImageResponse'; import { getIBMPlexMonoMedium } from '@/site/font'; import { ImageResponse } from 'next/og'; import { getImageResponseCacheControlHeaders } from '@/image-response/cache'; -import { IS_PRODUCTION, STATICALLY_OPTIMIZED_OG_IMAGES } from '@/site/config'; +import { + IS_PRODUCTION, + STATICALLY_OPTIMIZED_PHOTO_OG_IMAGES, +} from '@/site/config'; import { getPhotoIds } from '@/photo/db/query'; import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db'; import { isNextImageReadyBasedOnPhotos } from '@/photo'; @@ -12,7 +15,7 @@ import { isNextImageReadyBasedOnPhotos } from '@/photo'; export let generateStaticParams: (() => Promise<{ photoId: string }[]>) | undefined = undefined; -if (STATICALLY_OPTIMIZED_OG_IMAGES && IS_PRODUCTION) { +if (STATICALLY_OPTIMIZED_PHOTO_OG_IMAGES && IS_PRODUCTION) { generateStaticParams = async () => { const photos = await getPhotoIds({ limit: GENERATE_STATIC_PARAMS_LIMIT }); return photos.map(photoId => ({ photoId })); diff --git a/src/app/p/[photoId]/page.tsx b/src/app/p/[photoId]/page.tsx index 42e53c78..86ec9013 100644 --- a/src/app/p/[photoId]/page.tsx +++ b/src/app/p/[photoId]/page.tsx @@ -12,7 +12,7 @@ import { } from '@/site/paths'; import PhotoDetailPage from '@/photo/PhotoDetailPage'; import { getPhotosNearIdCached } from '@/photo/cache'; -import { IS_PRODUCTION, STATICALLY_OPTIMIZED_PAGES } from '@/site/config'; +import { IS_PRODUCTION, STATICALLY_OPTIMIZED_PHOTOS } from '@/site/config'; import { getPhotoIds } from '@/photo/db/query'; import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db'; import { cache } from 'react'; @@ -25,7 +25,7 @@ const getPhotosNearIdCachedCached = cache((photoId: string) => export let generateStaticParams: (() => Promise<{ photoId: string }[]>) | undefined = undefined; -if (STATICALLY_OPTIMIZED_PAGES && IS_PRODUCTION) { +if (STATICALLY_OPTIMIZED_PHOTOS && IS_PRODUCTION) { generateStaticParams = async () => { const photos = await getPhotoIds({ limit: GENERATE_STATIC_PARAMS_LIMIT }); return photos.map(photoId => ({ photoId })); diff --git a/src/app/shot-on/[make]/[model]/page.tsx b/src/app/shot-on/[make]/[model]/page.tsx index 2c26c36f..2a776ee7 100644 --- a/src/app/shot-on/[make]/[model]/page.tsx +++ b/src/app/shot-on/[make]/[model]/page.tsx @@ -5,6 +5,9 @@ import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo'; import { getPhotosCameraDataCached } from '@/camera/data'; import CameraOverview from '@/camera/CameraOverview'; import { cache } from 'react'; +import { STATICALLY_OPTIMIZED_PHOTO_CATEGORIES } from '@/site/config'; +import { IS_PRODUCTION } from '@/site/config'; +import { getUniqueCameras } from '@/photo/db/query'; const getPhotosCameraDataCachedCached = cache(( make: string, @@ -15,6 +18,16 @@ const getPhotosCameraDataCachedCached = cache(( INFINITE_SCROLL_GRID_INITIAL, )); +export let generateStaticParams: + (() => Promise<{ make: string, model: string }[]>) | undefined = undefined; + +if (STATICALLY_OPTIMIZED_PHOTO_CATEGORIES && IS_PRODUCTION) { + generateStaticParams = async () => { + const cameras = await getUniqueCameras(); + return cameras.map(({ camera: { make, model } }) => ({ make, model })); + }; +} + export async function generateMetadata({ params, }: CameraProps): Promise { diff --git a/src/app/tag/[tag]/page.tsx b/src/app/tag/[tag]/page.tsx index f134f6bc..0e19f3a7 100644 --- a/src/app/tag/[tag]/page.tsx +++ b/src/app/tag/[tag]/page.tsx @@ -1,4 +1,7 @@ import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo'; +import { getUniqueTags } from '@/photo/db/query'; +import { IS_PRODUCTION } from '@/site/config'; +import { STATICALLY_OPTIMIZED_PHOTO_CATEGORIES } from '@/site/config'; import { PATH_ROOT } from '@/site/paths'; import { generateMetaForTag } from '@/tag'; import TagOverview from '@/tag/TagOverview'; @@ -10,6 +13,16 @@ import { cache } from 'react'; const getPhotosTagDataCachedCached = cache((tag: string) => getPhotosTagDataCached({ tag, limit: INFINITE_SCROLL_GRID_INITIAL})); +export let generateStaticParams: + (() => Promise<{ tag: string }[]>) | undefined = undefined; + +if (STATICALLY_OPTIMIZED_PHOTO_CATEGORIES && IS_PRODUCTION) { + generateStaticParams = async () => { + const tags = await getUniqueTags(); + return tags.map(({ tag }) => ({ tag })); + }; +} + interface TagProps { params: Promise<{ tag: string }> } diff --git a/src/auth/SignInForm.tsx b/src/auth/SignInForm.tsx index f5cfab4c..8adef8af 100644 --- a/src/auth/SignInForm.tsx +++ b/src/auth/SignInForm.tsx @@ -6,7 +6,6 @@ import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus'; import { useActionState, useEffect, - useLayoutEffect, useRef, useState, } from 'react'; @@ -28,8 +27,9 @@ export default function SignInForm() { const [response, action] = useActionState(signInAction, undefined); const emailRef = useRef(null); - useLayoutEffect(() => { - emailRef.current?.focus(); + useEffect(() => { + const timeout = setTimeout(() => emailRef.current?.focus(), 100); + return () => clearTimeout(timeout); }, []); useEffect(() => { diff --git a/src/auth/actions.ts b/src/auth/actions.ts index 9f26b610..72c04dea 100644 --- a/src/auth/actions.ts +++ b/src/auth/actions.ts @@ -6,6 +6,7 @@ import { KEY_CREDENTIALS_SIGN_IN_ERROR, KEY_CREDENTIALS_SIGN_IN_ERROR_URL, auth, + generateAuthSecret, signIn, signOut, } from '@/auth'; @@ -47,3 +48,5 @@ export const getAuthAction = async () => auth(); export const logClientAuthUpdate = async (data: Session | null | undefined) => console.log('Client auth update', data); + +export const generateAuthSecretAction = async () => generateAuthSecret(); diff --git a/src/components/CopyButton.tsx b/src/components/CopyButton.tsx new file mode 100644 index 00000000..7c4fa939 --- /dev/null +++ b/src/components/CopyButton.tsx @@ -0,0 +1,32 @@ +import { BiCopy } from 'react-icons/bi'; +import LoaderButton from './primitives/LoaderButton'; +import clsx from 'clsx/lite'; +import { toastSuccess } from '@/toast'; + +export default function CopyButton({ + label, + text, + subtle, +}: { + label: string + text?: string, + subtle?: boolean +}) { + return ( + } + className={clsx( + 'translate-y-[2px]', + subtle && 'text-gray-300 dark:text-gray-700', + )} + onClick={text + ? () => { + navigator.clipboard.writeText(text); + toastSuccess(`${label} copied to clipboard`); + } + : undefined} + styleAs="link" + disabled={!text} + /> + ); +} diff --git a/src/components/FieldSetWithStatus.tsx b/src/components/FieldSetWithStatus.tsx index 5b0eda42..305ba493 100644 --- a/src/components/FieldSetWithStatus.tsx +++ b/src/components/FieldSetWithStatus.tsx @@ -58,7 +58,7 @@ export default function FieldSetWithStatus({ {!hideLabel && label &&
; + + const renderSubStatusWithEnvVar = ( + type: ComponentProps['type'], + variable: string, + ) => + renderSubStatus( + type, + renderEnvVars([variable]), + 'translate-y-[5px]', + ); const renderError = ({ connection, @@ -301,18 +302,7 @@ export default function SiteChecklistClient({ Store auth secret in environment variable: {!hasAuthSecret &&
- -
- {secret ? {secret} : } -
- {renderCopyButton('Secret', secret)} -
-
-
+
} {renderEnvVars(['AUTH_SECRET'])} @@ -426,6 +416,102 @@ export default function SiteChecklistClient({ {renderEnvVars(['AI_TEXT_AUTO_GENERATED_FIELDS'])} + } + optional + > + + Set environment variable to {'"1"'} to make site more responsive + by enabling static optimization + (i.e., rendering pages and images at build time): + {renderSubStatusWithEnvVar( + arePhotosStaticallyOptimized ? 'checked' : 'optional', + 'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTOS', + )} + {renderSubStatusWithEnvVar( + arePhotoOGImagesStaticallyOptimized ? 'checked' : 'optional', + 'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_OG_IMAGES', + )} + {renderSubStatusWithEnvVar( + arePhotoCategoriesStaticallyOptimized ? 'checked' : 'optional', + 'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORIES', + )} + + + Set environment variable to {'"1"'} to prevent + image uploads being compressed before storing: + {renderEnvVars(['NEXT_PUBLIC_PRESERVE_ORIGINAL_UPLOADS'])} + + + Set environment variable to {'"1"'} to prevent + image blur data being stored and displayed: + {renderEnvVars(['NEXT_PUBLIC_BLUR_DISABLED'])} + + + } + optional + > + + Set environment variable to {'"1"'} to hide EXIF data: + {renderEnvVars(['NEXT_PUBLIC_HIDE_EXIF_DATA'])} + + + Set environment variable to {'"1"'} to hide + taken at time from photo meta: + {renderEnvVars(['NEXT_PUBLIC_HIDE_TAKEN_AT_TIME'])} + + + Set environment variable to {'"1"'} to hide + {' '} + X button from share modal: + {renderEnvVars(['NEXT_PUBLIC_HIDE_SOCIAL'])} + + + Set environment variable to {'"1"'} to prevent + simulations showing up in /grid sidebar and + CMD-K results: + {renderEnvVars(['NEXT_PUBLIC_HIDE_FILM_SIMULATIONS'])} + + + Set environment variable to {'"1"'} to hide footer link: + {renderEnvVars(['NEXT_PUBLIC_HIDE_REPO_LINK'])} + + } @@ -452,34 +538,6 @@ export default function SiteChecklistClient({ (defaults to {'\'system\''}): {renderEnvVars(['NEXT_PUBLIC_DEFAULT_THEME'])} - - Set environment variable to {'"1"'} to enable - higher quality image storage: - {renderEnvVars(['NEXT_PUBLIC_PRO_MODE'])} - - - Set environment variable to {'"1"'} to enable static optimization, - i.e., rendering pages and images at build time: - {renderSubStatus( - arePagesStaticallyOptimized ? 'checked' : 'optional', - renderEnvVars(['NEXT_PUBLIC_STATICALLY_OPTIMIZE_PAGES']), - 'translate-y-[3.5px]', - )} - {renderSubStatus( - areOGImagesStaticallyOptimized ? 'checked' : 'optional', - renderEnvVars(['NEXT_PUBLIC_STATICALLY_OPTIMIZE_OG_IMAGES']), - 'translate-y-[3.5px]', - )} - - - Set environment variable to {'"1"'} to prevent - image blur data being stored and displayed: - {renderEnvVars(['NEXT_PUBLIC_BLUR_DISABLED'])} - - Set environment variable to {'"1"'} to hide footer link: - {renderEnvVars(['NEXT_PUBLIC_HIDE_REPO_LINK'])} + Set environment variable to any number to enforce aspect ratio + {' '} + (default is {'"1"'}, i.e., square)—set to {'"0"'} to disable: + {renderEnvVars(['NEXT_PUBLIC_GRID_ASPECT_RATIO'])} + + + Set environment variable to {'"1"'} to ensure large thumbnails + on photo grid views (if not configured, density is based on + aspect ratio configuration): + {renderEnvVars(['NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS'])} - - Set environment variable to {'"1"'} to hide - {' '} - X button from share modal: - {renderEnvVars(['NEXT_PUBLIC_HIDE_SOCIAL'])} - - - Set environment variable to {'"1"'} to prevent - simulations showing up in /grid sidebar and - CMD-K results: - {renderEnvVars(['NEXT_PUBLIC_HIDE_FILM_SIMULATIONS'])} - - - Set environment variable to {'"1"'} to hide EXIF data: - {renderEnvVars(['NEXT_PUBLIC_HIDE_EXIF_DATA'])} - - - Set environment variable to any number to enforce aspect ratio - {' '} - (default is {'"1"'}, i.e., square)—set to {'"0"'} to disable: - {renderEnvVars(['NEXT_PUBLIC_GRID_ASPECT_RATIO'])} - - - Set environment variable to {'"1"'} to ensure large thumbnails - on photo grid views (if not configured, density is based on - aspect ratio configuration): - {renderEnvVars(['NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS'])} - Commit    {commitSha - ? {commitSha} + ? commitUrl + ? + {commitSha} + + : {commitSha} : 'Not Found'}
} diff --git a/src/site/SiteChecklistServer.tsx b/src/site/SiteChecklistServer.tsx index 1d264d19..af73d43b 100644 --- a/src/site/SiteChecklistServer.tsx +++ b/src/site/SiteChecklistServer.tsx @@ -1,4 +1,3 @@ -import { generateAuthSecret } from '@/auth'; import SiteChecklistClient from './SiteChecklistClient'; import { CONFIG_CHECKLIST_STATUS } from '@/site/config'; import { testConnectionsAction } from '@/admin/actions'; @@ -8,14 +7,12 @@ export default async function SiteChecklistServer({ }: { simplifiedView?: boolean }) { - const secret = await generateAuthSecret().catch(() => 'TRY AGAIN'); const connectionErrors = await testConnectionsAction().catch(() => ({})); return ( ); } diff --git a/src/site/config.ts b/src/site/config.ts index eba577a0..249c59c4 100644 --- a/src/site/config.ts +++ b/src/site/config.ts @@ -14,10 +14,23 @@ export const SITE_TITLE = 'Photo Blog'; // SOURCE -export const VERCEL_COMMIT_MESSAGE = +const VERCEL_GIT_PROVIDER = + process.env.NEXT_PUBLIC_VERCEL_GIT_PROVIDER; +const VERCEL_GIT_REPO_OWNER = + process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER; +const VERCEL_GIT_REPO_SLUG = + process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG; +const VERCEL_GIT_COMMIT_MESSAGE = process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE; -export const VERCEL_COMMIT_SHA = +const VERCEL_GIT_COMMIT_SHA = process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA; +const VERCEL_GIT_COMMIT_SHA_SHORT = VERCEL_GIT_COMMIT_SHA + ? VERCEL_GIT_COMMIT_SHA.slice(0, 7) + : undefined; +const VERCEL_GIT_COMMIT_URL = VERCEL_GIT_PROVIDER === 'github' + // eslint-disable-next-line max-len + ? `https://github.com/${VERCEL_GIT_REPO_OWNER}/${VERCEL_GIT_REPO_SLUG}/commit/${VERCEL_GIT_COMMIT_SHA}` + : undefined; const VERCEL_ENV = process.env.NEXT_PUBLIC_VERCEL_ENV; const VERCEL_PRODUCTION_URL = process.env.VERCEL_PROJECT_PRODUCTION_URL; @@ -122,63 +135,85 @@ export const CURRENT_STORAGE: StorageType = : 'vercel-blob' ); +// AI + +export const AI_TEXT_GENERATION_ENABLED = + Boolean(process.env.OPENAI_SECRET_KEY); +export const AI_TEXT_AUTO_GENERATED_FIELDS = parseAiAutoGeneratedFieldsText( + process.env.AI_TEXT_AUTO_GENERATED_FIELDS); + +// PERFORMANCE + +export const STATICALLY_OPTIMIZED_PHOTOS = + process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTOS === '1' || + // Legacy environment variable name + process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE_PAGES === '1'; +export const STATICALLY_OPTIMIZED_PHOTO_OG_IMAGES = + process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_OG_IMAGES === '1' || + // Legacy environment variable name + process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE_OG_IMAGES === '1'; +export const STATICALLY_OPTIMIZED_PHOTO_CATEGORIES = + process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORIES === '1'; +export const PRESERVE_ORIGINAL_UPLOADS = + process.env.NEXT_PUBLIC_PRESERVE_ORIGINAL_UPLOADS === '1' || + // Legacy environment variable name + process.env.NEXT_PUBLIC_PRO_MODE === '1'; +export const BLUR_ENABLED = + process.env.NEXT_PUBLIC_BLUR_DISABLED !== '1'; + +// DISPLAY + +export const SHOW_EXIF_DATA = + process.env.NEXT_PUBLIC_HIDE_EXIF_DATA !== '1'; +export const SHOW_TAKEN_AT_TIME = + process.env.NEXT_PUBLIC_HIDE_TAKEN_AT_TIME !== '1'; +export const SHOW_SOCIAL = + process.env.NEXT_PUBLIC_HIDE_SOCIAL !== '1'; +export const SHOW_FILM_SIMULATIONS = + process.env.NEXT_PUBLIC_HIDE_FILM_SIMULATIONS !== '1'; +export const SHOW_REPO_LINK = + process.env.NEXT_PUBLIC_HIDE_REPO_LINK !== '1'; + // SETTINGS +export const GRID_HOMEPAGE_ENABLED = + process.env.NEXT_PUBLIC_GRID_HOMEPAGE === '1'; export const DEFAULT_THEME = process.env.NEXT_PUBLIC_DEFAULT_THEME === 'dark' ? 'dark' : process.env.NEXT_PUBLIC_DEFAULT_THEME === 'light' ? 'light' : 'system'; -export const PRO_MODE_ENABLED = - process.env.NEXT_PUBLIC_PRO_MODE === '1'; -export const GRID_HOMEPAGE_ENABLED = - process.env.NEXT_PUBLIC_GRID_HOMEPAGE === '1'; -export const STATICALLY_OPTIMIZED_PAGES = - process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE_PAGES === '1'; -export const STATICALLY_OPTIMIZED_OG_IMAGES = - process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE_OG_IMAGES === '1'; export const MATTE_PHOTOS = process.env.NEXT_PUBLIC_MATTE_PHOTOS === '1'; -export const BLUR_ENABLED = - process.env.NEXT_PUBLIC_BLUR_DISABLED !== '1'; export const GEO_PRIVACY_ENABLED = process.env.NEXT_PUBLIC_GEO_PRIVACY === '1'; -export const AI_TEXT_GENERATION_ENABLED = - Boolean(process.env.OPENAI_SECRET_KEY); -export const AI_TEXT_AUTO_GENERATED_FIELDS = parseAiAutoGeneratedFieldsText( - process.env.AI_TEXT_AUTO_GENERATED_FIELDS); -export const PRIORITY_ORDER_ENABLED = - process.env.NEXT_PUBLIC_IGNORE_PRIORITY_ORDER !== '1'; -export const PUBLIC_API_ENABLED = - process.env.NEXT_PUBLIC_PUBLIC_API === '1'; -export const ALLOW_PUBLIC_DOWNLOADS = - process.env.NEXT_PUBLIC_ALLOW_PUBLIC_DOWNLOADS === '1'; -export const SHOW_REPO_LINK = - process.env.NEXT_PUBLIC_HIDE_REPO_LINK !== '1'; -export const SHOW_SOCIAL = - process.env.NEXT_PUBLIC_HIDE_SOCIAL !== '1'; -export const SHOW_FILM_SIMULATIONS = - process.env.NEXT_PUBLIC_HIDE_FILM_SIMULATIONS !== '1'; -export const SHOW_EXIF_DATA = - process.env.NEXT_PUBLIC_HIDE_EXIF_DATA !== '1'; export const GRID_ASPECT_RATIO = process.env.NEXT_PUBLIC_GRID_ASPECT_RATIO ? parseFloat(process.env.NEXT_PUBLIC_GRID_ASPECT_RATIO) : 1; -export const OG_TEXT_BOTTOM_ALIGNMENT = - (process.env.NEXT_PUBLIC_OG_TEXT_ALIGNMENT ?? '').toUpperCase() === 'BOTTOM'; -export const IMAGE_ACTIONS_ENABLED = - process.env.NEXT_PUBLIC_IMAGE_ACTIONS === '1'; -export const ADMIN_DEBUG_TOOLS_ENABLED = process.env.ADMIN_DEBUG_TOOLS === '1'; - export const PREFERS_LOW_DENSITY_GRID = process.env.NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS === '1'; export const HIGH_DENSITY_GRID = GRID_ASPECT_RATIO <= 1 && !PREFERS_LOW_DENSITY_GRID; +export const ALLOW_PUBLIC_DOWNLOADS = + process.env.NEXT_PUBLIC_ALLOW_PUBLIC_DOWNLOADS === '1'; +export const PUBLIC_API_ENABLED = + process.env.NEXT_PUBLIC_PUBLIC_API === '1'; +export const PRIORITY_ORDER_ENABLED = + process.env.NEXT_PUBLIC_IGNORE_PRIORITY_ORDER !== '1'; +export const OG_TEXT_BOTTOM_ALIGNMENT = + (process.env.NEXT_PUBLIC_OG_TEXT_ALIGNMENT ?? '').toUpperCase() === 'BOTTOM'; +export const IMAGE_ACTIONS_ENABLED = + process.env.NEXT_PUBLIC_IMAGE_ACTIONS === '1'; + +// INTERNAL + +export const ADMIN_DEBUG_TOOLS_ENABLED = process.env.ADMIN_DEBUG_TOOLS === '1'; export const CONFIG_CHECKLIST_STATUS = { + // STORAGE hasDatabase: HAS_DATABASE, isPostgresSslEnabled: POSTGRES_SSL_ENABLED, hasVercelPostgres: ( @@ -196,32 +231,18 @@ export const CONFIG_CHECKLIST_STATUS = { ), hasMultipleStorageProviders: HAS_MULTIPLE_STORAGE_PROVIDERS, currentStorage: CURRENT_STORAGE, + // AUTH hasAuthSecret: Boolean(process.env.AUTH_SECRET), hasAdminUser: ( Boolean(process.env.ADMIN_EMAIL) && Boolean(process.env.ADMIN_PASSWORD) ), + // CONTENT hasDomain: Boolean(process.env.NEXT_PUBLIC_SITE_DOMAIN), hasTitle: Boolean(process.env.NEXT_PUBLIC_SITE_TITLE), hasDescription: HAS_DEFINED_SITE_DESCRIPTION, hasAbout: Boolean(process.env.NEXT_PUBLIC_SITE_ABOUT), - hasDefaultTheme: Boolean(process.env.NEXT_PUBLIC_DEFAULT_THEME), - showRepoLink: SHOW_REPO_LINK, - showSocial: SHOW_SOCIAL, - showFilmSimulations: SHOW_FILM_SIMULATIONS, - showExifInfo: SHOW_EXIF_DATA, - defaultTheme: DEFAULT_THEME, - isProModeEnabled: PRO_MODE_ENABLED, - isGridHomepageEnabled: GRID_HOMEPAGE_ENABLED, - isStaticallyOptimized: ( - STATICALLY_OPTIMIZED_PAGES || - STATICALLY_OPTIMIZED_OG_IMAGES - ), - arePagesStaticallyOptimized: STATICALLY_OPTIMIZED_PAGES, - areOGImagesStaticallyOptimized: STATICALLY_OPTIMIZED_OG_IMAGES, - arePhotosMatted: MATTE_PHOTOS, - isBlurEnabled: BLUR_ENABLED, - isGeoPrivacyEnabled: GEO_PRIVACY_ENABLED, + // AI isAiTextGenerationEnabled: AI_TEXT_GENERATION_ENABLED, aiTextAutoGeneratedFields: process.env.AI_TEXT_AUTO_GENERATED_FIELDS ? AI_TEXT_AUTO_GENERATED_FIELDS.length === 0 @@ -230,19 +251,44 @@ export const CONFIG_CHECKLIST_STATUS = { : ['all'], hasAiTextAutoGeneratedFields: Boolean(process.env.AI_TEXT_AUTO_GENERATED_FIELDS), - isPriorityOrderEnabled: PRIORITY_ORDER_ENABLED, - isPublicApiEnabled: PUBLIC_API_ENABLED, - arePublicDownloadsEnabled: ALLOW_PUBLIC_DOWNLOADS, - isOgTextBottomAligned: OG_TEXT_BOTTOM_ALIGNMENT, - isImageActionsEnabled: IMAGE_ACTIONS_ENABLED, + // PERFORMANCE + isStaticallyOptimized: ( + STATICALLY_OPTIMIZED_PHOTOS || + STATICALLY_OPTIMIZED_PHOTO_OG_IMAGES || + STATICALLY_OPTIMIZED_PHOTO_CATEGORIES + ), + arePhotosStaticallyOptimized: STATICALLY_OPTIMIZED_PHOTOS, + arePhotoOGImagesStaticallyOptimized: STATICALLY_OPTIMIZED_PHOTO_OG_IMAGES, + arePhotoCategoriesStaticallyOptimized: STATICALLY_OPTIMIZED_PHOTO_CATEGORIES, + areOriginalUploadsPreserved: PRESERVE_ORIGINAL_UPLOADS, + isBlurEnabled: BLUR_ENABLED, + // DISPLAY + showExifInfo: SHOW_EXIF_DATA, + showTakenAtTimeHidden: SHOW_TAKEN_AT_TIME, + showSocial: SHOW_SOCIAL, + showFilmSimulations: SHOW_FILM_SIMULATIONS, + showRepoLink: SHOW_REPO_LINK, + // SETTINGS + isGridHomepageEnabled: GRID_HOMEPAGE_ENABLED, + hasDefaultTheme: Boolean(process.env.NEXT_PUBLIC_DEFAULT_THEME), + defaultTheme: DEFAULT_THEME, + arePhotosMatted: MATTE_PHOTOS, + isGeoPrivacyEnabled: GEO_PRIVACY_ENABLED, gridAspectRatio: GRID_ASPECT_RATIO, hasGridAspectRatio: Boolean(process.env.NEXT_PUBLIC_GRID_ASPECT_RATIO), gridDensity: HIGH_DENSITY_GRID, hasGridDensityPreference: Boolean(process.env.NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS), + arePublicDownloadsEnabled: ALLOW_PUBLIC_DOWNLOADS, + isPublicApiEnabled: PUBLIC_API_ENABLED, + isPriorityOrderEnabled: PRIORITY_ORDER_ENABLED, + isOgTextBottomAligned: OG_TEXT_BOTTOM_ALIGNMENT, + isImageActionsEnabled: IMAGE_ACTIONS_ENABLED, + // MISC baseUrl: BASE_URL, - commitSha: VERCEL_COMMIT_SHA ? VERCEL_COMMIT_SHA.slice(0, 7) : undefined, - commitMessage: VERCEL_COMMIT_MESSAGE, + commitSha: VERCEL_GIT_COMMIT_SHA_SHORT, + commitMessage: VERCEL_GIT_COMMIT_MESSAGE, + commitUrl: VERCEL_GIT_COMMIT_URL, }; export type ConfigChecklistStatus = typeof CONFIG_CHECKLIST_STATUS; diff --git a/src/site/sonner.css b/src/site/sonner.css index 1ef6f492..26412d6f 100644 --- a/src/site/sonner.css +++ b/src/site/sonner.css @@ -4,6 +4,8 @@ [data-sonner-toaster] { position: fixed; --mobile-offset: 12px !important; + --mobile-offset-left: var(--mobile-offset) !important; + --mobile-offset-right: var(--mobile-offset) !important; right: var(--mobile-offset); left: var(--mobile-offset); width: 100% !important; diff --git a/src/utility/date.ts b/src/utility/date.ts index 30662c76..f7d34acd 100644 --- a/src/utility/date.ts +++ b/src/utility/date.ts @@ -2,56 +2,78 @@ import { parseISO, parse, format } from 'date-fns'; import { formatInTimeZone } from 'date-fns-tz'; import { Timezone } from './timezone'; -const DATE_STRING_FORMAT_TINY = 'dd MMM yy'; -const DATE_STRING_FORMAT_TINY_PLACEHOLDER = '00 000 00'; +const DATE_STRING_FORMAT_TINY = 'dd MMM yy'; +const DATE_STRING_FORMAT_TINY_PLACEHOLDER = '00 000 00'; -const DATE_STRING_FORMAT_SHORT = 'dd MMM yyyy'; -const DATE_STRING_FORMAT_SHORT_PLACEHOLDER = '00 000 0000'; +const DATE_STRING_FORMAT_SHORT = 'dd MMM yyyy'; +const DATE_STRING_FORMAT_SHORT_PLACEHOLDER = '00 000 0000'; -const DATE_STRING_FORMAT_MEDIUM = 'dd MMM yy h:mma'; -const DATE_STRING_FORMAT_MEDIUM_PLACEHOLDER = '00 000 00 00:0000'; +const DATE_STRING_FORMAT_MEDIUM = 'dd MMM yy h:mma'; +const DATE_STRING_FORMAT_MEDIUM_PLACEHOLDER = '00 000 00 00:0000'; -const DATE_STRING_FORMAT_LONG = 'dd MMM yyyy h:mma'; -const DATE_STRING_FORMAT_LONG_PLACEHOLDER = '00 000 0000 00:0000'; +const DATE_STRING_FORMAT_LONG = 'dd MMM yyyy h:mma'; +const DATE_STRING_FORMAT_LONG_PLACEHOLDER = '00 000 0000 00:0000'; -const DATE_STRING_FORMAT_POSTGRES = 'yyyy-MM-dd HH:mm:ss'; +const DATE_STRING_FORMAT_POSTGRES = 'yyyy-MM-dd HH:mm:ss'; + +export const VALIDATION_EXAMPLE_POSTGRES = '2025-01-03T21:00:44.000Z'; +export const VALIDATION_EXAMPLE_POSTGRES_NAIVE = '2025-01-03 16:00:44'; type AmbiguousTimestamp = number | string; type Length = 'tiny' | 'short' | 'medium' | 'long'; -export const formatDate = ( +export const formatDate = ({ + date, + length = 'long', + timezone, + hideTime, + showPlaceholder, +}: { date: Date, - length: Length = 'long', + length?: Length, timezone?: Timezone, + hideTime?: boolean, showPlaceholder?: boolean, -) => { - switch (length) { - case 'tiny': return showPlaceholder - ? DATE_STRING_FORMAT_TINY_PLACEHOLDER - : timezone - ? formatInTimeZone(date, timezone, DATE_STRING_FORMAT_TINY) - : format(date, DATE_STRING_FORMAT_TINY); - case 'short': return showPlaceholder - ? DATE_STRING_FORMAT_SHORT_PLACEHOLDER - : timezone - ? formatInTimeZone(date, timezone, DATE_STRING_FORMAT_SHORT) - : format(date, DATE_STRING_FORMAT_SHORT); - case 'medium': return showPlaceholder - ? DATE_STRING_FORMAT_MEDIUM_PLACEHOLDER - : timezone - ? formatInTimeZone(date, timezone, DATE_STRING_FORMAT_MEDIUM) - : format(date, DATE_STRING_FORMAT_MEDIUM); - default: return showPlaceholder +}) => { + let formatString = !hideTime + ? DATE_STRING_FORMAT_LONG + : DATE_STRING_FORMAT_SHORT; + let placeholderString = !hideTime ? DATE_STRING_FORMAT_LONG_PLACEHOLDER - : timezone - ? formatInTimeZone(date, timezone, DATE_STRING_FORMAT_LONG) - : format(date, DATE_STRING_FORMAT_LONG); + : DATE_STRING_FORMAT_SHORT_PLACEHOLDER; + + switch (length) { + case 'tiny': + formatString = DATE_STRING_FORMAT_TINY; + placeholderString = DATE_STRING_FORMAT_TINY_PLACEHOLDER; + break; + case 'short': + formatString = DATE_STRING_FORMAT_SHORT; + placeholderString = DATE_STRING_FORMAT_SHORT_PLACEHOLDER; + break; + case 'medium': + formatString = !hideTime + ? DATE_STRING_FORMAT_MEDIUM + : DATE_STRING_FORMAT_SHORT; + placeholderString = !hideTime + ? DATE_STRING_FORMAT_MEDIUM_PLACEHOLDER + : DATE_STRING_FORMAT_SHORT_PLACEHOLDER; + break; } + + return showPlaceholder + ? placeholderString + : timezone + ? formatInTimeZone(date, timezone, formatString) + : format(date, formatString); }; export const formatDateFromPostgresString = (date: string, length?: Length) => - formatDate(parse(date, DATE_STRING_FORMAT_POSTGRES, new Date()), length); + formatDate({ + date: parse(date, DATE_STRING_FORMAT_POSTGRES, new Date()), + length, + }); export const formatDateForPostgres = (date: Date) => date.toISOString().replace( @@ -103,3 +125,23 @@ export const generateLocalPostgresString = () => export const generateLocalNaivePostgresString = () => format(new Date(), DATE_STRING_FORMAT_POSTGRES); + +// Form validation to prevent Postgres runtime errors + +// POSTGRES: 2025-01-03T21:00:44.000Z +export const validatePostgresDateString = (date = ''): boolean => + /^(\d{4}-\d{2}-\d{2})T\d{2}:\d{2}:\d{2}(.[\d]+)*Z$/.test(date); + +export const validationMessagePostgresDateString = (date = '') => + validatePostgresDateString(date) + ? undefined + : `Invalid format (${VALIDATION_EXAMPLE_POSTGRES})`; + +// NAIVE: 2025-01-03 16:00:44 +export const validateNaivePostgresDateString = (date = ''): boolean => + /^(\d{4}-\d{2}-\d{2}) \d{2}:\d{2}:\d{2}$/.test(date); + +export const validationMessageNaivePostgresDateString = (date = '') => + validateNaivePostgresDateString(date) + ? undefined + : `Invalid format (${VALIDATION_EXAMPLE_POSTGRES_NAIVE})`; diff --git a/src/utility/url.ts b/src/utility/url.ts index c41dc8e7..61fbae23 100644 --- a/src/utility/url.ts +++ b/src/utility/url.ts @@ -5,6 +5,13 @@ export const shortenUrl = (url?: string) => url .replace(/\/$/, '') : undefined; +// Remove protocol, and trailing slash from url +export const removeUrlProtocol = (url?: string) => url + ? url + .replace(/^(?:https?:\/\/)?/i, '') + .replace(/\/$/, '') + : undefined; + // Add protocol to url and remove trailing slash export const makeUrlAbsolute = (url?: string) => url !== undefined ? (!url.startsWith('http') ? `https://${url}` : url) diff --git a/src/utility/useOnPathChange.ts b/src/utility/useOnPathChange.ts new file mode 100644 index 00000000..34aa6875 --- /dev/null +++ b/src/utility/useOnPathChange.ts @@ -0,0 +1,14 @@ +import { usePathname } from 'next/navigation'; +import { useEffect, useRef } from 'react'; + +export default function useOnPathChange(onPathChange: () => void) { + const path = usePathname(); + + const initialPath = useRef(path); + + useEffect(() => { + if (initialPath.current !== path) { + onPathChange(); + } + }, [path, onPathChange]); +} diff --git a/tailwind.config.js b/tailwind.config.js index f86a24d3..a728d01d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -28,12 +28,18 @@ module.exports = { animation: { 'rotate-pulse': 'rotate-pulse 0.75s linear infinite normal both running', + 'fade-in': + 'fade-in 0.5s linear', 'hover-drift': 'hover-drift 8s linear infinite', 'hover-wobble': 'hover-wobble 6s linear infinite normal both running', }, keyframes: { + 'fade-in': { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, 'rotate-pulse': { '0%': { transform: 'rotate(0deg) scale(1)' }, '50%': { transform: 'rotate(180deg) scale(0.8)' },