From 008425cdfb41ae8de587f90dd93b6ff0bf696f6d Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 20 Jan 2024 11:39:37 -0600 Subject: [PATCH 01/13] Upgrade to next 14.1.0 + next-auth beta.5 --- package.json | 32 +- pnpm-lock.yaml | 2248 +++++++++++++++++++++++++++++---------------- src/auth/index.ts | 2 +- 3 files changed, 1495 insertions(+), 787 deletions(-) diff --git a/package.json b/package.json index 52ea1f07..ce339750 100644 --- a/package.json +++ b/package.json @@ -9,36 +9,36 @@ "analyze": "ANALYZE=true next build" }, "dependencies": { - "@aws-sdk/client-s3": "3.490.0", - "@aws-sdk/s3-request-presigner": "3.490.0", + "@aws-sdk/client-s3": "3.496.0", + "@aws-sdk/s3-request-presigner": "3.496.0", "@headlessui/react": "2.0.0-alpha.4", - "@next/bundle-analyzer": "14.0.4", + "@next/bundle-analyzer": "14.1.0", "@tailwindcss/forms": "^0.5.7", "@testing-library/jest-dom": "^6.2.0", "@testing-library/react": "^14.1.2", "@types/jest": "^29.5.11", - "@types/node": "^20.11.0", - "@types/react": "18.2.47", + "@types/node": "^20.11.5", + "@types/react": "18.2.48", "@types/react-dom": "18.2.18", - "@typescript-eslint/eslint-plugin": "^6.18.1", - "@typescript-eslint/parser": "^6.18.1", - "@vercel/analytics": "^1.1.1", - "@vercel/blob": "^0.17.0", + "@typescript-eslint/eslint-plugin": "^6.19.0", + "@typescript-eslint/parser": "^6.19.0", + "@vercel/analytics": "^1.1.2", + "@vercel/blob": "^0.19.0", "@vercel/postgres": "0.5.1", - "@vercel/speed-insights": "^1.0.3", - "autoprefixer": "10.4.16", - "camelcase-keys": "^9.1.2", + "@vercel/speed-insights": "^1.0.5", + "autoprefixer": "10.4.17", + "camelcase-keys": "^9.1.3", "clsx": "^2.1.0", - "date-fns": "^3.2.0", + "date-fns": "^3.3.0", "eslint": "8.56.0", - "eslint-config-next": "14.0.4", + "eslint-config-next": "14.1.0", "exifr": "^7.1.3", "framer-motion": "^10.18.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "nanoid": "^5.0.4", - "next": "14.0.4", - "next-auth": "5.0.0-beta.4", + "next": "14.1.0", + "next-auth": "5.0.0-beta.5", "next-themes": "^0.2.1", "postcss": "8.4.33", "react": "18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4148d81a..be86b6e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,17 +6,17 @@ settings: dependencies: '@aws-sdk/client-s3': - specifier: 3.490.0 - version: 3.490.0 + specifier: 3.496.0 + version: 3.496.0 '@aws-sdk/s3-request-presigner': - specifier: 3.490.0 - version: 3.490.0 + specifier: 3.496.0 + version: 3.496.0 '@headlessui/react': specifier: 2.0.0-alpha.4 version: 2.0.0-alpha.4(react-dom@18.2.0)(react@18.2.0) '@next/bundle-analyzer': - specifier: 14.0.4 - version: 14.0.4 + specifier: 14.1.0 + version: 14.1.0 '@tailwindcss/forms': specifier: ^0.5.7 version: 0.5.7(tailwindcss@3.4.1) @@ -30,50 +30,50 @@ dependencies: specifier: ^29.5.11 version: 29.5.11 '@types/node': - specifier: ^20.11.0 - version: 20.11.0 + specifier: ^20.11.5 + version: 20.11.5 '@types/react': - specifier: 18.2.47 - version: 18.2.47 + specifier: 18.2.48 + version: 18.2.48 '@types/react-dom': specifier: 18.2.18 version: 18.2.18 '@typescript-eslint/eslint-plugin': - specifier: ^6.18.1 - version: 6.18.1(@typescript-eslint/parser@6.18.1)(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.19.0 + version: 6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.18.1 - version: 6.18.1(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.19.0 + version: 6.19.0(eslint@8.56.0)(typescript@5.3.3) '@vercel/analytics': - specifier: ^1.1.1 - version: 1.1.1 + specifier: ^1.1.2 + version: 1.1.2 '@vercel/blob': - specifier: ^0.17.0 - version: 0.17.0 + specifier: ^0.19.0 + version: 0.19.0 '@vercel/postgres': specifier: 0.5.1 version: 0.5.1 '@vercel/speed-insights': - specifier: ^1.0.3 - version: 1.0.3 + specifier: ^1.0.5 + version: 1.0.5(@babel/core@7.23.7)(react-dom@18.2.0)(typescript@5.3.3)(vite@4.5.2) autoprefixer: - specifier: 10.4.16 - version: 10.4.16(postcss@8.4.33) + specifier: 10.4.17 + version: 10.4.17(postcss@8.4.33) camelcase-keys: - specifier: ^9.1.2 - version: 9.1.2 + specifier: ^9.1.3 + version: 9.1.3 clsx: specifier: ^2.1.0 version: 2.1.0 date-fns: - specifier: ^3.2.0 - version: 3.2.0 + specifier: ^3.3.0 + version: 3.3.0 eslint: specifier: 8.56.0 version: 8.56.0 eslint-config-next: - specifier: 14.0.4 - version: 14.0.4(eslint@8.56.0)(typescript@5.3.3) + specifier: 14.1.0 + version: 14.1.0(eslint@8.56.0)(typescript@5.3.3) exifr: specifier: ^7.1.3 version: 7.1.3 @@ -82,7 +82,7 @@ dependencies: version: 10.18.0(react-dom@18.2.0)(react@18.2.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.11.0) + version: 29.7.0(@types/node@20.11.5) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -90,14 +90,14 @@ dependencies: specifier: ^5.0.4 version: 5.0.4 next: - specifier: 14.0.4 - version: 14.0.4(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) next-auth: - specifier: 5.0.0-beta.4 - version: 5.0.0-beta.4(next@14.0.4)(react@18.2.0) + specifier: 5.0.0-beta.5 + version: 5.0.0-beta.5(next@14.1.0)(react@18.2.0) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@14.0.4)(react-dom@18.2.0)(react@18.2.0) + version: 0.2.1(next@14.1.0)(react-dom@18.2.0)(react@18.2.0) postcss: specifier: 8.4.33 version: 8.4.33 @@ -147,8 +147,8 @@ packages: '@jridgewell/trace-mapping': 0.3.20 dev: false - /@auth/core@0.18.4: - resolution: {integrity: sha512-GsNhsP1xE/3FoNS3dVkPjqRljLNJ4iyL2OLv3klQGNvw3bMpROFcK4lqhx7+pPHiamnVaYt2vg1xbB+lsNaevg==} + /@auth/core@0.21.0: + resolution: {integrity: sha512-jUWYs8gjy2GvtP9dd/4S9KcwZ660Cm/IkybiAq96/2Ooku9SKk5SUG+UTEwkyLuaQ38ZgfwggfpDOgzsXEcufA==} peerDependencies: nodemailer: ^6.8.0 peerDependenciesMeta: @@ -156,6 +156,7 @@ packages: optional: true dependencies: '@panva/hkdf': 1.1.1 + '@types/cookie': 0.6.0 cookie: 0.6.0 jose: 5.2.0 oauth4webapi: 2.4.0 @@ -167,7 +168,7 @@ packages: resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} dependencies: '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 + '@aws-sdk/types': 3.496.0 tslib: 1.14.1 dev: false @@ -175,7 +176,7 @@ packages: resolution: {integrity: sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==} dependencies: '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 + '@aws-sdk/types': 3.496.0 tslib: 1.14.1 dev: false @@ -191,7 +192,7 @@ packages: '@aws-crypto/ie11-detection': 3.0.0 '@aws-crypto/supports-web-crypto': 3.0.0 '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 + '@aws-sdk/types': 3.496.0 '@aws-sdk/util-locate-window': 3.465.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 @@ -204,7 +205,7 @@ packages: '@aws-crypto/sha256-js': 3.0.0 '@aws-crypto/supports-web-crypto': 3.0.0 '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 + '@aws-sdk/types': 3.496.0 '@aws-sdk/util-locate-window': 3.465.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 @@ -214,7 +215,7 @@ packages: resolution: {integrity: sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==} dependencies: '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.489.0 + '@aws-sdk/types': 3.496.0 tslib: 1.14.1 dev: false @@ -227,503 +228,503 @@ packages: /@aws-crypto/util@3.0.0: resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} dependencies: - '@aws-sdk/types': 3.489.0 + '@aws-sdk/types': 3.496.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 dev: false - /@aws-sdk/client-s3@3.490.0: - resolution: {integrity: sha512-fBj3CJ3+5R+l/sc93Z9mKw8gM2b9K6vEhC9qSCG2XNymLd9YqlRft1peQ7VymrWywAHX3Koz1GCUrFEVNONiMw==} + /@aws-sdk/client-s3@3.496.0: + resolution: {integrity: sha512-Q16iIP8SmM/7uWHbTCRnvXgM+RxgEDHQmkKL1bvdPLhfu4q1+RwWwJ/WS+1amwQtwvWc8Z51W4XEsokJmqOYUA==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha1-browser': 3.0.0 '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.490.0 - '@aws-sdk/core': 3.490.0 - '@aws-sdk/credential-provider-node': 3.490.0 - '@aws-sdk/middleware-bucket-endpoint': 3.489.0 - '@aws-sdk/middleware-expect-continue': 3.489.0 - '@aws-sdk/middleware-flexible-checksums': 3.489.0 - '@aws-sdk/middleware-host-header': 3.489.0 - '@aws-sdk/middleware-location-constraint': 3.489.0 - '@aws-sdk/middleware-logger': 3.489.0 - '@aws-sdk/middleware-recursion-detection': 3.489.0 - '@aws-sdk/middleware-sdk-s3': 3.489.0 - '@aws-sdk/middleware-signing': 3.489.0 - '@aws-sdk/middleware-ssec': 3.489.0 - '@aws-sdk/middleware-user-agent': 3.489.0 - '@aws-sdk/region-config-resolver': 3.489.0 - '@aws-sdk/signature-v4-multi-region': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@aws-sdk/util-user-agent-browser': 3.489.0 - '@aws-sdk/util-user-agent-node': 3.489.0 - '@aws-sdk/xml-builder': 3.485.0 - '@smithy/config-resolver': 2.0.23 - '@smithy/core': 1.2.2 - '@smithy/eventstream-serde-browser': 2.0.16 - '@smithy/eventstream-serde-config-resolver': 2.0.16 - '@smithy/eventstream-serde-node': 2.0.16 - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/hash-blob-browser': 2.0.17 - '@smithy/hash-node': 2.0.18 - '@smithy/hash-stream-node': 2.0.18 - '@smithy/invalid-dependency': 2.0.16 - '@smithy/md5-js': 2.0.18 - '@smithy/middleware-content-length': 2.0.18 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/middleware-stack': 2.0.10 - '@smithy/node-config-provider': 2.1.9 - '@smithy/node-http-handler': 2.2.2 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-base64': 2.0.1 - '@smithy/util-body-length-browser': 2.0.1 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.24 - '@smithy/util-defaults-mode-node': 2.0.32 - '@smithy/util-endpoints': 1.0.8 - '@smithy/util-retry': 2.0.9 - '@smithy/util-stream': 2.0.24 - '@smithy/util-utf8': 2.0.2 - '@smithy/util-waiter': 2.0.16 + '@aws-sdk/client-sts': 3.496.0 + '@aws-sdk/core': 3.496.0 + '@aws-sdk/credential-provider-node': 3.496.0 + '@aws-sdk/middleware-bucket-endpoint': 3.496.0 + '@aws-sdk/middleware-expect-continue': 3.496.0 + '@aws-sdk/middleware-flexible-checksums': 3.496.0 + '@aws-sdk/middleware-host-header': 3.496.0 + '@aws-sdk/middleware-location-constraint': 3.496.0 + '@aws-sdk/middleware-logger': 3.496.0 + '@aws-sdk/middleware-recursion-detection': 3.496.0 + '@aws-sdk/middleware-sdk-s3': 3.496.0 + '@aws-sdk/middleware-signing': 3.496.0 + '@aws-sdk/middleware-ssec': 3.496.0 + '@aws-sdk/middleware-user-agent': 3.496.0 + '@aws-sdk/region-config-resolver': 3.496.0 + '@aws-sdk/signature-v4-multi-region': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@aws-sdk/util-endpoints': 3.496.0 + '@aws-sdk/util-user-agent-browser': 3.496.0 + '@aws-sdk/util-user-agent-node': 3.496.0 + '@aws-sdk/xml-builder': 3.496.0 + '@smithy/config-resolver': 2.1.1 + '@smithy/core': 1.3.1 + '@smithy/eventstream-serde-browser': 2.1.1 + '@smithy/eventstream-serde-config-resolver': 2.1.1 + '@smithy/eventstream-serde-node': 2.1.1 + '@smithy/fetch-http-handler': 2.4.1 + '@smithy/hash-blob-browser': 2.1.1 + '@smithy/hash-node': 2.1.1 + '@smithy/hash-stream-node': 2.1.1 + '@smithy/invalid-dependency': 2.1.1 + '@smithy/md5-js': 2.1.1 + '@smithy/middleware-content-length': 2.1.1 + '@smithy/middleware-endpoint': 2.4.1 + '@smithy/middleware-retry': 2.1.1 + '@smithy/middleware-serde': 2.1.1 + '@smithy/middleware-stack': 2.1.1 + '@smithy/node-config-provider': 2.2.1 + '@smithy/node-http-handler': 2.3.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/url-parser': 2.1.1 + '@smithy/util-base64': 2.1.1 + '@smithy/util-body-length-browser': 2.1.1 + '@smithy/util-body-length-node': 2.2.1 + '@smithy/util-defaults-mode-browser': 2.1.1 + '@smithy/util-defaults-mode-node': 2.1.1 + '@smithy/util-endpoints': 1.1.1 + '@smithy/util-retry': 2.1.1 + '@smithy/util-stream': 2.1.1 + '@smithy/util-utf8': 2.1.1 + '@smithy/util-waiter': 2.1.1 fast-xml-parser: 4.2.5 tslib: 2.6.2 transitivePeerDependencies: - aws-crt dev: false - /@aws-sdk/client-sso@3.490.0: - resolution: {integrity: sha512-yfxoHmCL1w/IKmFRfzCxdVCQrGlSQf4eei9iVEm5oi3iE8REFyPj3o/BmKQEHG3h2ITK5UbdYDb5TY4xoYHsyA==} + /@aws-sdk/client-sso@3.496.0: + resolution: {integrity: sha512-fuaMuxKg7CMUsP9l3kxYWCOxFsBjdA0xj5nlikaDm1661/gB4KkAiGqRY8LsQkpNXvXU8Nj+f7oCFADFyGYzyw==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/core': 3.490.0 - '@aws-sdk/middleware-host-header': 3.489.0 - '@aws-sdk/middleware-logger': 3.489.0 - '@aws-sdk/middleware-recursion-detection': 3.489.0 - '@aws-sdk/middleware-user-agent': 3.489.0 - '@aws-sdk/region-config-resolver': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@aws-sdk/util-user-agent-browser': 3.489.0 - '@aws-sdk/util-user-agent-node': 3.489.0 - '@smithy/config-resolver': 2.0.23 - '@smithy/core': 1.2.2 - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/hash-node': 2.0.18 - '@smithy/invalid-dependency': 2.0.16 - '@smithy/middleware-content-length': 2.0.18 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/middleware-stack': 2.0.10 - '@smithy/node-config-provider': 2.1.9 - '@smithy/node-http-handler': 2.2.2 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-base64': 2.0.1 - '@smithy/util-body-length-browser': 2.0.1 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.24 - '@smithy/util-defaults-mode-node': 2.0.32 - '@smithy/util-endpoints': 1.0.8 - '@smithy/util-retry': 2.0.9 - '@smithy/util-utf8': 2.0.2 + '@aws-sdk/core': 3.496.0 + '@aws-sdk/middleware-host-header': 3.496.0 + '@aws-sdk/middleware-logger': 3.496.0 + '@aws-sdk/middleware-recursion-detection': 3.496.0 + '@aws-sdk/middleware-user-agent': 3.496.0 + '@aws-sdk/region-config-resolver': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@aws-sdk/util-endpoints': 3.496.0 + '@aws-sdk/util-user-agent-browser': 3.496.0 + '@aws-sdk/util-user-agent-node': 3.496.0 + '@smithy/config-resolver': 2.1.1 + '@smithy/core': 1.3.1 + '@smithy/fetch-http-handler': 2.4.1 + '@smithy/hash-node': 2.1.1 + '@smithy/invalid-dependency': 2.1.1 + '@smithy/middleware-content-length': 2.1.1 + '@smithy/middleware-endpoint': 2.4.1 + '@smithy/middleware-retry': 2.1.1 + '@smithy/middleware-serde': 2.1.1 + '@smithy/middleware-stack': 2.1.1 + '@smithy/node-config-provider': 2.2.1 + '@smithy/node-http-handler': 2.3.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/url-parser': 2.1.1 + '@smithy/util-base64': 2.1.1 + '@smithy/util-body-length-browser': 2.1.1 + '@smithy/util-body-length-node': 2.2.1 + '@smithy/util-defaults-mode-browser': 2.1.1 + '@smithy/util-defaults-mode-node': 2.1.1 + '@smithy/util-endpoints': 1.1.1 + '@smithy/util-retry': 2.1.1 + '@smithy/util-utf8': 2.1.1 tslib: 2.6.2 transitivePeerDependencies: - aws-crt dev: false - /@aws-sdk/client-sts@3.490.0: - resolution: {integrity: sha512-n2vQ5Qu2qi2I0XMI+IH99ElpIRHOJTa1+sqNC4juMYxKQBMvw+EnsqUtaL3QvTHoyxNB/R7mpkeBB6SzPQ1TtA==} + /@aws-sdk/client-sts@3.496.0: + resolution: {integrity: sha512-3pSdqgegdwbK3CT1WvGHhA+Bf91R9cr8G1Ynp+iU2wZvy8ueJfMUk0NYfjo3EEv0YhSbMLKuduzZfvQHFHXYhw==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/core': 3.490.0 - '@aws-sdk/credential-provider-node': 3.490.0 - '@aws-sdk/middleware-host-header': 3.489.0 - '@aws-sdk/middleware-logger': 3.489.0 - '@aws-sdk/middleware-recursion-detection': 3.489.0 - '@aws-sdk/middleware-user-agent': 3.489.0 - '@aws-sdk/region-config-resolver': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@aws-sdk/util-user-agent-browser': 3.489.0 - '@aws-sdk/util-user-agent-node': 3.489.0 - '@smithy/config-resolver': 2.0.23 - '@smithy/core': 1.2.2 - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/hash-node': 2.0.18 - '@smithy/invalid-dependency': 2.0.16 - '@smithy/middleware-content-length': 2.0.18 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/middleware-stack': 2.0.10 - '@smithy/node-config-provider': 2.1.9 - '@smithy/node-http-handler': 2.2.2 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-base64': 2.0.1 - '@smithy/util-body-length-browser': 2.0.1 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.24 - '@smithy/util-defaults-mode-node': 2.0.32 - '@smithy/util-endpoints': 1.0.8 - '@smithy/util-middleware': 2.0.9 - '@smithy/util-retry': 2.0.9 - '@smithy/util-utf8': 2.0.2 + '@aws-sdk/core': 3.496.0 + '@aws-sdk/credential-provider-node': 3.496.0 + '@aws-sdk/middleware-host-header': 3.496.0 + '@aws-sdk/middleware-logger': 3.496.0 + '@aws-sdk/middleware-recursion-detection': 3.496.0 + '@aws-sdk/middleware-user-agent': 3.496.0 + '@aws-sdk/region-config-resolver': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@aws-sdk/util-endpoints': 3.496.0 + '@aws-sdk/util-user-agent-browser': 3.496.0 + '@aws-sdk/util-user-agent-node': 3.496.0 + '@smithy/config-resolver': 2.1.1 + '@smithy/core': 1.3.1 + '@smithy/fetch-http-handler': 2.4.1 + '@smithy/hash-node': 2.1.1 + '@smithy/invalid-dependency': 2.1.1 + '@smithy/middleware-content-length': 2.1.1 + '@smithy/middleware-endpoint': 2.4.1 + '@smithy/middleware-retry': 2.1.1 + '@smithy/middleware-serde': 2.1.1 + '@smithy/middleware-stack': 2.1.1 + '@smithy/node-config-provider': 2.2.1 + '@smithy/node-http-handler': 2.3.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/url-parser': 2.1.1 + '@smithy/util-base64': 2.1.1 + '@smithy/util-body-length-browser': 2.1.1 + '@smithy/util-body-length-node': 2.2.1 + '@smithy/util-defaults-mode-browser': 2.1.1 + '@smithy/util-defaults-mode-node': 2.1.1 + '@smithy/util-endpoints': 1.1.1 + '@smithy/util-middleware': 2.1.1 + '@smithy/util-retry': 2.1.1 + '@smithy/util-utf8': 2.1.1 fast-xml-parser: 4.2.5 tslib: 2.6.2 transitivePeerDependencies: - aws-crt dev: false - /@aws-sdk/core@3.490.0: - resolution: {integrity: sha512-TSBWkXtxMU7q1Zo6w3v5wIOr/sj7P5Jw3OyO7lJrFGsPsDC2xwpxkVqTesDxkzgMRypO52xjYEmveagn1xxBHg==} + /@aws-sdk/core@3.496.0: + resolution: {integrity: sha512-yT+ug7Cw/3eJi7x2es0+46x12+cIJm5Xv+GPWsrTFD1TKgqO/VPEgfDtHFagDNbFmjNQA65Ygc/kEdIX9ICX/A==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/core': 1.2.2 - '@smithy/protocol-http': 3.0.12 - '@smithy/signature-v4': 2.0.18 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 + '@smithy/core': 1.3.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/signature-v4': 2.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/credential-provider-env@3.489.0: - resolution: {integrity: sha512-5PqYsx9G5SB2tqPT9/z/u0EkF6D4wP6HTMWQs+DfMdmwXihrqQAgeYaTtV3KbXqb88p6sfacwxhUvE6+Rm494w==} + /@aws-sdk/credential-provider-env@3.496.0: + resolution: {integrity: sha512-lukQMJ8SWWP5RqkRNOHi/H+WMhRvSWa3Fc5Jf/VP6xHiPLfF1XafcvthtV91e0VwPCiseI+HqChrcGq8pvnxHw==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/property-provider': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/credential-provider-ini@3.490.0: - resolution: {integrity: sha512-7m63zyCpVqj9FsoDxWMWWRvL6c7zZzOcXYkHZmHujVVlmAXH0RT/vkXFkYgt+Ku+ov+v5NQrzwO5TmVoRt6O8g==} + /@aws-sdk/credential-provider-ini@3.496.0: + resolution: {integrity: sha512-2nD1jp1sIwcQaWK1y/9ruQOkW16RUxZpzgjbW/gnK3iiUXwx+/FNQWxshud+GTSx3Q4x6eIhqsbjtP4VVPPuUA==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/credential-provider-env': 3.489.0 - '@aws-sdk/credential-provider-process': 3.489.0 - '@aws-sdk/credential-provider-sso': 3.490.0 - '@aws-sdk/credential-provider-web-identity': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@smithy/credential-provider-imds': 2.1.5 - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 + '@aws-sdk/credential-provider-env': 3.496.0 + '@aws-sdk/credential-provider-process': 3.496.0 + '@aws-sdk/credential-provider-sso': 3.496.0 + '@aws-sdk/credential-provider-web-identity': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@smithy/credential-provider-imds': 2.2.1 + '@smithy/property-provider': 2.1.1 + '@smithy/shared-ini-file-loader': 2.3.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 transitivePeerDependencies: - aws-crt dev: false - /@aws-sdk/credential-provider-node@3.490.0: - resolution: {integrity: sha512-Gh33u2O5Xbout8G3z/Z5H/CZzdG1ophxf/XS3iMFxA1cazQ7swY1UMmGvB7Lm7upvax5anXouItD1Ph3gzKc4w==} + /@aws-sdk/credential-provider-node@3.496.0: + resolution: {integrity: sha512-IVF9RvLePfRa5S5/eBIRChJCWOzQkGwM8P/L79Gl84u/cH2oSG4NtUI/YTDlrtmnYn7YsGhINSV0WnzfF2twfQ==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/credential-provider-env': 3.489.0 - '@aws-sdk/credential-provider-ini': 3.490.0 - '@aws-sdk/credential-provider-process': 3.489.0 - '@aws-sdk/credential-provider-sso': 3.490.0 - '@aws-sdk/credential-provider-web-identity': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@smithy/credential-provider-imds': 2.1.5 - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 + '@aws-sdk/credential-provider-env': 3.496.0 + '@aws-sdk/credential-provider-ini': 3.496.0 + '@aws-sdk/credential-provider-process': 3.496.0 + '@aws-sdk/credential-provider-sso': 3.496.0 + '@aws-sdk/credential-provider-web-identity': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@smithy/credential-provider-imds': 2.2.1 + '@smithy/property-provider': 2.1.1 + '@smithy/shared-ini-file-loader': 2.3.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 transitivePeerDependencies: - aws-crt dev: false - /@aws-sdk/credential-provider-process@3.489.0: - resolution: {integrity: sha512-3vKQYJZ5cZYjy0870CPmbmKRBgATw2xCygxhn4m4UDCjOXVXcGUtYD51DMWsvBo3S0W8kH+FIJV4yuEDMFqLFQ==} + /@aws-sdk/credential-provider-process@3.496.0: + resolution: {integrity: sha512-/YZscCTGOKVmGr916Th4XF8Sz6JDtZ/n2loHG9exok9iy/qIbACsTRNLP9zexPxhPoue/oZqecY5xbVljfY34A==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/property-provider': 2.1.1 + '@smithy/shared-ini-file-loader': 2.3.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/credential-provider-sso@3.490.0: - resolution: {integrity: sha512-3UUBUoPbFvT58IhS4Vb23omYj/QPNkjgxu9p9ruQ3KSjLkanI4w8t/l/jljA65q83P7CoLnM5UKG9L7RA8/V1Q==} + /@aws-sdk/credential-provider-sso@3.496.0: + resolution: {integrity: sha512-eP7GxpT2QYubSDG7uk1GJW4eNymZCq65IxDyEFCXOP/kfqkxriCY+iVEFG6/Mo3LxvgrgHXU4jxrCAXMAWN43g==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/client-sso': 3.490.0 - '@aws-sdk/token-providers': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 + '@aws-sdk/client-sso': 3.496.0 + '@aws-sdk/token-providers': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@smithy/property-provider': 2.1.1 + '@smithy/shared-ini-file-loader': 2.3.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 transitivePeerDependencies: - aws-crt dev: false - /@aws-sdk/credential-provider-web-identity@3.489.0: - resolution: {integrity: sha512-mjIuE2Wg1H/ds0nXQ/7vfusEDudmdd8YzKZI1y5O4n60iZZtyB2RNIECtvLMx1EQAKclidY7/06qQkArrGau5Q==} + /@aws-sdk/credential-provider-web-identity@3.496.0: + resolution: {integrity: sha512-IbP+qLlvJSpNPj+zW6TtFuLRTK5Tf0hW+2pom4vFyi5YSH4pn8UOC136UdewX8vhXGS9BJQ5zBDMasIyl5VeGQ==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/property-provider': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-bucket-endpoint@3.489.0: - resolution: {integrity: sha512-6rJ5bpNMKo7sEKQ6p2DMbQwM+ahMYASRxfdyH7hs18blvlcS20H1RYpNmJMqPPjxMwUWruty2JPMIRl4DFcv8w==} + /@aws-sdk/middleware-bucket-endpoint@3.496.0: + resolution: {integrity: sha512-B+ilBMSs3+LJuo2bl2KB8GFdu+8PPVtYEWtwhNkmnaU8iMisgMBp5uuM8sUDvJX7I4iSF0WbgnhguX4cJqfAew==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-arn-parser': 3.465.0 - '@smithy/node-config-provider': 2.1.9 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - '@smithy/util-config-provider': 2.1.0 + '@aws-sdk/types': 3.496.0 + '@aws-sdk/util-arn-parser': 3.495.0 + '@smithy/node-config-provider': 2.2.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/types': 2.9.1 + '@smithy/util-config-provider': 2.2.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-expect-continue@3.489.0: - resolution: {integrity: sha512-2RZfnVZFaGHwzPDQJsyf9SXufu1gUd4VsMhm7dC7SWF85XmpDrozbFznS/tD22QdtyWjerLoydZJMq229hpPqg==} + /@aws-sdk/middleware-expect-continue@3.496.0: + resolution: {integrity: sha512-+exo5DVc+BeDus2iI6Fz1thefHGDXxUhHZ+4VHQ6HkStMy3Y22HugyEGHSQZmtRL86Hjr7dFbEWFsC47a2ItGA==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/protocol-http': 3.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-flexible-checksums@3.489.0: - resolution: {integrity: sha512-Cy3rBUMr4P7raxzrJFWNRshfKrKV2EojawaC9Bfk/T8aFlV+FmVrRg4ISAXMOfS5pfy3xfAbvkzjOaeqCsGfrA==} + /@aws-sdk/middleware-flexible-checksums@3.496.0: + resolution: {integrity: sha512-yQIWfjEMvgsAJ7ku224vXDjXPD+f9zfKZFialJva8VUlEr7hQp4CQ0rxV3YThSaixKEDDs5k6kOjWAd2BPGr2A==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/crc32': 3.0.0 '@aws-crypto/crc32c': 3.0.0 - '@aws-sdk/types': 3.489.0 - '@smithy/is-array-buffer': 2.0.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - '@smithy/util-utf8': 2.0.2 + '@aws-sdk/types': 3.496.0 + '@smithy/is-array-buffer': 2.1.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/types': 2.9.1 + '@smithy/util-utf8': 2.1.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-host-header@3.489.0: - resolution: {integrity: sha512-Cl7HJ1jhOfllwf0CRx1eB4ypRGMqdGKWpc0eSTXty7wWSvCdMZUhwfjQqu2bIOIlgYxg/gFu6TVmVZ6g4O8PlA==} + /@aws-sdk/middleware-host-header@3.496.0: + resolution: {integrity: sha512-jUdPpSJeqCYXf6hSjfwsfHway7peIV8Vz51w/BN91bF4vB/bYwAC5o9/iJiK/EoByp5asxA8fg9wFOyGjzdbLg==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/protocol-http': 3.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-location-constraint@3.489.0: - resolution: {integrity: sha512-NIVr+kHR2N6gxFeE3TNw2mEBxgj0N9xXBLy3dNYMMlAUvQlT/0z9HlC9+3XqcTS/Z5ElF/+pei6nqXTVt0He9A==} + /@aws-sdk/middleware-location-constraint@3.496.0: + resolution: {integrity: sha512-i4ocJ2Zs86OtPREbB18InFukhqg2qtBxb5gywv79IHDPVmpOYE4m/3v3yGUrkjfF2GTlUL0k5FskNNqw41yfng==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-logger@3.489.0: - resolution: {integrity: sha512-+EVDnWese61MdImcBNAgz/AhTcIZJaska/xsU3GWU9CP905x4a4qZdB7fExFMDu1Jlz5pJqNteFYYHCFMJhHfg==} + /@aws-sdk/middleware-logger@3.496.0: + resolution: {integrity: sha512-EwMVSY6iBMeGbVnvwdaFl/ClMS/YWtxCAo+bcEtgk8ltRuo7qgbJem8Km/fvWC1vdWvIbe4ArdJ8iGzq62ffAw==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-recursion-detection@3.489.0: - resolution: {integrity: sha512-m4rU+fTzziQcu9DKjRNZ4nQlXENEd2ZnJblJV4ONdWqqEjbmOgOj3P6aCCQlJdIbzuNvX1FBOZ5tY59ZpERo7Q==} + /@aws-sdk/middleware-recursion-detection@3.496.0: + resolution: {integrity: sha512-+IuOcFsfqg2WAnaEzH6KhVbicqCxtOq9w3DH2jwTpddRlCx2Kqf6wCzg8luhHRGyjBZdsbIS+OXwyMevoppawA==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/protocol-http': 3.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-sdk-s3@3.489.0: - resolution: {integrity: sha512-/GGASx7mK9qEgy1znvleYMZKVqm3sOdGghqKdy2zgoGcH2jH+fZrLM0lDMT9bvdITmOCbJJs2rVHP3xm/ZWcXg==} + /@aws-sdk/middleware-sdk-s3@3.496.0: + resolution: {integrity: sha512-OKrTPzubisQCQzPuF4G7jmbYt71o6W7oefmW9zm1MpGokRSJeC9zv4aT1gkMglpXEHgvL0S5fUVGi0AtF/F8Kw==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-arn-parser': 3.465.0 - '@smithy/node-config-provider': 2.1.9 - '@smithy/protocol-http': 3.0.12 - '@smithy/signature-v4': 2.0.18 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/util-config-provider': 2.1.0 + '@aws-sdk/types': 3.496.0 + '@aws-sdk/util-arn-parser': 3.495.0 + '@smithy/node-config-provider': 2.2.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/signature-v4': 2.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/util-config-provider': 2.2.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-signing@3.489.0: - resolution: {integrity: sha512-rlHcWYZn6Ym3v/u0DvKNDiD7ogIzEsHlerm0lowTiQbszkFobOiUClRTALwvsUZdAAztl706qO1OKbnGnD6Ubw==} + /@aws-sdk/middleware-signing@3.496.0: + resolution: {integrity: sha512-Oq73Brs4IConvWnRlh8jM1V7LHoTw9SVQklu/QW2FPlNrB3B8fuTdWHHYIWv7ybw1bykXoCY99v865Mmq/Or/g==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/property-provider': 2.0.17 - '@smithy/protocol-http': 3.0.12 - '@smithy/signature-v4': 2.0.18 - '@smithy/types': 2.8.0 - '@smithy/util-middleware': 2.0.9 + '@aws-sdk/types': 3.496.0 + '@smithy/property-provider': 2.1.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/signature-v4': 2.1.1 + '@smithy/types': 2.9.1 + '@smithy/util-middleware': 2.1.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-ssec@3.489.0: - resolution: {integrity: sha512-5RQg8dqERAmi1OfVEV9fbTA5NKmcvKDYP79YtH08IEFIsHWU1Y5NoqL7mXkkNyBrJNBVyasYijAbTzOuM707eg==} + /@aws-sdk/middleware-ssec@3.496.0: + resolution: {integrity: sha512-6RUFEgGqKGq8N8W9tsctS8KRlYnmD/yiExb/LvblCJqV1DWoD0psRFWNz8TQZtujHklG5dHjuq+aN/qicjBNdw==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/middleware-user-agent@3.489.0: - resolution: {integrity: sha512-M54Cv2fAN3GGgdfUjLtZ4wFUIrfM/ivbXv4DgpcNsacEQ2g4H+weQgKp41X7XZW8MWAzl+k1zJaryK69RYNQkQ==} + /@aws-sdk/middleware-user-agent@3.496.0: + resolution: {integrity: sha512-+iMtRxFk0GmFWNUF4ilxylOQd9PZdR4ZC9jkcPIh1PZlvKtpCyFywKlk5RRZKklSoJ/CttcqwhMvOXTNbWm/0w==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@aws-sdk/util-endpoints': 3.496.0 + '@smithy/protocol-http': 3.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/region-config-resolver@3.489.0: - resolution: {integrity: sha512-UvrnB78XTz9ddby7mr0vuUHn2MO3VTjzaIu+GQhyedMGQU0QlIQrYOlzbbu4LC5rL1O8FxFLUxRe/AAjgwyuGw==} + /@aws-sdk/region-config-resolver@3.496.0: + resolution: {integrity: sha512-URrNVOPHPgEDm6QFu6lDC2cUFs+Jx23mA3jEwCvoKlXiEY/ZoWjH8wlX3OMUlLrF1qoUTuD03jjrJzF6zoCgug==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/node-config-provider': 2.1.9 - '@smithy/types': 2.8.0 - '@smithy/util-config-provider': 2.1.0 - '@smithy/util-middleware': 2.0.9 + '@aws-sdk/types': 3.496.0 + '@smithy/node-config-provider': 2.2.1 + '@smithy/types': 2.9.1 + '@smithy/util-config-provider': 2.2.1 + '@smithy/util-middleware': 2.1.1 tslib: 2.6.2 dev: false - /@aws-sdk/s3-request-presigner@3.490.0: - resolution: {integrity: sha512-ZHs+FlcTv9MKMM0b9svxxQio4FiRxDNstKYG8sbm9YEoahYV25h3K3butUiThaiOeYePOD7jHdbdXz4/XasxXg==} + /@aws-sdk/s3-request-presigner@3.496.0: + resolution: {integrity: sha512-l4FMNKYjEDRwjry5zG0TAmfKY/COh/ZoGiUGfTUXaL92NzNqv8NpREHVvL7Rp6YeGzF1/j6/1LeVzDct94lc/Q==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/signature-v4-multi-region': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-format-url': 3.489.0 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 + '@aws-sdk/signature-v4-multi-region': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@aws-sdk/util-format-url': 3.496.0 + '@smithy/middleware-endpoint': 2.4.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/signature-v4-multi-region@3.489.0: - resolution: {integrity: sha512-kYFM7Opu36EkFlzXdVNOBFpQApgnuaTu/U/qYhGyuzeD+HNnYgZEsd/tDro1DQ074jVy3GN9ttJSYxq5I4oTkA==} + /@aws-sdk/signature-v4-multi-region@3.496.0: + resolution: {integrity: sha512-zi3cL8+dRVSvC0PA6votwEHF4l9uxOyQTiRfgpFgzJ9iiPbsrtWCalGCwN0UyzmeDv7eViU6FK1YTHH/OgDJ4A==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/middleware-sdk-s3': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@smithy/protocol-http': 3.0.12 - '@smithy/signature-v4': 2.0.18 - '@smithy/types': 2.8.0 + '@aws-sdk/middleware-sdk-s3': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@smithy/protocol-http': 3.1.1 + '@smithy/signature-v4': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/token-providers@3.489.0: - resolution: {integrity: sha512-hSgjB8CMQoA8EIQ0ripDjDtbBcWDSa+7vSBYPIzksyknaGERR/GUfGXLV2dpm5t17FgFG6irT5f3ZlBzarL8Dw==} + /@aws-sdk/token-providers@3.496.0: + resolution: {integrity: sha512-fyi8RcObEa1jNETJdc2H6q9VHrrdKCj/b6+fbLvymb7mUVRd0aWUn+24SNUImnSOnrwYnwaMfyyEC388X4MbFQ==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/middleware-host-header': 3.489.0 - '@aws-sdk/middleware-logger': 3.489.0 - '@aws-sdk/middleware-recursion-detection': 3.489.0 - '@aws-sdk/middleware-user-agent': 3.489.0 - '@aws-sdk/region-config-resolver': 3.489.0 - '@aws-sdk/types': 3.489.0 - '@aws-sdk/util-endpoints': 3.489.0 - '@aws-sdk/util-user-agent-browser': 3.489.0 - '@aws-sdk/util-user-agent-node': 3.489.0 - '@smithy/config-resolver': 2.0.23 - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/hash-node': 2.0.18 - '@smithy/invalid-dependency': 2.0.16 - '@smithy/middleware-content-length': 2.0.18 - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/middleware-stack': 2.0.10 - '@smithy/node-config-provider': 2.1.9 - '@smithy/node-http-handler': 2.2.2 - '@smithy/property-provider': 2.0.17 - '@smithy/protocol-http': 3.0.12 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-base64': 2.0.1 - '@smithy/util-body-length-browser': 2.0.1 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.24 - '@smithy/util-defaults-mode-node': 2.0.32 - '@smithy/util-endpoints': 1.0.8 - '@smithy/util-retry': 2.0.9 - '@smithy/util-utf8': 2.0.2 + '@aws-sdk/middleware-host-header': 3.496.0 + '@aws-sdk/middleware-logger': 3.496.0 + '@aws-sdk/middleware-recursion-detection': 3.496.0 + '@aws-sdk/middleware-user-agent': 3.496.0 + '@aws-sdk/region-config-resolver': 3.496.0 + '@aws-sdk/types': 3.496.0 + '@aws-sdk/util-endpoints': 3.496.0 + '@aws-sdk/util-user-agent-browser': 3.496.0 + '@aws-sdk/util-user-agent-node': 3.496.0 + '@smithy/config-resolver': 2.1.1 + '@smithy/fetch-http-handler': 2.4.1 + '@smithy/hash-node': 2.1.1 + '@smithy/invalid-dependency': 2.1.1 + '@smithy/middleware-content-length': 2.1.1 + '@smithy/middleware-endpoint': 2.4.1 + '@smithy/middleware-retry': 2.1.1 + '@smithy/middleware-serde': 2.1.1 + '@smithy/middleware-stack': 2.1.1 + '@smithy/node-config-provider': 2.2.1 + '@smithy/node-http-handler': 2.3.1 + '@smithy/property-provider': 2.1.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/shared-ini-file-loader': 2.3.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/url-parser': 2.1.1 + '@smithy/util-base64': 2.1.1 + '@smithy/util-body-length-browser': 2.1.1 + '@smithy/util-body-length-node': 2.2.1 + '@smithy/util-defaults-mode-browser': 2.1.1 + '@smithy/util-defaults-mode-node': 2.1.1 + '@smithy/util-endpoints': 1.1.1 + '@smithy/util-retry': 2.1.1 + '@smithy/util-utf8': 2.1.1 tslib: 2.6.2 transitivePeerDependencies: - aws-crt dev: false - /@aws-sdk/types@3.489.0: - resolution: {integrity: sha512-kcDtLfKog/p0tC4gAeqJqWxAiEzfe2LRPnKamvSG2Mjbthx4R/alE2dxyIq/wW+nvRv0fqR3OD5kD1+eVfdr/w==} + /@aws-sdk/types@3.496.0: + resolution: {integrity: sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@aws-sdk/util-arn-parser@3.465.0: - resolution: {integrity: sha512-zOJ82vzDJFqBX9yZBlNeHHrul/kpx/DCoxzW5UBbZeb26kfV53QhMSoEmY8/lEbBqlqargJ/sgRC845GFhHNQw==} + /@aws-sdk/util-arn-parser@3.495.0: + resolution: {integrity: sha512-hwdA3XAippSEUxs7jpznwD63YYFR+LtQvlEcebPTgWR9oQgG9TfS+39PUfbnEeje1ICuOrN3lrFqFbmP9uzbMg==} engines: {node: '>=14.0.0'} dependencies: tslib: 2.6.2 dev: false - /@aws-sdk/util-endpoints@3.489.0: - resolution: {integrity: sha512-uGyG1u84ATX03mf7bT4xD9XD/vlYJGD5+RxMN/UpzeTfzXfh+jvCQWbOQ44z8ttFJWYQQqrLxkfpF/JgvALzLA==} + /@aws-sdk/util-endpoints@3.496.0: + resolution: {integrity: sha512-1QzOiWHi383ZwqSi/R2KgKCd7M+6DxkxI5acqLPm8mvDRDP2jRjrnVaC0g9/tlttWousGEemDUWStwrD2mVYSw==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 - '@smithy/util-endpoints': 1.0.8 + '@aws-sdk/types': 3.496.0 + '@smithy/types': 2.9.1 + '@smithy/util-endpoints': 1.1.1 tslib: 2.6.2 dev: false - /@aws-sdk/util-format-url@3.489.0: - resolution: {integrity: sha512-yqIf9RMdOSxMUrv1BVDmrYp5kjLh4RxA17BTqzcQK8cXkRBqBP8ydbCQXENSv8LZSMH7AnrXNHBD1eiVuKRzZw==} + /@aws-sdk/util-format-url@3.496.0: + resolution: {integrity: sha512-GYRqLEUVoIkD8+ULliODFWWRHGyjlanLCnj8faahZXUke6Ey32MG40RgPTu/2eFkUyS6U7sVdt7oLY8MIHShPQ==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/querystring-builder': 2.0.16 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/querystring-builder': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false @@ -734,17 +735,17 @@ packages: tslib: 2.6.2 dev: false - /@aws-sdk/util-user-agent-browser@3.489.0: - resolution: {integrity: sha512-85B9KMsuMpAZauzWQ16r52ZBAHYnznW6BVitnBglsibN7oJKn10Hggt4QGuRhvQFCxQ8YhvBl7r+vQGFO4hxIw==} + /@aws-sdk/util-user-agent-browser@3.496.0: + resolution: {integrity: sha512-4j2spN+h0I0qfSMsGvJXTfQBu1e18rPdekKvzsGJxhaAE1tNgUfUT4nbvc5uVn0sNjZmirskmJ3kfbzVOrqIFg==} dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/types': 2.9.1 bowser: 2.11.0 tslib: 2.6.2 dev: false - /@aws-sdk/util-user-agent-node@3.489.0: - resolution: {integrity: sha512-CYdkBHig8sFNc0dv11Ni9WXvZQHeI5+z77OrDHKkbidFx/V4BDTuwZw4K1vWg62pzFOEfzunJFiULRcDZWJR3w==} + /@aws-sdk/util-user-agent-node@3.496.0: + resolution: {integrity: sha512-h0Ax0jlDc7UIo3KoSI4C4tVLBFoiAdx3+DhTVfgLS7x93d41dMlziPoBX2RgdcFn37qnzw6AQKTVTMwDbRCGpg==} engines: {node: '>=14.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -752,9 +753,9 @@ packages: aws-crt: optional: true dependencies: - '@aws-sdk/types': 3.489.0 - '@smithy/node-config-provider': 2.1.9 - '@smithy/types': 2.8.0 + '@aws-sdk/types': 3.496.0 + '@smithy/node-config-provider': 2.2.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false @@ -764,11 +765,11 @@ packages: tslib: 2.6.2 dev: false - /@aws-sdk/xml-builder@3.485.0: - resolution: {integrity: sha512-xQexPM6LINOIkf3NLFywplcbApifZRMWFN41TDWYSNgCUa5uC9fntfenw8N/HTx1n+McRCWSAFBTjDqY/2OLCQ==} + /@aws-sdk/xml-builder@3.496.0: + resolution: {integrity: sha512-GvEjh537IIeOw1ZkZuB37sV12u+ipS5Z1dwjEC/HAvhl5ac23ULtTr1/n+U1gLNN+BAKSWjKiQ2ksj8DiUzeyw==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false @@ -1108,6 +1109,11 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: false + /@discoveryjs/json-ext@0.5.7: + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + dev: false + /@emotion/is-prop-valid@0.8.8: resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} requiresBuild: true @@ -1122,6 +1128,204 @@ packages: dev: false optional: true + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1273,7 +1477,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -1294,14 +1498,14 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 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@20.11.0) + jest-config: 29.7.0(@types/node@20.11.5) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -1329,7 +1533,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 jest-mock: 29.7.0 dev: false @@ -1356,7 +1560,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.11.0 + '@types/node': 20.11.5 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -1389,7 +1593,7 @@ packages: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.20 - '@types/node': 20.11.0 + '@types/node': 20.11.5 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -1477,7 +1681,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.11.0 + '@types/node': 20.11.5 '@types/yargs': 17.0.32 chalk: 4.1.2 dev: false @@ -1518,27 +1722,27 @@ packages: '@types/pg': 8.6.6 dev: false - /@next/bundle-analyzer@14.0.4: - resolution: {integrity: sha512-Nn2PiCkFBJBlVmpSGVNItpISws0fuc9E8AkCafBz/moRv1cfASOpFBBVzSRfWLP9BPdAhfDkb6TafN0rvs2IJQ==} + /@next/bundle-analyzer@14.1.0: + resolution: {integrity: sha512-RJWjnlMp/1WSW0ahAdawV22WgJiC6BVaFS5Xfhw6gP7NJEX3cAJjh4JqSHKGr8GnLNRaFCVTQdDPoX84E421BA==} dependencies: - webpack-bundle-analyzer: 4.7.0 + webpack-bundle-analyzer: 4.10.1 transitivePeerDependencies: - bufferutil - utf-8-validate dev: false - /@next/env@14.0.4: - resolution: {integrity: sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==} + /@next/env@14.1.0: + resolution: {integrity: sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw==} dev: false - /@next/eslint-plugin-next@14.0.4: - resolution: {integrity: sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ==} + /@next/eslint-plugin-next@14.1.0: + resolution: {integrity: sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q==} dependencies: - glob: 7.1.7 + glob: 10.3.10 dev: false - /@next/swc-darwin-arm64@14.0.4: - resolution: {integrity: sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==} + /@next/swc-darwin-arm64@14.1.0: + resolution: {integrity: sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -1546,8 +1750,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@14.0.4: - resolution: {integrity: sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==} + /@next/swc-darwin-x64@14.1.0: + resolution: {integrity: sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -1555,8 +1759,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@14.0.4: - resolution: {integrity: sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==} + /@next/swc-linux-arm64-gnu@14.1.0: + resolution: {integrity: sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1564,8 +1768,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@14.0.4: - resolution: {integrity: sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==} + /@next/swc-linux-arm64-musl@14.1.0: + resolution: {integrity: sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1573,8 +1777,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@14.0.4: - resolution: {integrity: sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==} + /@next/swc-linux-x64-gnu@14.1.0: + resolution: {integrity: sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1582,8 +1786,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@14.0.4: - resolution: {integrity: sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==} + /@next/swc-linux-x64-musl@14.1.0: + resolution: {integrity: sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1591,8 +1795,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@14.0.4: - resolution: {integrity: sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==} + /@next/swc-win32-arm64-msvc@14.1.0: + resolution: {integrity: sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -1600,8 +1804,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@14.0.4: - resolution: {integrity: sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==} + /@next/swc-win32-ia32-msvc@14.1.0: + resolution: {integrity: sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -1609,8 +1813,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@14.0.4: - resolution: {integrity: sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==} + /@next/swc-win32-x64-msvc@14.1.0: + resolution: {integrity: sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1791,461 +1995,530 @@ packages: '@sinonjs/commons': 3.0.0 dev: false - /@smithy/abort-controller@2.0.16: - resolution: {integrity: sha512-4foO7738k8kM9flMHu3VLabqu7nPgvIj8TB909S0CnKx0YZz/dcDH3pZ/4JHdatfxlZdKF1JWOYCw9+v3HVVsw==} + /@smithy/abort-controller@2.1.1: + resolution: {integrity: sha512-1+qdrUqLhaALYL0iOcN43EP6yAXXQ2wWZ6taf4S2pNGowmOc5gx+iMQv+E42JizNJjB0+gEadOXeV1Bf7JWL1Q==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/chunked-blob-reader-native@2.0.1: - resolution: {integrity: sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==} + /@smithy/chunked-blob-reader-native@2.1.1: + resolution: {integrity: sha512-zNW+43dltfNMUrBEYLMWgI8lQr0uhtTcUyxkgC9EP4j17WREzgSFMPUFVrVV6Rc2+QtWERYjb4tzZnQGa7R9fQ==} dependencies: - '@smithy/util-base64': 2.0.1 + '@smithy/util-base64': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/chunked-blob-reader@2.0.0: - resolution: {integrity: sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==} + /@smithy/chunked-blob-reader@2.1.1: + resolution: {integrity: sha512-NjNFCKxC4jVvn+lUr3Yo4/PmUJj3tbyqH6GNHueyTGS5Q27vlEJ1MkNhUDV8QGxJI7Bodnc2pD18lU2zRfhHlQ==} dependencies: tslib: 2.6.2 dev: false - /@smithy/config-resolver@2.0.23: - resolution: {integrity: sha512-XakUqgtP2YY8Mi+Nlif5BiqJgWdvfxJafSpOSQeCOMizu+PUhE4fBQSy6xFcR+eInrwVadaABNxoJyGUMn15ew==} + /@smithy/config-resolver@2.1.1: + resolution: {integrity: sha512-lxfLDpZm+AWAHPFZps5JfDoO9Ux1764fOgvRUBpHIO8HWHcSN1dkgsago1qLRVgm1BZ8RCm8cgv99QvtaOWIhw==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/node-config-provider': 2.1.9 - '@smithy/types': 2.8.0 - '@smithy/util-config-provider': 2.1.0 - '@smithy/util-middleware': 2.0.9 + '@smithy/node-config-provider': 2.2.1 + '@smithy/types': 2.9.1 + '@smithy/util-config-provider': 2.2.1 + '@smithy/util-middleware': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/core@1.2.2: - resolution: {integrity: sha512-uLjrskLT+mWb0emTR5QaiAIxVEU7ndpptDaVDrTwwhD+RjvHhjIiGQ3YL5jKk1a5VSDQUA2RGkXvJ6XKRcz6Dg==} + /@smithy/core@1.3.1: + resolution: {integrity: sha512-tf+NIu9FkOh312b6M9G4D68is4Xr7qptzaZGZUREELF8ysE1yLKphqt7nsomjKZVwW7WE5pDDex9idowNGRQ/Q==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-retry': 2.0.26 - '@smithy/middleware-serde': 2.0.16 - '@smithy/protocol-http': 3.0.12 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/util-middleware': 2.0.9 + '@smithy/middleware-endpoint': 2.4.1 + '@smithy/middleware-retry': 2.1.1 + '@smithy/middleware-serde': 2.1.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/util-middleware': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/credential-provider-imds@2.1.5: - resolution: {integrity: sha512-VfvE6Wg1MUWwpTZFBnUD7zxvPhLY8jlHCzu6bCjlIYoWgXCDzZAML76IlZUEf45nib3rjehnFgg0s1rgsuN/bg==} + /@smithy/credential-provider-imds@2.2.1: + resolution: {integrity: sha512-7XHjZUxmZYnONheVQL7j5zvZXga+EWNgwEAP6OPZTi7l8J4JTeNh9aIOfE5fKHZ/ee2IeNOh54ZrSna+Vc6TFA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/node-config-provider': 2.1.9 - '@smithy/property-provider': 2.0.17 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 + '@smithy/node-config-provider': 2.2.1 + '@smithy/property-provider': 2.1.1 + '@smithy/types': 2.9.1 + '@smithy/url-parser': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/eventstream-codec@2.0.16: - resolution: {integrity: sha512-umYh5pdCE9GHgiMAH49zu9wXWZKNHHdKPm/lK22WYISTjqu29SepmpWNmPiBLy/yUu4HFEGJHIFrDWhbDlApaw==} + /@smithy/eventstream-codec@2.1.1: + resolution: {integrity: sha512-E8KYBxBIuU4c+zrpR22VsVrOPoEDzk35bQR3E+xm4k6Pa6JqzkDOdMyf9Atac5GPNKHJBdVaQ4JtjdWX2rl/nw==} dependencies: '@aws-crypto/crc32': 3.0.0 - '@smithy/types': 2.8.0 - '@smithy/util-hex-encoding': 2.0.0 + '@smithy/types': 2.9.1 + '@smithy/util-hex-encoding': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/eventstream-serde-browser@2.0.16: - resolution: {integrity: sha512-W+BdiN728R57KuZOcG0GczpIOEFf8S5RP/OdVH7T3FMCy8HU2bBU0vB5xZZR5c00VRdoeWrohNv3XlHoZuGRoA==} + /@smithy/eventstream-serde-browser@2.1.1: + resolution: {integrity: sha512-JvEdCmGlZUay5VtlT8/kdR6FlvqTDUiJecMjXsBb0+k1H/qc9ME5n2XKPo8q/MZwEIA1GmGgYMokKGjVvMiDow==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/eventstream-serde-universal': 2.0.16 - '@smithy/types': 2.8.0 + '@smithy/eventstream-serde-universal': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/eventstream-serde-config-resolver@2.0.16: - resolution: {integrity: sha512-8qrE4nh+Tg6m1SMFK8vlzoK+8bUFTlIhXidmmQfASMninXW3Iu0T0bI4YcIk4nLznHZdybQ0qGydIanvVZxzVg==} + /@smithy/eventstream-serde-config-resolver@2.1.1: + resolution: {integrity: sha512-EqNqXYp3+dk//NmW3NAgQr9bEQ7fsu/CcxQmTiq07JlaIcne/CBWpMZETyXm9w5LXkhduBsdXdlMscfDUDn2fA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/eventstream-serde-node@2.0.16: - resolution: {integrity: sha512-NRNQuOa6mQdFSkqzY0IV37swHWx0SEoKxFtUfdZvfv0AVQPlSw4N7E3kcRSCpnHBr1kCuWWirdDlWcjWuD81MA==} + /@smithy/eventstream-serde-node@2.1.1: + resolution: {integrity: sha512-LF882q/aFidFNDX7uROAGxq3H0B7rjyPkV6QDn6/KDQ+CG7AFkRccjxRf1xqajq/Pe4bMGGr+VKAaoF6lELIQw==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/eventstream-serde-universal': 2.0.16 - '@smithy/types': 2.8.0 + '@smithy/eventstream-serde-universal': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/eventstream-serde-universal@2.0.16: - resolution: {integrity: sha512-ZyLnGaYQMLc75j9kKEVMJ3X6bdBE9qWxhZdTXM5RIltuytxJC3FaOhawBxjE+IL1enmWSIohHGZCm/pLwEliQA==} + /@smithy/eventstream-serde-universal@2.1.1: + resolution: {integrity: sha512-LR0mMT+XIYTxk4k2fIxEA1BPtW3685QlqufUEUAX1AJcfFfxNDKEvuCRZbO8ntJb10DrIFVJR9vb0MhDCi0sAQ==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/eventstream-codec': 2.0.16 - '@smithy/types': 2.8.0 + '@smithy/eventstream-codec': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/fetch-http-handler@2.3.2: - resolution: {integrity: sha512-O9R/OlnAOTsnysuSDjt0v2q6DcSvCz5cCFC/CFAWWcLyBwJDeFyGTCTszgpQTb19+Fi8uRwZE5/3ziAQBFeDMQ==} + /@smithy/fetch-http-handler@2.4.1: + resolution: {integrity: sha512-VYGLinPsFqH68lxfRhjQaSkjXM7JysUOJDTNjHBuN/ykyRb2f1gyavN9+VhhPTWCy32L4yZ2fdhpCs/nStEicg==} dependencies: - '@smithy/protocol-http': 3.0.12 - '@smithy/querystring-builder': 2.0.16 - '@smithy/types': 2.8.0 - '@smithy/util-base64': 2.0.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/querystring-builder': 2.1.1 + '@smithy/types': 2.9.1 + '@smithy/util-base64': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/hash-blob-browser@2.0.17: - resolution: {integrity: sha512-/mPpv1sRiRDdjO4zZuO8be6eeabmg5AVgKDfnmmqkpBtRyMGSJb968fjRuHt+FRAsIGywgIKJFmUUAYjhsi1oQ==} + /@smithy/hash-blob-browser@2.1.1: + resolution: {integrity: sha512-jizu1+2PAUjiGIfRtlPEU8Yo6zn+d78ti/ZHDesdf1SUn2BuZW433JlPoCOLH3dBoEEvTgLvQ8tUGSoTTALA+A==} dependencies: - '@smithy/chunked-blob-reader': 2.0.0 - '@smithy/chunked-blob-reader-native': 2.0.1 - '@smithy/types': 2.8.0 + '@smithy/chunked-blob-reader': 2.1.1 + '@smithy/chunked-blob-reader-native': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/hash-node@2.0.18: - resolution: {integrity: sha512-gN2JFvAgnZCyDN9rJgcejfpK0uPPJrSortVVVVWsru9whS7eQey6+gj2eM5ln2i6rHNntIXzal1Fm9XOPuoaKA==} + /@smithy/hash-node@2.1.1: + resolution: {integrity: sha512-Qhoq0N8f2OtCnvUpCf+g1vSyhYQrZjhSwvJ9qvR8BUGOtTXiyv2x1OD2e6jVGmlpC4E4ax1USHoyGfV9JFsACg==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 - '@smithy/util-buffer-from': 2.0.0 - '@smithy/util-utf8': 2.0.2 + '@smithy/types': 2.9.1 + '@smithy/util-buffer-from': 2.1.1 + '@smithy/util-utf8': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/hash-stream-node@2.0.18: - resolution: {integrity: sha512-OuFk+ITpv8CtxGjQcS8GA04faNycu9UMm6YobvQzjeEoXZ0dLF6sRfuzD+3S8RHPKpTyLuXtKG1+GiJycZ5TcA==} + /@smithy/hash-stream-node@2.1.1: + resolution: {integrity: sha512-VgDaKcfCy0iHcmtAZgZ3Yw9g37Gkn2JsQiMtFQXUh8Wmo3GfNgDwLOtdhJ272pOT7DStzpe9cNr+eV5Au8KfQA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 - '@smithy/util-utf8': 2.0.2 + '@smithy/types': 2.9.1 + '@smithy/util-utf8': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/invalid-dependency@2.0.16: - resolution: {integrity: sha512-apEHakT/kmpNo1VFHP4W/cjfeP9U0x5qvfsLJubgp7UM/gq4qYp0GbqdE7QhsjUaYvEnrftRqs7+YrtWreV0wA==} + /@smithy/invalid-dependency@2.1.1: + resolution: {integrity: sha512-7WTgnKw+VPg8fxu2v9AlNOQ5yaz6RA54zOVB4f6vQuR0xFKd+RzlCpt0WidYTsye7F+FYDIaS/RnJW4pxjNInw==} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/is-array-buffer@2.0.0: - resolution: {integrity: sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==} + /@smithy/is-array-buffer@2.1.1: + resolution: {integrity: sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==} engines: {node: '>=14.0.0'} dependencies: tslib: 2.6.2 dev: false - /@smithy/md5-js@2.0.18: - resolution: {integrity: sha512-bHwZ8/m6RbERQdVW5rJ2LzeW8qxfXv6Q/S7Fiudhso4pWRrksqLx3nsGZw7bmqqfN4zLqkxydxSa9+4c7s5zxg==} + /@smithy/md5-js@2.1.1: + resolution: {integrity: sha512-L3MbIYBIdLlT+MWTYrdVSv/dow1+6iZ1Ad7xS0OHxTTs17d753ZcpOV4Ro7M7tRAVWML/sg2IAp/zzCb6aAttg==} dependencies: - '@smithy/types': 2.8.0 - '@smithy/util-utf8': 2.0.2 + '@smithy/types': 2.9.1 + '@smithy/util-utf8': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/middleware-content-length@2.0.18: - resolution: {integrity: sha512-ZJ9uKPTfxYheTKSKYB+GCvcj+izw9WGzRLhjn8n254q0jWLojUzn7Vw0l4R/Gq7Wdpf/qmk/ptD+6CCXHNVCaw==} + /@smithy/middleware-content-length@2.1.1: + resolution: {integrity: sha512-rSr9ezUl9qMgiJR0UVtVOGEZElMdGFyl8FzWEF5iEKTlcWxGr2wTqGfDwtH3LAB7h+FPkxqv4ZU4cpuCN9Kf/g==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 + '@smithy/protocol-http': 3.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/middleware-endpoint@2.3.0: - resolution: {integrity: sha512-VsOAG2YQ8ykjSmKO+CIXdJBIWFo6AAvG6Iw95BakBTqk66/4BI7XyqLevoNSq/lZ6NgZv24sLmrcIN+fLDWBCg==} + /@smithy/middleware-endpoint@2.4.1: + resolution: {integrity: sha512-XPZTb1E2Oav60Ven3n2PFx+rX9EDsU/jSTA8VDamt7FXks67ekjPY/XrmmPDQaFJOTUHJNKjd8+kZxVO5Ael4Q==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/middleware-serde': 2.0.16 - '@smithy/node-config-provider': 2.1.9 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 - '@smithy/url-parser': 2.0.16 - '@smithy/util-middleware': 2.0.9 + '@smithy/middleware-serde': 2.1.1 + '@smithy/node-config-provider': 2.2.1 + '@smithy/shared-ini-file-loader': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/url-parser': 2.1.1 + '@smithy/util-middleware': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/middleware-retry@2.0.26: - resolution: {integrity: sha512-Qzpxo0U5jfNiq9iD38U3e2bheXwvTEX4eue9xruIvEgh+UKq6dKuGqcB66oBDV7TD/mfoJi9Q/VmaiqwWbEp7A==} + /@smithy/middleware-retry@2.1.1: + resolution: {integrity: sha512-eMIHOBTXro6JZ+WWzZWd/8fS8ht5nS5KDQjzhNMHNRcG5FkNTqcKpYhw7TETMYzbLfhO5FYghHy1vqDWM4FLDA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/node-config-provider': 2.1.9 - '@smithy/protocol-http': 3.0.12 - '@smithy/service-error-classification': 2.0.9 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 - '@smithy/util-middleware': 2.0.9 - '@smithy/util-retry': 2.0.9 + '@smithy/node-config-provider': 2.2.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/service-error-classification': 2.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/util-middleware': 2.1.1 + '@smithy/util-retry': 2.1.1 tslib: 2.6.2 uuid: 8.3.2 dev: false - /@smithy/middleware-serde@2.0.16: - resolution: {integrity: sha512-5EAd4t30pcc4M8TSSGq7q/x5IKrxfXR5+SrU4bgxNy7RPHQo2PSWBUco9C+D9Tfqp/JZvprRpK42dnupZafk2g==} + /@smithy/middleware-serde@2.1.1: + resolution: {integrity: sha512-D8Gq0aQBeE1pxf3cjWVkRr2W54t+cdM2zx78tNrVhqrDykRA7asq8yVJij1u5NDtKzKqzBSPYh7iW0svUKg76g==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/middleware-stack@2.0.10: - resolution: {integrity: sha512-I2rbxctNq9FAPPEcuA1ntZxkTKOPQFy7YBPOaD/MLg1zCvzv21CoNxR0py6J8ZVC35l4qE4nhxB0f7TF5/+Ldw==} + /@smithy/middleware-stack@2.1.1: + resolution: {integrity: sha512-KPJhRlhsl8CjgGXK/DoDcrFGfAqoqvuwlbxy+uOO4g2Azn1dhH+GVfC3RAp+6PoL5PWPb+vt6Z23FP+Mr6qeCw==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/node-config-provider@2.1.9: - resolution: {integrity: sha512-tUyW/9xrRy+s7RXkmQhgYkAPMpTIF8izK4orhHjNFEKR3QZiOCbWB546Y8iB/Fpbm3O9+q0Af9rpywLKJOwtaQ==} + /@smithy/node-config-provider@2.2.1: + resolution: {integrity: sha512-epzK3x1xNxA9oJgHQ5nz+2j6DsJKdHfieb+YgJ7ATWxzNcB7Hc+Uya2TUck5MicOPhDV8HZImND7ZOecVr+OWg==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/property-provider': 2.0.17 - '@smithy/shared-ini-file-loader': 2.2.8 - '@smithy/types': 2.8.0 + '@smithy/property-provider': 2.1.1 + '@smithy/shared-ini-file-loader': 2.3.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/node-http-handler@2.2.2: - resolution: {integrity: sha512-XO58TO/Eul/IBQKFKaaBtXJi0ItEQQCT+NI4IiKHCY/4KtqaUT6y/wC1EvDqlA9cP7Dyjdj7FdPs4DyynH3u7g==} + /@smithy/node-http-handler@2.3.1: + resolution: {integrity: sha512-gLA8qK2nL9J0Rk/WEZSvgin4AppvuCYRYg61dcUo/uKxvMZsMInL5I5ZdJTogOvdfVug3N2dgI5ffcUfS4S9PA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/abort-controller': 2.0.16 - '@smithy/protocol-http': 3.0.12 - '@smithy/querystring-builder': 2.0.16 - '@smithy/types': 2.8.0 + '@smithy/abort-controller': 2.1.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/querystring-builder': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/property-provider@2.0.17: - resolution: {integrity: sha512-+VkeZbVu7qtQ2DjI48Qwaf9fPOr3gZIwxQpuLJgRRSkWsdSvmaTCxI3gzRFKePB63Ts9r4yjn4HkxSCSkdWmcQ==} + /@smithy/property-provider@2.1.1: + resolution: {integrity: sha512-FX7JhhD/o5HwSwg6GLK9zxrMUrGnb3PzNBrcthqHKBc3dH0UfgEAU24xnJ8F0uow5mj17UeBEOI6o3CF2k7Mhw==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/protocol-http@3.0.12: - resolution: {integrity: sha512-Xz4iaqLiaBfbQpB9Hgi3VcZYbP7xRDXYhd8XWChh4v94uw7qwmvlxdU5yxzfm6ACJM66phHrTbS5TVvj5uQ72w==} + /@smithy/protocol-http@3.1.1: + resolution: {integrity: sha512-6ZRTSsaXuSL9++qEwH851hJjUA0OgXdQFCs+VDw4tGH256jQ3TjYY/i34N4vd24RV3nrjNsgd1yhb57uMoKbzQ==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/querystring-builder@2.0.16: - resolution: {integrity: sha512-Q/GsJT0C0mijXMRs7YhZLLCP5FcuC4797lYjKQkME5CZohnLC4bEhylAd2QcD3gbMKNjCw8+T2I27WKiV/wToA==} + /@smithy/querystring-builder@2.1.1: + resolution: {integrity: sha512-C/ko/CeEa8jdYE4gt6nHO5XDrlSJ3vdCG0ZAc6nD5ZIE7LBp0jCx4qoqp7eoutBu7VrGMXERSRoPqwi1WjCPbg==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 - '@smithy/util-uri-escape': 2.0.0 + '@smithy/types': 2.9.1 + '@smithy/util-uri-escape': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/querystring-parser@2.0.16: - resolution: {integrity: sha512-c4ueAuL6BDYKWpkubjrQthZKoC3L5kql5O++ovekNxiexRXTlLIVlCR4q3KziOktLIw66EU9SQljPXd/oN6Okg==} + /@smithy/querystring-parser@2.1.1: + resolution: {integrity: sha512-H4+6jKGVhG1W4CIxfBaSsbm98lOO88tpDWmZLgkJpt8Zkk/+uG0FmmqMuCAc3HNM2ZDV+JbErxr0l5BcuIf/XQ==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/service-error-classification@2.0.9: - resolution: {integrity: sha512-0K+8GvtwI7VkGmmInPydM2XZyBfIqLIbfR7mDQ+oPiz8mIinuHbV6sxOLdvX1Jv/myk7XTK9orgt3tuEpBu/zg==} + /@smithy/service-error-classification@2.1.1: + resolution: {integrity: sha512-txEdZxPUgM1PwGvDvHzqhXisrc5LlRWYCf2yyHfvITWioAKat7srQvpjMAvgzf0t6t7j8yHrryXU9xt7RZqFpw==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 dev: false - /@smithy/shared-ini-file-loader@2.2.8: - resolution: {integrity: sha512-E62byatbwSWrtq9RJ7xN40tqrRKDGrEL4EluyNpaIDvfvet06a/QC58oHw2FgVaEgkj0tXZPjZaKrhPfpoU0qw==} + /@smithy/shared-ini-file-loader@2.3.1: + resolution: {integrity: sha512-2E2kh24igmIznHLB6H05Na4OgIEilRu0oQpYXo3LCNRrawHAcfDKq9004zJs+sAMt2X5AbY87CUCJ7IpqpSgdw==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/signature-v4@2.0.18: - resolution: {integrity: sha512-SJRAj9jT/l9ocm8D0GojMbnA1sp7I4JeStOQ4lEXI8A5eHE73vbjlzlqIFB7cLvIgau0oUl4cGVpF9IGCrvjlw==} + /@smithy/signature-v4@2.1.1: + resolution: {integrity: sha512-Hb7xub0NHuvvQD3YwDSdanBmYukoEkhqBjqoxo+bSdC0ryV9cTfgmNjuAQhTPYB6yeU7hTR+sPRiFMlxqv6kmg==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/eventstream-codec': 2.0.16 - '@smithy/is-array-buffer': 2.0.0 - '@smithy/types': 2.8.0 - '@smithy/util-hex-encoding': 2.0.0 - '@smithy/util-middleware': 2.0.9 - '@smithy/util-uri-escape': 2.0.0 - '@smithy/util-utf8': 2.0.2 + '@smithy/eventstream-codec': 2.1.1 + '@smithy/is-array-buffer': 2.1.1 + '@smithy/types': 2.9.1 + '@smithy/util-hex-encoding': 2.1.1 + '@smithy/util-middleware': 2.1.1 + '@smithy/util-uri-escape': 2.1.1 + '@smithy/util-utf8': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/smithy-client@2.2.1: - resolution: {integrity: sha512-SpD7FLK92XV2fon2hMotaNDa2w5VAy5/uVjP9WFmjGSgWM8pTPVkHcDl1yFs5Z8LYbij0FSz+DbCBK6i+uXXUA==} + /@smithy/smithy-client@2.3.1: + resolution: {integrity: sha512-YsTdU8xVD64r2pLEwmltrNvZV6XIAC50LN6ivDopdt+YiF/jGH6PY9zUOu0CXD/d8GMB8gbhnpPsdrjAXHS9QA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/middleware-endpoint': 2.3.0 - '@smithy/middleware-stack': 2.0.10 - '@smithy/protocol-http': 3.0.12 - '@smithy/types': 2.8.0 - '@smithy/util-stream': 2.0.24 + '@smithy/middleware-endpoint': 2.4.1 + '@smithy/middleware-stack': 2.1.1 + '@smithy/protocol-http': 3.1.1 + '@smithy/types': 2.9.1 + '@smithy/util-stream': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/types@2.8.0: - resolution: {integrity: sha512-h9sz24cFgt/W1Re22OlhQKmUZkNh244ApgRsUDYinqF8R+QgcsBIX344u2j61TPshsTz3CvL6HYU1DnQdsSrHA==} + /@smithy/types@2.9.1: + resolution: {integrity: sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw==} engines: {node: '>=14.0.0'} dependencies: tslib: 2.6.2 dev: false - /@smithy/url-parser@2.0.16: - resolution: {integrity: sha512-Wfz5WqAoRT91TjRy1JeLR0fXtkIXHGsMbgzKFTx7E68SrZ55TB8xoG+vm11Ru4gheFTMXjAjwAxv1jQdC+pAQA==} + /@smithy/url-parser@2.1.1: + resolution: {integrity: sha512-qC9Bv8f/vvFIEkHsiNrUKYNl8uKQnn4BdhXl7VzQRP774AwIjiSMMwkbT+L7Fk8W8rzYVifzJNYxv1HwvfBo3Q==} dependencies: - '@smithy/querystring-parser': 2.0.16 - '@smithy/types': 2.8.0 + '@smithy/querystring-parser': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/util-base64@2.0.1: - resolution: {integrity: sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==} + /@smithy/util-base64@2.1.1: + resolution: {integrity: sha512-UfHVpY7qfF/MrgndI5PexSKVTxSZIdz9InghTFa49QOvuu9I52zLPLUHXvHpNuMb1iD2vmc6R+zbv/bdMipR/g==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/util-buffer-from': 2.0.0 + '@smithy/util-buffer-from': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/util-body-length-browser@2.0.1: - resolution: {integrity: sha512-NXYp3ttgUlwkaug4bjBzJ5+yIbUbUx8VsSLuHZROQpoik+gRkIBeEG9MPVYfvPNpuXb/puqodeeUXcKFe7BLOQ==} + /@smithy/util-body-length-browser@2.1.1: + resolution: {integrity: sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==} dependencies: tslib: 2.6.2 dev: false - /@smithy/util-body-length-node@2.1.0: - resolution: {integrity: sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==} + /@smithy/util-body-length-node@2.2.1: + resolution: {integrity: sha512-/ggJG+ta3IDtpNVq4ktmEUtOkH1LW64RHB5B0hcr5ZaWBmo96UX2cIOVbjCqqDickTXqBWZ4ZO0APuaPrD7Abg==} engines: {node: '>=14.0.0'} dependencies: tslib: 2.6.2 dev: false - /@smithy/util-buffer-from@2.0.0: - resolution: {integrity: sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==} + /@smithy/util-buffer-from@2.1.1: + resolution: {integrity: sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/is-array-buffer': 2.0.0 + '@smithy/is-array-buffer': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/util-config-provider@2.1.0: - resolution: {integrity: sha512-S6V0JvvhQgFSGLcJeT1CBsaTR03MM8qTuxMH9WPCCddlSo2W0V5jIHimHtIQALMLEDPGQ0ROSRr/dU0O+mxiQg==} + /@smithy/util-config-provider@2.2.1: + resolution: {integrity: sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==} engines: {node: '>=14.0.0'} dependencies: tslib: 2.6.2 dev: false - /@smithy/util-defaults-mode-browser@2.0.24: - resolution: {integrity: sha512-TsP5mBuLgO2C21+laNG2nHYZEyUdkbGURv2tHvSuQQxLz952MegX95uwdxOY2jR2H4GoKuVRfdJq7w4eIjGYeg==} + /@smithy/util-defaults-mode-browser@2.1.1: + resolution: {integrity: sha512-lqLz/9aWRO6mosnXkArtRuQqqZBhNpgI65YDpww4rVQBuUT7qzKbDLG5AmnQTCiU4rOquaZO/Kt0J7q9Uic7MA==} engines: {node: '>= 10.0.0'} dependencies: - '@smithy/property-provider': 2.0.17 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 + '@smithy/property-provider': 2.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 bowser: 2.11.0 tslib: 2.6.2 dev: false - /@smithy/util-defaults-mode-node@2.0.32: - resolution: {integrity: sha512-d0S33dXA2cq1NyorVMroMrEtqKMr3MlyLITcfTBf9pXiigYiPMOtbSI7czHIfDbuVuM89Cg0urAgpt73QV9mPQ==} + /@smithy/util-defaults-mode-node@2.1.1: + resolution: {integrity: sha512-tYVrc+w+jSBfBd267KDnvSGOh4NMz+wVH7v4CClDbkdPfnjvImBZsOURncT5jsFwR9KCuDyPoSZq4Pa6+eCUrA==} engines: {node: '>= 10.0.0'} dependencies: - '@smithy/config-resolver': 2.0.23 - '@smithy/credential-provider-imds': 2.1.5 - '@smithy/node-config-provider': 2.1.9 - '@smithy/property-provider': 2.0.17 - '@smithy/smithy-client': 2.2.1 - '@smithy/types': 2.8.0 + '@smithy/config-resolver': 2.1.1 + '@smithy/credential-provider-imds': 2.2.1 + '@smithy/node-config-provider': 2.2.1 + '@smithy/property-provider': 2.1.1 + '@smithy/smithy-client': 2.3.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/util-endpoints@1.0.8: - resolution: {integrity: sha512-l8zVuyZZ61IzZBYp5NWvsAhbaAjYkt0xg9R4xUASkg5SEeTT2meHOJwJHctKMFUXe4QZbn9fR2MaBYjP2119+w==} + /@smithy/util-endpoints@1.1.1: + resolution: {integrity: sha512-sI4d9rjoaekSGEtq3xSb2nMjHMx8QXcz2cexnVyRWsy4yQ9z3kbDpX+7fN0jnbdOp0b3KSTZJZ2Yb92JWSanLw==} engines: {node: '>= 14.0.0'} dependencies: - '@smithy/node-config-provider': 2.1.9 - '@smithy/types': 2.8.0 + '@smithy/node-config-provider': 2.2.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/util-hex-encoding@2.0.0: - resolution: {integrity: sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==} + /@smithy/util-hex-encoding@2.1.1: + resolution: {integrity: sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==} engines: {node: '>=14.0.0'} dependencies: tslib: 2.6.2 dev: false - /@smithy/util-middleware@2.0.9: - resolution: {integrity: sha512-PnCnBJ07noMX1lMDTEefmxSlusWJUiLfrme++MfK5TD0xz8NYmakgoXy5zkF/16zKGmiwOeKAztWT/Vjk1KRIQ==} + /@smithy/util-middleware@2.1.1: + resolution: {integrity: sha512-mKNrk8oz5zqkNcbcgAAepeJbmfUW6ogrT2Z2gDbIUzVzNAHKJQTYmH9jcy0jbWb+m7ubrvXKb6uMjkSgAqqsFA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.8.0 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/util-retry@2.0.9: - resolution: {integrity: sha512-46BFWe9RqB6g7f4mxm3W3HlqknqQQmWHKlhoqSFZuGNuiDU5KqmpebMbvC3tjTlUkqn4xa2Z7s3Hwb0HNs5scw==} + /@smithy/util-retry@2.1.1: + resolution: {integrity: sha512-Mg+xxWPTeSPrthpC5WAamJ6PW4Kbo01Fm7lWM1jmGRvmrRdsd3192Gz2fBXAMURyXpaNxyZf6Hr/nQ4q70oVEA==} engines: {node: '>= 14.0.0'} dependencies: - '@smithy/service-error-classification': 2.0.9 - '@smithy/types': 2.8.0 + '@smithy/service-error-classification': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false - /@smithy/util-stream@2.0.24: - resolution: {integrity: sha512-hRpbcRrOxDriMVmbya+Mv77VZVupxRAsfxVDKS54XuiURhdiwCUXJP0X1iJhHinuUf6n8pBF0MkG9C8VooMnWw==} + /@smithy/util-stream@2.1.1: + resolution: {integrity: sha512-J7SMIpUYvU4DQN55KmBtvaMc7NM3CZ2iWICdcgaovtLzseVhAqFRYqloT3mh0esrFw+3VEK6nQFteFsTqZSECQ==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/fetch-http-handler': 2.3.2 - '@smithy/node-http-handler': 2.2.2 - '@smithy/types': 2.8.0 - '@smithy/util-base64': 2.0.1 - '@smithy/util-buffer-from': 2.0.0 - '@smithy/util-hex-encoding': 2.0.0 - '@smithy/util-utf8': 2.0.2 + '@smithy/fetch-http-handler': 2.4.1 + '@smithy/node-http-handler': 2.3.1 + '@smithy/types': 2.9.1 + '@smithy/util-base64': 2.1.1 + '@smithy/util-buffer-from': 2.1.1 + '@smithy/util-hex-encoding': 2.1.1 + '@smithy/util-utf8': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/util-uri-escape@2.0.0: - resolution: {integrity: sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==} + /@smithy/util-uri-escape@2.1.1: + resolution: {integrity: sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==} engines: {node: '>=14.0.0'} dependencies: tslib: 2.6.2 dev: false - /@smithy/util-utf8@2.0.2: - resolution: {integrity: sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==} + /@smithy/util-utf8@2.1.1: + resolution: {integrity: sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/util-buffer-from': 2.0.0 + '@smithy/util-buffer-from': 2.1.1 tslib: 2.6.2 dev: false - /@smithy/util-waiter@2.0.16: - resolution: {integrity: sha512-5i4YONHQ6HoUWDd+X0frpxTXxSXgJhUFl+z0iMy/zpUmVeCQY2or3Vss6DzHKKMMQL4pmVHpQm9WayHDorFdZg==} + /@smithy/util-waiter@2.1.1: + resolution: {integrity: sha512-kYy6BLJJNif+uqNENtJqWdXcpqo1LS+nj1AfXcDhOpqpSHJSAkVySLyZV9fkmuVO21lzGoxjvd1imGGJHph/IA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/abort-controller': 2.0.16 - '@smithy/types': 2.8.0 + '@smithy/abort-controller': 2.1.1 + '@smithy/types': 2.9.1 tslib: 2.6.2 dev: false + /@sveltejs/kit@1.30.3(svelte@4.2.9)(vite@4.5.2): + resolution: {integrity: sha512-0DzVXfU4h+tChFvoc8C61IqErCyskD4ydSIDjpKS2lYlEzIYrtYrY7juSqACFxqcvZAnOEXvSY+zZ8br0+ZMMg==} + engines: {node: ^16.14 || >=18} + hasBin: true + requiresBuild: true + peerDependencies: + svelte: ^3.54.0 || ^4.0.0-next.0 || ^5.0.0-next.0 + vite: ^4.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte': 2.5.3(svelte@4.2.9)(vite@4.5.2) + '@types/cookie': 0.5.4 + cookie: 0.5.0 + devalue: 4.3.2 + esm-env: 1.0.0 + kleur: 4.1.5 + magic-string: 0.30.5 + mrmime: 1.0.1 + sade: 1.8.1 + set-cookie-parser: 2.6.0 + sirv: 2.0.4 + svelte: 4.2.9 + tiny-glob: 0.2.9 + undici: 5.26.5 + vite: 4.5.2(@types/node@20.11.5) + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.5.3)(svelte@4.2.9)(vite@4.5.2): + resolution: {integrity: sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==} + engines: {node: ^14.18.0 || >= 16} + requiresBuild: true + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^2.2.0 + svelte: ^3.54.0 || ^4.0.0 + vite: ^4.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte': 2.5.3(svelte@4.2.9)(vite@4.5.2) + debug: 4.3.4 + svelte: 4.2.9 + vite: 4.5.2(@types/node@20.11.5) + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /@sveltejs/vite-plugin-svelte@2.5.3(svelte@4.2.9)(vite@4.5.2): + resolution: {integrity: sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w==} + engines: {node: ^14.18.0 || >= 16} + requiresBuild: true + peerDependencies: + svelte: ^3.54.0 || ^4.0.0 || ^5.0.0-next.0 + vite: ^4.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 1.0.4(@sveltejs/vite-plugin-svelte@2.5.3)(svelte@4.2.9)(vite@4.5.2) + debug: 4.3.4 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.5 + svelte: 4.2.9 + svelte-hmr: 0.15.3(svelte@4.2.9) + vite: 4.5.2(@types/node@20.11.5) + vitefu: 0.2.5(vite@4.5.2) + transitivePeerDependencies: + - supports-color + dev: false + optional: true + /@swc/helpers@0.5.2: resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} dependencies: @@ -2313,7 +2586,7 @@ packages: chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.6.3 - jest: 29.7.0(@types/node@20.11.0) + jest: 29.7.0(@types/node@20.11.5) lodash: 4.17.21 redent: 3.0.0 dev: false @@ -2370,10 +2643,26 @@ packages: '@babel/types': 7.23.6 dev: false + /@types/cookie@0.5.4: + resolution: {integrity: sha512-7z/eR6O859gyWIAjuvBWFzNURmf2oPBmJlfVWkwehU5nzIyjwBsTh7WMmEEV4JFnHuQ3ex4oyTvfKzcyJVDBNA==} + requiresBuild: true + dev: false + optional: true + + /@types/cookie@0.6.0: + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + dev: false + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + requiresBuild: true + dev: false + optional: true + /@types/graceful-fs@4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} dependencies: - '@types/node': 20.11.0 + '@types/node': 20.11.5 dev: false /@types/istanbul-lib-coverage@2.0.6: @@ -2402,7 +2691,7 @@ packages: /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: - '@types/node': 20.11.0 + '@types/node': 20.11.5 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 dev: false @@ -2415,8 +2704,8 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: false - /@types/node@20.11.0: - resolution: {integrity: sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==} + /@types/node@20.11.5: + resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} dependencies: undici-types: 5.26.5 dev: false @@ -2424,7 +2713,7 @@ packages: /@types/pg@8.6.6: resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} dependencies: - '@types/node': 20.11.0 + '@types/node': 20.11.5 pg-protocol: 1.6.0 pg-types: 2.2.0 dev: false @@ -2436,11 +2725,11 @@ packages: /@types/react-dom@18.2.18: resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==} dependencies: - '@types/react': 18.2.47 + '@types/react': 18.2.48 dev: false - /@types/react@18.2.47: - resolution: {integrity: sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==} + /@types/react@18.2.48: + resolution: {integrity: sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==} dependencies: '@types/prop-types': 15.7.11 '@types/scheduler': 0.16.8 @@ -2473,8 +2762,8 @@ packages: '@types/yargs-parser': 21.0.3 dev: false - /@typescript-eslint/eslint-plugin@6.18.1(@typescript-eslint/parser@6.18.1)(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==} + /@typescript-eslint/eslint-plugin@6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -2485,11 +2774,11 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.18.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/scope-manager': 6.18.1 - '@typescript-eslint/type-utils': 6.18.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.18.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.18.1 + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/type-utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.19.0 debug: 4.3.4 eslint: 8.56.0 graphemer: 1.4.0 @@ -2502,8 +2791,8 @@ packages: - supports-color dev: false - /@typescript-eslint/parser@6.18.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==} + /@typescript-eslint/parser@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -2512,10 +2801,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.18.1 - '@typescript-eslint/types': 6.18.1 - '@typescript-eslint/typescript-estree': 6.18.1(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.18.1 + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.19.0 debug: 4.3.4 eslint: 8.56.0 typescript: 5.3.3 @@ -2523,16 +2812,16 @@ packages: - supports-color dev: false - /@typescript-eslint/scope-manager@6.18.1: - resolution: {integrity: sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==} + /@typescript-eslint/scope-manager@6.19.0: + resolution: {integrity: sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.18.1 - '@typescript-eslint/visitor-keys': 6.18.1 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/visitor-keys': 6.19.0 dev: false - /@typescript-eslint/type-utils@6.18.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==} + /@typescript-eslint/type-utils@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -2541,8 +2830,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.18.1(typescript@5.3.3) - '@typescript-eslint/utils': 6.18.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) debug: 4.3.4 eslint: 8.56.0 ts-api-utils: 1.0.3(typescript@5.3.3) @@ -2551,13 +2840,13 @@ packages: - supports-color dev: false - /@typescript-eslint/types@6.18.1: - resolution: {integrity: sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==} + /@typescript-eslint/types@6.19.0: + resolution: {integrity: sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==} engines: {node: ^16.0.0 || >=18.0.0} dev: false - /@typescript-eslint/typescript-estree@6.18.1(typescript@5.3.3): - resolution: {integrity: sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==} + /@typescript-eslint/typescript-estree@6.19.0(typescript@5.3.3): + resolution: {integrity: sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -2565,8 +2854,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.18.1 - '@typescript-eslint/visitor-keys': 6.18.1 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/visitor-keys': 6.19.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -2578,8 +2867,8 @@ packages: - supports-color dev: false - /@typescript-eslint/utils@6.18.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==} + /@typescript-eslint/utils@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -2587,9 +2876,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 6.18.1 - '@typescript-eslint/types': 6.18.1 - '@typescript-eslint/typescript-estree': 6.18.1(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) eslint: 8.56.0 semver: 7.5.4 transitivePeerDependencies: @@ -2597,11 +2886,11 @@ packages: - typescript dev: false - /@typescript-eslint/visitor-keys@6.18.1: - resolution: {integrity: sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==} + /@typescript-eslint/visitor-keys@6.19.0: + resolution: {integrity: sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.18.1 + '@typescript-eslint/types': 6.19.0 eslint-visitor-keys: 3.4.3 dev: false @@ -2609,14 +2898,14 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: false - /@vercel/analytics@1.1.1: - resolution: {integrity: sha512-+NqgNmSabg3IFfxYhrWCfB/H+RCUOCR5ExRudNG2+pcRehq628DJB5e1u1xqwpLtn4pAYii4D98w7kofORAGQA==} + /@vercel/analytics@1.1.2: + resolution: {integrity: sha512-CodhkLCQ/EHzjX8k+Qg+OzTBY0UadykrcfolfSOJVZZY/ZJM5nbhztm9KdbYvMfqKlasAr1+OYy0ThZnDA/MYA==} dependencies: server-only: 0.0.1 dev: false - /@vercel/blob@0.17.0: - resolution: {integrity: sha512-A4ynlS02VrOShQTTl0XC3lfHpK9O0KyXTeTTeLgATiXWv/PfgKst6QLbBgMTBrSp3FmtitWSvUUeLeU69S1c5A==} + /@vercel/blob@0.19.0: + resolution: {integrity: sha512-F3TliTcBeSa8AJ1FfP5A2MPolyfQr27JvQ0ElrhYK0uK8eN0K7V5+1h3Dp+vVPLQold80nRC8VGzwHZsHFDKew==} engines: {node: '>=16.14'} dependencies: async-retry: 1.3.3 @@ -2634,10 +2923,123 @@ packages: ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3) dev: false - /@vercel/speed-insights@1.0.3: - resolution: {integrity: sha512-bKIt0HDdF6hP2bJZyS+za3k6sKeAXNRLSIUbwVwvyvKdsHBWS6ILBvmD1wXHZZyTqjU1TP7dTE/F6lHM6rBdKA==} + /@vercel/speed-insights@1.0.5(@babel/core@7.23.7)(react-dom@18.2.0)(typescript@5.3.3)(vite@4.5.2): + resolution: {integrity: sha512-UWU28pZ60NI6mp4nTkdZxR8fiB1zrMBUmaqC4rjXUKCgawlrfWZzI7SZq16FqiXeBrlfpACPziekS7MZBvu51w==} + requiresBuild: true + optionalDependencies: + '@sveltejs/kit': 1.30.3(svelte@4.2.9)(vite@4.5.2) + next: 14.1.0(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + svelte: 4.2.9 + vue: 3.4.15(typescript@5.3.3) + vue-router: 4.2.5(vue@3.4.15) + transitivePeerDependencies: + - '@babel/core' + - '@opentelemetry/api' + - babel-plugin-macros + - react-dom + - sass + - supports-color + - typescript + - vite + dev: false + + /@vue/compiler-core@3.4.15: + resolution: {integrity: sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==} + requiresBuild: true + dependencies: + '@babel/parser': 7.23.6 + '@vue/shared': 3.4.15 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: false + optional: true + + /@vue/compiler-dom@3.4.15: + resolution: {integrity: sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==} + requiresBuild: true + dependencies: + '@vue/compiler-core': 3.4.15 + '@vue/shared': 3.4.15 + dev: false + optional: true + + /@vue/compiler-sfc@3.4.15: + resolution: {integrity: sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==} + requiresBuild: true + dependencies: + '@babel/parser': 7.23.6 + '@vue/compiler-core': 3.4.15 + '@vue/compiler-dom': 3.4.15 + '@vue/compiler-ssr': 3.4.15 + '@vue/shared': 3.4.15 + estree-walker: 2.0.2 + magic-string: 0.30.5 + postcss: 8.4.33 + source-map-js: 1.0.2 + dev: false + optional: true + + /@vue/compiler-ssr@3.4.15: + resolution: {integrity: sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==} + requiresBuild: true + dependencies: + '@vue/compiler-dom': 3.4.15 + '@vue/shared': 3.4.15 + dev: false + optional: true + + /@vue/devtools-api@6.5.1: + resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==} requiresBuild: true dev: false + optional: true + + /@vue/reactivity@3.4.15: + resolution: {integrity: sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==} + requiresBuild: true + dependencies: + '@vue/shared': 3.4.15 + dev: false + optional: true + + /@vue/runtime-core@3.4.15: + resolution: {integrity: sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==} + requiresBuild: true + dependencies: + '@vue/reactivity': 3.4.15 + '@vue/shared': 3.4.15 + dev: false + optional: true + + /@vue/runtime-dom@3.4.15: + resolution: {integrity: sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==} + requiresBuild: true + dependencies: + '@vue/runtime-core': 3.4.15 + '@vue/shared': 3.4.15 + csstype: 3.1.3 + dev: false + optional: true + + /@vue/server-renderer@3.4.15(vue@3.4.15): + resolution: {integrity: sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==} + requiresBuild: true + peerDependencies: + vue: 3.4.15 + dependencies: + '@vue/compiler-ssr': 3.4.15 + '@vue/shared': 3.4.15 + vue: 3.4.15(typescript@5.3.3) + dev: false + optional: true + + /@vue/shared@3.4.15: + resolution: {integrity: sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==} + requiresBuild: true + dev: false + optional: true /abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} @@ -2864,15 +3266,15 @@ packages: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: false - /autoprefixer@10.4.16(postcss@8.4.33): - resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==} + /autoprefixer@10.4.17(postcss@8.4.33): + resolution: {integrity: sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: postcss: ^8.1.0 dependencies: browserslist: 4.22.2 - caniuse-lite: 1.0.30001572 + caniuse-lite: 1.0.30001579 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -2896,6 +3298,14 @@ packages: dequal: 2.0.3 dev: false + /axobject-query@4.0.0: + resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} + requiresBuild: true + dependencies: + dequal: 2.0.3 + dev: false + optional: true + /babel-jest@29.7.0(@babel/core@7.23.7): resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -3006,7 +3416,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001572 + caniuse-lite: 1.0.30001579 electron-to-chromium: 1.4.616 node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.22.2) @@ -3060,8 +3470,8 @@ packages: engines: {node: '>= 6'} dev: false - /camelcase-keys@9.1.2: - resolution: {integrity: sha512-nFhquwz7p3nWSHeVYoIkefNPdR2Rt4EuKs9/gaqx3DhJL6HkNHIEcsH+D6N4NvW/MHxc4TT+rp0rc4K7E7x9hw==} + /camelcase-keys@9.1.3: + resolution: {integrity: sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg==} engines: {node: '>=16'} dependencies: camelcase: 8.0.0 @@ -3085,8 +3495,8 @@ packages: engines: {node: '>=16'} dev: false - /caniuse-lite@1.0.30001572: - resolution: {integrity: sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==} + /caniuse-lite@1.0.30001579: + resolution: {integrity: sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==} dev: false /chalk@2.4.2: @@ -3171,6 +3581,18 @@ packages: engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} dev: false + /code-red@1.0.4: + resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + requiresBuild: true + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + '@types/estree': 1.0.5 + acorn: 8.11.3 + estree-walker: 3.0.3 + periscopic: 3.1.0 + dev: false + optional: true + /collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} dev: false @@ -3221,12 +3643,19 @@ packages: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: false + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + requiresBuild: true + dev: false + optional: true + /cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} dev: false - /create-jest@29.7.0(@types/node@20.11.0): + /create-jest@29.7.0(@types/node@20.11.5): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -3235,7 +3664,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.11.0) + jest-config: 29.7.0(@types/node@20.11.5) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -3254,6 +3683,16 @@ packages: which: 2.0.2 dev: false + /css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + requiresBuild: true + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.0.2 + dev: false + optional: true + /css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} dev: false @@ -3296,8 +3735,12 @@ packages: whatwg-url: 11.0.0 dev: false - /date-fns@3.2.0: - resolution: {integrity: sha512-E4KWKavANzeuusPi0jUjpuI22SURAznGkx7eZV+4i6x2A+IZxAMcajgkvuDAU1bg40+xuhW1zRdVIIM/4khuIg==} + /date-fns@3.3.0: + resolution: {integrity: sha512-xuouT0GuI2W8yXhCMn/AXbSl1Av3wu2hJXxMnnILTY3bYY0UgNK0qOwVXqdFBrobW5qbX1TuOTgMw7c2H2OuhA==} + dev: false + + /debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} dev: false /debug@3.2.7: @@ -3402,6 +3845,12 @@ packages: engines: {node: '>=8'} dev: false + /devalue@4.3.2: + resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} + requiresBuild: true + dev: false + optional: true + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: false @@ -3598,6 +4047,37 @@ packages: is-symbol: 1.0.4 dev: false + /esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: false + optional: true + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -3630,8 +4110,8 @@ packages: source-map: 0.6.1 dev: false - /eslint-config-next@14.0.4(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ==} + /eslint-config-next@14.1.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -3639,13 +4119,13 @@ packages: typescript: optional: true dependencies: - '@next/eslint-plugin-next': 14.0.4 + '@next/eslint-plugin-next': 14.1.0 '@rushstack/eslint-patch': 1.6.1 - '@typescript-eslint/parser': 6.18.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.56.0) eslint-plugin-react: 7.33.2(eslint@8.56.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0) @@ -3665,7 +4145,7 @@ packages: - supports-color dev: false - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0): + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0): resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -3675,8 +4155,8 @@ packages: debug: 4.3.4 enhanced-resolve: 5.15.0 eslint: 8.56.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) fast-glob: 3.3.2 get-tsconfig: 4.7.2 is-core-module: 2.13.1 @@ -3688,7 +4168,7 @@ packages: - supports-color dev: false - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -3709,16 +4189,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.18.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) debug: 3.2.7 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) transitivePeerDependencies: - supports-color dev: false - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} engines: {node: '>=4'} peerDependencies: @@ -3728,7 +4208,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.18.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -3737,7 +4217,7 @@ packages: doctrine: 2.1.0 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -3872,6 +4352,12 @@ packages: - supports-color dev: false + /esm-env@1.0.0: + resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} + requiresBuild: true + dev: false + optional: true + /espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3906,6 +4392,20 @@ packages: engines: {node: '>=4.0'} dev: false + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + requiresBuild: true + dev: false + optional: true + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + requiresBuild: true + dependencies: + '@types/estree': 1.0.5 + dev: false + optional: true + /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -4163,10 +4663,6 @@ packages: is-glob: 4.0.3 dev: false - /glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: false - /glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} @@ -4179,17 +4675,6 @@ packages: path-scurry: 1.10.1 dev: false - /glob@7.1.7: - resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: false - /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -4220,6 +4705,12 @@ packages: define-properties: 1.2.1 dev: false + /globalyzer@0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + requiresBuild: true + dev: false + optional: true + /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -4232,6 +4723,12 @@ packages: slash: 3.0.0 dev: false + /globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + requiresBuild: true + dev: false + optional: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -4520,10 +5017,23 @@ packages: engines: {node: '>=8'} dev: false + /is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + dev: false + /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: false + /is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + requiresBuild: true + dependencies: + '@types/estree': 1.0.5 + dev: false + optional: true + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -4688,7 +5198,7 @@ packages: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -4709,7 +5219,7 @@ packages: - supports-color dev: false - /jest-cli@29.7.0(@types/node@20.11.0): + /jest-cli@29.7.0(@types/node@20.11.5): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -4723,10 +5233,10 @@ packages: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.11.0) + create-jest: 29.7.0(@types/node@20.11.5) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.11.0) + jest-config: 29.7.0(@types/node@20.11.5) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -4737,7 +5247,7 @@ packages: - ts-node dev: false - /jest-config@29.7.0(@types/node@20.11.0): + /jest-config@29.7.0(@types/node@20.11.5): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -4752,7 +5262,7 @@ packages: '@babel/core': 7.23.7 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 babel-jest: 29.7.0(@babel/core@7.23.7) chalk: 4.1.2 ci-info: 3.9.0 @@ -4818,7 +5328,7 @@ packages: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.11.0 + '@types/node': 20.11.5 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -4835,7 +5345,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 jest-mock: 29.7.0 jest-util: 29.7.0 dev: false @@ -4851,7 +5361,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.11.0 + '@types/node': 20.11.5 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -4902,7 +5412,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 jest-util: 29.7.0 dev: false @@ -4957,7 +5467,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -4988,7 +5498,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -5040,7 +5550,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -5065,7 +5575,7 @@ packages: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.0 + '@types/node': 20.11.5 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -5077,13 +5587,13 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.11.0 + '@types/node': 20.11.5 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 dev: false - /jest@29.7.0(@types/node@20.11.0): + /jest@29.7.0(@types/node@20.11.5): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -5096,7 +5606,7 @@ packages: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.11.0) + jest-cli: 29.7.0(@types/node@20.11.5) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -5229,6 +5739,13 @@ packages: engines: {node: '>=6'} dev: false + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + requiresBuild: true + dev: false + optional: true + /language-subtag-registry@0.3.22: resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} dev: false @@ -5267,6 +5784,12 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: false + /locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + requiresBuild: true + dev: false + optional: true + /locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -5319,6 +5842,15 @@ packages: hasBin: true dev: false + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} + requiresBuild: true + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + optional: true + /make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} @@ -5337,6 +5869,12 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false + /mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + requiresBuild: true + dev: false + optional: true + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: false @@ -5403,9 +5941,23 @@ packages: engines: {node: '>=16 || 14 >=14.17'} dev: false + /mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + requiresBuild: true + dev: false + optional: true + /mrmime@1.0.1: resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} engines: {node: '>=10'} + requiresBuild: true + dev: false + optional: true + + /mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} dev: false /ms@2.1.2: @@ -5440,8 +5992,8 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: false - /next-auth@5.0.0-beta.4(next@14.0.4)(react@18.2.0): - resolution: {integrity: sha512-vgocjvwPA8gxd/zrIP/vr9lJ/HeNe+C56lPP1D3sdyenHt8KncQV6ro7q0xCsDp1fcOKx7WAWVZH5o8aMxDzgw==} + /next-auth@5.0.0-beta.5(next@14.1.0)(react@18.2.0): + resolution: {integrity: sha512-tEYIPhm/i0byW4xf9Ldlsnh7ckBQfNvMjOA3B3eXQX9taAQWb8earravSn1fjk4fKfKvaOApFJkks0VeI7Vy/A==} peerDependencies: next: ^14 nodemailer: ^6.6.5 @@ -5450,25 +6002,25 @@ packages: nodemailer: optional: true dependencies: - '@auth/core': 0.18.4 - next: 14.0.4(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) + '@auth/core': 0.21.0 + next: 14.1.0(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false - /next-themes@0.2.1(next@14.0.4)(react-dom@18.2.0)(react@18.2.0): + /next-themes@0.2.1(next@14.1.0)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} peerDependencies: next: '*' react: '*' react-dom: '*' dependencies: - next: 14.0.4(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) + next: 14.1.0(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /next@14.0.4(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==} + /next@14.1.0(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -5482,26 +6034,25 @@ packages: sass: optional: true dependencies: - '@next/env': 14.0.4 + '@next/env': 14.1.0 '@swc/helpers': 0.5.2 busboy: 1.6.0 - caniuse-lite: 1.0.30001572 + caniuse-lite: 1.0.30001579 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) styled-jsx: 5.1.1(@babel/core@7.23.7)(react@18.2.0) - watchpack: 2.4.0 optionalDependencies: - '@next/swc-darwin-arm64': 14.0.4 - '@next/swc-darwin-x64': 14.0.4 - '@next/swc-linux-arm64-gnu': 14.0.4 - '@next/swc-linux-arm64-musl': 14.0.4 - '@next/swc-linux-x64-gnu': 14.0.4 - '@next/swc-linux-x64-musl': 14.0.4 - '@next/swc-win32-arm64-msvc': 14.0.4 - '@next/swc-win32-ia32-msvc': 14.0.4 - '@next/swc-win32-x64-msvc': 14.0.4 + '@next/swc-darwin-arm64': 14.1.0 + '@next/swc-darwin-x64': 14.1.0 + '@next/swc-linux-arm64-gnu': 14.1.0 + '@next/swc-linux-arm64-musl': 14.1.0 + '@next/swc-linux-x64-gnu': 14.1.0 + '@next/swc-linux-x64-musl': 14.1.0 + '@next/swc-win32-arm64-msvc': 14.1.0 + '@next/swc-win32-ia32-msvc': 14.1.0 + '@next/swc-win32-x64-msvc': 14.1.0 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -5743,6 +6294,16 @@ packages: engines: {node: '>=8'} dev: false + /periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + requiresBuild: true + dependencies: + '@types/estree': 1.0.5 + estree-walker: 3.0.3 + is-reference: 3.0.2 + dev: false + optional: true + /pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} engines: {node: '>=4.0.0'} @@ -6125,12 +6686,30 @@ packages: glob: 7.2.3 dev: false + /rollup@3.29.4: + resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: false + optional: true + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 dev: false + /sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + mri: 1.2.0 + dev: false + optional: true + /safe-array-concat@1.0.1: resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} engines: {node: '>=0.4'} @@ -6187,6 +6766,12 @@ packages: resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} dev: false + /set-cookie-parser@2.6.0: + resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + requiresBuild: true + dev: false + optional: true + /set-function-length@1.1.1: resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} engines: {node: '>= 0.4'} @@ -6235,13 +6820,13 @@ packages: engines: {node: '>=14'} dev: false - /sirv@1.0.19: - resolution: {integrity: sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==} + /sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} dependencies: '@polka/url': 1.0.0-next.24 - mrmime: 1.0.1 - totalist: 1.1.0 + mrmime: 2.0.0 + totalist: 3.0.1 dev: false /sisteransi@1.0.5: @@ -6471,6 +7056,38 @@ packages: engines: {node: '>= 0.4'} dev: false + /svelte-hmr@0.15.3(svelte@4.2.9): + resolution: {integrity: sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + requiresBuild: true + peerDependencies: + svelte: ^3.19.0 || ^4.0.0 + dependencies: + svelte: 4.2.9 + dev: false + optional: true + + /svelte@4.2.9: + resolution: {integrity: sha512-hsoB/WZGEPFXeRRLPhPrbRz67PhP6sqYgvwcAs+gWdSQSvNDw+/lTeUJSWe5h2xC97Fz/8QxAOqItwBzNJPU8w==} + engines: {node: '>=16'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.20 + '@types/estree': 1.0.5 + acorn: 8.11.3 + aria-query: 5.3.0 + axobject-query: 4.0.0 + code-red: 1.0.4 + css-tree: 2.3.1 + estree-walker: 3.0.3 + is-reference: 3.0.2 + locate-character: 3.0.0 + magic-string: 0.30.5 + periscopic: 3.1.0 + dev: false + optional: true + /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: false @@ -6541,6 +7158,15 @@ packages: any-promise: 1.3.0 dev: false + /tiny-glob@0.2.9: + resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + requiresBuild: true + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + dev: false + optional: true + /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: false @@ -6557,8 +7183,8 @@ packages: is-number: 7.0.0 dev: false - /totalist@1.1.0: - resolution: {integrity: sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==} + /totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} dev: false @@ -6699,6 +7325,15 @@ packages: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: false + /undici@5.26.5: + resolution: {integrity: sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==} + engines: {node: '>=14.0'} + requiresBuild: true + dependencies: + '@fastify/busboy': 2.1.0 + dev: false + optional: true + /undici@5.28.2: resolution: {integrity: sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==} engines: {node: '>=14.0'} @@ -6761,6 +7396,83 @@ packages: convert-source-map: 2.0.0 dev: false + /vite@4.5.2(@types/node@20.11.5): + resolution: {integrity: sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.11.5 + esbuild: 0.18.20 + postcss: 8.4.33 + rollup: 3.29.4 + optionalDependencies: + fsevents: 2.3.3 + dev: false + optional: true + + /vitefu@0.2.5(vite@4.5.2): + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + requiresBuild: true + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 4.5.2(@types/node@20.11.5) + dev: false + optional: true + + /vue-router@4.2.5(vue@3.4.15): + resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==} + peerDependencies: + vue: ^3.2.0 + dependencies: + '@vue/devtools-api': 6.5.1 + vue: 3.4.15(typescript@5.3.3) + dev: false + optional: true + + /vue@3.4.15(typescript@5.3.3): + resolution: {integrity: sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@vue/compiler-dom': 3.4.15 + '@vue/compiler-sfc': 3.4.15 + '@vue/runtime-dom': 3.4.15 + '@vue/server-renderer': 3.4.15(vue@3.4.15) + '@vue/shared': 3.4.15 + typescript: 5.3.3 + dev: false + optional: true + /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} @@ -6774,32 +7486,28 @@ packages: makeerror: 1.0.12 dev: false - /watchpack@2.4.0: - resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} - engines: {node: '>=10.13.0'} - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - dev: false - /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} dev: false - /webpack-bundle-analyzer@4.7.0: - resolution: {integrity: sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg==} + /webpack-bundle-analyzer@4.10.1: + resolution: {integrity: sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==} engines: {node: '>= 10.13.0'} hasBin: true dependencies: + '@discoveryjs/json-ext': 0.5.7 acorn: 8.11.3 acorn-walk: 8.3.1 - chalk: 4.1.2 commander: 7.2.0 + debounce: 1.2.1 + escape-string-regexp: 4.0.0 gzip-size: 6.0.0 - lodash: 4.17.21 + html-escaper: 2.0.2 + is-plain-object: 5.0.0 opener: 1.5.2 - sirv: 1.0.19 + picocolors: 1.0.0 + sirv: 2.0.4 ws: 7.5.9 transitivePeerDependencies: - bufferutil diff --git a/src/auth/index.ts b/src/auth/index.ts index 0bf0d476..53337314 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -20,7 +20,7 @@ export const { process.env.ADMIN_EMAIL && process.env.ADMIN_EMAIL === email && process.env.ADMIN_PASSWORD && process.env.ADMIN_PASSWORD === password ) { - const user: User = { id: '1', email, name: 'Admin User' }; + const user: User = { email, name: 'Admin User' }; return user; } else { return null; From 973f4f15e714f1f66ed5ef01cf02863e0e09b5aa Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 20 Jan 2024 11:56:13 -0600 Subject: [PATCH 02/13] =?UTF-8?q?Fix=20photo=20admin=20=E2=80=A2=E2=80=A2?= =?UTF-8?q?=E2=80=A2=20menu=20positioning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/photo/PhotoLarge.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index c8b7817d..935a3b55 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -84,10 +84,9 @@ export default function PhotoLarge({ - +
+ +
{tags.length > 0 && From 01549ffc8809da1f66a55ac8f2d03de3c3d076ca Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 20 Jan 2024 12:05:36 -0600 Subject: [PATCH 03/13] Fix tag delete confirmation text --- src/app/admin/tags/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/admin/tags/page.tsx b/src/app/admin/tags/page.tsx index a3db7b47..54756b28 100644 --- a/src/app/admin/tags/page.tsx +++ b/src/app/admin/tags/page.tsx @@ -41,7 +41,7 @@ export default async function AdminTagsPage() { action={deletePhotoTagGloballyAction} confirmText={ // eslint-disable-next-line max-len - `Are you sure you want to remove "${formatTag(tag)}?" from ${photoQuantityText(count, false).toLowerCase()}?`} + `Are you sure you want to remove "${formatTag(tag)}" from ${photoQuantityText(count, false).toLowerCase()}?`} > From 16c524abc48aaa074ce38d134d6c6b33003618d3 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 20 Jan 2024 22:13:05 -0600 Subject: [PATCH 04/13] Add support for Cloudflare R2 storage --- .vscode/settings.json | 1 + README.md | 37 ++++++++++- next.config.js | 6 ++ src/admin/BlobUrls.tsx | 2 +- src/app/admin/uploads/blob/route.tsx | 2 +- .../presigned-url/[key]/route.ts | 15 ++++- src/cache/index.ts | 2 +- src/photo/PhotoUpload.tsx | 2 +- src/photo/actions.ts | 2 +- src/photo/server.ts | 2 +- src/services/{blob => storage}/aws-s3.ts | 28 +-------- src/services/storage/cloudflare-r2.ts | 32 ++++++++++ src/services/{blob => storage}/index.ts | 62 ++++++++++++++++--- src/services/{blob => storage}/vercel-blob.ts | 0 src/site/SiteChecklistClient.tsx | 31 +++++++--- src/site/config.ts | 39 ++++++++++-- 16 files changed, 208 insertions(+), 55 deletions(-) rename src/app/api/{aws-s3 => storage}/presigned-url/[key]/route.ts (57%) rename src/services/{blob => storage}/aws-s3.ts (75%) create mode 100644 src/services/storage/cloudflare-r2.ts rename src/services/{blob => storage}/index.ts (59%) rename src/services/{blob => storage}/vercel-blob.ts (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json index e664ce2a..84c45555 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,7 @@ "ARROWRIGHT", "Astia", "camelcase", + "cloudflarestorage", "CredentialsSignin", "Eterna", "exif", diff --git a/README.md b/README.md index 919f2553..bcdaf2d8 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,42 @@ Installation - `NEXT_PUBLIC_GRID_ASPECT_RATIO = 1.5` sets aspect ratio for grid tiles (defaults to `1`—setting to `0` removes the constraint) - `NEXT_PUBLIC_OG_TEXT_ALIGNMENT = BOTTOM` keeps OG image text bottom aligned (default is top) -### Setup alternate storage +### Configure alternate storage + +Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). + +If you have multiple adapters, you can set one as preferred by storing `aws-s3`, `cloudflare-r2`, or `vercel-blob` in `NEXT_PUBLIC_STORAGE_PREFERENCE`. + +#### Cloudflare R2 + +1. Setup bucket + - [Create R2 bucket](https://developers.cloudflare.com/r2/) with default settings + - Setup CORS under bucket settings: + ```json + [{ + "AllowedHeaders": ["*"] + "AllowedOrigins": [ + "http://localhost:3000", + "https://{VERCEL_PROJECT_NAME}*.vercel.app", + "{PRODUCTION_DOMAIN}" + ], + "AllowedMethods": [ + "GET", + "PUT" + ], + }] + ``` + - Enable R2.dev subdomain (necessary in order to serve files publicly without a custom domain) + - Store 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_DEV_SUBDOMAIN`: r2.dev subdomain, e.g., "pub-jf90908..." +2. Setup 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. + - Store credentials (⚠️ _Ensure access keys are not prefixed with `NEXT_PUBLIC`_): + - `CLOUDFLARE_R2_ACCESS_KEY` + - `CLOUDFLARE_R2_SECRET_ACCESS_KEY` #### AWS S3 diff --git a/next.config.js b/next.config.js index 9ee18918..bd880f53 100644 --- a/next.config.js +++ b/next.config.js @@ -6,6 +6,11 @@ const VERCEL_BLOB_HOSTNAME = VERCEL_BLOB_STORE_ID ? `${VERCEL_BLOB_STORE_ID}.public.blob.vercel-storage.com` : undefined; +const CLOUDFLARE_R2_HOSTNAME = + process.env.NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN + ? `${process.env.NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN}.r2.dev` + : undefined; + const AWS_S3_HOSTNAME = process.env.NEXT_PUBLIC_AWS_S3_BUCKET && process.env.NEXT_PUBLIC_AWS_S3_REGION @@ -28,6 +33,7 @@ const nextConfig = { imageSizes: [200], remotePatterns: [] .concat(createRemotePattern(VERCEL_BLOB_HOSTNAME)) + .concat(createRemotePattern(CLOUDFLARE_R2_HOSTNAME)) .concat(createRemotePattern(AWS_S3_HOSTNAME)), minimumCacheTTL: 31536000, }, diff --git a/src/admin/BlobUrls.tsx b/src/admin/BlobUrls.tsx index 29020f8e..bed92015 100644 --- a/src/admin/BlobUrls.tsx +++ b/src/admin/BlobUrls.tsx @@ -2,7 +2,7 @@ import { Fragment } from 'react'; import AdminGrid from './AdminGrid'; import Link from 'next/link'; import ImageTiny from '@/components/ImageTiny'; -import { fileNameForBlobUrl } from '@/services/blob'; +import { fileNameForBlobUrl } from '@/services/storage'; import FormWithConfirm from '@/components/FormWithConfirm'; import { deleteBlobPhotoAction } from '@/photo/actions'; import DeleteButton from './DeleteButton'; diff --git a/src/app/admin/uploads/blob/route.tsx b/src/app/admin/uploads/blob/route.tsx index 22b14c3d..a6436018 100644 --- a/src/app/admin/uploads/blob/route.tsx +++ b/src/app/admin/uploads/blob/route.tsx @@ -4,7 +4,7 @@ import { ACCEPTED_PHOTO_FILE_TYPES, MAX_PHOTO_UPLOAD_SIZE_IN_BYTES, } from '@/photo'; -import { isUploadPathnameValid } from '@/services/blob'; +import { isUploadPathnameValid } from '@/services/storage'; import { handleUpload, type HandleUploadBody } from '@vercel/blob/client'; import { NextResponse } from 'next/server'; diff --git a/src/app/api/aws-s3/presigned-url/[key]/route.ts b/src/app/api/storage/presigned-url/[key]/route.ts similarity index 57% rename from src/app/api/aws-s3/presigned-url/[key]/route.ts rename to src/app/api/storage/presigned-url/[key]/route.ts index e2e858fe..2b77455d 100644 --- a/src/app/api/aws-s3/presigned-url/[key]/route.ts +++ b/src/app/api/storage/presigned-url/[key]/route.ts @@ -2,7 +2,12 @@ import { auth } from '@/auth'; import { awsS3Client, awsS3PutObjectCommandForKey, -} from '@/services/blob/aws-s3'; +} from '@/services/storage/aws-s3'; +import { + cloudflareR2Client, + cloudflareR2PutObjectCommandForKey, +} from '@/services/storage/cloudflare-r2'; +import { STORAGE_PREFERENCE } from '@/site/config'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; export const runtime = 'edge'; @@ -14,8 +19,12 @@ export async function GET( const session = await auth(); if (session?.user && key) { const url = await getSignedUrl( - awsS3Client(), - awsS3PutObjectCommandForKey(key), + STORAGE_PREFERENCE === 'cloudflare-r2' + ? cloudflareR2Client() + : awsS3Client(), + STORAGE_PREFERENCE === 'cloudflare-r2' + ? cloudflareR2PutObjectCommandForKey(key) + : awsS3PutObjectCommandForKey(key), { expiresIn: 3600 } ); return new Response( diff --git a/src/cache/index.ts b/src/cache/index.ts index ce35f63b..d67f3ade 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -24,7 +24,7 @@ import { getPhotosNearId, } from '@/services/vercel-postgres'; import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo'; -import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob'; +import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/storage'; import type { Session } from 'next-auth'; import { createCameraKey } from '@/camera'; import { PATHS_ADMIN } from '@/site/paths'; diff --git a/src/photo/PhotoUpload.tsx b/src/photo/PhotoUpload.tsx index 71d6a12f..b50fcdff 100644 --- a/src/photo/PhotoUpload.tsx +++ b/src/photo/PhotoUpload.tsx @@ -1,7 +1,7 @@ 'use client'; import { useState } from 'react'; -import { uploadPhotoFromClient } from '@/services/blob'; +import { uploadPhotoFromClient } from '@/services/storage'; import { useRouter } from 'next/navigation'; import { PATH_ADMIN_UPLOADS, pathForAdminUploadUrl } from '@/site/paths'; import ImageInput from '../components/ImageInput'; diff --git a/src/photo/actions.ts b/src/photo/actions.ts index f017d0f4..1aa5ef2a 100644 --- a/src/photo/actions.ts +++ b/src/photo/actions.ts @@ -17,7 +17,7 @@ import { redirect } from 'next/navigation'; import { convertUploadToPhoto, deleteBlobUrl, -} from '@/services/blob'; +} from '@/services/storage'; import { revalidateAdminPaths, revalidateAllKeysAndPaths, diff --git a/src/photo/server.ts b/src/photo/server.ts index 7971c917..d0887746 100644 --- a/src/photo/server.ts +++ b/src/photo/server.ts @@ -1,7 +1,7 @@ import { getExtensionFromBlobUrl, getIdFromBlobUrl, -} from '@/services/blob'; +} from '@/services/storage'; import { convertExifToFormData } from '@/photo/form'; import { getFujifilmSimulationFromMakerNote, diff --git a/src/services/blob/aws-s3.ts b/src/services/storage/aws-s3.ts similarity index 75% rename from src/services/blob/aws-s3.ts rename to src/services/storage/aws-s3.ts index bff189ca..4ce72ee5 100644 --- a/src/services/blob/aws-s3.ts +++ b/src/services/storage/aws-s3.ts @@ -1,4 +1,3 @@ -import { generateNanoid } from '@/utility/nanoid'; import { S3Client, CopyObjectCommand, @@ -6,13 +5,14 @@ import { ListObjectsCommand, PutObjectCommand, } from '@aws-sdk/client-s3'; +import { generateBlobId } from '.'; const AWS_S3_BUCKET = process.env.NEXT_PUBLIC_AWS_S3_BUCKET ?? ''; const AWS_S3_REGION = process.env.NEXT_PUBLIC_AWS_S3_REGION ?? ''; const AWS_S3_ACCESS_KEY = process.env.AWS_S3_ACCESS_KEY ?? ''; const AWS_S3_SECRET_ACCESS_KEY = process.env.AWS_S3_SECRET_ACCESS_KEY ?? ''; - -const API_PATH_PRESIGNED_URL = '/api/aws-s3/presigned-url'; +export const AWS_S3_BASE_URL = + `https://${AWS_S3_BUCKET}.s3.${AWS_S3_REGION}.amazonaws.com`; export const awsS3Client = () => new S3Client({ region: AWS_S3_REGION, @@ -22,36 +22,14 @@ export const awsS3Client = () => new S3Client({ }, }); -export const AWS_S3_BASE_URL = - `https://${AWS_S3_BUCKET}.s3.${AWS_S3_REGION}.amazonaws.com`; - export const isUrlFromAwsS3 = (url: string) => url.startsWith(AWS_S3_BASE_URL); const urlForKey = (key?: string) => `${AWS_S3_BASE_URL}/${key}`; -const generateBlobId = () => generateNanoid(16); - export const awsS3PutObjectCommandForKey = (Key: string) => new PutObjectCommand({ Bucket: AWS_S3_BUCKET, Key, ACL: 'public-read' }); -export const awsS3UploadFromClient = async ( - file: File | Blob, - fileName: string, - extension: string, - addRandomSuffix?: boolean, -) => { - const key = addRandomSuffix - ? `${fileName}-${generateBlobId()}.${extension}` - : `${fileName}.${extension}`; - - const url = await fetch(`${API_PATH_PRESIGNED_URL}/${key}`) - .then((response) => response.text()); - - return fetch(url, { method: 'PUT', body: file }) - .then(() => urlForKey(key)); -}; - export const awsS3Copy = async ( fileNameSource: string, fileNameDestination: string, diff --git a/src/services/storage/cloudflare-r2.ts b/src/services/storage/cloudflare-r2.ts new file mode 100644 index 00000000..1595e4d1 --- /dev/null +++ b/src/services/storage/cloudflare-r2.ts @@ -0,0 +1,32 @@ +import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3'; + +const CLOUDFLARE_R2_BUCKET = + process.env.NEXT_PUBLIC_CLOUDFLARE_R2_BUCKET ?? ''; +const CLOUDFLARE_R2_ACCOUNT_ID = + process.env.NEXT_PUBLIC_CLOUDFLARE_R2_ACCOUNT_ID ?? ''; +const CLOUDFLARE_R2_DEV_SUBDOMAIN = + process.env.NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN ?? ''; +const CLOUDFLARE_R2_ACCESS_KEY = + process.env.CLOUDFLARE_R2_ACCESS_KEY ?? ''; +const CLOUDFLARE_R2_SECRET_ACCESS_KEY = + process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY ?? ''; +const CLOUDFLARE_R2_ENDPOINT = + `https://${CLOUDFLARE_R2_ACCOUNT_ID}.r2.cloudflarestorage.com`; + +export const CLOUDFLARE_R2_BASE_URL_PRIVATE = + `${CLOUDFLARE_R2_ENDPOINT}/${CLOUDFLARE_R2_BUCKET}`; + +export const CLOUDFLARE_R2_BASE_URL_PUBLIC = + `https://${CLOUDFLARE_R2_DEV_SUBDOMAIN}.r2.dev`; + +export const cloudflareR2Client = () => new S3Client({ + region: 'auto', + endpoint: CLOUDFLARE_R2_ENDPOINT, + credentials: { + accessKeyId: CLOUDFLARE_R2_ACCESS_KEY, + secretAccessKey: CLOUDFLARE_R2_SECRET_ACCESS_KEY, + }, +}); + +export const cloudflareR2PutObjectCommandForKey = (Key: string) => + new PutObjectCommand({ Bucket: CLOUDFLARE_R2_BUCKET, Key }); diff --git a/src/services/blob/index.ts b/src/services/storage/index.ts similarity index 59% rename from src/services/blob/index.ts rename to src/services/storage/index.ts index fc9f6c17..5917cfbc 100644 --- a/src/services/blob/index.ts +++ b/src/services/storage/index.ts @@ -10,16 +10,44 @@ import { awsS3Copy, awsS3Delete, awsS3List, - awsS3UploadFromClient, isUrlFromAwsS3, } from './aws-s3'; -import { HAS_AWS_S3_STORAGE, HAS_AWS_S3_STORAGE_CLIENT } from '@/site/config'; +import { + STORAGE_PREFERENCE, + HAS_AWS_S3_STORAGE, +} from '@/site/config'; +import { generateNanoid } from '@/utility/nanoid'; +import { CLOUDFLARE_R2_BASE_URL_PUBLIC } from './cloudflare-r2'; + +export const generateBlobId = () => generateNanoid(16); + +export type StorageType = + 'vercel-blob' | + 'aws-s3' | + 'cloudflare-r2'; + +export const labelForStorage = (type: StorageType): string => { + switch (type) { + case 'vercel-blob': return 'Vercel Blob'; + case 'cloudflare-r2': return 'Cloudflare R2'; + case 'aws-s3': return 'AWS S3'; + } +}; + +const blobBaseUrlForStorage = (type: StorageType) => { + switch (type) { + case 'vercel-blob': return VERCEL_BLOB_BASE_URL; + case 'cloudflare-r2': return CLOUDFLARE_R2_BASE_URL_PUBLIC; + case 'aws-s3': return AWS_S3_BASE_URL; + } +}; + +export const BLOB_BASE_URL = blobBaseUrlForStorage(STORAGE_PREFERENCE); + +const API_PATH_PRESIGNED_URL = '/api/storage/presigned-url'; const PREFIX_UPLOAD = 'upload'; const PREFIX_PHOTO = 'photo'; -const BLOB_BASE_URL = HAS_AWS_S3_STORAGE_CLIENT - ? AWS_S3_BASE_URL - : VERCEL_BLOB_BASE_URL; const REGEX_UPLOAD_PATH = new RegExp( `(?:${PREFIX_UPLOAD})\.[a-z]{1,4}`, @@ -46,11 +74,31 @@ export const isUploadPathnameValid = (pathname?: string) => const getFileNameFromBlobUrl = (url: string) => (new URL(url).pathname.match(/\/(.+)$/)?.[1]) ?? ''; +export const uploadFromClientViaPresignedUrl = async ( + file: File | Blob, + fileName: string, + extension: string, + addRandomSuffix?: boolean, +) => { + const key = addRandomSuffix + ? `${fileName}-${generateBlobId()}.${extension}` + : `${fileName}.${extension}`; + + const url = await fetch(`${API_PATH_PRESIGNED_URL}/${key}`) + .then((response) => response.text()); + + return fetch(url, { method: 'PUT', body: file }) + .then(() => `${BLOB_BASE_URL}/${key}`); +}; + export const uploadPhotoFromClient = async ( file: File | Blob, extension = 'jpg', -) => HAS_AWS_S3_STORAGE_CLIENT - ? awsS3UploadFromClient(file, PREFIX_UPLOAD, extension, true) +) => ( + STORAGE_PREFERENCE === 'cloudflare-r2' || + STORAGE_PREFERENCE === 'aws-s3' +) + ? uploadFromClientViaPresignedUrl(file, PREFIX_UPLOAD, extension, true) : vercelBlobUploadFromClient(file, `${PREFIX_UPLOAD}.${extension}`); export const convertUploadToPhoto = async ( diff --git a/src/services/blob/vercel-blob.ts b/src/services/storage/vercel-blob.ts similarity index 100% rename from src/services/blob/vercel-blob.ts rename to src/services/storage/vercel-blob.ts diff --git a/src/site/SiteChecklistClient.tsx b/src/site/SiteChecklistClient.tsx index 80484739..9417c5d8 100644 --- a/src/site/SiteChecklistClient.tsx +++ b/src/site/SiteChecklistClient.tsx @@ -19,12 +19,15 @@ import Checklist from '@/components/Checklist'; import { toastSuccess } from '@/toast'; import { ConfigChecklistStatus } from './config'; import StatusIcon from '@/components/StatusIcon'; +import { labelForStorage } from '@/services/storage'; export default function SiteChecklistClient({ hasPostgres, - hasBlob, - hasVercelBlob, + hasStorage, + hasVercelBlobStorage, + hasCloudflareR2Storage, hasAwsS3Storage, + storagePreference, hasAuth, hasAdminUser, hasTitle, @@ -139,14 +142,17 @@ export default function SiteChecklistClient({ and connect to project {renderSubStatus( - hasVercelBlob ? 'checked' : 'optional', + hasVercelBlobStorage ? 'checked' : 'optional', <> - Vercel Blob: + {labelForStorage('vercel-blob')}: {' '} {renderLink( // eslint-disable-next-line max-len @@ -157,10 +163,21 @@ export default function SiteChecklistClient({ and connect to project , )} + {renderSubStatus( + hasCloudflareR2Storage ? 'checked' : 'optional', + <> + {labelForStorage('cloudflare-r2')}: + {' '} + {renderLink( + 'https://github.com/sambecker/exif-photo-blog#cloudflare-r2', + 'create/configure bucket', + )} + + )} {renderSubStatus( hasAwsS3Storage ? 'checked' : 'optional', <> - AWS S3: + {labelForStorage('aws-s3')}: {' '} {renderLink( 'https://github.com/sambecker/exif-photo-blog#aws-s3', diff --git a/src/site/config.ts b/src/site/config.ts index 4cfb07be..1cc4b59e 100644 --- a/src/site/config.ts +++ b/src/site/config.ts @@ -1,3 +1,4 @@ +import type { StorageType } from '@/services/storage'; import { makeUrlAbsolute, shortenUrl } from '@/utility/url'; // META / DOMAINS @@ -31,12 +32,22 @@ export const BASE_URL = process.env.NODE_ENV === 'production' : 'http://localhost:3000'; // STORAGE: VERCEL BLOB -export const HAS_VERCEL_BLOB = +export const HAS_VERCEL_BLOB_STORAGE = (process.env.BLOB_READ_WRITE_TOKEN ?? '').length > 0; +// STORAGE: Cloudflare R2 +// Includes separate check for client-side usage, i.e., url construction +export const HAS_CLOUDFLARE_R2_STORAGE_CLIENT = + (process.env.NEXT_PUBLIC_CLOUDFLARE_R2_BUCKET ?? '').length > 0 && + (process.env.NEXT_PUBLIC_CLOUDFLARE_R2_ACCOUNT_ID ?? '').length > 0 && + (process.env.NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN ?? '').length > 0; +export const HAS_CLOUDFLARE_R2_STORAGE = + HAS_CLOUDFLARE_R2_STORAGE_CLIENT && + (process.env.CLOUDFLARE_R2_ACCESS_KEY ?? '').length > 0 && + (process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY ?? '').length > 0; + // STORAGE: AWS S3 -// Includes separate check for client-side usage, -// i.e., uploading, url construction +// Includes separate check for client-side usage, i.e., url construction export const HAS_AWS_S3_STORAGE_CLIENT = (process.env.NEXT_PUBLIC_AWS_S3_BUCKET ?? '').length > 0 && (process.env.NEXT_PUBLIC_AWS_S3_REGION ?? '').length > 0; @@ -45,6 +56,17 @@ export const HAS_AWS_S3_STORAGE = (process.env.AWS_S3_ACCESS_KEY ?? '').length > 0 && (process.env.AWS_S3_SECRET_ACCESS_KEY ?? '').length > 0; +// Storage preference relies on client-only keys +// so that it's available in the browser when uploading +export const STORAGE_PREFERENCE: StorageType = + (process.env.NEXT_PUBLIC_STORAGE_PREFERENCE as StorageType | undefined) || ( + HAS_CLOUDFLARE_R2_STORAGE_CLIENT + ? 'cloudflare-r2' + : HAS_AWS_S3_STORAGE_CLIENT + ? 'aws-s3' + : 'vercel-blob' + ); + // SETTINGS export const PRO_MODE_ENABLED = process.env.NEXT_PUBLIC_PRO_MODE === '1'; @@ -65,9 +87,14 @@ export const HIGH_DENSITY_GRID = GRID_ASPECT_RATIO <= 1; export const CONFIG_CHECKLIST_STATUS = { hasPostgres: (process.env.POSTGRES_HOST ?? '').length > 0, - hasBlob: HAS_VERCEL_BLOB || HAS_AWS_S3_STORAGE, - hasVercelBlob: HAS_VERCEL_BLOB, + hasVercelBlobStorage: HAS_VERCEL_BLOB_STORAGE, + hasCloudflareR2Storage: HAS_CLOUDFLARE_R2_STORAGE, hasAwsS3Storage: HAS_AWS_S3_STORAGE, + hasStorage: + HAS_VERCEL_BLOB_STORAGE || + HAS_CLOUDFLARE_R2_STORAGE || + HAS_AWS_S3_STORAGE, + storagePreference: STORAGE_PREFERENCE, hasAuth: (process.env.AUTH_SECRET ?? '').length > 0, hasAdminUser: ( (process.env.ADMIN_EMAIL ?? '').length > 0 && @@ -89,6 +116,6 @@ export type ConfigChecklistStatus = typeof CONFIG_CHECKLIST_STATUS; export const IS_SITE_READY = CONFIG_CHECKLIST_STATUS.hasPostgres && - CONFIG_CHECKLIST_STATUS.hasBlob && + CONFIG_CHECKLIST_STATUS.hasStorage && CONFIG_CHECKLIST_STATUS.hasAuth && CONFIG_CHECKLIST_STATUS.hasAdminUser; From 2d244faec6198f6de31a94b612edc98aa6d5a62f Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 20 Jan 2024 22:14:20 -0600 Subject: [PATCH 05/13] Update README storage --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index bcdaf2d8..27f5dec3 100644 --- a/README.md +++ b/README.md @@ -73,9 +73,7 @@ Installation ### Configure alternate storage -Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). - -If you have multiple adapters, you can set one as preferred by storing `aws-s3`, `cloudflare-r2`, or `vercel-blob` in `NEXT_PUBLIC_STORAGE_PREFERENCE`. +Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). If you have multiple adapters, you can set one as preferred by storing "aws-s3," "cloudflare-r2," or "vercel-blob" in `NEXT_PUBLIC_STORAGE_PREFERENCE`. #### Cloudflare R2 From 5176649ad682bd6fcb54027e37c6902c3eb44555 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 20 Jan 2024 22:39:23 -0600 Subject: [PATCH 06/13] Refactor storage api paths --- .../blob/route.tsx => api/storage/vercel-blob/route.ts} | 2 +- src/services/storage/index.ts | 5 ++--- src/services/storage/vercel-blob.ts | 4 ++-- src/site/paths.ts | 8 ++++++-- 4 files changed, 11 insertions(+), 8 deletions(-) rename src/app/{admin/uploads/blob/route.tsx => api/storage/vercel-blob/route.ts} (96%) diff --git a/src/app/admin/uploads/blob/route.tsx b/src/app/api/storage/vercel-blob/route.ts similarity index 96% rename from src/app/admin/uploads/blob/route.tsx rename to src/app/api/storage/vercel-blob/route.ts index a6436018..e41543c6 100644 --- a/src/app/admin/uploads/blob/route.tsx +++ b/src/app/api/storage/vercel-blob/route.ts @@ -9,7 +9,7 @@ import { handleUpload, type HandleUploadBody } from '@vercel/blob/client'; import { NextResponse } from 'next/server'; export async function POST(request: Request): Promise { - const body = (await request.json()) as HandleUploadBody; + const body: HandleUploadBody = await request.json(); try { const jsonResponse = await handleUpload({ diff --git a/src/services/storage/index.ts b/src/services/storage/index.ts index 5917cfbc..8e7b0810 100644 --- a/src/services/storage/index.ts +++ b/src/services/storage/index.ts @@ -18,6 +18,7 @@ import { } from '@/site/config'; import { generateNanoid } from '@/utility/nanoid'; import { CLOUDFLARE_R2_BASE_URL_PUBLIC } from './cloudflare-r2'; +import { PATH_API_PRESIGNED_URL } from '@/site/paths'; export const generateBlobId = () => generateNanoid(16); @@ -44,8 +45,6 @@ const blobBaseUrlForStorage = (type: StorageType) => { export const BLOB_BASE_URL = blobBaseUrlForStorage(STORAGE_PREFERENCE); -const API_PATH_PRESIGNED_URL = '/api/storage/presigned-url'; - const PREFIX_UPLOAD = 'upload'; const PREFIX_PHOTO = 'photo'; @@ -84,7 +83,7 @@ export const uploadFromClientViaPresignedUrl = async ( ? `${fileName}-${generateBlobId()}.${extension}` : `${fileName}.${extension}`; - const url = await fetch(`${API_PATH_PRESIGNED_URL}/${key}`) + const url = await fetch(`${PATH_API_PRESIGNED_URL}/${key}`) .then((response) => response.text()); return fetch(url, { method: 'PUT', body: file }) diff --git a/src/services/storage/vercel-blob.ts b/src/services/storage/vercel-blob.ts index f14b2041..5a664f6b 100644 --- a/src/services/storage/vercel-blob.ts +++ b/src/services/storage/vercel-blob.ts @@ -1,4 +1,4 @@ -import { PATH_ADMIN_UPLOAD_BLOB } from '@/site/paths'; +import { PATH_API_VERCEL_BLOB_UPLOAD } from '@/site/paths'; import { copy, del, list } from '@vercel/blob'; import { upload } from '@vercel/blob/client'; @@ -18,7 +18,7 @@ export const vercelBlobUploadFromClient = async ( file, { access: 'public', - handleUploadUrl: PATH_ADMIN_UPLOAD_BLOB, + handleUploadUrl: PATH_API_VERCEL_BLOB_UPLOAD, }, ) .then(({ url }) => url); diff --git a/src/site/paths.ts b/src/site/paths.ts index 77c8d9f2..e6b699ce 100644 --- a/src/site/paths.ts +++ b/src/site/paths.ts @@ -12,6 +12,7 @@ export const PATH_ROOT = '/'; export const PATH_GRID = '/grid'; export const PATH_SETS = '/sets'; export const PATH_ADMIN = '/admin'; +export const PATH_API = '/api'; export const PATH_SIGN_IN = '/sign-in'; export const PATH_OG = '/og'; @@ -31,9 +32,13 @@ const PATH_FILM_SIMULATION_DYNAMIC = `${PREFIX_FILM_SIMULATION}/[simulation]`; export const PATH_ADMIN_PHOTOS = `${PATH_ADMIN}/photos`; export const PATH_ADMIN_UPLOADS = `${PATH_ADMIN}/uploads`; export const PATH_ADMIN_TAGS = `${PATH_ADMIN}/tags`; -export const PATH_ADMIN_UPLOAD_BLOB = `${PATH_ADMIN_UPLOADS}/blob`; export const PATH_ADMIN_CONFIGURATION = `${PATH_ADMIN}/configuration`; +// API paths +export const PATH_API_STORAGE = `${PATH_API}/storage`; +export const PATH_API_VERCEL_BLOB_UPLOAD = `${PATH_API_STORAGE}/vercel-blob`; +export const PATH_API_PRESIGNED_URL = `${PATH_API_STORAGE}/presigned-url`; + // Modifiers const SHARE = 'share'; const NEXT = 'next'; @@ -44,7 +49,6 @@ export const PATHS_ADMIN = [ PATH_ADMIN_PHOTOS, PATH_ADMIN_UPLOADS, PATH_ADMIN_TAGS, - PATH_ADMIN_UPLOAD_BLOB, PATH_ADMIN_CONFIGURATION, ]; From 3bd89f62b5629c6d709f8007177a31a113e68f1f Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 20 Jan 2024 23:40:18 -0600 Subject: [PATCH 07/13] Add listing/deleting Cloudflare blobs --- src/admin/BlobUrls.tsx | 4 +- src/photo/server.ts | 8 +-- src/services/storage/aws-s3.ts | 18 +++---- src/services/storage/cloudflare-r2.ts | 29 ++++++++++- src/services/storage/index.ts | 70 +++++++++++++++++++++------ src/services/storage/vercel-blob.ts | 3 ++ 6 files changed, 100 insertions(+), 32 deletions(-) diff --git a/src/admin/BlobUrls.tsx b/src/admin/BlobUrls.tsx index bed92015..da354a48 100644 --- a/src/admin/BlobUrls.tsx +++ b/src/admin/BlobUrls.tsx @@ -2,7 +2,7 @@ import { Fragment } from 'react'; import AdminGrid from './AdminGrid'; import Link from 'next/link'; import ImageTiny from '@/components/ImageTiny'; -import { fileNameForBlobUrl } from '@/services/storage'; +import { fileNameForStorageUrl } from '@/services/storage'; import FormWithConfirm from '@/components/FormWithConfirm'; import { deleteBlobPhotoAction } from '@/photo/actions'; import DeleteButton from './DeleteButton'; @@ -21,7 +21,7 @@ export default function BlobUrls({ {urls.map(url => { const addUploadPath = pathForAdminUploadUrl(url); - const uploadFileName = fileNameForBlobUrl(url); + const uploadFileName = fileNameForStorageUrl(url); return => { const url = decodeURIComponent(blobPath); - const blobId = getIdFromBlobUrl(url); + const blobId = getIdFromStorageUrl(url); - const extension = getExtensionFromBlobUrl(url); + const extension = getExtensionFromStorageUrl(url); const fileBytes = blobPath ? await fetch(url) diff --git a/src/services/storage/aws-s3.ts b/src/services/storage/aws-s3.ts index 4ce72ee5..b7bb8f55 100644 --- a/src/services/storage/aws-s3.ts +++ b/src/services/storage/aws-s3.ts @@ -22,11 +22,11 @@ export const awsS3Client = () => new S3Client({ }, }); +const urlForKey = (key?: string) => `${AWS_S3_BASE_URL}/${key}`; + export const isUrlFromAwsS3 = (url: string) => url.startsWith(AWS_S3_BASE_URL); -const urlForKey = (key?: string) => `${AWS_S3_BASE_URL}/${key}`; - export const awsS3PutObjectCommandForKey = (Key: string) => new PutObjectCommand({ Bucket: AWS_S3_BUCKET, Key, ACL: 'public-read' }); @@ -49,16 +49,16 @@ export const awsS3Copy = async ( .then(() => urlForKey(fileNameDestination)); }; -export const awsS3Delete = async (Key: string) => { - awsS3Client().send(new DeleteObjectCommand({ - Bucket: AWS_S3_BUCKET, - Key, - })); -}; - export const awsS3List = async (Prefix: string) => awsS3Client().send(new ListObjectsCommand({ Bucket: AWS_S3_BUCKET, Prefix, })) .then((data) => data.Contents?.map(({ Key }) => urlForKey(Key)) ?? []); + +export const awsS3Delete = async (Key: string) => { + awsS3Client().send(new DeleteObjectCommand({ + Bucket: AWS_S3_BUCKET, + Key, + })); +}; diff --git a/src/services/storage/cloudflare-r2.ts b/src/services/storage/cloudflare-r2.ts index 1595e4d1..5be6d9b0 100644 --- a/src/services/storage/cloudflare-r2.ts +++ b/src/services/storage/cloudflare-r2.ts @@ -1,4 +1,9 @@ -import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3'; +import { + S3Client, + ListObjectsCommand, + PutObjectCommand, + DeleteObjectCommand, +} from '@aws-sdk/client-s3'; const CLOUDFLARE_R2_BUCKET = process.env.NEXT_PUBLIC_CLOUDFLARE_R2_BUCKET ?? ''; @@ -28,5 +33,27 @@ export const cloudflareR2Client = () => new S3Client({ }, }); +const urlForKey = (key?: string, isPublic = true) => isPublic + ? `${CLOUDFLARE_R2_BASE_URL_PUBLIC}/${key}` + : `${CLOUDFLARE_R2_BASE_URL_PRIVATE}/${key}`; + +export const isUrlFromCloudflareR2 = (url: string) => + url.startsWith(CLOUDFLARE_R2_BASE_URL_PRIVATE) || + url.startsWith(CLOUDFLARE_R2_BASE_URL_PUBLIC); + export const cloudflareR2PutObjectCommandForKey = (Key: string) => new PutObjectCommand({ Bucket: CLOUDFLARE_R2_BUCKET, Key }); + +export const cloudflareR2List = async (Prefix: string) => + cloudflareR2Client().send(new ListObjectsCommand({ + Bucket: CLOUDFLARE_R2_BUCKET, + Prefix, + })) + .then((data) => data.Contents?.map(({ Key }) => urlForKey(Key)) ?? []); + +export const cloudflareR2Delete = async (Key: string) => { + cloudflareR2Client().send(new DeleteObjectCommand({ + Bucket: CLOUDFLARE_R2_BUCKET, + Key, + })); +}; diff --git a/src/services/storage/index.ts b/src/services/storage/index.ts index 8e7b0810..79d9b73f 100644 --- a/src/services/storage/index.ts +++ b/src/services/storage/index.ts @@ -15,9 +15,16 @@ import { import { STORAGE_PREFERENCE, HAS_AWS_S3_STORAGE, + HAS_VERCEL_BLOB_STORAGE, + HAS_CLOUDFLARE_R2_STORAGE, } from '@/site/config'; import { generateNanoid } from '@/utility/nanoid'; -import { CLOUDFLARE_R2_BASE_URL_PUBLIC } from './cloudflare-r2'; +import { + CLOUDFLARE_R2_BASE_URL_PUBLIC, + cloudflareR2Delete, + cloudflareR2List, + isUrlFromCloudflareR2, +} from './cloudflare-r2'; import { PATH_API_PRESIGNED_URL } from '@/site/paths'; export const generateBlobId = () => generateNanoid(16); @@ -35,7 +42,7 @@ export const labelForStorage = (type: StorageType): string => { } }; -const blobBaseUrlForStorage = (type: StorageType) => { +export const blobBaseUrlForStorage = (type: StorageType) => { switch (type) { case 'vercel-blob': return VERCEL_BLOB_BASE_URL; case 'cloudflare-r2': return CLOUDFLARE_R2_BASE_URL_PUBLIC; @@ -43,7 +50,15 @@ const blobBaseUrlForStorage = (type: StorageType) => { } }; -export const BLOB_BASE_URL = blobBaseUrlForStorage(STORAGE_PREFERENCE); +export const storageTypeFromUrl = (url: string): StorageType => { + if (isUrlFromCloudflareR2(url)) { + return 'cloudflare-r2'; + } else if (isUrlFromAwsS3(url)) { + return 'aws-s3'; + } else { + return 'vercel-blob'; + } +}; const PREFIX_UPLOAD = 'upload'; const PREFIX_PHOTO = 'photo'; @@ -58,13 +73,21 @@ const REGEX_UPLOAD_ID = new RegExp( 'i', ); -export const fileNameForBlobUrl = (url: string) => - url.replace(`${BLOB_BASE_URL}/`, ''); +export const fileNameForStorageUrl = (url: string) => { + switch (storageTypeFromUrl(url)) { + case 'vercel-blob': + return url.replace(`${VERCEL_BLOB_BASE_URL}/`, ''); + case 'cloudflare-r2': + return url.replace(`${CLOUDFLARE_R2_BASE_URL_PUBLIC}/`, ''); + case 'aws-s3': + return url.replace(`${AWS_S3_BASE_URL}/`, ''); + } +}; -export const getExtensionFromBlobUrl = (url: string) => +export const getExtensionFromStorageUrl = (url: string) => url.match(/.([a-z]{1,4})$/i)?.[1]; -export const getIdFromBlobUrl = (url: string) => +export const getIdFromStorageUrl = (url: string) => url.match(REGEX_UPLOAD_ID)?.[1]; export const isUploadPathnameValid = (pathname?: string) => @@ -87,7 +110,7 @@ export const uploadFromClientViaPresignedUrl = async ( .then((response) => response.text()); return fetch(url, { method: 'PUT', body: file }) - .then(() => `${BLOB_BASE_URL}/${key}`); + .then(() => `${blobBaseUrlForStorage(STORAGE_PREFERENCE)}/${key}`); }; export const uploadPhotoFromClient = async ( @@ -105,7 +128,7 @@ export const convertUploadToPhoto = async ( photoId?: string, ): Promise => { const fileName = photoId ? `${PREFIX_PHOTO}-${photoId}` : `${PREFIX_PHOTO}`; - const fileExtension = getExtensionFromBlobUrl(uploadUrl); + const fileExtension = getExtensionFromStorageUrl(uploadUrl); const photoUrl = `${fileName}.${fileExtension ?? 'jpg'}`; const useAwsS3 = HAS_AWS_S3_STORAGE && isUrlFromAwsS3(uploadUrl); @@ -123,14 +146,29 @@ export const convertUploadToPhoto = async ( return url; }; -export const deleteBlobUrl = (url: string) => - HAS_AWS_S3_STORAGE && isUrlFromAwsS3(url) - ? awsS3Delete(getFileNameFromBlobUrl(url)) - : vercelBlobDelete(url); +export const deleteBlobUrl = (url: string) => { + switch (storageTypeFromUrl(url)) { + case 'vercel-blob': return vercelBlobDelete(url); + case 'cloudflare-r2': return cloudflareR2Delete(getFileNameFromBlobUrl(url)); + case 'aws-s3': return awsS3Delete(getFileNameFromBlobUrl(url)); + } +}; -export const getBlobUploadUrls = (): Promise => HAS_AWS_S3_STORAGE - ? awsS3List(`${PREFIX_UPLOAD}-`) - : vercelBlobList(`${PREFIX_UPLOAD}-`); +export const getBlobUploadUrls = async (): Promise => { + const urls: string[] = []; + + if (HAS_VERCEL_BLOB_STORAGE) { + urls.push(...await vercelBlobList(`${PREFIX_UPLOAD}-`)); + } + if (HAS_AWS_S3_STORAGE) { + urls.push(...await awsS3List(`${PREFIX_UPLOAD}-`)); + } + if (HAS_CLOUDFLARE_R2_STORAGE) { + urls.push(...await cloudflareR2List(`${PREFIX_UPLOAD}-`)); + } + + return urls; +}; export const getBlobPhotoUrls = (): Promise => HAS_AWS_S3_STORAGE ? awsS3List(`${PREFIX_PHOTO}-`) diff --git a/src/services/storage/vercel-blob.ts b/src/services/storage/vercel-blob.ts index 5a664f6b..a8b5094f 100644 --- a/src/services/storage/vercel-blob.ts +++ b/src/services/storage/vercel-blob.ts @@ -9,6 +9,9 @@ const VERCEL_BLOB_STORE_ID = process.env.BLOB_READ_WRITE_TOKEN?.match( export const VERCEL_BLOB_BASE_URL = `https://${VERCEL_BLOB_STORE_ID}.public.blob.vercel-storage.com`; +export const isUrlFromVercelBlob = (url: string) => + url.startsWith(VERCEL_BLOB_BASE_URL); + export const vercelBlobUploadFromClient = async ( file: File | Blob, fileName: string, From 04dd1baef496c0564e2fb8d654432a1ab79095db Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 20 Jan 2024 23:50:57 -0600 Subject: [PATCH 08/13] Tweak checklist copy --- src/site/SiteChecklistClient.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/SiteChecklistClient.tsx b/src/site/SiteChecklistClient.tsx index 9417c5d8..39086660 100644 --- a/src/site/SiteChecklistClient.tsx +++ b/src/site/SiteChecklistClient.tsx @@ -144,7 +144,7 @@ export default function SiteChecklistClient({ Date: Sun, 21 Jan 2024 11:14:12 -0600 Subject: [PATCH 09/13] Implement upload -> photo copy in R2 --- src/admin/{BlobUrls.tsx => StorageUrls.tsx} | 2 +- src/app/admin/layout.tsx | 4 +- src/app/admin/photos/page.tsx | 8 +-- src/app/admin/uploads/page.tsx | 8 +-- src/cache/index.ts | 20 +++--- src/photo/actions.ts | 6 +- src/services/storage/aws-s3.ts | 4 +- src/services/storage/cloudflare-r2.ts | 20 ++++++ src/services/storage/index.ts | 76 ++++++++++++++------- 9 files changed, 100 insertions(+), 48 deletions(-) rename src/admin/{BlobUrls.tsx => StorageUrls.tsx} (98%) diff --git a/src/admin/BlobUrls.tsx b/src/admin/StorageUrls.tsx similarity index 98% rename from src/admin/BlobUrls.tsx rename to src/admin/StorageUrls.tsx index da354a48..c4c1ef55 100644 --- a/src/admin/BlobUrls.tsx +++ b/src/admin/StorageUrls.tsx @@ -10,7 +10,7 @@ import { clsx } from 'clsx/lite'; import { pathForAdminUploadUrl } from '@/site/paths'; import AddButton from './AddButton'; -export default function BlobUrls({ +export default function StorageUrls({ title, urls, }: { diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx index 072b0d73..95efd54a 100644 --- a/src/app/admin/layout.tsx +++ b/src/app/admin/layout.tsx @@ -1,6 +1,6 @@ import AdminNav from '@/admin/AdminNav'; import { - getBlobUploadUrlsNoStore, + getStorageUploadUrlsNoStore, getPhotosCountIncludingHiddenCached, getUniqueTagsCached, } from '@/cache'; @@ -21,7 +21,7 @@ export default async function AdminLayout({ countTags, ] = await Promise.all([ getPhotosCountIncludingHiddenCached(), - getBlobUploadUrlsNoStore() + getStorageUploadUrlsNoStore() .then(urls => urls.length) .catch(e => { console.error(`Error getting blob upload urls: ${e}`); diff --git a/src/app/admin/photos/page.tsx b/src/app/admin/photos/page.tsx index 2474f3d2..27f53955 100644 --- a/src/app/admin/photos/page.tsx +++ b/src/app/admin/photos/page.tsx @@ -14,7 +14,7 @@ import { import { titleForPhoto } from '@/photo'; import MorePhotos from '@/photo/MorePhotos'; import { - getBlobPhotoUrlsNoStore, + getStoragePhotoUrlsNoStore, getPhotosCached, getPhotosCountIncludingHiddenCached, } from '@/cache'; @@ -26,7 +26,7 @@ import { import AdminGrid from '@/admin/AdminGrid'; import DeleteButton from '@/admin/DeleteButton'; import EditButton from '@/admin/EditButton'; -import BlobUrls from '@/admin/BlobUrls'; +import StorageUrls from '@/admin/StorageUrls'; import { PRO_MODE_ENABLED } from '@/site/config'; import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus'; import IconGrSync from '@/site/IconGrSync'; @@ -45,7 +45,7 @@ export default async function AdminPhotosPage({ ] = await Promise.all([ getPhotosCached({ includeHidden: true, sortBy: 'createdAt', limit }), getPhotosCountIncludingHiddenCached(), - DEBUG_PHOTO_BLOBS ? getBlobPhotoUrlsNoStore() : [], + DEBUG_PHOTO_BLOBS ? getStoragePhotoUrlsNoStore() : [], ]); const showMorePhotos = count > photos.length; @@ -60,7 +60,7 @@ export default async function AdminPhotosPage({ 'border-b pb-6', 'border-gray-200 dark:border-gray-700', )}> - diff --git a/src/app/admin/uploads/page.tsx b/src/app/admin/uploads/page.tsx index 9e4e281a..8108e6eb 100644 --- a/src/app/admin/uploads/page.tsx +++ b/src/app/admin/uploads/page.tsx @@ -1,12 +1,12 @@ -import BlobUrls from '@/admin/BlobUrls'; -import { getBlobUploadUrlsNoStore } from '@/cache'; +import StorageUrls from '@/admin/StorageUrls'; +import { getStorageUploadUrlsNoStore } from '@/cache'; import SiteGrid from '@/components/SiteGrid'; export default async function AdminUploadsPage() { - const blobUrls = await getBlobUploadUrlsNoStore(); + const storageUrls = await getStorageUploadUrlsNoStore(); return ( } + contentMain={} /> ); } diff --git a/src/cache/index.ts b/src/cache/index.ts index d67f3ade..179bbbbb 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -24,7 +24,7 @@ import { getPhotosNearId, } from '@/services/vercel-postgres'; import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo'; -import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/storage'; +import { getStoragePhotoUrls, getStorageUploadUrls } from '@/services/storage'; import type { Session } from 'next-auth'; import { createCameraKey } from '@/camera'; import { PATHS_ADMIN } from '@/site/paths'; @@ -218,15 +218,17 @@ export const getPhotoNoStore = (...args: Parameters) => { return getPhoto(...args); }; -export const getBlobUploadUrlsNoStore: typeof getBlobUploadUrls = (...args) => { - unstable_noStore(); - return getBlobUploadUrls(...args); -}; +export const getStorageUploadUrlsNoStore: typeof getStorageUploadUrls = + (...args) => { + unstable_noStore(); + return getStorageUploadUrls(...args); + }; -export const getBlobPhotoUrlsNoStore: typeof getBlobPhotoUrls = (...args) => { - unstable_noStore(); - return getBlobPhotoUrls(...args); -}; +export const getStoragePhotoUrlsNoStore: typeof getStoragePhotoUrls = + (...args) => { + unstable_noStore(); + return getStoragePhotoUrls(...args); + }; export const getImageCacheHeadersForAuth = (session: Session | null) => { return { diff --git a/src/photo/actions.ts b/src/photo/actions.ts index 1aa5ef2a..bbbe1865 100644 --- a/src/photo/actions.ts +++ b/src/photo/actions.ts @@ -16,7 +16,7 @@ import { import { redirect } from 'next/navigation'; import { convertUploadToPhoto, - deleteBlobUrl, + deleteStorageUrl, } from '@/services/storage'; import { revalidateAdminPaths, @@ -66,7 +66,7 @@ export async function toggleFavoritePhoto(photoId: string) { export async function deletePhotoAction(formData: FormData) { await Promise.all([ - deleteBlobUrl(formData.get('url') as string), + deleteStorageUrl(formData.get('url') as string), sqlDeletePhoto(formData.get('id') as string), ]); @@ -94,7 +94,7 @@ export async function renamePhotoTagGloballyAction(formData: FormData) { } export async function deleteBlobPhotoAction(formData: FormData) { - await deleteBlobUrl(formData.get('url') as string); + await deleteStorageUrl(formData.get('url') as string); revalidateAdminPaths(); diff --git a/src/services/storage/aws-s3.ts b/src/services/storage/aws-s3.ts index b7bb8f55..2ec518d5 100644 --- a/src/services/storage/aws-s3.ts +++ b/src/services/storage/aws-s3.ts @@ -5,7 +5,7 @@ import { ListObjectsCommand, PutObjectCommand, } from '@aws-sdk/client-s3'; -import { generateBlobId } from '.'; +import { generateStorageId } from '.'; const AWS_S3_BUCKET = process.env.NEXT_PUBLIC_AWS_S3_BUCKET ?? ''; const AWS_S3_REGION = process.env.NEXT_PUBLIC_AWS_S3_REGION ?? ''; @@ -38,7 +38,7 @@ export const awsS3Copy = async ( const name = fileNameSource.split('.')[0]; const extension = fileNameSource.split('.')[1]; const Key = addRandomSuffix - ? `${name}-${generateBlobId()}.${extension}` + ? `${name}-${generateStorageId()}.${extension}` : fileNameDestination; return awsS3Client().send(new CopyObjectCommand({ Bucket: AWS_S3_BUCKET, diff --git a/src/services/storage/cloudflare-r2.ts b/src/services/storage/cloudflare-r2.ts index 5be6d9b0..7866005a 100644 --- a/src/services/storage/cloudflare-r2.ts +++ b/src/services/storage/cloudflare-r2.ts @@ -3,7 +3,9 @@ import { ListObjectsCommand, PutObjectCommand, DeleteObjectCommand, + CopyObjectCommand, } from '@aws-sdk/client-s3'; +import { generateStorageId } from '.'; const CLOUDFLARE_R2_BUCKET = process.env.NEXT_PUBLIC_CLOUDFLARE_R2_BUCKET ?? ''; @@ -44,6 +46,24 @@ export const isUrlFromCloudflareR2 = (url: string) => export const cloudflareR2PutObjectCommandForKey = (Key: string) => new PutObjectCommand({ Bucket: CLOUDFLARE_R2_BUCKET, Key }); +export const cloudflareR2Copy = async ( + fileNameSource: string, + fileNameDestination: string, + addRandomSuffix?: boolean, +) => { + const name = fileNameSource.split('.')[0]; + const extension = fileNameSource.split('.')[1]; + const Key = addRandomSuffix + ? `${name}-${generateStorageId()}.${extension}` + : fileNameDestination; + return cloudflareR2Client().send(new CopyObjectCommand({ + Bucket: CLOUDFLARE_R2_BUCKET, + CopySource: `${CLOUDFLARE_R2_BUCKET}/${fileNameSource}`, + Key, + })) + .then(() => urlForKey(fileNameDestination)); +}; + export const cloudflareR2List = async (Prefix: string) => cloudflareR2Client().send(new ListObjectsCommand({ Bucket: CLOUDFLARE_R2_BUCKET, diff --git a/src/services/storage/index.ts b/src/services/storage/index.ts index 79d9b73f..64605928 100644 --- a/src/services/storage/index.ts +++ b/src/services/storage/index.ts @@ -21,13 +21,14 @@ import { import { generateNanoid } from '@/utility/nanoid'; import { CLOUDFLARE_R2_BASE_URL_PUBLIC, + cloudflareR2Copy, cloudflareR2Delete, cloudflareR2List, isUrlFromCloudflareR2, } from './cloudflare-r2'; import { PATH_API_PRESIGNED_URL } from '@/site/paths'; -export const generateBlobId = () => generateNanoid(16); +export const generateStorageId = () => generateNanoid(16); export type StorageType = 'vercel-blob' | @@ -42,7 +43,7 @@ export const labelForStorage = (type: StorageType): string => { } }; -export const blobBaseUrlForStorage = (type: StorageType) => { +export const baseUrlForStorage = (type: StorageType) => { switch (type) { case 'vercel-blob': return VERCEL_BLOB_BASE_URL; case 'cloudflare-r2': return CLOUDFLARE_R2_BASE_URL_PUBLIC; @@ -93,7 +94,7 @@ export const getIdFromStorageUrl = (url: string) => export const isUploadPathnameValid = (pathname?: string) => pathname?.match(REGEX_UPLOAD_PATH); -const getFileNameFromBlobUrl = (url: string) => +const getFileNameFromStorageUrl = (url: string) => (new URL(url).pathname.match(/\/(.+)$/)?.[1]) ?? ''; export const uploadFromClientViaPresignedUrl = async ( @@ -103,14 +104,14 @@ export const uploadFromClientViaPresignedUrl = async ( addRandomSuffix?: boolean, ) => { const key = addRandomSuffix - ? `${fileName}-${generateBlobId()}.${extension}` + ? `${fileName}-${generateStorageId()}.${extension}` : `${fileName}.${extension}`; const url = await fetch(`${PATH_API_PRESIGNED_URL}/${key}`) .then((response) => response.text()); return fetch(url, { method: 'PUT', body: file }) - .then(() => `${blobBaseUrlForStorage(STORAGE_PREFERENCE)}/${key}`); + .then(() => `${baseUrlForStorage(STORAGE_PREFERENCE)}/${key}`); }; export const uploadPhotoFromClient = async ( @@ -131,45 +132,74 @@ export const convertUploadToPhoto = async ( const fileExtension = getExtensionFromStorageUrl(uploadUrl); const photoUrl = `${fileName}.${fileExtension ?? 'jpg'}`; - const useAwsS3 = HAS_AWS_S3_STORAGE && isUrlFromAwsS3(uploadUrl); + const storageType = storageTypeFromUrl(uploadUrl); - const url = await (useAwsS3 - ? awsS3Copy(uploadUrl, photoUrl, photoId === undefined) - : vercelBlobCopy(uploadUrl, photoUrl, photoId === undefined)); + let url: string | undefined; + // Copy file + switch (storageType) { + case 'vercel-blob': + url = await vercelBlobCopy(uploadUrl, photoUrl, photoId === undefined); + break; + case 'cloudflare-r2': + url = await cloudflareR2Copy( + getFileNameFromStorageUrl(uploadUrl), + photoUrl, + photoId === undefined, + ); + break; + case 'aws-s3': + url = await awsS3Copy(uploadUrl, photoUrl, photoId === undefined); + break; + } + + // If successful, delete original file if (url) { - await (useAwsS3 - ? awsS3Delete(getFileNameFromBlobUrl(uploadUrl)) - : vercelBlobDelete(uploadUrl)); + switch (storageType) { + case 'vercel-blob': + await vercelBlobDelete(uploadUrl); + break; + case 'cloudflare-r2': + await cloudflareR2Delete(getFileNameFromStorageUrl(uploadUrl)); + break; + case 'aws-s3': + await awsS3Delete(getFileNameFromStorageUrl(uploadUrl)); + break; + } } return url; }; -export const deleteBlobUrl = (url: string) => { +export const deleteStorageUrl = (url: string) => { switch (storageTypeFromUrl(url)) { - case 'vercel-blob': return vercelBlobDelete(url); - case 'cloudflare-r2': return cloudflareR2Delete(getFileNameFromBlobUrl(url)); - case 'aws-s3': return awsS3Delete(getFileNameFromBlobUrl(url)); + case 'vercel-blob': + return vercelBlobDelete(url); + case 'cloudflare-r2': + return cloudflareR2Delete(getFileNameFromStorageUrl(url)); + case 'aws-s3': + return awsS3Delete(getFileNameFromStorageUrl(url)); } }; -export const getBlobUploadUrls = async (): Promise => { +const getStorageUrlsForPrefix = async (prefix = ''): Promise => { const urls: string[] = []; if (HAS_VERCEL_BLOB_STORAGE) { - urls.push(...await vercelBlobList(`${PREFIX_UPLOAD}-`)); + urls.push(...await vercelBlobList(prefix)); } if (HAS_AWS_S3_STORAGE) { - urls.push(...await awsS3List(`${PREFIX_UPLOAD}-`)); + urls.push(...await awsS3List(prefix)); } if (HAS_CLOUDFLARE_R2_STORAGE) { - urls.push(...await cloudflareR2List(`${PREFIX_UPLOAD}-`)); + urls.push(...await cloudflareR2List(prefix)); } return urls; }; -export const getBlobPhotoUrls = (): Promise => HAS_AWS_S3_STORAGE - ? awsS3List(`${PREFIX_PHOTO}-`) - : vercelBlobList(`${PREFIX_PHOTO}-`); +export const getStorageUploadUrls = () => + getStorageUrlsForPrefix(`${PREFIX_UPLOAD}-`); + +export const getStoragePhotoUrls = () => + getStorageUrlsForPrefix(`${PREFIX_PHOTO}-`); From ce7aa2654207c16184d4c2a4263ee00251443363 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 21 Jan 2024 11:26:23 -0600 Subject: [PATCH 10/13] Tweak README hierarchy --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 27f5dec3..d11f01b8 100644 --- a/README.md +++ b/README.md @@ -71,11 +71,11 @@ Installation - `NEXT_PUBLIC_GRID_ASPECT_RATIO = 1.5` sets aspect ratio for grid tiles (defaults to `1`—setting to `0` removes the constraint) - `NEXT_PUBLIC_OG_TEXT_ALIGNMENT = BOTTOM` keeps OG image text bottom aligned (default is top) -### Configure alternate storage +## Configure alternate storage Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). If you have multiple adapters, you can set one as preferred by storing "aws-s3," "cloudflare-r2," or "vercel-blob" in `NEXT_PUBLIC_STORAGE_PREFERENCE`. -#### Cloudflare R2 +### Cloudflare R2 1. Setup bucket - [Create R2 bucket](https://developers.cloudflare.com/r2/) with default settings @@ -106,7 +106,7 @@ Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used a - `CLOUDFLARE_R2_ACCESS_KEY` - `CLOUDFLARE_R2_SECRET_ACCESS_KEY` -#### AWS S3 +### AWS S3 1. Setup bucket - [Create S3 bucket](https://s3.console.aws.amazon.com/s3) with "ACLs enabled," and "Block all public access" turned off From 3ea54b2a21752595962ff8d035ebd966ff6b71f2 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 21 Jan 2024 11:40:29 -0600 Subject: [PATCH 11/13] Simplify storage configuration text --- src/app/api/storage/presigned-url/[key]/route.ts | 6 +++--- src/services/storage/index.ts | 8 ++++---- src/site/SiteChecklistClient.tsx | 12 +++++++----- src/site/config.ts | 15 +++++++++++---- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/app/api/storage/presigned-url/[key]/route.ts b/src/app/api/storage/presigned-url/[key]/route.ts index 2b77455d..da506a22 100644 --- a/src/app/api/storage/presigned-url/[key]/route.ts +++ b/src/app/api/storage/presigned-url/[key]/route.ts @@ -7,7 +7,7 @@ import { cloudflareR2Client, cloudflareR2PutObjectCommandForKey, } from '@/services/storage/cloudflare-r2'; -import { STORAGE_PREFERENCE } from '@/site/config'; +import { CURRENT_STORAGE } from '@/site/config'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; export const runtime = 'edge'; @@ -19,10 +19,10 @@ export async function GET( const session = await auth(); if (session?.user && key) { const url = await getSignedUrl( - STORAGE_PREFERENCE === 'cloudflare-r2' + CURRENT_STORAGE === 'cloudflare-r2' ? cloudflareR2Client() : awsS3Client(), - STORAGE_PREFERENCE === 'cloudflare-r2' + CURRENT_STORAGE === 'cloudflare-r2' ? cloudflareR2PutObjectCommandForKey(key) : awsS3PutObjectCommandForKey(key), { expiresIn: 3600 } diff --git a/src/services/storage/index.ts b/src/services/storage/index.ts index 64605928..2b58ebe3 100644 --- a/src/services/storage/index.ts +++ b/src/services/storage/index.ts @@ -13,7 +13,7 @@ import { isUrlFromAwsS3, } from './aws-s3'; import { - STORAGE_PREFERENCE, + CURRENT_STORAGE, HAS_AWS_S3_STORAGE, HAS_VERCEL_BLOB_STORAGE, HAS_CLOUDFLARE_R2_STORAGE, @@ -111,15 +111,15 @@ export const uploadFromClientViaPresignedUrl = async ( .then((response) => response.text()); return fetch(url, { method: 'PUT', body: file }) - .then(() => `${baseUrlForStorage(STORAGE_PREFERENCE)}/${key}`); + .then(() => `${baseUrlForStorage(CURRENT_STORAGE)}/${key}`); }; export const uploadPhotoFromClient = async ( file: File | Blob, extension = 'jpg', ) => ( - STORAGE_PREFERENCE === 'cloudflare-r2' || - STORAGE_PREFERENCE === 'aws-s3' + CURRENT_STORAGE === 'cloudflare-r2' || + CURRENT_STORAGE === 'aws-s3' ) ? uploadFromClientViaPresignedUrl(file, PREFIX_UPLOAD, extension, true) : vercelBlobUploadFromClient(file, `${PREFIX_UPLOAD}.${extension}`); diff --git a/src/site/SiteChecklistClient.tsx b/src/site/SiteChecklistClient.tsx index 39086660..98a20c6f 100644 --- a/src/site/SiteChecklistClient.tsx +++ b/src/site/SiteChecklistClient.tsx @@ -27,7 +27,8 @@ export default function SiteChecklistClient({ hasVercelBlobStorage, hasCloudflareR2Storage, hasAwsS3Storage, - storagePreference, + hasMultipleStorageProviders, + currentStorage, hasAuth, hasAdminUser, hasTitle, @@ -142,10 +143,11 @@ export default function SiteChecklistClient({ and connect to project diff --git a/src/site/config.ts b/src/site/config.ts index 1cc4b59e..c8f131f1 100644 --- a/src/site/config.ts +++ b/src/site/config.ts @@ -56,9 +56,15 @@ export const HAS_AWS_S3_STORAGE = (process.env.AWS_S3_ACCESS_KEY ?? '').length > 0 && (process.env.AWS_S3_SECRET_ACCESS_KEY ?? '').length > 0; -// Storage preference relies on client-only keys -// so that it's available in the browser when uploading -export const STORAGE_PREFERENCE: StorageType = +export const HAS_MULTIPLE_STORAGE_PROVIDERS = [ + HAS_VERCEL_BLOB_STORAGE, + HAS_CLOUDFLARE_R2_STORAGE, + HAS_AWS_S3_STORAGE, +].filter(Boolean).length > 1; + +// Storage preference requires client-available keys +// so it can be reached in the browser when uploading +export const CURRENT_STORAGE: StorageType = (process.env.NEXT_PUBLIC_STORAGE_PREFERENCE as StorageType | undefined) || ( HAS_CLOUDFLARE_R2_STORAGE_CLIENT ? 'cloudflare-r2' @@ -94,7 +100,8 @@ export const CONFIG_CHECKLIST_STATUS = { HAS_VERCEL_BLOB_STORAGE || HAS_CLOUDFLARE_R2_STORAGE || HAS_AWS_S3_STORAGE, - storagePreference: STORAGE_PREFERENCE, + hasMultipleStorageProviders: HAS_MULTIPLE_STORAGE_PROVIDERS, + currentStorage: CURRENT_STORAGE, hasAuth: (process.env.AUTH_SECRET ?? '').length > 0, hasAdminUser: ( (process.env.ADMIN_EMAIL ?? '').length > 0 && From 311b63586b37877f6a9861691e2b75115f04d4cd Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 21 Jan 2024 11:41:05 -0600 Subject: [PATCH 12/13] Reorder checklist props --- src/site/SiteChecklistClient.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/SiteChecklistClient.tsx b/src/site/SiteChecklistClient.tsx index 98a20c6f..6ea9004e 100644 --- a/src/site/SiteChecklistClient.tsx +++ b/src/site/SiteChecklistClient.tsx @@ -40,8 +40,8 @@ export default function SiteChecklistClient({ isPriorityOrderEnabled, isPublicApiEnabled, isOgTextBottomAligned, - showRefreshButton, gridAspectRatio, + showRefreshButton, secret, }: ConfigChecklistStatus & { showRefreshButton?: boolean From 5c07cf22f4086060f9fdd8daa8490a82d02ff6ce Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 21 Jan 2024 11:56:27 -0600 Subject: [PATCH 13/13] Tweak storage README header --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d11f01b8..8ebd954d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Installation - `NEXT_PUBLIC_GRID_ASPECT_RATIO = 1.5` sets aspect ratio for grid tiles (defaults to `1`—setting to `0` removes the constraint) - `NEXT_PUBLIC_OG_TEXT_ALIGNMENT = BOTTOM` keeps OG image text bottom aligned (default is top) -## Configure alternate storage +## Alternate storage providers Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). If you have multiple adapters, you can set one as preferred by storing "aws-s3," "cloudflare-r2," or "vercel-blob" in `NEXT_PUBLIC_STORAGE_PREFERENCE`.