From 58922110f9f3eb7644ac4259d1a521517d223712 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Thu, 28 Sep 2023 13:57:29 -0500 Subject: [PATCH 01/15] Bump dependencies --- package.json | 8 +- pnpm-lock.yaml | 1226 ++++++++++++++++++++++++------------------------ 2 files changed, 626 insertions(+), 608 deletions(-) diff --git a/package.json b/package.json index 0a73754e..2ff8f84c 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,13 @@ "dependencies": { "@next/bundle-analyzer": "^13.5.3", "@tailwindcss/forms": "^0.5.6", - "@types/node": "^20.7.0", - "@types/react": "18.2.22", - "@types/react-dom": "18.2.7", + "@types/node": "^20.7.1", + "@types/react": "18.2.23", + "@types/react-dom": "18.2.8", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", "@vercel/analytics": "^1.0.2", - "@vercel/blob": "^0.12.5", + "@vercel/blob": "^0.13.0", "@vercel/postgres": "0.5.0", "autoprefixer": "10.4.16", "camelcase-keys": "^9.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af930c6a..47306a5d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,78 +1,108 @@ -lockfileVersion: 5.4 +lockfileVersion: '6.0' -specifiers: - '@next/bundle-analyzer': ^13.5.3 - '@tailwindcss/forms': ^0.5.6 - '@types/node': ^20.7.0 - '@types/react': 18.2.22 - '@types/react-dom': 18.2.7 - '@typescript-eslint/eslint-plugin': ^6.7.3 - '@typescript-eslint/parser': ^6.7.3 - '@vercel/analytics': ^1.0.2 - '@vercel/blob': ^0.12.5 - '@vercel/postgres': 0.5.0 - autoprefixer: 10.4.16 - camelcase-keys: ^9.0.0 - date-fns: ^2.30.0 - eslint: 8.50.0 - eslint-config-next: 13.5.3 - framer-motion: ^10.16.4 - nanoid: ^5.0.1 - next: ^13.5.3 - next-auth: 0.0.0-manual.5749b095 - next-themes: ^0.2.1 - postcss: 8.4.30 - react: 18.2.0 - react-dom: 18.2.0 - react-icons: ^4.11.0 - sonner: ^1.0.3 - tailwindcss: 3.3.3 - ts-exif-parser: ^0.2.2 - typescript: 5.2.2 +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false dependencies: - '@next/bundle-analyzer': 13.5.3 - '@tailwindcss/forms': 0.5.6_tailwindcss@3.3.3 - '@types/node': 20.7.0 - '@types/react': 18.2.22 - '@types/react-dom': 18.2.7 - '@typescript-eslint/eslint-plugin': 6.7.3_ptdtxirkj6smbsapfa2xu7c5iq - '@typescript-eslint/parser': 6.7.3_jk7qbkaijtltyu4ajmze3dfiwa - '@vercel/analytics': 1.0.2 - '@vercel/blob': 0.12.5 - '@vercel/postgres': 0.5.0 - autoprefixer: 10.4.16_postcss@8.4.30 - camelcase-keys: 9.0.0 - date-fns: 2.30.0 - eslint: 8.50.0 - eslint-config-next: 13.5.3_jk7qbkaijtltyu4ajmze3dfiwa - framer-motion: 10.16.4_biqbaboplfbrettd7655fr4n2y - nanoid: 5.0.1 - next: 13.5.3_biqbaboplfbrettd7655fr4n2y - next-auth: 0.0.0-manual.5749b095_next@13.5.3+react@18.2.0 - next-themes: 0.2.1_vs65xldtmolprftbsqonkgfxyi - postcss: 8.4.30 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - react-icons: 4.11.0_react@18.2.0 - sonner: 1.0.3_biqbaboplfbrettd7655fr4n2y - tailwindcss: 3.3.3 - ts-exif-parser: 0.2.2 - typescript: 5.2.2 + '@next/bundle-analyzer': + specifier: ^13.5.3 + version: 13.5.3 + '@tailwindcss/forms': + specifier: ^0.5.6 + version: 0.5.6(tailwindcss@3.3.3) + '@types/node': + specifier: ^20.7.1 + version: 20.7.1 + '@types/react': + specifier: 18.2.23 + version: 18.2.23 + '@types/react-dom': + specifier: 18.2.8 + version: 18.2.8 + '@typescript-eslint/eslint-plugin': + specifier: ^6.7.3 + version: 6.7.3(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/parser': + specifier: ^6.7.3 + version: 6.7.3(eslint@8.50.0)(typescript@5.2.2) + '@vercel/analytics': + specifier: ^1.0.2 + version: 1.0.2 + '@vercel/blob': + specifier: ^0.13.0 + version: 0.13.0 + '@vercel/postgres': + specifier: 0.5.0 + version: 0.5.0 + autoprefixer: + specifier: 10.4.16 + version: 10.4.16(postcss@8.4.30) + camelcase-keys: + specifier: ^9.0.0 + version: 9.0.0 + date-fns: + specifier: ^2.30.0 + version: 2.30.0 + eslint: + specifier: 8.50.0 + version: 8.50.0 + eslint-config-next: + specifier: 13.5.3 + version: 13.5.3(eslint@8.50.0)(typescript@5.2.2) + framer-motion: + specifier: ^10.16.4 + version: 10.16.4(react-dom@18.2.0)(react@18.2.0) + nanoid: + specifier: ^5.0.1 + version: 5.0.1 + next: + specifier: ^13.5.3 + version: 13.5.3(react-dom@18.2.0)(react@18.2.0) + next-auth: + specifier: 0.0.0-manual.5749b095 + version: 0.0.0-manual.5749b095(next@13.5.3)(react@18.2.0) + next-themes: + specifier: ^0.2.1 + version: 0.2.1(next@13.5.3)(react-dom@18.2.0)(react@18.2.0) + postcss: + specifier: 8.4.30 + version: 8.4.30 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + react-icons: + specifier: ^4.11.0 + version: 4.11.0(react@18.2.0) + sonner: + specifier: ^1.0.3 + version: 1.0.3(react-dom@18.2.0)(react@18.2.0) + tailwindcss: + specifier: 3.3.3 + version: 3.3.3 + ts-exif-parser: + specifier: ^0.2.2 + version: 0.2.2 + typescript: + specifier: 5.2.2 + version: 5.2.2 packages: - /@aashutoshrathi/word-wrap/1.2.6: + /@aashutoshrathi/word-wrap@1.2.6: resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} dev: false - /@alloc/quick-lru/5.2.0: + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} dev: false - /@auth/core/0.0.0-manual.e9863699: + /@auth/core@0.0.0-manual.e9863699: resolution: {integrity: sha512-/hVzGuFw7nAZimliD8kpuKnNjvkRu+jpaVhYB/FaIXLNJFNwhbO2MgXBnr5tvLIHgRJnR5C9UN5RNpQXiFHuSA==} peerDependencies: nodemailer: ^6.8.0 @@ -85,10 +115,10 @@ packages: jose: 4.14.6 oauth4webapi: 2.3.0 preact: 10.11.3 - preact-render-to-string: 5.2.3_preact@10.11.3 + preact-render-to-string: 5.2.3(preact@10.11.3) dev: false - /@babel/code-frame/7.22.13: + /@babel/code-frame@7.22.13: resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} engines: {node: '>=6.9.0'} dependencies: @@ -96,12 +126,12 @@ packages: chalk: 2.4.2 dev: false - /@babel/helper-validator-identifier/7.22.20: + /@babel/helper-validator-identifier@7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} dev: false - /@babel/highlight/7.22.20: + /@babel/highlight@7.22.20: resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} engines: {node: '>=6.9.0'} dependencies: @@ -110,14 +140,14 @@ packages: js-tokens: 4.0.0 dev: false - /@babel/runtime/7.22.15: + /@babel/runtime@7.22.15: resolution: {integrity: sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.0 dev: false - /@emotion/is-prop-valid/0.8.8: + /@emotion/is-prop-valid@0.8.8: resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} requiresBuild: true dependencies: @@ -125,12 +155,13 @@ packages: dev: false optional: true - /@emotion/memoize/0.7.4: + /@emotion/memoize@0.7.4: resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + requiresBuild: true dev: false optional: true - /@eslint-community/eslint-utils/4.4.0_eslint@8.50.0: + /@eslint-community/eslint-utils@4.4.0(eslint@8.50.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -140,12 +171,12 @@ packages: eslint-visitor-keys: 3.4.3 dev: false - /@eslint-community/regexpp/4.8.1: + /@eslint-community/regexpp@4.8.1: resolution: {integrity: sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: false - /@eslint/eslintrc/2.1.2: + /@eslint/eslintrc@2.1.2: resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: @@ -162,12 +193,12 @@ packages: - supports-color dev: false - /@eslint/js/8.50.0: + /@eslint/js@8.50.0: resolution: {integrity: sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false - /@humanwhocodes/config-array/0.11.11: + /@humanwhocodes/config-array@0.11.11: resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} engines: {node: '>=10.10.0'} dependencies: @@ -178,57 +209,57 @@ packages: - supports-color dev: false - /@humanwhocodes/module-importer/1.0.1: + /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} dev: false - /@humanwhocodes/object-schema/1.2.1: + /@humanwhocodes/object-schema@1.2.1: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: false - /@jest/environment/29.7.0: + /@jest/environment@29.7.0: resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.0 + '@types/node': 20.7.1 jest-mock: 29.7.0 dev: false - /@jest/fake-timers/29.7.0: + /@jest/fake-timers@29.7.0: resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.7.0 + '@types/node': 20.7.1 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 dev: false - /@jest/schemas/29.6.3: + /@jest/schemas@29.6.3: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@sinclair/typebox': 0.27.8 dev: false - /@jest/types/29.6.3: + /@jest/types@29.6.3: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 20.7.0 + '@types/node': 20.7.1 '@types/yargs': 17.0.24 chalk: 4.1.2 dev: false - /@jridgewell/gen-mapping/0.3.3: + /@jridgewell/gen-mapping@0.3.3: resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} dependencies: @@ -237,34 +268,34 @@ packages: '@jridgewell/trace-mapping': 0.3.19 dev: false - /@jridgewell/resolve-uri/3.1.1: + /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} dev: false - /@jridgewell/set-array/1.1.2: + /@jridgewell/set-array@1.1.2: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} dev: false - /@jridgewell/sourcemap-codec/1.4.15: + /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} dev: false - /@jridgewell/trace-mapping/0.3.19: + /@jridgewell/trace-mapping@0.3.19: resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==} dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 dev: false - /@neondatabase/serverless/0.6.0: + /@neondatabase/serverless@0.6.0: resolution: {integrity: sha512-qXxBRYN0m2v8kVQBfMxbzNGn2xFAhTXFibzQlE++NfJ56Shz3m7+MyBBtXDlEH+3Wfa6lToDXf1MElocY4sJ3w==} dependencies: '@types/pg': 8.6.6 dev: false - /@next/bundle-analyzer/13.5.3: + /@next/bundle-analyzer@13.5.3: resolution: {integrity: sha512-AUHl9hu/0SNo2TCu9awOGY5hJdQHTPThYbjKk3rmjL04GfYAotn5i5pFQGqe209mbCxtu+QnvMEHLXU4GdFi1Q==} dependencies: webpack-bundle-analyzer: 4.7.0 @@ -273,17 +304,17 @@ packages: - utf-8-validate dev: false - /@next/env/13.5.3: + /@next/env@13.5.3: resolution: {integrity: sha512-X4te86vsbjsB7iO4usY9jLPtZ827Mbx+WcwNBGUOIuswuTAKQtzsuoxc/6KLxCMvogKG795MhrR1LDhYgDvasg==} dev: false - /@next/eslint-plugin-next/13.5.3: + /@next/eslint-plugin-next@13.5.3: resolution: {integrity: sha512-lbZOoEjzSuTtpk9UgV9rOmxYw+PsSfNR+00mZcInqooiDMZ1u+RqT1YQYLsEZPW1kumZoQe5+exkCBtZ2xn0uw==} dependencies: glob: 7.1.7 dev: false - /@next/swc-darwin-arm64/13.5.3: + /@next/swc-darwin-arm64@13.5.3: resolution: {integrity: sha512-6hiYNJxJmyYvvKGrVThzo4nTcqvqUTA/JvKim7Auaj33NexDqSNwN5YrrQu+QhZJCIpv2tULSHt+lf+rUflLSw==} engines: {node: '>= 10'} cpu: [arm64] @@ -292,7 +323,7 @@ packages: dev: false optional: true - /@next/swc-darwin-x64/13.5.3: + /@next/swc-darwin-x64@13.5.3: resolution: {integrity: sha512-UpBKxu2ob9scbpJyEq/xPgpdrgBgN3aLYlxyGqlYX5/KnwpJpFuIHU2lx8upQQ7L+MEmz+fA1XSgesoK92ppwQ==} engines: {node: '>= 10'} cpu: [x64] @@ -301,7 +332,7 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu/13.5.3: + /@next/swc-linux-arm64-gnu@13.5.3: resolution: {integrity: sha512-5AzM7Yx1Ky+oLY6pHs7tjONTF22JirDPd5Jw/3/NazJ73uGB05NqhGhB4SbeCchg7SlVYVBeRMrMSZwJwq/xoA==} engines: {node: '>= 10'} cpu: [arm64] @@ -310,7 +341,7 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl/13.5.3: + /@next/swc-linux-arm64-musl@13.5.3: resolution: {integrity: sha512-A/C1shbyUhj7wRtokmn73eBksjTM7fFQoY2v/0rTM5wehpkjQRLOXI8WJsag2uLhnZ4ii5OzR1rFPwoD9cvOgA==} engines: {node: '>= 10'} cpu: [arm64] @@ -319,7 +350,7 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu/13.5.3: + /@next/swc-linux-x64-gnu@13.5.3: resolution: {integrity: sha512-FubPuw/Boz8tKkk+5eOuDHOpk36F80rbgxlx4+xty/U71e3wZZxVYHfZXmf0IRToBn1Crb8WvLM9OYj/Ur815g==} engines: {node: '>= 10'} cpu: [x64] @@ -328,7 +359,7 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl/13.5.3: + /@next/swc-linux-x64-musl@13.5.3: resolution: {integrity: sha512-DPw8nFuM1uEpbX47tM3wiXIR0Qa+atSzs9Q3peY1urkhofx44o7E1svnq+a5Q0r8lAcssLrwiM+OyJJgV/oj7g==} engines: {node: '>= 10'} cpu: [x64] @@ -337,7 +368,7 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc/13.5.3: + /@next/swc-win32-arm64-msvc@13.5.3: resolution: {integrity: sha512-zBPSP8cHL51Gub/YV8UUePW7AVGukp2D8JU93IHbVDu2qmhFAn9LWXiOOLKplZQKxnIPUkJTQAJDCWBWU4UWUA==} engines: {node: '>= 10'} cpu: [arm64] @@ -346,7 +377,7 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc/13.5.3: + /@next/swc-win32-ia32-msvc@13.5.3: resolution: {integrity: sha512-ONcL/lYyGUj4W37D4I2I450SZtSenmFAvapkJQNIJhrPMhzDU/AdfLkW98NvH1D2+7FXwe7yclf3+B7v28uzBQ==} engines: {node: '>= 10'} cpu: [ia32] @@ -355,7 +386,7 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc/13.5.3: + /@next/swc-win32-x64-msvc@13.5.3: resolution: {integrity: sha512-2Vz2tYWaLqJvLcWbbTlJ5k9AN6JD7a5CN2pAeIzpbecK8ZF/yobA39cXtv6e+Z8c5UJuVOmaTldEAIxvsIux/Q==} engines: {node: '>= 10'} cpu: [x64] @@ -364,7 +395,7 @@ packages: dev: false optional: true - /@nodelib/fs.scandir/2.1.5: + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} dependencies: @@ -372,12 +403,12 @@ packages: run-parallel: 1.2.0 dev: false - /@nodelib/fs.stat/2.0.5: + /@nodelib/fs.stat@2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} dev: false - /@nodelib/fs.walk/1.2.8: + /@nodelib/fs.walk@1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} dependencies: @@ -385,41 +416,41 @@ packages: fastq: 1.15.0 dev: false - /@panva/hkdf/1.1.1: + /@panva/hkdf@1.1.1: resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} dev: false - /@polka/url/1.0.0-next.23: + /@polka/url@1.0.0-next.23: resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==} dev: false - /@rushstack/eslint-patch/1.4.0: + /@rushstack/eslint-patch@1.4.0: resolution: {integrity: sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg==} dev: false - /@sinclair/typebox/0.27.8: + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: false - /@sinonjs/commons/3.0.0: + /@sinonjs/commons@3.0.0: resolution: {integrity: sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==} dependencies: type-detect: 4.0.8 dev: false - /@sinonjs/fake-timers/10.3.0: + /@sinonjs/fake-timers@10.3.0: resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} dependencies: '@sinonjs/commons': 3.0.0 dev: false - /@swc/helpers/0.5.2: + /@swc/helpers@0.5.2: resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} dependencies: tslib: 2.6.2 dev: false - /@tailwindcss/forms/0.5.6_tailwindcss@3.3.3: + /@tailwindcss/forms@0.5.6(tailwindcss@3.3.3): resolution: {integrity: sha512-Fw+2BJ0tmAwK/w01tEFL5TiaJBX1NLT1/YbWgvm7ws3Qcn11kiXxzNTEQDMs5V3mQemhB56l3u0i9dwdzSQldA==} peerDependencies: tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1' @@ -428,100 +459,100 @@ packages: tailwindcss: 3.3.3 dev: false - /@tootallnate/once/2.0.0: + /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} dev: false - /@types/istanbul-lib-coverage/2.0.4: + /@types/istanbul-lib-coverage@2.0.4: resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} dev: false - /@types/istanbul-lib-report/3.0.0: + /@types/istanbul-lib-report@3.0.0: resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} dependencies: '@types/istanbul-lib-coverage': 2.0.4 dev: false - /@types/istanbul-reports/3.0.1: + /@types/istanbul-reports@3.0.1: resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} dependencies: '@types/istanbul-lib-report': 3.0.0 dev: false - /@types/jsdom/20.0.1: + /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: - '@types/node': 20.7.0 + '@types/node': 20.7.1 '@types/tough-cookie': 4.0.3 parse5: 7.1.2 dev: false - /@types/json-schema/7.0.13: + /@types/json-schema@7.0.13: resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==} dev: false - /@types/json5/0.0.29: + /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: false - /@types/node/20.7.0: - resolution: {integrity: sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==} + /@types/node@20.7.1: + resolution: {integrity: sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==} dev: false - /@types/pg/8.6.6: + /@types/pg@8.6.6: resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} dependencies: - '@types/node': 20.7.0 + '@types/node': 20.7.1 pg-protocol: 1.6.0 pg-types: 2.2.0 dev: false - /@types/prop-types/15.7.6: + /@types/prop-types@15.7.6: resolution: {integrity: sha512-RK/kBbYOQQHLYj9Z95eh7S6t7gq4Ojt/NT8HTk8bWVhA5DaF+5SMnxHKkP4gPNN3wAZkKP+VjAf0ebtYzf+fxg==} dev: false - /@types/react-dom/18.2.7: - resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==} + /@types/react-dom@18.2.8: + resolution: {integrity: sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw==} dependencies: - '@types/react': 18.2.22 + '@types/react': 18.2.23 dev: false - /@types/react/18.2.22: - resolution: {integrity: sha512-60fLTOLqzarLED2O3UQImc/lsNRgG0jE/a1mPW9KjMemY0LMITWEsbS4VvZ4p6rorEHd5YKxxmMKSDK505GHpA==} + /@types/react@18.2.23: + resolution: {integrity: sha512-qHLW6n1q2+7KyBEYnrZpcsAmU/iiCh9WGCKgXvMxx89+TYdJWRjZohVIo9XTcoLhfX3+/hP0Pbulu3bCZQ9PSA==} dependencies: '@types/prop-types': 15.7.6 '@types/scheduler': 0.16.3 csstype: 3.1.2 dev: false - /@types/scheduler/0.16.3: + /@types/scheduler@0.16.3: resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} dev: false - /@types/semver/7.5.2: + /@types/semver@7.5.2: resolution: {integrity: sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==} dev: false - /@types/stack-utils/2.0.1: + /@types/stack-utils@2.0.1: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} dev: false - /@types/tough-cookie/4.0.3: + /@types/tough-cookie@4.0.3: resolution: {integrity: sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==} dev: false - /@types/yargs-parser/21.0.0: + /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} dev: false - /@types/yargs/17.0.24: + /@types/yargs@17.0.24: resolution: {integrity: sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==} dependencies: '@types/yargs-parser': 21.0.0 dev: false - /@typescript-eslint/eslint-plugin/6.7.3_ptdtxirkj6smbsapfa2xu7c5iq: + /@typescript-eslint/eslint-plugin@6.7.3(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2): resolution: {integrity: sha512-vntq452UHNltxsaaN+L9WyuMch8bMd9CqJ3zhzTPXXidwbf5mqqKCVXEuvRZUqLJSTLeWE65lQwyXsRGnXkCTA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -533,10 +564,10 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.8.1 - '@typescript-eslint/parser': 6.7.3_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) '@typescript-eslint/scope-manager': 6.7.3 - '@typescript-eslint/type-utils': 6.7.3_jk7qbkaijtltyu4ajmze3dfiwa - '@typescript-eslint/utils': 6.7.3_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/type-utils': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.7.3(eslint@8.50.0)(typescript@5.2.2) '@typescript-eslint/visitor-keys': 6.7.3 debug: 4.3.4 eslint: 8.50.0 @@ -544,13 +575,13 @@ packages: ignore: 5.2.4 natural-compare: 1.4.0 semver: 7.5.4 - ts-api-utils: 1.0.3_typescript@5.2.2 + ts-api-utils: 1.0.3(typescript@5.2.2) typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: false - /@typescript-eslint/parser/6.7.3_jk7qbkaijtltyu4ajmze3dfiwa: + /@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.2.2): resolution: {integrity: sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -562,7 +593,7 @@ packages: dependencies: '@typescript-eslint/scope-manager': 6.7.3 '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/typescript-estree': 6.7.3_typescript@5.2.2 + '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2) '@typescript-eslint/visitor-keys': 6.7.3 debug: 4.3.4 eslint: 8.50.0 @@ -571,7 +602,7 @@ packages: - supports-color dev: false - /@typescript-eslint/scope-manager/6.7.3: + /@typescript-eslint/scope-manager@6.7.3: resolution: {integrity: sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: @@ -579,7 +610,7 @@ packages: '@typescript-eslint/visitor-keys': 6.7.3 dev: false - /@typescript-eslint/type-utils/6.7.3_jk7qbkaijtltyu4ajmze3dfiwa: + /@typescript-eslint/type-utils@6.7.3(eslint@8.50.0)(typescript@5.2.2): resolution: {integrity: sha512-Fc68K0aTDrKIBvLnKTZ5Pf3MXK495YErrbHb1R6aTpfK5OdSFj0rVN7ib6Tx6ePrZ2gsjLqr0s98NG7l96KSQw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -589,22 +620,22 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.7.3_typescript@5.2.2 - '@typescript-eslint/utils': 6.7.3_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2) + '@typescript-eslint/utils': 6.7.3(eslint@8.50.0)(typescript@5.2.2) debug: 4.3.4 eslint: 8.50.0 - ts-api-utils: 1.0.3_typescript@5.2.2 + ts-api-utils: 1.0.3(typescript@5.2.2) typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: false - /@typescript-eslint/types/6.7.3: + /@typescript-eslint/types@6.7.3: resolution: {integrity: sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw==} engines: {node: ^16.0.0 || >=18.0.0} dev: false - /@typescript-eslint/typescript-estree/6.7.3_typescript@5.2.2: + /@typescript-eslint/typescript-estree@6.7.3(typescript@5.2.2): resolution: {integrity: sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -619,24 +650,24 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - ts-api-utils: 1.0.3_typescript@5.2.2 + ts-api-utils: 1.0.3(typescript@5.2.2) typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: false - /@typescript-eslint/utils/6.7.3_jk7qbkaijtltyu4ajmze3dfiwa: + /@typescript-eslint/utils@6.7.3(eslint@8.50.0)(typescript@5.2.2): resolution: {integrity: sha512-vzLkVder21GpWRrmSR9JxGZ5+ibIUSudXlW52qeKpzUEQhRSmyZiVDDj3crAth7+5tmN1ulvgKaCU2f/bPRCzg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0_eslint@8.50.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) '@types/json-schema': 7.0.13 '@types/semver': 7.5.2 '@typescript-eslint/scope-manager': 6.7.3 '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/typescript-estree': 6.7.3_typescript@5.2.2 + '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2) eslint: 8.50.0 semver: 7.5.4 transitivePeerDependencies: @@ -644,7 +675,7 @@ packages: - typescript dev: false - /@typescript-eslint/visitor-keys/6.7.3: + /@typescript-eslint/visitor-keys@6.7.3: resolution: {integrity: sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: @@ -652,16 +683,16 @@ packages: eslint-visitor-keys: 3.4.3 dev: false - /@vercel/analytics/1.0.2: + /@vercel/analytics@1.0.2: resolution: {integrity: sha512-BZFxVrv24VbNNl5xMxqUojQIegEeXMI6rX3rg1uVLYUEXsuKNBSAEQf4BWEcjQDp/8aYJOj6m8V4PUA3x/cxgg==} dev: false - /@vercel/blob/0.12.5: - resolution: {integrity: sha512-XCsg9W2WrDlQGnw9X38RbM2mtfhTvp4x9lThx4Cr496c0f4IIoMbuwiFd9uvu228D+RcyeopTN7KJAUERCSogw==} + /@vercel/blob@0.13.0: + resolution: {integrity: sha512-yFdhikaXaiyS9aJzu2XdgHHkion/mK0vcRzgVxDncojx9Qla5J5IIHnp7bS6BeGuz7ru2VGkwVOHFfjEFW9rAw==} engines: {node: '>=16.14'} dependencies: jest-environment-jsdom: 29.7.0 - undici: 5.24.0 + undici: 5.25.1 transitivePeerDependencies: - bufferutil - canvas @@ -669,28 +700,28 @@ packages: - utf-8-validate dev: false - /@vercel/postgres/0.5.0: + /@vercel/postgres@0.5.0: resolution: {integrity: sha512-MFWp9SZmADqBe2x2mzEvwmGLiwOd8PVkUxYeBZx/RqdHl0bd8/1BH0zBR+zSimGyi9P/MVtZoJLdf5dkWw9m5Q==} engines: {node: '>=14.6'} dependencies: '@neondatabase/serverless': 0.6.0 bufferutil: 4.0.7 utf-8-validate: 6.0.3 - ws: 8.14.2_2adebc2xdjqbcvbjxkodkhadp4 + ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@6.0.3) dev: false - /abab/2.0.6: + /abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} dev: false - /acorn-globals/7.0.1: + /acorn-globals@7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} dependencies: acorn: 8.10.0 acorn-walk: 8.2.0 dev: false - /acorn-jsx/5.3.2_acorn@8.10.0: + /acorn-jsx@5.3.2(acorn@8.10.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -698,18 +729,18 @@ packages: acorn: 8.10.0 dev: false - /acorn-walk/8.2.0: + /acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} dev: false - /acorn/8.10.0: + /acorn@8.10.0: resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} engines: {node: '>=0.4.0'} hasBin: true dev: false - /agent-base/6.0.2: + /agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: @@ -718,7 +749,7 @@ packages: - supports-color dev: false - /ajv/6.12.6: + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: fast-deep-equal: 3.1.3 @@ -727,35 +758,35 @@ packages: uri-js: 4.4.1 dev: false - /ansi-regex/5.0.1: + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} dev: false - /ansi-styles/3.2.1: + /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} dependencies: color-convert: 1.9.3 dev: false - /ansi-styles/4.3.0: + /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} dependencies: color-convert: 2.0.1 dev: false - /ansi-styles/5.2.0: + /ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} dev: false - /any-promise/1.3.0: + /any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} dev: false - /anymatch/3.1.3: + /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} dependencies: @@ -763,28 +794,28 @@ packages: picomatch: 2.3.1 dev: false - /arg/5.0.2: + /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} dev: false - /argparse/2.0.1: + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: false - /aria-query/5.3.0: + /aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} dependencies: dequal: 2.0.3 dev: false - /array-buffer-byte-length/1.0.0: + /array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} dependencies: call-bind: 1.0.2 is-array-buffer: 3.0.2 dev: false - /array-includes/3.1.7: + /array-includes@3.1.7: resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} engines: {node: '>= 0.4'} dependencies: @@ -795,12 +826,12 @@ packages: is-string: 1.0.7 dev: false - /array-union/2.1.0: + /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} dev: false - /array.prototype.findlastindex/1.2.3: + /array.prototype.findlastindex@1.2.3: resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} engines: {node: '>= 0.4'} dependencies: @@ -811,7 +842,7 @@ packages: get-intrinsic: 1.2.1 dev: false - /array.prototype.flat/1.3.2: + /array.prototype.flat@1.3.2: resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} engines: {node: '>= 0.4'} dependencies: @@ -821,7 +852,7 @@ packages: es-shim-unscopables: 1.0.0 dev: false - /array.prototype.flatmap/1.3.2: + /array.prototype.flatmap@1.3.2: resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} engines: {node: '>= 0.4'} dependencies: @@ -831,7 +862,7 @@ packages: es-shim-unscopables: 1.0.0 dev: false - /array.prototype.tosorted/1.1.2: + /array.prototype.tosorted@1.1.2: resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==} dependencies: call-bind: 1.0.2 @@ -841,7 +872,7 @@ packages: get-intrinsic: 1.2.1 dev: false - /arraybuffer.prototype.slice/1.0.2: + /arraybuffer.prototype.slice@1.0.2: resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} engines: {node: '>= 0.4'} dependencies: @@ -854,21 +885,21 @@ packages: is-shared-array-buffer: 1.0.2 dev: false - /ast-types-flow/0.0.7: + /ast-types-flow@0.0.7: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} dev: false - /asynciterator.prototype/1.0.0: + /asynciterator.prototype@1.0.0: resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} dependencies: has-symbols: 1.0.3 dev: false - /asynckit/0.4.0: + /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: false - /autoprefixer/10.4.16_postcss@8.4.30: + /autoprefixer@10.4.16(postcss@8.4.30): resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==} engines: {node: ^10 || ^12 || >=14} hasBin: true @@ -884,46 +915,46 @@ packages: postcss-value-parser: 4.2.0 dev: false - /available-typed-arrays/1.0.5: + /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} dev: false - /axe-core/4.8.1: + /axe-core@4.8.1: resolution: {integrity: sha512-9l850jDDPnKq48nbad8SiEelCv4OrUWrKab/cPj0GScVg6cb6NbCCt/Ulk26QEq5jP9NnGr04Bit1BHyV6r5CQ==} engines: {node: '>=4'} dev: false - /axobject-query/3.2.1: + /axobject-query@3.2.1: resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} dependencies: dequal: 2.0.3 dev: false - /balanced-match/1.0.2: + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: false - /binary-extensions/2.2.0: + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} dev: false - /brace-expansion/1.1.11: + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 dev: false - /braces/3.0.2: + /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} dependencies: fill-range: 7.0.1 dev: false - /browserslist/4.21.10: + /browserslist@4.21.10: resolution: {integrity: sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -931,10 +962,10 @@ packages: caniuse-lite: 1.0.30001538 electron-to-chromium: 1.4.525 node-releases: 2.0.13 - update-browserslist-db: 1.0.11_browserslist@4.21.10 + update-browserslist-db: 1.0.11(browserslist@4.21.10) dev: false - /bufferutil/4.0.7: + /bufferutil@4.0.7: resolution: {integrity: sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==} engines: {node: '>=6.14.2'} requiresBuild: true @@ -942,31 +973,31 @@ packages: node-gyp-build: 4.6.1 dev: false - /busboy/1.6.0: + /busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} dependencies: streamsearch: 1.1.0 dev: false - /call-bind/1.0.2: + /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: function-bind: 1.1.1 get-intrinsic: 1.2.1 dev: false - /callsites/3.1.0: + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} dev: false - /camelcase-css/2.0.1: + /camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} dev: false - /camelcase-keys/9.0.0: + /camelcase-keys@9.0.0: resolution: {integrity: sha512-GdZ92DNXdcfFB/5Kq4O82EL6UW5neiRBhfNP5M3mGw7CX2sPDbVA04ZPLsqbp7oMi2l3m2I0AZ/kFP5Nk5kopA==} engines: {node: '>=16'} dependencies: @@ -976,16 +1007,16 @@ packages: type-fest: 4.3.1 dev: false - /camelcase/8.0.0: + /camelcase@8.0.0: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} dev: false - /caniuse-lite/1.0.30001538: + /caniuse-lite@1.0.30001538: resolution: {integrity: sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==} dev: false - /chalk/2.4.2: + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} dependencies: @@ -994,7 +1025,7 @@ packages: supports-color: 5.5.0 dev: false - /chalk/4.1.2: + /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} dependencies: @@ -1002,7 +1033,7 @@ packages: supports-color: 7.2.0 dev: false - /chokidar/3.5.3: + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} dependencies: @@ -1017,63 +1048,63 @@ packages: fsevents: 2.3.3 dev: false - /ci-info/3.8.0: + /ci-info@3.8.0: resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} engines: {node: '>=8'} dev: false - /client-only/0.0.1: + /client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} dev: false - /color-convert/1.9.3: + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: color-name: 1.1.3 dev: false - /color-convert/2.0.1: + /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 dev: false - /color-name/1.1.3: + /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} dev: false - /color-name/1.1.4: + /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: false - /combined-stream/1.0.8: + /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 dev: false - /commander/4.1.1: + /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} dev: false - /commander/7.2.0: + /commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} dev: false - /concat-map/0.0.1: + /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: false - /cookie/0.5.0: + /cookie@0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} dev: false - /cross-spawn/7.0.3: + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} dependencies: @@ -1082,36 +1113,36 @@ packages: which: 2.0.2 dev: false - /cssesc/3.0.0: + /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true dev: false - /cssom/0.3.8: + /cssom@0.3.8: resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} dev: false - /cssom/0.5.0: + /cssom@0.5.0: resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} dev: false - /cssstyle/2.3.0: + /cssstyle@2.3.0: resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} engines: {node: '>=8'} dependencies: cssom: 0.3.8 dev: false - /csstype/3.1.2: + /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} dev: false - /damerau-levenshtein/1.0.8: + /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: false - /data-urls/3.0.2: + /data-urls@3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} dependencies: @@ -1120,14 +1151,14 @@ packages: whatwg-url: 11.0.0 dev: false - /date-fns/2.30.0: + /date-fns@2.30.0: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} dependencies: '@babel/runtime': 7.22.15 dev: false - /debug/3.2.7: + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: supports-color: '*' @@ -1138,7 +1169,7 @@ packages: ms: 2.1.3 dev: false - /debug/4.3.4: + /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -1150,15 +1181,15 @@ packages: ms: 2.1.2 dev: false - /decimal.js/10.4.3: + /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} dev: false - /deep-is/0.1.4: + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: false - /define-data-property/1.1.0: + /define-data-property@1.1.0: resolution: {integrity: sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==} engines: {node: '>= 0.4'} dependencies: @@ -1167,7 +1198,7 @@ packages: has-property-descriptors: 1.0.0 dev: false - /define-properties/1.2.1: + /define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} dependencies: @@ -1176,65 +1207,65 @@ packages: object-keys: 1.1.1 dev: false - /delayed-stream/1.0.0: + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} dev: false - /dequal/2.0.3: + /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} dev: false - /didyoumean/1.2.2: + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: false - /dir-glob/3.0.1: + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} dependencies: path-type: 4.0.0 dev: false - /dlv/1.1.3: + /dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} dev: false - /doctrine/2.1.0: + /doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} dependencies: esutils: 2.0.3 dev: false - /doctrine/3.0.0: + /doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} dependencies: esutils: 2.0.3 dev: false - /domexception/4.0.0: + /domexception@4.0.0: resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} engines: {node: '>=12'} dependencies: webidl-conversions: 7.0.0 dev: false - /duplexer/0.1.2: + /duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} dev: false - /electron-to-chromium/1.4.525: + /electron-to-chromium@1.4.525: resolution: {integrity: sha512-GIZ620hDK4YmIqAWkscG4W6RwY6gOx1y5J6f4JUQwctiJrqH2oxZYU4mXHi35oV32tr630UcepBzSBGJ/WYcZA==} dev: false - /emoji-regex/9.2.2: + /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} dev: false - /enhanced-resolve/5.15.0: + /enhanced-resolve@5.15.0: resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} engines: {node: '>=10.13.0'} dependencies: @@ -1242,12 +1273,12 @@ packages: tapable: 2.2.1 dev: false - /entities/4.5.0: + /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} dev: false - /es-abstract/1.22.2: + /es-abstract@1.22.2: resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==} engines: {node: '>= 0.4'} dependencies: @@ -1292,7 +1323,7 @@ packages: which-typed-array: 1.1.11 dev: false - /es-iterator-helpers/1.0.15: + /es-iterator-helpers@1.0.15: resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} dependencies: asynciterator.prototype: 1.0.0 @@ -1311,7 +1342,7 @@ packages: safe-array-concat: 1.0.1 dev: false - /es-set-tostringtag/2.0.1: + /es-set-tostringtag@2.0.1: resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} engines: {node: '>= 0.4'} dependencies: @@ -1320,13 +1351,13 @@ packages: has-tostringtag: 1.0.0 dev: false - /es-shim-unscopables/1.0.0: + /es-shim-unscopables@1.0.0: resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} dependencies: has: 1.0.3 dev: false - /es-to-primitive/1.2.1: + /es-to-primitive@1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} dependencies: @@ -1335,27 +1366,27 @@ packages: is-symbol: 1.0.4 dev: false - /escalade/3.1.1: + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} dev: false - /escape-string-regexp/1.0.5: + /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} dev: false - /escape-string-regexp/2.0.0: + /escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} dev: false - /escape-string-regexp/4.0.0: + /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} dev: false - /escodegen/2.1.0: + /escodegen@2.1.0: resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} engines: {node: '>=6.0'} hasBin: true @@ -1367,7 +1398,7 @@ packages: source-map: 0.6.1 dev: false - /eslint-config-next/13.5.3_jk7qbkaijtltyu4ajmze3dfiwa: + /eslint-config-next@13.5.3(eslint@8.50.0)(typescript@5.2.2): resolution: {integrity: sha512-VN2qbCpq2DMWgs7SVF8KTmc8bVaWz3s4nmcFqRLs7PNBt5AXejOhJuZ4zg2sCEHOvz5RvqdwLeI++NSCV6qHVg==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 @@ -1378,21 +1409,21 @@ packages: dependencies: '@next/eslint-plugin-next': 13.5.3 '@rushstack/eslint-patch': 1.4.0 - '@typescript-eslint/parser': 6.7.3_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) eslint: 8.50.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.0_o23aiopppmru2xcybrthvzqwfe - eslint-plugin-import: 2.28.1_4kx52kflemb4r2ccu6rqt44tqq - eslint-plugin-jsx-a11y: 6.7.1_eslint@8.50.0 - eslint-plugin-react: 7.33.2_eslint@8.50.0 - eslint-plugin-react-hooks: 4.6.0_eslint@8.50.0 + eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) + eslint-plugin-jsx-a11y: 6.7.1(eslint@8.50.0) + eslint-plugin-react: 7.33.2(eslint@8.50.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.50.0) typescript: 5.2.2 transitivePeerDependencies: - eslint-import-resolver-webpack - supports-color dev: false - /eslint-import-resolver-node/0.3.9: + /eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} dependencies: debug: 3.2.7 @@ -1402,7 +1433,7 @@ packages: - supports-color dev: false - /eslint-import-resolver-typescript/3.6.0_o23aiopppmru2xcybrthvzqwfe: + /eslint-import-resolver-typescript@3.6.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0): resolution: {integrity: sha512-QTHR9ddNnn35RTxlaEnx2gCxqFlF2SEN0SE2d17SqwyM7YOSI2GHWRYp5BiRkObTUNYPupC/3Fq2a0PpT+EKpg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -1412,8 +1443,8 @@ packages: debug: 4.3.4 enhanced-resolve: 5.15.0 eslint: 8.50.0 - eslint-module-utils: 2.8.0_2beh4qsezyz5o53vpzb3kmlbdu - eslint-plugin-import: 2.28.1_4kx52kflemb4r2ccu6rqt44tqq + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) fast-glob: 3.3.1 get-tsconfig: 4.7.0 is-core-module: 2.13.0 @@ -1425,7 +1456,7 @@ packages: - supports-color dev: false - /eslint-module-utils/2.8.0_2beh4qsezyz5o53vpzb3kmlbdu: + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -1446,16 +1477,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.7.3_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) debug: 3.2.7 eslint: 8.50.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.0_o23aiopppmru2xcybrthvzqwfe + eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0) transitivePeerDependencies: - supports-color dev: false - /eslint-plugin-import/2.28.1_4kx52kflemb4r2ccu6rqt44tqq: + /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0): resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} engines: {node: '>=4'} peerDependencies: @@ -1465,7 +1496,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.7.3_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -1474,7 +1505,7 @@ packages: doctrine: 2.1.0 eslint: 8.50.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0_2beh4qsezyz5o53vpzb3kmlbdu + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -1490,7 +1521,7 @@ packages: - supports-color dev: false - /eslint-plugin-jsx-a11y/6.7.1_eslint@8.50.0: + /eslint-plugin-jsx-a11y@6.7.1(eslint@8.50.0): resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} engines: {node: '>=4.0'} peerDependencies: @@ -1515,7 +1546,7 @@ packages: semver: 6.3.1 dev: false - /eslint-plugin-react-hooks/4.6.0_eslint@8.50.0: + /eslint-plugin-react-hooks@4.6.0(eslint@8.50.0): resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} engines: {node: '>=10'} peerDependencies: @@ -1524,7 +1555,7 @@ packages: eslint: 8.50.0 dev: false - /eslint-plugin-react/7.33.2_eslint@8.50.0: + /eslint-plugin-react@7.33.2(eslint@8.50.0): resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} engines: {node: '>=4'} peerDependencies: @@ -1549,7 +1580,7 @@ packages: string.prototype.matchall: 4.0.10 dev: false - /eslint-scope/7.2.2: + /eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: @@ -1557,17 +1588,17 @@ packages: estraverse: 5.3.0 dev: false - /eslint-visitor-keys/3.4.3: + /eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false - /eslint/8.50.0: + /eslint@8.50.0: resolution: {integrity: sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0_eslint@8.50.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) '@eslint-community/regexpp': 4.8.1 '@eslint/eslintrc': 2.1.2 '@eslint/js': 8.50.0 @@ -1608,50 +1639,50 @@ packages: - supports-color dev: false - /espree/9.6.1: + /espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: acorn: 8.10.0 - acorn-jsx: 5.3.2_acorn@8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) eslint-visitor-keys: 3.4.3 dev: false - /esprima/4.0.1: + /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true dev: false - /esquery/1.5.0: + /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} dependencies: estraverse: 5.3.0 dev: false - /esrecurse/4.3.0: + /esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} dependencies: estraverse: 5.3.0 dev: false - /estraverse/5.3.0: + /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} dev: false - /esutils/2.0.3: + /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} dev: false - /fast-deep-equal/3.1.3: + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: false - /fast-glob/3.3.1: + /fast-glob@3.3.1: resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} engines: {node: '>=8.6.0'} dependencies: @@ -1662,35 +1693,35 @@ packages: micromatch: 4.0.5 dev: false - /fast-json-stable-stringify/2.1.0: + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: false - /fast-levenshtein/2.0.6: + /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: false - /fastq/1.15.0: + /fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} dependencies: reusify: 1.0.4 dev: false - /file-entry-cache/6.0.1: + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: flat-cache: 3.1.0 dev: false - /fill-range/7.0.1: + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 dev: false - /find-up/5.0.0: + /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} dependencies: @@ -1698,7 +1729,7 @@ packages: path-exists: 4.0.0 dev: false - /flat-cache/3.1.0: + /flat-cache@3.1.0: resolution: {integrity: sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==} engines: {node: '>=12.0.0'} dependencies: @@ -1707,17 +1738,17 @@ packages: rimraf: 3.0.2 dev: false - /flatted/3.2.9: + /flatted@3.2.9: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: false - /for-each/0.3.3: + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: is-callable: 1.2.7 dev: false - /form-data/4.0.0: + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} dependencies: @@ -1726,11 +1757,11 @@ packages: mime-types: 2.1.35 dev: false - /fraction.js/4.3.6: + /fraction.js@4.3.6: resolution: {integrity: sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==} dev: false - /framer-motion/10.16.4_biqbaboplfbrettd7655fr4n2y: + /framer-motion@10.16.4(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-p9V9nGomS3m6/CALXqv6nFGMuFOxbWsmaOrdmhyQimMIlLl3LC7h7l86wge/Js/8cRu5ktutS/zlzgR7eBOtFA==} peerDependencies: react: ^18.0.0 @@ -1742,17 +1773,17 @@ packages: optional: true dependencies: react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) tslib: 2.6.2 optionalDependencies: '@emotion/is-prop-valid': 0.8.8 dev: false - /fs.realpath/1.0.0: + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: false - /fsevents/2.3.3: + /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] @@ -1760,11 +1791,11 @@ packages: dev: false optional: true - /function-bind/1.1.1: + /function-bind@1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: false - /function.prototype.name/1.1.6: + /function.prototype.name@1.1.6: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} engines: {node: '>= 0.4'} dependencies: @@ -1774,11 +1805,11 @@ packages: functions-have-names: 1.2.3 dev: false - /functions-have-names/1.2.3: + /functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: false - /get-intrinsic/1.2.1: + /get-intrinsic@1.2.1: resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} dependencies: function-bind: 1.1.1 @@ -1787,7 +1818,7 @@ packages: has-symbols: 1.0.3 dev: false - /get-symbol-description/1.0.0: + /get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} dependencies: @@ -1795,31 +1826,31 @@ packages: get-intrinsic: 1.2.1 dev: false - /get-tsconfig/4.7.0: + /get-tsconfig@4.7.0: resolution: {integrity: sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==} dependencies: resolve-pkg-maps: 1.0.0 dev: false - /glob-parent/5.1.2: + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 dev: false - /glob-parent/6.0.2: + /glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} dependencies: is-glob: 4.0.3 dev: false - /glob-to-regexp/0.4.1: + /glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} dev: false - /glob/7.1.6: + /glob@7.1.6: resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} dependencies: fs.realpath: 1.0.0 @@ -1830,7 +1861,7 @@ packages: path-is-absolute: 1.0.1 dev: false - /glob/7.1.7: + /glob@7.1.7: resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} dependencies: fs.realpath: 1.0.0 @@ -1841,7 +1872,7 @@ packages: path-is-absolute: 1.0.1 dev: false - /glob/7.2.3: + /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: fs.realpath: 1.0.0 @@ -1852,21 +1883,21 @@ packages: path-is-absolute: 1.0.1 dev: false - /globals/13.21.0: + /globals@13.21.0: resolution: {integrity: sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 dev: false - /globalthis/1.0.3: + /globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} dependencies: define-properties: 1.2.1 dev: false - /globby/11.1.0: + /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} dependencies: @@ -1878,79 +1909,79 @@ packages: slash: 3.0.0 dev: false - /gopd/1.0.1: + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.1 dev: false - /graceful-fs/4.2.11: + /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} dev: false - /graphemer/1.4.0: + /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: false - /gzip-size/6.0.0: + /gzip-size@6.0.0: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} dependencies: duplexer: 0.1.2 dev: false - /has-bigints/1.0.2: + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: false - /has-flag/3.0.0: + /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} dev: false - /has-flag/4.0.0: + /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} dev: false - /has-property-descriptors/1.0.0: + /has-property-descriptors@1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: get-intrinsic: 1.2.1 dev: false - /has-proto/1.0.1: + /has-proto@1.0.1: resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} engines: {node: '>= 0.4'} dev: false - /has-symbols/1.0.3: + /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} dev: false - /has-tostringtag/1.0.0: + /has-tostringtag@1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.3 dev: false - /has/1.0.3: + /has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 dev: false - /html-encoding-sniffer/3.0.0: + /html-encoding-sniffer@3.0.0: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} dependencies: whatwg-encoding: 2.0.0 dev: false - /http-proxy-agent/5.0.0: + /http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} engines: {node: '>= 6'} dependencies: @@ -1961,7 +1992,7 @@ packages: - supports-color dev: false - /https-proxy-agent/5.0.1: + /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} dependencies: @@ -1971,19 +2002,19 @@ packages: - supports-color dev: false - /iconv-lite/0.6.3: + /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 dev: false - /ignore/5.2.4: + /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} dev: false - /import-fresh/3.3.0: + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} dependencies: @@ -1991,23 +2022,23 @@ packages: resolve-from: 4.0.0 dev: false - /imurmurhash/0.1.4: + /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} dev: false - /inflight/1.0.6: + /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: once: 1.4.0 wrappy: 1.0.2 dev: false - /inherits/2.0.4: + /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: false - /internal-slot/1.0.5: + /internal-slot@1.0.5: resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} engines: {node: '>= 0.4'} dependencies: @@ -2016,7 +2047,7 @@ packages: side-channel: 1.0.4 dev: false - /is-array-buffer/3.0.2: + /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: call-bind: 1.0.2 @@ -2024,27 +2055,27 @@ packages: is-typed-array: 1.1.12 dev: false - /is-async-function/2.0.0: + /is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 dev: false - /is-bigint/1.0.4: + /is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: has-bigints: 1.0.2 dev: false - /is-binary-path/2.1.0: + /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} dependencies: binary-extensions: 2.2.0 dev: false - /is-boolean-object/1.1.2: + /is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} dependencies: @@ -2052,80 +2083,80 @@ packages: has-tostringtag: 1.0.0 dev: false - /is-callable/1.2.7: + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} dev: false - /is-core-module/2.13.0: + /is-core-module@2.13.0: resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} dependencies: has: 1.0.3 dev: false - /is-date-object/1.0.5: + /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 dev: false - /is-extglob/2.1.1: + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} dev: false - /is-finalizationregistry/1.0.2: + /is-finalizationregistry@1.0.2: resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} dependencies: call-bind: 1.0.2 dev: false - /is-generator-function/1.0.10: + /is-generator-function@1.0.10: resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 dev: false - /is-glob/4.0.3: + /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 dev: false - /is-map/2.0.2: + /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} dev: false - /is-negative-zero/2.0.2: + /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} dev: false - /is-number-object/1.0.7: + /is-number-object@1.0.7: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 dev: false - /is-number/7.0.0: + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} dev: false - /is-path-inside/3.0.3: + /is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} dev: false - /is-potential-custom-element-name/1.0.1: + /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: false - /is-regex/1.1.4: + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} dependencies: @@ -2133,63 +2164,63 @@ packages: has-tostringtag: 1.0.0 dev: false - /is-set/2.0.2: + /is-set@2.0.2: resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} dev: false - /is-shared-array-buffer/1.0.2: + /is-shared-array-buffer@1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: call-bind: 1.0.2 dev: false - /is-string/1.0.7: + /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 dev: false - /is-symbol/1.0.4: + /is-symbol@1.0.4: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.3 dev: false - /is-typed-array/1.1.12: + /is-typed-array@1.1.12: resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} engines: {node: '>= 0.4'} dependencies: which-typed-array: 1.1.11 dev: false - /is-weakmap/2.0.1: + /is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} dev: false - /is-weakref/1.0.2: + /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.2 dev: false - /is-weakset/2.0.2: + /is-weakset@2.0.2: resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.1 dev: false - /isarray/2.0.5: + /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} dev: false - /isexe/2.0.0: + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: false - /iterator.prototype/1.1.2: + /iterator.prototype@1.1.2: resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} dependencies: define-properties: 1.2.1 @@ -2199,7 +2230,7 @@ packages: set-function-name: 2.0.1 dev: false - /jest-environment-jsdom/29.7.0: + /jest-environment-jsdom@29.7.0: resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -2212,7 +2243,7 @@ packages: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.7.0 + '@types/node': 20.7.1 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -2222,7 +2253,7 @@ packages: - utf-8-validate dev: false - /jest-message-util/29.7.0: + /jest-message-util@29.7.0: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: @@ -2237,48 +2268,48 @@ packages: stack-utils: 2.0.6 dev: false - /jest-mock/29.7.0: + /jest-mock@29.7.0: resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.0 + '@types/node': 20.7.1 jest-util: 29.7.0 dev: false - /jest-util/29.7.0: + /jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.0 + '@types/node': 20.7.1 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 picomatch: 2.3.1 dev: false - /jiti/1.20.0: + /jiti@1.20.0: resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==} hasBin: true dev: false - /jose/4.14.6: + /jose@4.14.6: resolution: {integrity: sha512-EqJPEUlZD0/CSUMubKtMaYUOtWe91tZXTWMJZoKSbLk+KtdhNdcvppH8lA9XwVu2V4Ailvsj0GBZJ2ZwDjfesQ==} dev: false - /js-tokens/4.0.0: + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: false - /js-yaml/4.1.0: + /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true dependencies: argparse: 2.0.1 dev: false - /jsdom/20.0.3: + /jsdom@20.0.3: resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} engines: {node: '>=14'} peerDependencies: @@ -2311,7 +2342,7 @@ packages: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - ws: 8.14.2 + ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@6.0.3) xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -2319,26 +2350,26 @@ packages: - utf-8-validate dev: false - /json-buffer/3.0.1: + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: false - /json-schema-traverse/0.4.1: + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: false - /json-stable-stringify-without-jsonify/1.0.1: + /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: false - /json5/1.0.2: + /json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true dependencies: minimist: 1.2.8 dev: false - /jsx-ast-utils/3.3.5: + /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} dependencies: @@ -2348,23 +2379,23 @@ packages: object.values: 1.1.7 dev: false - /keyv/4.5.3: + /keyv@4.5.3: resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==} dependencies: json-buffer: 3.0.1 dev: false - /language-subtag-registry/0.3.22: + /language-subtag-registry@0.3.22: resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} dev: false - /language-tags/1.0.5: + /language-tags@1.0.5: resolution: {integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==} dependencies: language-subtag-registry: 0.3.22 dev: false - /levn/0.4.1: + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} dependencies: @@ -2372,55 +2403,55 @@ packages: type-check: 0.4.0 dev: false - /lilconfig/2.1.0: + /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} dev: false - /lines-and-columns/1.2.4: + /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: false - /locate-path/6.0.0: + /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} dependencies: p-locate: 5.0.0 dev: false - /lodash.merge/4.6.2: + /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: false - /lodash/4.17.21: + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: false - /loose-envify/1.4.0: + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true dependencies: js-tokens: 4.0.0 dev: false - /lru-cache/6.0.0: + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} dependencies: yallist: 4.0.0 dev: false - /map-obj/5.0.0: + /map-obj@5.0.0: resolution: {integrity: sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false - /merge2/1.4.1: + /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} dev: false - /micromatch/4.0.5: + /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} dependencies: @@ -2428,47 +2459,47 @@ packages: picomatch: 2.3.1 dev: false - /mime-db/1.52.0: + /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} dev: false - /mime-types/2.1.35: + /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 dev: false - /mini-svg-data-uri/1.4.4: + /mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true dev: false - /minimatch/3.1.2: + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 dev: false - /minimist/1.2.8: + /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: false - /mrmime/1.0.1: + /mrmime@1.0.1: resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} engines: {node: '>=10'} dev: false - /ms/2.1.2: + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: false - /ms/2.1.3: + /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: false - /mz/2.7.0: + /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} dependencies: any-promise: 1.3.0 @@ -2476,23 +2507,23 @@ packages: thenify-all: 1.6.0 dev: false - /nanoid/3.3.6: + /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true dev: false - /nanoid/5.0.1: + /nanoid@5.0.1: resolution: {integrity: sha512-vWeVtV5Cw68aML/QaZvqN/3QQXc6fBfIieAlu05m7FZW2Dgb+3f0xc0TTxuJW+7u30t7iSDTV/j3kVI0oJqIfQ==} engines: {node: ^18 || >=20} hasBin: true dev: false - /natural-compare/1.4.0: + /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: false - /next-auth/0.0.0-manual.5749b095_next@13.5.3+react@18.2.0: + /next-auth@0.0.0-manual.5749b095(next@13.5.3)(react@18.2.0): resolution: {integrity: sha512-ah7lwQtGKLVxXEbadGp7Nt+qnYTHLHzEA7/btMf2M+SK3UosUsqZXZpt8/6HT9O+SN67kEXoZk8TW42bTiJRUA==} peerDependencies: next: ^13.4.13 @@ -2503,23 +2534,23 @@ packages: optional: true dependencies: '@auth/core': 0.0.0-manual.e9863699 - next: 13.5.3_biqbaboplfbrettd7655fr4n2y + next: 13.5.3(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false - /next-themes/0.2.1_vs65xldtmolprftbsqonkgfxyi: + /next-themes@0.2.1(next@13.5.3)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} peerDependencies: next: '*' react: '*' react-dom: '*' dependencies: - next: 13.5.3_biqbaboplfbrettd7655fr4n2y + next: 13.5.3(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) dev: false - /next/13.5.3_biqbaboplfbrettd7655fr4n2y: + /next@13.5.3(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-4Nt4HRLYDW/yRpJ/QR2t1v63UOMS55A38dnWv3UDOWGezuY0ZyFO1ABNbD7mulVzs9qVhgy2+ppjdsANpKP1mg==} engines: {node: '>=16.14.0'} hasBin: true @@ -2540,8 +2571,8 @@ packages: caniuse-lite: 1.0.30001538 postcss: 8.4.14 react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - styled-jsx: 5.1.1_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) + styled-jsx: 5.1.1(react@18.2.0) watchpack: 2.4.0 zod: 3.21.4 optionalDependencies: @@ -2559,53 +2590,53 @@ packages: - babel-plugin-macros dev: false - /node-gyp-build/4.6.1: + /node-gyp-build@4.6.1: resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==} hasBin: true dev: false - /node-releases/2.0.13: + /node-releases@2.0.13: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: false - /normalize-path/3.0.0: + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} dev: false - /normalize-range/0.1.2: + /normalize-range@0.1.2: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} dev: false - /nwsapi/2.2.7: + /nwsapi@2.2.7: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: false - /oauth4webapi/2.3.0: + /oauth4webapi@2.3.0: resolution: {integrity: sha512-JGkb5doGrwzVDuHwgrR4nHJayzN4h59VCed6EW8Tql6iHDfZIabCJvg6wtbn5q6pyB2hZruI3b77Nudvq7NmvA==} dev: false - /object-assign/4.1.1: + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} dev: false - /object-hash/3.0.0: + /object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} dev: false - /object-inspect/1.12.3: + /object-inspect@1.12.3: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} dev: false - /object-keys/1.1.1: + /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} dev: false - /object.assign/4.1.4: + /object.assign@4.1.4: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} engines: {node: '>= 0.4'} dependencies: @@ -2615,7 +2646,7 @@ packages: object-keys: 1.1.1 dev: false - /object.entries/1.1.7: + /object.entries@1.1.7: resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} engines: {node: '>= 0.4'} dependencies: @@ -2624,7 +2655,7 @@ packages: es-abstract: 1.22.2 dev: false - /object.fromentries/2.0.7: + /object.fromentries@2.0.7: resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} engines: {node: '>= 0.4'} dependencies: @@ -2633,7 +2664,7 @@ packages: es-abstract: 1.22.2 dev: false - /object.groupby/1.0.1: + /object.groupby@1.0.1: resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} dependencies: call-bind: 1.0.2 @@ -2642,14 +2673,14 @@ packages: get-intrinsic: 1.2.1 dev: false - /object.hasown/1.1.3: + /object.hasown@1.1.3: resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==} dependencies: define-properties: 1.2.1 es-abstract: 1.22.2 dev: false - /object.values/1.1.7: + /object.values@1.1.7: resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} engines: {node: '>= 0.4'} dependencies: @@ -2658,18 +2689,18 @@ packages: es-abstract: 1.22.2 dev: false - /once/1.4.0: + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 dev: false - /opener/1.5.2: + /opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true dev: false - /optionator/0.9.3: + /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} dependencies: @@ -2681,67 +2712,67 @@ packages: type-check: 0.4.0 dev: false - /p-limit/3.1.0: + /p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} dependencies: yocto-queue: 0.1.0 dev: false - /p-locate/5.0.0: + /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} dependencies: p-limit: 3.1.0 dev: false - /parent-module/1.0.1: + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} dependencies: callsites: 3.1.0 dev: false - /parse5/7.1.2: + /parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} dependencies: entities: 4.5.0 dev: false - /path-exists/4.0.0: + /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} dev: false - /path-is-absolute/1.0.1: + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} dev: false - /path-key/3.1.1: + /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} dev: false - /path-parse/1.0.7: + /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: false - /path-type/4.0.0: + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} dev: false - /pg-int8/1.0.1: + /pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} engines: {node: '>=4.0.0'} dev: false - /pg-protocol/1.6.0: + /pg-protocol@1.6.0: resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==} dev: false - /pg-types/2.2.0: + /pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} dependencies: @@ -2752,26 +2783,26 @@ packages: postgres-interval: 1.2.0 dev: false - /picocolors/1.0.0: + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: false - /picomatch/2.3.1: + /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} dev: false - /pify/2.3.0: + /pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} dev: false - /pirates/4.0.6: + /pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} dev: false - /postcss-import/15.1.0_postcss@8.4.30: + /postcss-import@15.1.0(postcss@8.4.30): resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} peerDependencies: @@ -2783,7 +2814,7 @@ packages: resolve: 1.22.6 dev: false - /postcss-js/4.0.1_postcss@8.4.30: + /postcss-js@4.0.1(postcss@8.4.30): resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: @@ -2793,7 +2824,7 @@ packages: postcss: 8.4.30 dev: false - /postcss-load-config/4.0.1_postcss@8.4.30: + /postcss-load-config@4.0.1(postcss@8.4.30): resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} engines: {node: '>= 14'} peerDependencies: @@ -2810,7 +2841,7 @@ packages: yaml: 2.3.2 dev: false - /postcss-nested/6.0.1_postcss@8.4.30: + /postcss-nested@6.0.1(postcss@8.4.30): resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} engines: {node: '>=12.0'} peerDependencies: @@ -2820,7 +2851,7 @@ packages: postcss-selector-parser: 6.0.13 dev: false - /postcss-selector-parser/6.0.13: + /postcss-selector-parser@6.0.13: resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} engines: {node: '>=4'} dependencies: @@ -2828,11 +2859,11 @@ packages: util-deprecate: 1.0.2 dev: false - /postcss-value-parser/4.2.0: + /postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} dev: false - /postcss/8.4.14: + /postcss@8.4.14: resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} engines: {node: ^10 || ^12 || >=14} dependencies: @@ -2841,7 +2872,7 @@ packages: source-map-js: 1.0.2 dev: false - /postcss/8.4.30: + /postcss@8.4.30: resolution: {integrity: sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==} engines: {node: ^10 || ^12 || >=14} dependencies: @@ -2850,29 +2881,29 @@ packages: source-map-js: 1.0.2 dev: false - /postgres-array/2.0.0: + /postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} dev: false - /postgres-bytea/1.0.0: + /postgres-bytea@1.0.0: resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} engines: {node: '>=0.10.0'} dev: false - /postgres-date/1.0.7: + /postgres-date@1.0.7: resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} engines: {node: '>=0.10.0'} dev: false - /postgres-interval/1.2.0: + /postgres-interval@1.2.0: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} dependencies: xtend: 4.0.2 dev: false - /preact-render-to-string/5.2.3_preact@10.11.3: + /preact-render-to-string@5.2.3(preact@10.11.3): resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} peerDependencies: preact: '>=10' @@ -2881,16 +2912,16 @@ packages: pretty-format: 3.8.0 dev: false - /preact/10.11.3: + /preact@10.11.3: resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} dev: false - /prelude-ls/1.2.1: + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} dev: false - /pretty-format/29.7.0: + /pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: @@ -2899,11 +2930,11 @@ packages: react-is: 18.2.0 dev: false - /pretty-format/3.8.0: + /pretty-format@3.8.0: resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} dev: false - /prop-types/15.8.1: + /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: loose-envify: 1.4.0 @@ -2911,29 +2942,29 @@ packages: react-is: 16.13.1 dev: false - /psl/1.9.0: + /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: false - /punycode/2.3.0: + /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} dev: false - /querystringify/2.2.0: + /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} dev: false - /queue-microtask/1.2.3: + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: false - /quick-lru/6.1.2: + /quick-lru@6.1.2: resolution: {integrity: sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==} engines: {node: '>=12'} dev: false - /react-dom/18.2.0_react@18.2.0: + /react-dom@18.2.0(react@18.2.0): resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: react: ^18.2.0 @@ -2943,7 +2974,7 @@ packages: scheduler: 0.23.0 dev: false - /react-icons/4.11.0_react@18.2.0: + /react-icons@4.11.0(react@18.2.0): resolution: {integrity: sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA==} peerDependencies: react: '*' @@ -2951,35 +2982,35 @@ packages: react: 18.2.0 dev: false - /react-is/16.13.1: + /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} dev: false - /react-is/18.2.0: + /react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: false - /react/18.2.0: + /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} dependencies: loose-envify: 1.4.0 dev: false - /read-cache/1.0.0: + /read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} dependencies: pify: 2.3.0 dev: false - /readdirp/3.6.0: + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 dev: false - /reflect.getprototypeof/1.0.4: + /reflect.getprototypeof@1.0.4: resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} engines: {node: '>= 0.4'} dependencies: @@ -2991,11 +3022,11 @@ packages: which-builtin-type: 1.1.3 dev: false - /regenerator-runtime/0.14.0: + /regenerator-runtime@0.14.0: resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} dev: false - /regexp.prototype.flags/1.5.1: + /regexp.prototype.flags@1.5.1: resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} engines: {node: '>= 0.4'} dependencies: @@ -3004,20 +3035,20 @@ packages: set-function-name: 2.0.1 dev: false - /requires-port/1.0.0: + /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: false - /resolve-from/4.0.0: + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} dev: false - /resolve-pkg-maps/1.0.0: + /resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} dev: false - /resolve/1.22.6: + /resolve@1.22.6: resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==} hasBin: true dependencies: @@ -3026,7 +3057,7 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: false - /resolve/2.0.0-next.4: + /resolve@2.0.0-next.4: resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} hasBin: true dependencies: @@ -3035,25 +3066,25 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: false - /reusify/1.0.4: + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} dev: false - /rimraf/3.0.2: + /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: glob: 7.2.3 dev: false - /run-parallel/1.2.0: + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 dev: false - /safe-array-concat/1.0.1: + /safe-array-concat@1.0.1: resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} engines: {node: '>=0.4'} dependencies: @@ -3063,7 +3094,7 @@ packages: isarray: 2.0.5 dev: false - /safe-regex-test/1.0.0: + /safe-regex-test@1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} dependencies: call-bind: 1.0.2 @@ -3071,33 +3102,33 @@ packages: is-regex: 1.1.4 dev: false - /safer-buffer/2.1.2: + /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: false - /sax/1.2.4: + /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} dev: false - /saxes/6.0.0: + /saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} dependencies: xmlchars: 2.2.0 dev: false - /scheduler/0.23.0: + /scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: loose-envify: 1.4.0 dev: false - /semver/6.3.1: + /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true dev: false - /semver/7.5.4: + /semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} hasBin: true @@ -3105,7 +3136,7 @@ packages: lru-cache: 6.0.0 dev: false - /set-function-name/2.0.1: + /set-function-name@2.0.1: resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} engines: {node: '>= 0.4'} dependencies: @@ -3114,19 +3145,19 @@ packages: has-property-descriptors: 1.0.0 dev: false - /shebang-command/2.0.0: + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 dev: false - /shebang-regex/3.0.0: + /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} dev: false - /side-channel/1.0.4: + /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 @@ -3134,7 +3165,7 @@ packages: object-inspect: 1.12.3 dev: false - /sirv/1.0.19: + /sirv@1.0.19: resolution: {integrity: sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==} engines: {node: '>= 10'} dependencies: @@ -3143,46 +3174,46 @@ packages: totalist: 1.1.0 dev: false - /slash/3.0.0: + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} dev: false - /sonner/1.0.3_biqbaboplfbrettd7655fr4n2y: + /sonner@1.0.3(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-hBoA2zKuYW3lUnpx4K0vAn8j77YuYiwvP9sLQfieNS2pd5FkT20sMyPTDJnl9S+5T27ZJbwQRPiujwvDBwhZQg==} peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 dependencies: react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) dev: false - /source-map-js/1.0.2: + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} dev: false - /source-map/0.6.1: + /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} requiresBuild: true dev: false optional: true - /stack-utils/2.0.6: + /stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} dependencies: escape-string-regexp: 2.0.0 dev: false - /streamsearch/1.1.0: + /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} dev: false - /string.prototype.matchall/4.0.10: + /string.prototype.matchall@4.0.10: resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} dependencies: call-bind: 1.0.2 @@ -3196,7 +3227,7 @@ packages: side-channel: 1.0.4 dev: false - /string.prototype.trim/1.2.8: + /string.prototype.trim@1.2.8: resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} engines: {node: '>= 0.4'} dependencies: @@ -3205,7 +3236,7 @@ packages: es-abstract: 1.22.2 dev: false - /string.prototype.trimend/1.0.7: + /string.prototype.trimend@1.0.7: resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} dependencies: call-bind: 1.0.2 @@ -3213,7 +3244,7 @@ packages: es-abstract: 1.22.2 dev: false - /string.prototype.trimstart/1.0.7: + /string.prototype.trimstart@1.0.7: resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} dependencies: call-bind: 1.0.2 @@ -3221,24 +3252,24 @@ packages: es-abstract: 1.22.2 dev: false - /strip-ansi/6.0.1: + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 dev: false - /strip-bom/3.0.0: + /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} dev: false - /strip-json-comments/3.1.1: + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} dev: false - /styled-jsx/5.1.1_react@18.2.0: + /styled-jsx@5.1.1(react@18.2.0): resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} engines: {node: '>= 12.0.0'} peerDependencies: @@ -3255,7 +3286,7 @@ packages: react: 18.2.0 dev: false - /sucrase/3.34.0: + /sucrase@3.34.0: resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} engines: {node: '>=8'} hasBin: true @@ -3269,30 +3300,30 @@ packages: ts-interface-checker: 0.1.13 dev: false - /supports-color/5.5.0: + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} dependencies: has-flag: 3.0.0 dev: false - /supports-color/7.2.0: + /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} dependencies: has-flag: 4.0.0 dev: false - /supports-preserve-symlinks-flag/1.0.0: + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} dev: false - /symbol-tree/3.2.4: + /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: false - /tailwindcss/3.3.3: + /tailwindcss@3.3.3: resolution: {integrity: sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==} engines: {node: '>=14.0.0'} hasBin: true @@ -3312,10 +3343,10 @@ packages: object-hash: 3.0.0 picocolors: 1.0.0 postcss: 8.4.30 - postcss-import: 15.1.0_postcss@8.4.30 - postcss-js: 4.0.1_postcss@8.4.30 - postcss-load-config: 4.0.1_postcss@8.4.30 - postcss-nested: 6.0.1_postcss@8.4.30 + postcss-import: 15.1.0(postcss@8.4.30) + postcss-js: 4.0.1(postcss@8.4.30) + postcss-load-config: 4.0.1(postcss@8.4.30) + postcss-nested: 6.0.1(postcss@8.4.30) postcss-selector-parser: 6.0.13 resolve: 1.22.6 sucrase: 3.34.0 @@ -3323,41 +3354,41 @@ packages: - ts-node dev: false - /tapable/2.2.1: + /tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} dev: false - /text-table/0.2.0: + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: false - /thenify-all/1.6.0: + /thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} dependencies: thenify: 3.3.1 dev: false - /thenify/3.3.1: + /thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} dependencies: any-promise: 1.3.0 dev: false - /to-regex-range/5.0.1: + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 dev: false - /totalist/1.1.0: + /totalist@1.1.0: resolution: {integrity: sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==} engines: {node: '>=6'} dev: false - /tough-cookie/4.1.3: + /tough-cookie@4.1.3: resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} engines: {node: '>=6'} dependencies: @@ -3367,14 +3398,14 @@ packages: url-parse: 1.5.10 dev: false - /tr46/3.0.0: + /tr46@3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} dependencies: punycode: 2.3.0 dev: false - /ts-api-utils/1.0.3_typescript@5.2.2: + /ts-api-utils@1.0.3(typescript@5.2.2): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} peerDependencies: @@ -3383,17 +3414,17 @@ packages: typescript: 5.2.2 dev: false - /ts-exif-parser/0.2.2: + /ts-exif-parser@0.2.2: resolution: {integrity: sha512-Z7qGRfvHaISUOErkKfc8Tp+GBnfMWCSyduiLJR0x/b/wKp60oiOvORk73fFML3l8Kf0gVX48mrRsYUcBEb5avQ==} dependencies: sax: 1.2.4 dev: false - /ts-interface-checker/0.1.13: + /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} dev: false - /tsconfig-paths/3.14.2: + /tsconfig-paths@3.14.2: resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} dependencies: '@types/json5': 0.0.29 @@ -3402,33 +3433,33 @@ packages: strip-bom: 3.0.0 dev: false - /tslib/2.6.2: + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: false - /type-check/0.4.0: + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.2.1 dev: false - /type-detect/4.0.8: + /type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} dev: false - /type-fest/0.20.2: + /type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} dev: false - /type-fest/4.3.1: + /type-fest@4.3.1: resolution: {integrity: sha512-pphNW/msgOUSkJbH58x8sqpq8uQj6b0ZKGxEsLKMUnGorRcDjrUaLS+39+/ub41JNTwrrMyJcUB8+YZs3mbwqw==} engines: {node: '>=16'} dev: false - /typed-array-buffer/1.0.0: + /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} engines: {node: '>= 0.4'} dependencies: @@ -3437,7 +3468,7 @@ packages: is-typed-array: 1.1.12 dev: false - /typed-array-byte-length/1.0.0: + /typed-array-byte-length@1.0.0: resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} engines: {node: '>= 0.4'} dependencies: @@ -3447,7 +3478,7 @@ packages: is-typed-array: 1.1.12 dev: false - /typed-array-byte-offset/1.0.0: + /typed-array-byte-offset@1.0.0: resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} engines: {node: '>= 0.4'} dependencies: @@ -3458,7 +3489,7 @@ packages: is-typed-array: 1.1.12 dev: false - /typed-array-length/1.0.4: + /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} dependencies: call-bind: 1.0.2 @@ -3466,13 +3497,13 @@ packages: is-typed-array: 1.1.12 dev: false - /typescript/5.2.2: + /typescript@5.2.2: resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} engines: {node: '>=14.17'} hasBin: true dev: false - /unbox-primitive/1.0.2: + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: call-bind: 1.0.2 @@ -3481,19 +3512,19 @@ packages: which-boxed-primitive: 1.0.2 dev: false - /undici/5.24.0: - resolution: {integrity: sha512-OKlckxBjFl0oXxcj9FU6oB8fDAaiRUq+D8jrFWGmOfI/gIyjk/IeS75LMzgYKUaeHzLUcYvf9bbJGSrUwTfwwQ==} + /undici@5.25.1: + resolution: {integrity: sha512-nTw6b2G2OqP6btYPyghCgV4hSwjJlL/78FMJatVLCa3otj6PCOQSt6dVtYt82OtNqFz8XsnJ+vsXLADPXjPhqw==} engines: {node: '>=14.0'} dependencies: busboy: 1.6.0 dev: false - /universalify/0.2.0: + /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} dev: false - /update-browserslist-db/1.0.11_browserslist@4.21.10: + /update-browserslist-db@1.0.11(browserslist@4.21.10): resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} hasBin: true peerDependencies: @@ -3504,20 +3535,20 @@ packages: picocolors: 1.0.0 dev: false - /uri-js/4.4.1: + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.3.0 dev: false - /url-parse/1.5.10: + /url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} dependencies: querystringify: 2.2.0 requires-port: 1.0.0 dev: false - /utf-8-validate/6.0.3: + /utf-8-validate@6.0.3: resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==} engines: {node: '>=6.14.2'} requiresBuild: true @@ -3525,18 +3556,18 @@ packages: node-gyp-build: 4.6.1 dev: false - /util-deprecate/1.0.2: + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: false - /w3c-xmlserializer/4.0.0: + /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} dependencies: xml-name-validator: 4.0.0 dev: false - /watchpack/2.4.0: + /watchpack@2.4.0: resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} engines: {node: '>=10.13.0'} dependencies: @@ -3544,12 +3575,12 @@ packages: graceful-fs: 4.2.11 dev: false - /webidl-conversions/7.0.0: + /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} dev: false - /webpack-bundle-analyzer/4.7.0: + /webpack-bundle-analyzer@4.7.0: resolution: {integrity: sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg==} engines: {node: '>= 10.13.0'} hasBin: true @@ -3568,19 +3599,19 @@ packages: - utf-8-validate dev: false - /whatwg-encoding/2.0.0: + /whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} dependencies: iconv-lite: 0.6.3 dev: false - /whatwg-mimetype/3.0.0: + /whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} dev: false - /whatwg-url/11.0.0: + /whatwg-url@11.0.0: resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} engines: {node: '>=12'} dependencies: @@ -3588,7 +3619,7 @@ packages: webidl-conversions: 7.0.0 dev: false - /which-boxed-primitive/1.0.2: + /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: is-bigint: 1.0.4 @@ -3598,7 +3629,7 @@ packages: is-symbol: 1.0.4 dev: false - /which-builtin-type/1.1.3: + /which-builtin-type@1.1.3: resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} engines: {node: '>= 0.4'} dependencies: @@ -3616,7 +3647,7 @@ packages: which-typed-array: 1.1.11 dev: false - /which-collection/1.0.1: + /which-collection@1.0.1: resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} dependencies: is-map: 2.0.2 @@ -3625,7 +3656,7 @@ packages: is-weakset: 2.0.2 dev: false - /which-typed-array/1.1.11: + /which-typed-array@1.1.11: resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} engines: {node: '>= 0.4'} dependencies: @@ -3636,7 +3667,7 @@ packages: has-tostringtag: 1.0.0 dev: false - /which/2.0.2: + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true @@ -3644,11 +3675,11 @@ packages: isexe: 2.0.0 dev: false - /wrappy/1.0.2: + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: false - /ws/7.5.9: + /ws@7.5.9: resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} engines: {node: '>=8.3.0'} peerDependencies: @@ -3661,20 +3692,7 @@ packages: optional: true dev: false - /ws/8.14.2: - resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: false - - /ws/8.14.2_2adebc2xdjqbcvbjxkodkhadp4: + /ws@8.14.2(bufferutil@4.0.7)(utf-8-validate@6.0.3): resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} engines: {node: '>=10.0.0'} peerDependencies: @@ -3690,34 +3708,34 @@ packages: utf-8-validate: 6.0.3 dev: false - /xml-name-validator/4.0.0: + /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} dev: false - /xmlchars/2.2.0: + /xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} dev: false - /xtend/4.0.2: + /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} dev: false - /yallist/4.0.0: + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: false - /yaml/2.3.2: + /yaml@2.3.2: resolution: {integrity: sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==} engines: {node: '>= 14'} dev: false - /yocto-queue/0.1.0: + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: false - /zod/3.21.4: + /zod@3.21.4: resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} dev: false From f126f4b0a7a43423e34c557cee5d1043aa3f6dd0 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Thu, 28 Sep 2023 20:12:06 -0500 Subject: [PATCH 02/15] Make blur capture more robust --- src/components/CanvasBlurCapture.tsx | 46 +++++++++++++++++++--------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/components/CanvasBlurCapture.tsx b/src/components/CanvasBlurCapture.tsx index ae85b044..7660234a 100644 --- a/src/components/CanvasBlurCapture.tsx +++ b/src/components/CanvasBlurCapture.tsx @@ -2,6 +2,8 @@ import { useEffect, useRef } from 'react'; +const RETRY_DELAY = 2000; + export default function CanvasBlurCapture({ imageUrl, onCapture, @@ -21,23 +23,20 @@ export default function CanvasBlurCapture({ scale?: number quality?: number }) { - const ref = useRef(null); + const refCanvas = useRef(null); + const refHasCompleted = useRef(false); + const refTimeouts = useRef([]); useEffect(() => { - let timeout: NodeJS.Timeout; - - const image = new Image(); - image.crossOrigin = 'anonymous'; - image.src = imageUrl; - image.onload = () => { - timeout = setTimeout(() => { - const canvas = ref.current; + const capture = () => { + if (!refHasCompleted.current) { + const canvas = refCanvas.current; if (canvas) { canvas.width = width * scale; canvas.height = height * scale; canvas.style.width = `${width}px`; canvas.style.height = `${height}px`; - const context = ref.current?.getContext('2d'); + const context = refCanvas.current?.getContext('2d'); if (context) { context.scale(scale, scale); context.filter = @@ -48,18 +47,35 @@ export default function CanvasBlurCapture({ -edgeCompensation, -edgeCompensation, width + edgeCompensation * 2, - width * image.height / image.width - + edgeCompensation * 2, + width * image.height / image.width + edgeCompensation * 2, ); + refHasCompleted.current = true; onCapture(canvas.toDataURL('image/jpeg', quality)); + } else { + console.error('Cannot get 2d context'); + // Retry capture in case canvas is not available + refTimeouts.current.push(setTimeout(capture, RETRY_DELAY)); } } else { console.error('Cannot generate blur data: canvas not found'); + // Retry capture in case canvas is not available + refTimeouts.current.push(setTimeout(capture, RETRY_DELAY)); } - }, 2000); + } }; - return () => clearTimeout(timeout); + const image = new Image(); + image.crossOrigin = 'anonymous'; + image.src = imageUrl; + image.onload = capture; + + // Attempt delayed capture in case image.onload never fires + refTimeouts.current.push(setTimeout(capture, RETRY_DELAY)); + + // Store timeout ref to ensure it's closed over + // in cleanup function (recommended by exhaustive-deps) + const timeouts = refTimeouts.current; + return () => timeouts.forEach(clearTimeout); }, [ imageUrl, onCapture, @@ -71,6 +87,6 @@ export default function CanvasBlurCapture({ ]); return ( - + ); } From 3d279cdab5789596fffda561b97b5bfd94a8c834 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Fri, 29 Sep 2023 13:40:08 -0500 Subject: [PATCH 03/15] Refactor paths/escape handling, add test coverage --- .vscode/settings.json | 1 + __tests__/path.test.ts | 81 + jest.config.mjs | 19 + package.json | 6 + pnpm-lock.yaml | 1796 ++++++++++++++++- src/app/(auth-state)/admin/photos/page.tsx | 8 +- src/app/(static)/grid/page.tsx | 3 +- src/app/(static)/og/page.tsx | 3 +- src/app/(static)/p/[photoId]/layout.tsx | 8 +- src/app/(static)/p/[photoId]/share/page.tsx | 3 +- src/app/(static)/page.tsx | 3 +- src/app/(static)/t/[tag]/[photoId]/layout.tsx | 8 +- .../(static)/t/[tag]/[photoId]/share/page.tsx | 3 +- src/app/layout.tsx | 2 + src/app/sign-in/page.tsx | 3 +- src/components/Modal.tsx | 6 +- src/components/Nav.tsx | 18 +- src/photo/PhotoEscapeHandler.tsx | 27 + src/photo/PhotoGrid.tsx | 57 +- src/photo/PhotoLinks.tsx | 17 +- src/photo/ViewSwitcher.tsx | 3 +- src/site/paths.ts | 114 +- 22 files changed, 2106 insertions(+), 83 deletions(-) create mode 100644 __tests__/path.test.ts create mode 100644 jest.config.mjs create mode 100644 src/photo/PhotoEscapeHandler.tsx diff --git a/.vscode/settings.json b/.vscode/settings.json index e25b8baa..e45a8d61 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,6 +14,7 @@ "thephotoblog", "trpc", "unnest", + "UsKSGcbt", "WRHGZC", "zadd", "zrange" diff --git a/__tests__/path.test.ts b/__tests__/path.test.ts new file mode 100644 index 00000000..8168e6d1 --- /dev/null +++ b/__tests__/path.test.ts @@ -0,0 +1,81 @@ +import '@testing-library/jest-dom'; +import { + getEscapePath, + getPathComponents, + isPathPhoto, + isPathPhotoShare, + isPathTag, + isPathTagPhoto, + isPathTagPhotoShare, + isPathTagShare, +} from '@/site/paths'; + +const PHOTO_ID = 'UsKSGcbt'; +const TAG = 'tag-name'; +const SHARE = 'share'; + +const PATH_ROOT = '/'; +const PATH_GRID = '/grid'; +const PATH_ADMIN = '/admin/photos'; +const PATH_PHOTO = `/p/${PHOTO_ID}`; +const PATH_PHOTO_SHARE = `${PATH_PHOTO}/${SHARE}`; +const PATH_TAG = `/t/${TAG}`; +const PATH_TAG_SHARE = `${PATH_TAG}/${SHARE}`; +const PATH_TAG_PHOTO = `${PATH_TAG}/${PHOTO_ID}`; +const PATH_TAG_PHOTO_SHARE = `${PATH_TAG}/${PHOTO_ID}/${SHARE}`; + +describe('Paths', () => { + it('can be classified', () => { + // Positive + expect(isPathPhoto(PATH_PHOTO)).toBe(true); + expect(isPathPhotoShare(PATH_PHOTO_SHARE)).toBe(true); + expect(isPathTag(PATH_TAG)).toBe(true); + expect(isPathTagShare(PATH_TAG_SHARE)).toBe(true); + expect(isPathTagPhoto(PATH_TAG_PHOTO)).toBe(true); + expect(isPathTagPhotoShare(PATH_TAG_PHOTO_SHARE)).toBe(true); + // Negative + expect(isPathPhoto(PATH_TAG_PHOTO_SHARE)).toBe(false); + expect(isPathPhotoShare(PATH_TAG_PHOTO)).toBe(false); + expect(isPathTag(PATH_TAG_SHARE)).toBe(false); + expect(isPathTagShare(PATH_TAG)).toBe(false); + expect(isPathTagPhoto(PATH_PHOTO_SHARE)).toBe(false); + expect(isPathTagPhotoShare(PATH_PHOTO)).toBe(false); + }); + it('can be parsed', () => { + expect(getPathComponents(PATH_ROOT)).toEqual({}); + expect(getPathComponents(PATH_PHOTO)).toEqual({ + photoId: PHOTO_ID, + }); + expect(getPathComponents(PATH_PHOTO_SHARE)).toEqual({ + photoId: PHOTO_ID, + }); + expect(getPathComponents(PATH_TAG)).toEqual({ + tag: TAG, + }); + expect(getPathComponents(PATH_TAG_SHARE)).toEqual({ + tag: TAG, + }); + expect(getPathComponents(PATH_TAG_PHOTO)).toEqual({ + photoId: PHOTO_ID, + tag: TAG, + }); + expect(getPathComponents(PATH_TAG_PHOTO_SHARE)).toEqual({ + photoId: PHOTO_ID, + tag: TAG, + }); + }); + it('can be escaped', () => { + // Root views + expect(getEscapePath(PATH_ROOT)).toEqual(undefined); + expect(getEscapePath(PATH_GRID)).toEqual(undefined); + expect(getEscapePath(PATH_ADMIN)).toEqual(undefined); + // Photo views + expect(getEscapePath(PATH_PHOTO)).toEqual(PATH_GRID); + expect(getEscapePath(PATH_PHOTO_SHARE)).toEqual(PATH_PHOTO); + // Tag views + expect(getEscapePath(PATH_TAG)).toEqual(PATH_GRID); + expect(getEscapePath(PATH_TAG_SHARE)).toEqual(PATH_TAG); + expect(getEscapePath(PATH_TAG_PHOTO)).toEqual(PATH_TAG); + expect(getEscapePath(PATH_TAG_PHOTO_SHARE)).toEqual(PATH_TAG_PHOTO); + }); +}); diff --git a/jest.config.mjs b/jest.config.mjs new file mode 100644 index 00000000..b063a90b --- /dev/null +++ b/jest.config.mjs @@ -0,0 +1,19 @@ +/* eslint-disable max-len */ +import nextJest from 'next/jest.js'; + +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: './', +}); + +// Add any custom config to be passed to Jest +/** @type {import('jest').Config} */ +const config = { + // Add more setup options before each test is run + // setupFilesAfterEnv: ['/jest.setup.js'], + + testEnvironment: 'jest-environment-jsdom', +}; + +// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async +export default createJestConfig(config); diff --git a/package.json b/package.json index 2ff8f84c..8375e2ed 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,15 @@ "build": "next build", "start": "next start", "lint": "next lint", + "test": "jest --watch", "analyze": "ANALYZE=true next build" }, "dependencies": { "@next/bundle-analyzer": "^13.5.3", "@tailwindcss/forms": "^0.5.6", + "@testing-library/jest-dom": "^6.1.3", + "@testing-library/react": "^14.0.0", + "@types/jest": "^29.5.5", "@types/node": "^20.7.1", "@types/react": "18.2.23", "@types/react-dom": "18.2.8", @@ -24,6 +28,8 @@ "eslint": "8.50.0", "eslint-config-next": "13.5.3", "framer-motion": "^10.16.4", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", "nanoid": "^5.0.1", "next": "^13.5.3", "next-auth": "0.0.0-manual.5749b095", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47306a5d..51b4c4f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,15 @@ dependencies: '@tailwindcss/forms': specifier: ^0.5.6 version: 0.5.6(tailwindcss@3.3.3) + '@testing-library/jest-dom': + specifier: ^6.1.3 + version: 6.1.3(@types/jest@29.5.5)(jest@29.7.0) + '@testing-library/react': + specifier: ^14.0.0 + version: 14.0.0(react-dom@18.2.0)(react@18.2.0) + '@types/jest': + specifier: ^29.5.5 + version: 29.5.5 '@types/node': specifier: ^20.7.1 version: 20.7.1 @@ -53,12 +62,18 @@ dependencies: framer-motion: specifier: ^10.16.4 version: 10.16.4(react-dom@18.2.0)(react@18.2.0) + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.7.1) + jest-environment-jsdom: + specifier: ^29.7.0 + version: 29.7.0 nanoid: specifier: ^5.0.1 version: 5.0.1 next: specifier: ^13.5.3 - version: 13.5.3(react-dom@18.2.0)(react@18.2.0) + version: 13.5.3(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) next-auth: specifier: 0.0.0-manual.5749b095 version: 0.0.0-manual.5749b095(next@13.5.3)(react@18.2.0) @@ -97,11 +112,23 @@ packages: engines: {node: '>=0.10.0'} dev: false + /@adobe/css-tools@4.3.1: + resolution: {integrity: sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==} + dev: false + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} dev: false + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.19 + dev: false + /@auth/core@0.0.0-manual.e9863699: resolution: {integrity: sha512-/hVzGuFw7nAZimliD8kpuKnNjvkRu+jpaVhYB/FaIXLNJFNwhbO2MgXBnr5tvLIHgRJnR5C9UN5RNpQXiFHuSA==} peerDependencies: @@ -126,11 +153,141 @@ packages: chalk: 2.4.2 dev: false + /@babel/compat-data@7.22.20: + resolution: {integrity: sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/core@7.23.0: + resolution: {integrity: sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.0 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0) + '@babel/helpers': 7.23.1 + '@babel/parser': 7.23.0 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.0 + '@babel/types': 7.23.0 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/generator@7.23.0: + resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.19 + jsesc: 2.5.2 + dev: false + + /@babel/helper-compilation-targets@7.22.15: + resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.22.20 + '@babel/helper-validator-option': 7.22.15 + browserslist: 4.21.10 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: false + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-module-transforms@7.23.0(@babel/core@7.23.0): + resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: false + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-string-parser@7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + dev: false + /@babel/helper-validator-identifier@7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} dev: false + /@babel/helper-validator-option@7.22.15: + resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helpers@7.23.1: + resolution: {integrity: sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.0 + '@babel/types': 7.23.0 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/highlight@7.22.20: resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} engines: {node: '>=6.9.0'} @@ -140,6 +297,143 @@ packages: js-tokens: 4.0.0 dev: false + /@babel/parser@7.23.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.0): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.23.0): + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.0): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.0): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.0): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.0): + resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.0): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.0): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.0): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.0): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.0): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.0): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.0): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.23.0): + resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + /@babel/runtime@7.22.15: resolution: {integrity: sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==} engines: {node: '>=6.9.0'} @@ -147,6 +441,46 @@ packages: regenerator-runtime: 0.14.0 dev: false + /@babel/template@7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + dev: false + + /@babel/traverse@7.23.0: + resolution: {integrity: sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.0 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/types@7.23.0: + resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: false + + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: false + /@emotion/is-prop-valid@0.8.8: resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} requiresBuild: true @@ -218,6 +552,77 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: false + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: false + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: false + + /@jest/console@29.7.0: + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.7.1 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + dev: false + + /@jest/core@29.7.0: + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.7.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.8.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.7.1) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + dev: false + /@jest/environment@29.7.0: resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -228,6 +633,23 @@ packages: jest-mock: 29.7.0 dev: false + /@jest/expect-utils@29.7.0: + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 + dev: false + + /@jest/expect@29.7.0: + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: false + /@jest/fake-timers@29.7.0: resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -240,6 +662,55 @@ packages: jest-util: 29.7.0 dev: false + /@jest/globals@29.7.0: + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@jest/reporters@29.7.0: + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.19 + '@types/node': 20.7.1 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 6.0.0 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.6 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.1.0 + transitivePeerDependencies: + - supports-color + dev: false + /@jest/schemas@29.6.3: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -247,6 +718,58 @@ packages: '@sinclair/typebox': 0.27.8 dev: false + /@jest/source-map@29.6.3: + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.19 + callsites: 3.1.0 + graceful-fs: 4.2.11 + dev: false + + /@jest/test-result@29.7.0: + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.4 + collect-v8-coverage: 1.0.2 + dev: false + + /@jest/test-sequencer@29.7.0: + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + dev: false + + /@jest/transform@29.7.0: + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.23.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.19 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.5 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + dev: false + /@jest/types@29.6.3: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -459,11 +982,108 @@ packages: tailwindcss: 3.3.3 dev: false + /@testing-library/dom@9.3.3: + resolution: {integrity: sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==} + engines: {node: '>=14'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/runtime': 7.22.15 + '@types/aria-query': 5.0.2 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + dev: false + + /@testing-library/jest-dom@6.1.3(@types/jest@29.5.5)(jest@29.7.0): + resolution: {integrity: sha512-YzpjRHoCBWPzpPNtg6gnhasqtE/5O4qz8WCwDEaxtfnPO6gkaLrnuXusrGSPyhIGPezr1HM7ZH0CFaUTY9PJEQ==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + peerDependencies: + '@jest/globals': '>= 28' + '@types/jest': '>= 28' + jest: '>= 28' + vitest: '>= 0.32' + peerDependenciesMeta: + '@jest/globals': + optional: true + '@types/jest': + optional: true + jest: + optional: true + vitest: + optional: true + dependencies: + '@adobe/css-tools': 4.3.1 + '@babel/runtime': 7.22.15 + '@types/jest': 29.5.5 + aria-query: 5.3.0 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.5.16 + jest: 29.7.0(@types/node@20.7.1) + lodash: 4.17.21 + redent: 3.0.0 + dev: false + + /@testing-library/react@14.0.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==} + engines: {node: '>=14'} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + dependencies: + '@babel/runtime': 7.22.15 + '@testing-library/dom': 9.3.3 + '@types/react-dom': 18.2.8 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} dev: false + /@types/aria-query@5.0.2: + resolution: {integrity: sha512-PHKZuMN+K5qgKIWhBodXzQslTo5P+K/6LqeKXS6O/4liIDdZqaX5RXrCK++LAw+y/nptN48YmUMFiQHRSWYwtQ==} + dev: false + + /@types/babel__core@7.20.2: + resolution: {integrity: sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==} + dependencies: + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + '@types/babel__generator': 7.6.5 + '@types/babel__template': 7.4.2 + '@types/babel__traverse': 7.20.2 + dev: false + + /@types/babel__generator@7.6.5: + resolution: {integrity: sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@types/babel__template@7.4.2: + resolution: {integrity: sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==} + dependencies: + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + dev: false + + /@types/babel__traverse@7.20.2: + resolution: {integrity: sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@types/graceful-fs@4.1.7: + resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} + dependencies: + '@types/node': 20.7.1 + dev: false + /@types/istanbul-lib-coverage@2.0.4: resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} dev: false @@ -480,6 +1100,13 @@ packages: '@types/istanbul-lib-report': 3.0.0 dev: false + /@types/jest@29.5.5: + resolution: {integrity: sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==} + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + dev: false + /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: @@ -758,6 +1385,13 @@ packages: uri-js: 4.4.1 dev: false + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: false + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -798,10 +1432,22 @@ packages: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} dev: false + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: false + /aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + dependencies: + deep-equal: 2.2.2 + dev: false + /aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} dependencies: @@ -931,6 +1577,78 @@ packages: dequal: 2.0.3 dev: false + /babel-jest@29.7.0(@babel/core@7.23.0): + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.23.0 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.2 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.23.0) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.22.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.0 + '@types/babel__core': 7.20.2 + '@types/babel__traverse': 7.20.2 + dev: false + + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.23.0): + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.23.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.0) + dev: false + + /babel-preset-jest@29.6.3(@babel/core@7.23.0): + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.0 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.23.0) + dev: false + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: false @@ -965,6 +1683,16 @@ packages: update-browserslist-db: 1.0.11(browserslist@4.21.10) dev: false + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: false + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: false + /bufferutil@4.0.7: resolution: {integrity: sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==} engines: {node: '>=6.14.2'} @@ -1007,6 +1735,16 @@ packages: type-fest: 4.3.1 dev: false + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: false + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: false + /camelcase@8.0.0: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} @@ -1025,6 +1763,14 @@ packages: supports-color: 5.5.0 dev: false + /chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -1033,6 +1779,11 @@ packages: supports-color: 7.2.0 dev: false + /char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: false + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -1053,10 +1804,32 @@ packages: engines: {node: '>=8'} dev: false + /cjs-module-lexer@1.2.3: + resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} + dev: false + /client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} dev: false + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: false + + /collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -1099,11 +1872,38 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: false + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: false + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: false + /cookie@0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} dev: false + /create-jest@29.7.0(@types/node@20.7.1): + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.7.1) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1113,6 +1913,10 @@ packages: which: 2.0.2 dev: false + /css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + dev: false + /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -1185,10 +1989,47 @@ packages: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} dev: false + /dedent@1.5.1: + resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + dev: false + + /deep-equal@2.2.2: + resolution: {integrity: sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.2 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.1 + is-arguments: 1.1.1 + is-array-buffer: 3.0.2 + is-date-object: 1.0.5 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + isarray: 2.0.5 + object-is: 1.1.5 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.1 + side-channel: 1.0.4 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.11 + dev: false + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: false + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: false + /define-data-property@1.1.0: resolution: {integrity: sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==} engines: {node: '>= 0.4'} @@ -1217,10 +2058,20 @@ packages: engines: {node: '>=6'} dev: false + /detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: false + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: false + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: false + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1246,6 +2097,10 @@ packages: esutils: 2.0.3 dev: false + /dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dev: false + /domexception@4.0.0: resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} engines: {node: '>=12'} @@ -1261,6 +2116,15 @@ packages: resolution: {integrity: sha512-GIZ620hDK4YmIqAWkscG4W6RwY6gOx1y5J6f4JUQwctiJrqH2oxZYU4mXHi35oV32tr630UcepBzSBGJ/WYcZA==} dev: false + /emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} dev: false @@ -1278,6 +2142,12 @@ packages: engines: {node: '>=0.12'} dev: false + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: false + /es-abstract@1.22.2: resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==} engines: {node: '>= 0.4'} @@ -1323,6 +2193,20 @@ packages: which-typed-array: 1.1.11 dev: false + /es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.2 + is-set: 2.0.2 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + dev: false + /es-iterator-helpers@1.0.15: resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} dependencies: @@ -1678,6 +2562,37 @@ packages: engines: {node: '>=0.10.0'} dev: false + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: false + + /exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: false + + /expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + dev: false + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: false @@ -1707,6 +2622,12 @@ packages: reusify: 1.0.4 dev: false + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: false + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -1721,6 +2642,14 @@ packages: to-regex-range: 5.0.1 dev: false + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: false + /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -1809,6 +2738,16 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: false + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: false + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + /get-intrinsic@1.2.1: resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} dependencies: @@ -1818,6 +2757,16 @@ packages: has-symbols: 1.0.3 dev: false + /get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: false + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: false + /get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -1883,6 +2832,11 @@ packages: path-is-absolute: 1.0.1 dev: false + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: false + /globals@13.21.0: resolution: {integrity: sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==} engines: {node: '>=8'} @@ -1981,6 +2935,10 @@ packages: whatwg-encoding: 2.0.0 dev: false + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: false + /http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} engines: {node: '>= 6'} @@ -2002,6 +2960,11 @@ packages: - supports-color dev: false + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: false + /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2022,11 +2985,25 @@ packages: resolve-from: 4.0.0 dev: false + /import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: false + /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} dev: false + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: false + /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: @@ -2047,6 +3024,14 @@ packages: side-channel: 1.0.4 dev: false + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: false + /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: @@ -2055,6 +3040,10 @@ packages: is-typed-array: 1.1.12 dev: false + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: false + /is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -2112,6 +3101,16 @@ packages: call-bind: 1.0.2 dev: false + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: false + /is-generator-function@1.0.10: resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} engines: {node: '>= 0.4'} @@ -2174,6 +3173,11 @@ packages: call-bind: 1.0.2 dev: false + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: false + /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -2220,6 +3224,65 @@ packages: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: false + /istanbul-lib-coverage@3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: false + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.23.0 + '@babel/parser': 7.23.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /istanbul-lib-instrument@6.0.0: + resolution: {integrity: sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==} + engines: {node: '>=10'} + dependencies: + '@babel/core': 7.23.0 + '@babel/parser': 7.23.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + dev: false + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: false + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: false + + /istanbul-reports@3.1.6: + resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: false + /iterator.prototype@1.1.2: resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} dependencies: @@ -2230,6 +3293,140 @@ packages: set-function-name: 2.0.1 dev: false + /jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + dev: false + + /jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.7.1 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.1 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.0.4 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: false + + /jest-cli@29.7.0(@types/node@20.7.1): + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@20.7.1) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@20.7.1) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: false + + /jest-config@29.7.0(@types/node@20.7.1): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.23.0 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.7.1 + babel-jest: 29.7.0(@babel/core@7.23.0) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: false + + /jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: false + + /jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + detect-newline: 3.1.0 + dev: false + + /jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + dev: false + /jest-environment-jsdom@29.7.0: resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2253,6 +3450,60 @@ packages: - utf-8-validate dev: false + /jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.7.1 + jest-mock: 29.7.0 + jest-util: 29.7.0 + dev: false + + /jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: false + + /jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.7 + '@types/node': 20.7.1 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: false + + /jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: false + /jest-message-util@29.7.0: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2277,6 +3528,135 @@ packages: jest-util: 29.7.0 dev: false + /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 29.7.0 + dev: false + + /jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: false + + /jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: false + + /jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.6 + resolve.exports: 2.0.2 + slash: 3.0.0 + dev: false + + /jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.7.1 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + dev: false + + /jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.7.1 + chalk: 4.1.2 + cjs-module-lexer: 1.2.3 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.23.0 + '@babel/generator': 7.23.0 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0) + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.23.0) + '@babel/types': 7.23.0 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.23.0) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + dev: false + /jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2289,6 +3669,63 @@ packages: picomatch: 2.3.1 dev: false + /jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + dev: false + + /jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.7.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + dev: false + + /jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 20.7.1 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: false + + /jest@29.7.0(@types/node@20.7.1): + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@20.7.1) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: false + /jiti@1.20.0: resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==} hasBin: true @@ -2302,6 +3739,14 @@ packages: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: false + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: false + /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2350,10 +3795,20 @@ packages: - utf-8-validate dev: false + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: false + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: false + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: false + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: false @@ -2369,6 +3824,12 @@ packages: minimist: 1.2.8 dev: false + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: false + /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -2385,6 +3846,11 @@ packages: json-buffer: 3.0.1 dev: false + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: false + /language-subtag-registry@0.3.22: resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} dev: false @@ -2395,6 +3861,11 @@ packages: language-subtag-registry: 0.3.22 dev: false + /leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: false + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -2412,6 +3883,13 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: false + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: false + /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2434,6 +3912,12 @@ packages: js-tokens: 4.0.0 dev: false + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: false + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -2441,11 +3925,33 @@ packages: yallist: 4.0.0 dev: false + /lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + dev: false + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: false + + /makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: false + /map-obj@5.0.0: resolution: {integrity: sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: false + /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -2471,6 +3977,16 @@ packages: mime-db: 1.52.0 dev: false + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: false + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: false + /mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true @@ -2534,7 +4050,7 @@ packages: optional: true dependencies: '@auth/core': 0.0.0-manual.e9863699 - next: 13.5.3(react-dom@18.2.0)(react@18.2.0) + next: 13.5.3(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false @@ -2545,12 +4061,12 @@ packages: react: '*' react-dom: '*' dependencies: - next: 13.5.3(react-dom@18.2.0)(react@18.2.0) + next: 13.5.3(@babel/core@7.23.0)(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@13.5.3(react-dom@18.2.0)(react@18.2.0): + /next@13.5.3(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-4Nt4HRLYDW/yRpJ/QR2t1v63UOMS55A38dnWv3UDOWGezuY0ZyFO1ABNbD7mulVzs9qVhgy2+ppjdsANpKP1mg==} engines: {node: '>=16.14.0'} hasBin: true @@ -2572,7 +4088,7 @@ packages: postcss: 8.4.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(react@18.2.0) + styled-jsx: 5.1.1(@babel/core@7.23.0)(react@18.2.0) watchpack: 2.4.0 zod: 3.21.4 optionalDependencies: @@ -2595,6 +4111,10 @@ packages: hasBin: true dev: false + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: false + /node-releases@2.0.13: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: false @@ -2609,6 +4129,13 @@ packages: engines: {node: '>=0.10.0'} dev: false + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: false + /nwsapi@2.2.7: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: false @@ -2631,6 +4158,14 @@ packages: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} dev: false + /object-is@1.1.5: + resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + dev: false + /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -2695,6 +4230,13 @@ packages: wrappy: 1.0.2 dev: false + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: false + /opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true @@ -2712,6 +4254,13 @@ packages: type-check: 0.4.0 dev: false + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: false + /p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -2719,6 +4268,13 @@ packages: yocto-queue: 0.1.0 dev: false + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: false + /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} @@ -2726,6 +4282,11 @@ packages: p-limit: 3.1.0 dev: false + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: false + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -2733,6 +4294,16 @@ packages: callsites: 3.1.0 dev: false + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.13 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: false + /parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} dependencies: @@ -2802,6 +4373,13 @@ packages: engines: {node: '>= 6'} dev: false + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: false + /postcss-import@15.1.0(postcss@8.4.30): resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} @@ -2921,6 +4499,15 @@ packages: engines: {node: '>= 0.8.0'} dev: false + /pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: false + /pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2934,6 +4521,14 @@ packages: resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} dev: false + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: false + /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: @@ -2951,6 +4546,10 @@ packages: engines: {node: '>=6'} dev: false + /pure-rand@6.0.4: + resolution: {integrity: sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==} + dev: false + /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} dev: false @@ -2986,6 +4585,10 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} dev: false + /react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: false + /react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: false @@ -3010,6 +4613,14 @@ packages: picomatch: 2.3.1 dev: false + /redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: false + /reflect.getprototypeof@1.0.4: resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} engines: {node: '>= 0.4'} @@ -3035,19 +4646,41 @@ packages: set-function-name: 2.0.1 dev: false + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: false + /resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: false + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} dev: false + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: false + /resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} dev: false + /resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + dev: false + /resolve@1.22.6: resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==} hasBin: true @@ -3165,6 +4798,10 @@ packages: object-inspect: 1.12.3 dev: false + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: false + /sirv@1.0.19: resolution: {integrity: sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==} engines: {node: '>= 10'} @@ -3174,6 +4811,10 @@ packages: totalist: 1.1.0 dev: false + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: false + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -3194,12 +4835,22 @@ packages: engines: {node: '>=0.10.0'} dev: false + /source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: false + /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} requiresBuild: true dev: false - optional: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false /stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} @@ -3208,11 +4859,35 @@ packages: escape-string-regexp: 2.0.0 dev: false + /stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + dependencies: + internal-slot: 1.0.5 + dev: false + /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} dev: false + /string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + /string.prototype.matchall@4.0.10: resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} dependencies: @@ -3264,12 +4939,29 @@ packages: engines: {node: '>=4'} dev: false + /strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: false + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: false + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: false + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} dev: false - /styled-jsx@5.1.1(react@18.2.0): + /styled-jsx@5.1.1(@babel/core@7.23.0)(react@18.2.0): resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} engines: {node: '>= 12.0.0'} peerDependencies: @@ -3282,6 +4974,7 @@ packages: babel-plugin-macros: optional: true dependencies: + '@babel/core': 7.23.0 client-only: 0.0.1 react: 18.2.0 dev: false @@ -3314,6 +5007,13 @@ packages: has-flag: 4.0.0 dev: false + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: false + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -3359,6 +5059,15 @@ packages: engines: {node: '>=6'} dev: false + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: false + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: false @@ -3376,6 +5085,15 @@ packages: any-promise: 1.3.0 dev: false + /tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: false + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: false + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3454,6 +5172,11 @@ packages: engines: {node: '>=10'} dev: false + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: false + /type-fest@4.3.1: resolution: {integrity: sha512-pphNW/msgOUSkJbH58x8sqpq8uQj6b0ZKGxEsLKMUnGorRcDjrUaLS+39+/ub41JNTwrrMyJcUB8+YZs3mbwqw==} engines: {node: '>=16'} @@ -3560,6 +5283,15 @@ packages: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: false + /v8-to-istanbul@9.1.0: + resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.19 + '@types/istanbul-lib-coverage': 2.0.4 + convert-source-map: 1.9.0 + dev: false + /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} @@ -3567,6 +5299,12 @@ packages: xml-name-validator: 4.0.0 dev: false + /walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: false + /watchpack@2.4.0: resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} engines: {node: '>=10.13.0'} @@ -3675,10 +5413,27 @@ packages: isexe: 2.0.0 dev: false + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: false + /write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: false + /ws@7.5.9: resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} engines: {node: '>=8.3.0'} @@ -3722,6 +5477,15 @@ packages: engines: {node: '>=0.4'} dev: false + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: false + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: false @@ -3731,6 +5495,24 @@ packages: engines: {node: '>= 14'} dev: false + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: false + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/src/app/(auth-state)/admin/photos/page.tsx b/src/app/(auth-state)/admin/photos/page.tsx index 2a848383..d0835eb6 100644 --- a/src/app/(auth-state)/admin/photos/page.tsx +++ b/src/app/(auth-state)/admin/photos/page.tsx @@ -13,7 +13,11 @@ import { import { FaRegEdit } from 'react-icons/fa'; import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus'; import { pathForBlobUrl } from '@/services/blob'; -import { pathForPhoto, pathForPhotoEdit } from '@/site/paths'; +import { + pathForAdminPhotos, + pathForPhoto, + pathForPhotoEdit, +} from '@/site/paths'; import { getPhotosLimitForQuery, titleForPhoto } from '@/photo'; import MorePhotos from '@/components/MorePhotos'; import { @@ -123,7 +127,7 @@ export default async function AdminPage({ )} {showMorePhotos && - } + } } diff --git a/src/app/(static)/grid/page.tsx b/src/app/(static)/grid/page.tsx index 241cf5a6..d2655dcb 100644 --- a/src/app/(static)/grid/page.tsx +++ b/src/app/(static)/grid/page.tsx @@ -10,6 +10,7 @@ import { generateOgImageMetaForPhotos, getPhotosLimitForQuery } from '@/photo'; import PhotoGrid from '@/photo/PhotoGrid'; import PhotosEmptyState from '@/photo/PhotosEmptyState'; import { MAX_PHOTOS_TO_SHOW_HOME } from '@/photo/image-response'; +import { pathForGrid } from '@/site/paths'; import PhotoTag from '@/tag/PhotoTag'; import { Metadata } from 'next'; @@ -45,7 +46,7 @@ export default async function GridPage({ contentMain={
{showMorePhotos && - } + }
} contentSide={tags && {showMorePhotos && - } + } ); } diff --git a/src/app/(static)/p/[photoId]/layout.tsx b/src/app/(static)/p/[photoId]/layout.tsx index 534abd02..834f561b 100644 --- a/src/app/(static)/p/[photoId]/layout.tsx +++ b/src/app/(static)/p/[photoId]/layout.tsx @@ -5,7 +5,11 @@ import { } from '@/photo'; import { Metadata } from 'next'; import { redirect } from 'next/navigation'; -import { absolutePathForPhoto, absolutePathForPhotoImage } from '@/site/paths'; +import { + PATH_ROOT, + absolutePathForPhoto, + absolutePathForPhotoImage, +} from '@/site/paths'; import PhotoDetailPage from '@/photo/PhotoDetailPage'; import { getPhotoCached, getPhotosCached } from '@/cache'; import { getPhotos } from '@/services/postgres'; @@ -58,7 +62,7 @@ export default async function PhotoPage({ }) { const photo = await getPhotoCached(photoId); - if (!photo) { redirect('/'); } + if (!photo) { redirect(PATH_ROOT); } const [ photosBefore, diff --git a/src/app/(static)/p/[photoId]/share/page.tsx b/src/app/(static)/p/[photoId]/share/page.tsx index 5fc0c871..0ffe0e2d 100644 --- a/src/app/(static)/p/[photoId]/share/page.tsx +++ b/src/app/(static)/p/[photoId]/share/page.tsx @@ -1,5 +1,6 @@ import { getPhotoCached } from '@/cache'; import PhotoShareModal from '@/photo/PhotoShareModal'; +import { PATH_ROOT } from '@/site/paths'; import { redirect } from 'next/navigation'; export const runtime = 'edge'; @@ -11,7 +12,7 @@ export default async function Share({ }) { const photo = await getPhotoCached(photoId); - if (!photo) { return redirect('/'); } + if (!photo) { return redirect(PATH_ROOT); } return ; } diff --git a/src/app/(static)/page.tsx b/src/app/(static)/page.tsx index 2fcb8570..57d7567d 100644 --- a/src/app/(static)/page.tsx +++ b/src/app/(static)/page.tsx @@ -5,6 +5,7 @@ import SiteGrid from '@/components/SiteGrid'; import { generateOgImageMetaForPhotos, getPhotosLimitForQuery } from '@/photo'; import PhotoLarge from '@/photo/PhotoLarge'; import PhotosEmptyState from '@/photo/PhotosEmptyState'; +import { pathForRoot } from '@/site/paths'; import { Metadata } from 'next'; export const runtime = 'edge'; @@ -49,7 +50,7 @@ export default async function HomePage({ /> {showMorePhotos && } + contentMain={} />} : diff --git a/src/app/(static)/t/[tag]/[photoId]/layout.tsx b/src/app/(static)/t/[tag]/[photoId]/layout.tsx index bd7a062a..c8315406 100644 --- a/src/app/(static)/t/[tag]/[photoId]/layout.tsx +++ b/src/app/(static)/t/[tag]/[photoId]/layout.tsx @@ -4,7 +4,11 @@ import { } from '@/photo'; import { Metadata } from 'next'; import { redirect } from 'next/navigation'; -import { absolutePathForPhoto, absolutePathForPhotoImage } from '@/site/paths'; +import { + PATH_ROOT, + absolutePathForPhoto, + absolutePathForPhotoImage, +} from '@/site/paths'; import PhotoDetailPage from '@/photo/PhotoDetailPage'; import { getPhotoCached, getPhotosCached } from '@/cache'; import { getPhotos, getUniqueTags } from '@/services/postgres'; @@ -64,7 +68,7 @@ export default async function PhotoTagPage({ }) { const photo = await getPhotoCached(photoId); - if (!photo) { redirect('/'); } + if (!photo) { redirect(PATH_ROOT); } const photos = await getPhotosCached({ tag }); diff --git a/src/app/(static)/t/[tag]/[photoId]/share/page.tsx b/src/app/(static)/t/[tag]/[photoId]/share/page.tsx index 521046ce..f120d70f 100644 --- a/src/app/(static)/t/[tag]/[photoId]/share/page.tsx +++ b/src/app/(static)/t/[tag]/[photoId]/share/page.tsx @@ -1,6 +1,7 @@ import { getPhotoCached } from '@/cache'; import PhotoShareModal from '@/photo/PhotoShareModal'; import { getPhotos, getUniqueTags } from '@/services/postgres'; +import { PATH_ROOT } from '@/site/paths'; import { redirect } from 'next/navigation'; export async function generateStaticParams() { @@ -24,7 +25,7 @@ export default async function Share({ }) { const photo = await getPhotoCached(photoId); - if (!photo) { return redirect('/'); } + if (!photo) { return redirect(PATH_ROOT); } return ; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 64e68e36..197c834a 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -7,6 +7,7 @@ import StateProvider from '@/state/AppStateProvider'; import ThemeProviderClient from '@/site/ThemeProviderClient'; import Nav from '@/components/Nav'; import ToasterWithThemes from '@/components/ToasterWithThemes'; +import PhotoEscapeHandler from '@/photo/PhotoEscapeHandler'; import '../site/globals.css'; @@ -77,6 +78,7 @@ export default function RootLayout({ + diff --git a/src/app/sign-in/page.tsx b/src/app/sign-in/page.tsx index 46838d83..1c50922a 100644 --- a/src/app/sign-in/page.tsx +++ b/src/app/sign-in/page.tsx @@ -1,5 +1,6 @@ import { auth } from '@/auth'; import SignInForm from '@/auth/SignInForm'; +import { PATH_ROOT } from '@/site/paths'; import { cc } from '@/utility/css'; import { redirect } from 'next/navigation'; @@ -9,7 +10,7 @@ export default async function SignInPage() { const session = await auth(); if (session?.user) { - redirect('/'); + redirect(PATH_ROOT); } return ( diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index 3f3bd86e..14895df2 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -6,6 +6,7 @@ import { cc } from '@/utility/css'; import useClickInsideOutside from '@/utility/useClickInsideOutside'; import { useRouter } from 'next/navigation'; import AnimateItems from './AnimateItems'; +import { PATH_ROOT } from '@/site/paths'; export default function Modal({ onClosePath, @@ -28,7 +29,10 @@ export default function Modal({ useClickInsideOutside({ htmlElements, - onClickOutside: () => router.push(onClosePath ?? '/', { scroll: false}), + onClickOutside: () => router.push( + onClosePath ?? PATH_ROOT, + { scroll: false }, + ), }); return ( diff --git a/src/components/Nav.tsx b/src/components/Nav.tsx index 2b7b1ba6..0b10c9e5 100644 --- a/src/components/Nav.tsx +++ b/src/components/Nav.tsx @@ -6,6 +6,12 @@ import Link from 'next/link'; import SiteGrid from './SiteGrid'; import { SITE_DOMAIN_OR_TITLE } from '@/site/config'; import ViewSwitcher, { SwitcherSelection } from '@/photo/ViewSwitcher'; +import { + PATH_ADMIN, + PATH_ROOT, + isPathGrid, + isPathProtected, +} from '@/site/paths'; export default function Nav({ showTextLinks }: { showTextLinks?: boolean }) { const isLoggedIn = false; @@ -23,11 +29,11 @@ export default function Nav({ showTextLinks }: { showTextLinks?: boolean }) { : ; const switcherSelectionForPath = (): SwitcherSelection | undefined => { - if (pathname === '/') { + if (pathname === PATH_ROOT) { return 'full-frame'; - } else if (pathname === '/grid') { + } else if (isPathGrid(pathname)) { return 'grid'; - } else if (pathname.startsWith('/admin')) { + } else if (isPathProtected(pathname)) { return 'admin'; } }; @@ -47,12 +53,12 @@ export default function Nav({ showTextLinks }: { showTextLinks?: boolean }) { showAdmin={isLoggedIn} /> {showTextLinks && <> - {renderLink('Home', '/')} - {renderLink('Admin', '/admin')} + {renderLink('Home', PATH_ROOT)} + {renderLink('Admin', PATH_ADMIN)} }
- {renderLink(SITE_DOMAIN_OR_TITLE, '/')} + {renderLink(SITE_DOMAIN_OR_TITLE, PATH_ROOT)}
} diff --git a/src/photo/PhotoEscapeHandler.tsx b/src/photo/PhotoEscapeHandler.tsx new file mode 100644 index 00000000..44aa4579 --- /dev/null +++ b/src/photo/PhotoEscapeHandler.tsx @@ -0,0 +1,27 @@ +'use client'; + +import { getEscapePath } from '@/site/paths'; +import { useRouter, usePathname } from 'next/navigation'; +import { useEffect } from 'react'; + +const LISTENER_KEYUP = 'keyup'; + +export default function PhotoEscapeHandler() { + const router = useRouter(); + + const pathname = usePathname(); + + const escapePath = getEscapePath(pathname); + + useEffect(() => { + const onKeyUp = (e: KeyboardEvent) => { + if (e.key.toUpperCase() === 'ESCAPE' && escapePath) { + router.push(escapePath, { scroll: false }); + }; + }; + window.addEventListener(LISTENER_KEYUP, onKeyUp); + return () => window.removeEventListener(LISTENER_KEYUP, onKeyUp); + }, [router, escapePath]); + + return null; +} diff --git a/src/photo/PhotoGrid.tsx b/src/photo/PhotoGrid.tsx index 3ebb0f8f..aa54697f 100644 --- a/src/photo/PhotoGrid.tsx +++ b/src/photo/PhotoGrid.tsx @@ -2,61 +2,44 @@ import { Photo } from '.'; import PhotoSmall from './PhotoSmall'; import { cc } from '@/utility/css'; import AnimateItems from '@/components/AnimateItems'; -import Link from 'next/link'; - -const PHOTOS_PER_PAGE = 6; -const PHOTOS_MAX = 35; export default function PhotoGrid({ photos, selectedPhoto, tag, - offset = 0, fast, animate = true, animateOnFirstLoadOnly, staggerOnFirstLoadOnly = true, - showMore, }: { photos: Photo[] selectedPhoto?: Photo tag?: string - offset?: number fast?: boolean animate?: boolean animateOnFirstLoadOnly?: boolean staggerOnFirstLoadOnly?: boolean - showMore?: boolean }) { return ( - <> - - )} - /> - {showMore && (offset + PHOTOS_PER_PAGE) < PHOTOS_MAX && - - More - } - + + )} + /> ); }; diff --git a/src/photo/PhotoLinks.tsx b/src/photo/PhotoLinks.tsx index c328a54c..ca01ca6f 100644 --- a/src/photo/PhotoLinks.tsx +++ b/src/photo/PhotoLinks.tsx @@ -8,6 +8,8 @@ import { pathForPhoto } from '@/site/paths'; import { useAppState } from '@/state'; import { AnimationConfig } from '@/components/AnimateItems'; +const LISTENER_KEYUP = 'keyup'; + const ANIMATION_LEFT: AnimationConfig = { type: 'left', duration: 0.3 }; const ANIMATION_RIGHT: AnimationConfig = { type: 'right', duration: 0.3 }; @@ -44,14 +46,17 @@ export default function PhotoLinks({ router.push(pathForPhoto(nextPhoto, tag), { scroll: false }); } break; - case 'ESCAPE': - router.push('/grid'); - break; }; }; - window.addEventListener('keyup', onKeyUp); - return () => window.removeEventListener('keyup', onKeyUp); - }, [router, setNextPhotoAnimation, previousPhoto, nextPhoto, tag]); + window.addEventListener(LISTENER_KEYUP, onKeyUp); + return () => window.removeEventListener(LISTENER_KEYUP, onKeyUp); + }, [ + router, + setNextPhotoAnimation, + previousPhoto, + nextPhoto, + tag, + ]); return ( <> diff --git a/src/photo/ViewSwitcher.tsx b/src/photo/ViewSwitcher.tsx index 07f4693a..2f82744f 100644 --- a/src/photo/ViewSwitcher.tsx +++ b/src/photo/ViewSwitcher.tsx @@ -2,6 +2,7 @@ import Switcher from '@/components/Switcher'; import SwitcherItem from '@/components/SwitcherItem'; import IconFullFrame from '@/icons/IconFullFrame'; import IconGrid from '@/icons/IconGrid'; +import { PATH_GRID } from '@/site/paths'; import { BiLockAlt } from 'react-icons/bi'; export type SwitcherSelection = 'full-frame' | 'grid' | 'admin'; @@ -23,7 +24,7 @@ export default function ViewSwitcher({ /> } - href="/grid" + href={PATH_GRID} active={currentSelection === 'grid'} noPadding /> diff --git a/src/site/paths.ts b/src/site/paths.ts index b286f04e..8dc636fd 100644 --- a/src/site/paths.ts +++ b/src/site/paths.ts @@ -1,55 +1,143 @@ import { Photo } from '@/photo'; import { BASE_URL } from './config'; +// Prefixes const PREFIX_PHOTO = '/p'; const PREFIX_TAG = '/t'; -const PREFIX_ADMIN = '/admin'; +// Modifiers const SHARE = 'share'; +const NEXT = 'next'; -export const PATH_ADMIN_PHOTOS = `${PREFIX_ADMIN}/photos`; -export const PATH_ADMIN_UPLOAD = `${PREFIX_ADMIN}/uploads`; +// Core paths +export const PATH_ROOT = '/'; +export const PATH_GRID = '/grid'; +export const PATH_ADMIN = '/admin'; +export const PATH_OG = '/og'; + +// Extended paths +export const PATH_ADMIN_PHOTOS = `${PATH_ADMIN}/photos`; +export const PATH_ADMIN_UPLOAD = `${PATH_ADMIN}/uploads`; export const PATH_ADMIN_UPLOAD_BLOB_HANDLER = `${PATH_ADMIN_UPLOAD}/blob`; +// Absolute paths export const ABSOLUTE_PATH_FOR_HOME_IMAGE = `${BASE_URL}/home-image`; -export const pathForPhoto = (photo: Photo, tag?: string) => - tag - ? `${pathForTag(tag)}/${photo.id}` - : `${PREFIX_PHOTO}/${photo.id}`; +const pathWithNext = (path: string, next?: number) => + next !== undefined ? `${path}?${NEXT}=${next}` : path; -export const pathForPhotoShare = (photo: Photo, tag?: string) => +export const pathForRoot = (next?: number) => + pathWithNext(PATH_ROOT, next); + +export const pathForGrid = (next?: number) => + pathWithNext(PATH_GRID, next); + +export const pathForAdminPhotos = (next?: number) => + pathWithNext(PATH_ADMIN_PHOTOS, next); + +export const pathForOg = (next?: number) => + pathWithNext(PATH_OG, next); + +type PhotoOrPhotoId = Photo | string; + +const getPhotoId = (photoOrPhotoId: PhotoOrPhotoId) => + typeof photoOrPhotoId === 'string' ? photoOrPhotoId : photoOrPhotoId.id; + +export const pathForPhoto = (photo: PhotoOrPhotoId, tag?: string) => + tag + ? `${pathForTag(tag)}/${getPhotoId(photo)}` + : `${PREFIX_PHOTO}/${getPhotoId(photo)}`; + +export const pathForPhotoShare = (photo: PhotoOrPhotoId, tag?: string) => `${pathForPhoto(photo, tag)}/${SHARE}`; -export const pathForPhotoEdit = (photo: Photo) => - `${PATH_ADMIN_PHOTOS}/${photo.id}/edit`; +export const pathForPhotoEdit = (photo: PhotoOrPhotoId) => + `${PATH_ADMIN_PHOTOS}/${getPhotoId(photo)}/edit`; export const pathForTag = (tag: string) => `${PREFIX_TAG}/${tag}`; export const pathForTagShare = (tag: string) => `${pathForTag(tag)}/${SHARE}`; -export const absolutePathForPhoto = (photo: Photo, tag?: string) => +export const absolutePathForPhoto = (photo: PhotoOrPhotoId, tag?: string) => `${BASE_URL}${pathForPhoto(photo, tag)}`; export const absolutePathForTag = (tag: string) => `${BASE_URL}${pathForTag(tag)}`; -export const absolutePathForPhotoImage = (photo: Photo) => +export const absolutePathForPhotoImage = (photo: PhotoOrPhotoId) => `${absolutePathForPhoto(photo)}/image`; export const absolutePathForTagImage = (tag: string) => `${absolutePathForTag(tag)}/image`; +// p/[photoId] export const isPathPhoto = (pathname = '') => /^\/p\/[^/]+\/?$/.test(pathname); +// p/[photoId]/share export const isPathPhotoShare = (pathname = '') => /^\/p\/[^/]+\/share\/?$/.test(pathname); +// t/[tagId] +export const isPathTag = (pathname = '') => + /^\/t\/[^/]+\/?$/.test(pathname); + +// t/[tagId]/share +export const isPathTagShare = (pathname = '') => + /^\/t\/[^/]+\/share\/?$/.test(pathname); + +// t/[tagId]/[photoId] +export const isPathTagPhoto = (pathname = '') => + /^\/t\/[^/]+\/[^/]+\/?$/.test(pathname); + +// t/[tagId]/[photoId]/share +export const isPathTagPhotoShare = (pathname = '') => + /^\/t\/[^/]+\/[^/]+\/share\/?$/.test(pathname); + +export const isPathGrid = (pathname = '') => + pathname.startsWith(PATH_GRID); + export const isPathSignIn = (pathname = '') => pathname.startsWith('/sign-in'); +export const isPathAdmin = (pathname = '') => + pathname.startsWith('/admin'); + export const isPathProtected = (pathname = '') => - pathname.startsWith(PREFIX_ADMIN) || + pathname.startsWith(PATH_ADMIN) || pathname === '/checklist'; + +export const getPathComponents = (pathname = ''): { + photoId?: string + tag?: string +} => { + const photoIdFromPhoto = pathname.match(/^\/p\/([^/]+)/)?.[1]; + const photoIdFromTag = pathname.match(/^\/t\/[^/]+\/((?!share)[^/]+)/)?.[1]; + const tag = pathname.match(/^\/t\/([^/]+)/)?.[1]; + return { + photoId: ( + photoIdFromPhoto || + photoIdFromTag + ), + tag, + }; +}; + +export const getEscapePath = (pathname?: string) => { + const { photoId, tag } = getPathComponents(pathname); + if ( + (photoId && isPathPhoto(pathname)) || + (tag && isPathTag(pathname)) + ) { + return PATH_GRID; + } else if (photoId && isPathTagPhotoShare(pathname)) { + return pathForPhoto(photoId, tag); + } else if (photoId && isPathPhotoShare(pathname)) { + return pathForPhoto(photoId); + } else if (tag && (isPathTagPhoto(pathname) || isPathTagShare(pathname))) { + return pathForTag(tag); + } else if (tag && isPathTagShare(pathname)) { + return pathForTag(tag); + } +}; From 003328f791903b96376b9603a58d6294328c833a Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Fri, 29 Sep 2023 16:10:27 -0500 Subject: [PATCH 04/15] Bump dependencies --- package.json | 8 +-- pnpm-lock.yaml | 134 ++++++++++++++++++++++++------------------------- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index 8375e2ed..4cd9588f 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "@testing-library/jest-dom": "^6.1.3", "@testing-library/react": "^14.0.0", "@types/jest": "^29.5.5", - "@types/node": "^20.7.1", + "@types/node": "^20.7.2", "@types/react": "18.2.23", "@types/react-dom": "18.2.8", "@typescript-eslint/eslint-plugin": "^6.7.3", @@ -23,7 +23,7 @@ "@vercel/blob": "^0.13.0", "@vercel/postgres": "0.5.0", "autoprefixer": "10.4.16", - "camelcase-keys": "^9.0.0", + "camelcase-keys": "^9.1.0", "date-fns": "^2.30.0", "eslint": "8.50.0", "eslint-config-next": "13.5.3", @@ -32,9 +32,9 @@ "jest-environment-jsdom": "^29.7.0", "nanoid": "^5.0.1", "next": "^13.5.3", - "next-auth": "0.0.0-manual.5749b095", + "next-auth": "0.0.0-manual.c885ac1d", "next-themes": "^0.2.1", - "postcss": "8.4.30", + "postcss": "8.4.31", "react": "18.2.0", "react-dom": "18.2.0", "react-icons": "^4.11.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 51b4c4f4..3f4fc42f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,8 +21,8 @@ dependencies: specifier: ^29.5.5 version: 29.5.5 '@types/node': - specifier: ^20.7.1 - version: 20.7.1 + specifier: ^20.7.2 + version: 20.7.2 '@types/react': specifier: 18.2.23 version: 18.2.23 @@ -46,10 +46,10 @@ dependencies: version: 0.5.0 autoprefixer: specifier: 10.4.16 - version: 10.4.16(postcss@8.4.30) + version: 10.4.16(postcss@8.4.31) camelcase-keys: - specifier: ^9.0.0 - version: 9.0.0 + specifier: ^9.1.0 + version: 9.1.0 date-fns: specifier: ^2.30.0 version: 2.30.0 @@ -64,7 +64,7 @@ dependencies: version: 10.16.4(react-dom@18.2.0)(react@18.2.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.7.1) + version: 29.7.0(@types/node@20.7.2) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -75,14 +75,14 @@ dependencies: specifier: ^13.5.3 version: 13.5.3(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) next-auth: - specifier: 0.0.0-manual.5749b095 - version: 0.0.0-manual.5749b095(next@13.5.3)(react@18.2.0) + specifier: 0.0.0-manual.c885ac1d + version: 0.0.0-manual.c885ac1d(next@13.5.3)(react@18.2.0) next-themes: specifier: ^0.2.1 version: 0.2.1(next@13.5.3)(react-dom@18.2.0)(react@18.2.0) postcss: - specifier: 8.4.30 - version: 8.4.30 + specifier: 8.4.31 + version: 8.4.31 react: specifier: 18.2.0 version: 18.2.0 @@ -573,7 +573,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -594,14 +594,14 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.8.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.7.1) + jest-config: 29.7.0(@types/node@20.7.2) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -629,7 +629,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 jest-mock: 29.7.0 dev: false @@ -656,7 +656,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.7.1 + '@types/node': 20.7.2 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -689,7 +689,7 @@ packages: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.19 - '@types/node': 20.7.1 + '@types/node': 20.7.2 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -777,7 +777,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 20.7.1 + '@types/node': 20.7.2 '@types/yargs': 17.0.24 chalk: 4.1.2 dev: false @@ -1021,7 +1021,7 @@ packages: chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.5.16 - jest: 29.7.0(@types/node@20.7.1) + jest: 29.7.0(@types/node@20.7.2) lodash: 4.17.21 redent: 3.0.0 dev: false @@ -1081,7 +1081,7 @@ packages: /@types/graceful-fs@4.1.7: resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} dependencies: - '@types/node': 20.7.1 + '@types/node': 20.7.2 dev: false /@types/istanbul-lib-coverage@2.0.4: @@ -1110,7 +1110,7 @@ packages: /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: - '@types/node': 20.7.1 + '@types/node': 20.7.2 '@types/tough-cookie': 4.0.3 parse5: 7.1.2 dev: false @@ -1123,14 +1123,14 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: false - /@types/node@20.7.1: - resolution: {integrity: sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==} + /@types/node@20.7.2: + resolution: {integrity: sha512-RcdC3hOBOauLP+r/kRt27NrByYtDjsXyAuSbR87O6xpsvi763WI+5fbSIvYJrXnt9w4RuxhV6eAXfIs7aaf/FQ==} dev: false /@types/pg@8.6.6: resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} dependencies: - '@types/node': 20.7.1 + '@types/node': 20.7.2 pg-protocol: 1.6.0 pg-types: 2.2.0 dev: false @@ -1545,7 +1545,7 @@ packages: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: false - /autoprefixer@10.4.16(postcss@8.4.30): + /autoprefixer@10.4.16(postcss@8.4.31): resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==} engines: {node: ^10 || ^12 || >=14} hasBin: true @@ -1557,7 +1557,7 @@ packages: fraction.js: 4.3.6 normalize-range: 0.1.2 picocolors: 1.0.0 - postcss: 8.4.30 + postcss: 8.4.31 postcss-value-parser: 4.2.0 dev: false @@ -1725,14 +1725,14 @@ packages: engines: {node: '>= 6'} dev: false - /camelcase-keys@9.0.0: - resolution: {integrity: sha512-GdZ92DNXdcfFB/5Kq4O82EL6UW5neiRBhfNP5M3mGw7CX2sPDbVA04ZPLsqbp7oMi2l3m2I0AZ/kFP5Nk5kopA==} + /camelcase-keys@9.1.0: + resolution: {integrity: sha512-RcLmR20cA5J6ZSqOQcPLcJ8fpiczDLVM5V5aOR0w7UgMcev35tPU8z8Q380wWekRRQDON9cLhWOuGm03VDQ7Hg==} engines: {node: '>=16'} dependencies: camelcase: 8.0.0 map-obj: 5.0.0 quick-lru: 6.1.2 - type-fest: 4.3.1 + type-fest: 4.3.2 dev: false /camelcase@5.3.1: @@ -1885,7 +1885,7 @@ packages: engines: {node: '>= 0.6'} dev: false - /create-jest@29.7.0(@types/node@20.7.1): + /create-jest@29.7.0(@types/node@20.7.2): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -1894,7 +1894,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.7.1) + jest-config: 29.7.0(@types/node@20.7.2) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -3310,7 +3310,7 @@ packages: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -3331,7 +3331,7 @@ packages: - supports-color dev: false - /jest-cli@29.7.0(@types/node@20.7.1): + /jest-cli@29.7.0(@types/node@20.7.2): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -3345,10 +3345,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.7.1) + create-jest: 29.7.0(@types/node@20.7.2) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.7.1) + jest-config: 29.7.0(@types/node@20.7.2) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -3359,7 +3359,7 @@ packages: - ts-node dev: false - /jest-config@29.7.0(@types/node@20.7.1): + /jest-config@29.7.0(@types/node@20.7.2): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -3374,7 +3374,7 @@ packages: '@babel/core': 7.23.0 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 babel-jest: 29.7.0(@babel/core@7.23.0) chalk: 4.1.2 ci-info: 3.8.0 @@ -3440,7 +3440,7 @@ packages: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.7.1 + '@types/node': 20.7.2 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -3457,7 +3457,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 jest-mock: 29.7.0 jest-util: 29.7.0 dev: false @@ -3473,7 +3473,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.7 - '@types/node': 20.7.1 + '@types/node': 20.7.2 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -3524,7 +3524,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 jest-util: 29.7.0 dev: false @@ -3579,7 +3579,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -3610,7 +3610,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -3662,7 +3662,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -3687,7 +3687,7 @@ packages: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.7.2 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -3699,13 +3699,13 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.7.1 + '@types/node': 20.7.2 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 dev: false - /jest@29.7.0(@types/node@20.7.1): + /jest@29.7.0(@types/node@20.7.2): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -3718,7 +3718,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.7.1) + jest-cli: 29.7.0(@types/node@20.7.2) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -4039,10 +4039,10 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: false - /next-auth@0.0.0-manual.5749b095(next@13.5.3)(react@18.2.0): - resolution: {integrity: sha512-ah7lwQtGKLVxXEbadGp7Nt+qnYTHLHzEA7/btMf2M+SK3UosUsqZXZpt8/6HT9O+SN67kEXoZk8TW42bTiJRUA==} + /next-auth@0.0.0-manual.c885ac1d(next@13.5.3)(react@18.2.0): + resolution: {integrity: sha512-kL5Ead+uIQNjfSWjo/MVxzte+jJSD+N/XIGkYmqyjQmNxE5wDvJ6zuwo+h+QPBnTVf+jmOsOlzr65tPN7OY5fA==} peerDependencies: - next: ^13.4.13 + next: ^13.5.3 nodemailer: ^6.6.5 react: ^18.2.0 peerDependenciesMeta: @@ -4380,29 +4380,29 @@ packages: find-up: 4.1.0 dev: false - /postcss-import@15.1.0(postcss@8.4.30): + /postcss-import@15.1.0(postcss@8.4.31): resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} peerDependencies: postcss: ^8.0.0 dependencies: - postcss: 8.4.30 + postcss: 8.4.31 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.6 dev: false - /postcss-js@4.0.1(postcss@8.4.30): + /postcss-js@4.0.1(postcss@8.4.31): resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 dependencies: camelcase-css: 2.0.1 - postcss: 8.4.30 + postcss: 8.4.31 dev: false - /postcss-load-config@4.0.1(postcss@8.4.30): + /postcss-load-config@4.0.1(postcss@8.4.31): resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} engines: {node: '>= 14'} peerDependencies: @@ -4415,17 +4415,17 @@ packages: optional: true dependencies: lilconfig: 2.1.0 - postcss: 8.4.30 + postcss: 8.4.31 yaml: 2.3.2 dev: false - /postcss-nested@6.0.1(postcss@8.4.30): + /postcss-nested@6.0.1(postcss@8.4.31): resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 dependencies: - postcss: 8.4.30 + postcss: 8.4.31 postcss-selector-parser: 6.0.13 dev: false @@ -4450,8 +4450,8 @@ packages: source-map-js: 1.0.2 dev: false - /postcss@8.4.30: - resolution: {integrity: sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==} + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.6 @@ -5042,11 +5042,11 @@ packages: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.0.0 - postcss: 8.4.30 - postcss-import: 15.1.0(postcss@8.4.30) - postcss-js: 4.0.1(postcss@8.4.30) - postcss-load-config: 4.0.1(postcss@8.4.30) - postcss-nested: 6.0.1(postcss@8.4.30) + postcss: 8.4.31 + postcss-import: 15.1.0(postcss@8.4.31) + postcss-js: 4.0.1(postcss@8.4.31) + postcss-load-config: 4.0.1(postcss@8.4.31) + postcss-nested: 6.0.1(postcss@8.4.31) postcss-selector-parser: 6.0.13 resolve: 1.22.6 sucrase: 3.34.0 @@ -5177,8 +5177,8 @@ packages: engines: {node: '>=10'} dev: false - /type-fest@4.3.1: - resolution: {integrity: sha512-pphNW/msgOUSkJbH58x8sqpq8uQj6b0ZKGxEsLKMUnGorRcDjrUaLS+39+/ub41JNTwrrMyJcUB8+YZs3mbwqw==} + /type-fest@4.3.2: + resolution: {integrity: sha512-VpwuOgnTsQUUWi0id8Hl4/xiQ+OoaeJGe8dnFjzubJYe/lOc2/d1Qx/d3FqWR0FlpOG/cvukAXfB12A49Y4iiA==} engines: {node: '>=16'} dev: false From e7658eb8a27734c50963c972bbd73d2fb49d1b74 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 30 Sep 2023 10:57:09 -0500 Subject: [PATCH 05/15] Abbreviate Apple to symbol on core pages --- src/photo/PhotoLarge.tsx | 5 ++--- src/photo/PhotoMakeModel.tsx | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/photo/PhotoMakeModel.tsx diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index 1510411c..5e11a715 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -6,6 +6,7 @@ import Link from 'next/link'; import { pathForPhoto, pathForPhotoShare } from '@/site/paths'; import PhotoTags from '@/tag/PhotoTags'; import ShareButton from '@/components/ShareButton'; +import PhotoMakeModel from './PhotoMakeModel'; export default function PhotoLarge({ photo, @@ -63,9 +64,7 @@ export default function PhotoLarge({ {tagsToShow.length > 0 && } -
- {photo.make} {photo.model} -
+ )} {renderMiniGrid(<>
    + {photo.make === 'Apple' + ? + : photo.make} +   + {photo.model} + + ); +} From 07931fca6da6a1020c850d5cc72b0976fe9f5e12 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 30 Sep 2023 23:30:01 -0500 Subject: [PATCH 06/15] Fix auth session type --- src/cache/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cache/index.ts b/src/cache/index.ts index 07b12d8b..b7d79606 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -1,4 +1,3 @@ -import type { Session } from 'next-auth/types'; import { revalidateTag, unstable_cache } from 'next/cache'; import { GetPhotosOptions, @@ -10,6 +9,7 @@ import { } from '@/services/postgres'; import { parseCachedPhotosDates, parseCachedPhotoDates } from '@/photo'; import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob'; +import { AuthSession } from 'next-auth'; const TAG_PHOTOS = 'photos'; const TAG_PHOTOS_COUNT = 'photos-count'; @@ -113,7 +113,7 @@ export const getBlobPhotoUrlsCached: typeof getBlobPhotoUrls = (...args) => } )(); -export const getImageCacheHeadersForAuth = (session?: Session) => { +export const getImageCacheHeadersForAuth = (session: AuthSession | null) => { return { 'Cache-Control': !session?.user ? 's-maxage=3600, stale-while-revalidate=59' From 3347ff30e7af8c9d6ee8840d48ea5defc22cfef7 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 30 Sep 2023 23:48:02 -0500 Subject: [PATCH 07/15] Add site title to root og image --- src/app/(static)/home-image/route.tsx | 7 ++++-- .../image-response/HomeImageResponse.tsx | 7 ++++++ .../components/ImageCaption.tsx | 3 +++ src/photo/index.ts | 25 ++++--------------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/app/(static)/home-image/route.tsx b/src/app/(static)/home-image/route.tsx index 0014e91d..6bf7ef96 100644 --- a/src/app/(static)/home-image/route.tsx +++ b/src/app/(static)/home-image/route.tsx @@ -5,6 +5,7 @@ import { MAX_PHOTOS_TO_SHOW_HOME, } from '@/photo/image-response'; import HomeImageResponse from '@/photo/image-response/HomeImageResponse'; +import { getIBMPlexMonoMedium } from '@/site/font'; import { ImageResponse } from 'next/server'; export const runtime = 'edge'; @@ -13,15 +14,17 @@ export async function GET() { const [ photos, headers, + { fontFamily, fonts }, ] = await Promise.all([ getPhotosCached({ limit: MAX_PHOTOS_TO_SHOW_HOME }), getImageCacheHeadersForAuth(await auth()), + getIBMPlexMonoMedium(), ]); const { width, height } = IMAGE_OG_SMALL_SIZE; return new ImageResponse( - , - { width, height, headers }, + , + { width, height, headers, fonts }, ); } diff --git a/src/photo/image-response/HomeImageResponse.tsx b/src/photo/image-response/HomeImageResponse.tsx index 5479dca4..512bda1a 100644 --- a/src/photo/image-response/HomeImageResponse.tsx +++ b/src/photo/image-response/HomeImageResponse.tsx @@ -1,4 +1,6 @@ +import { SITE_DOMAIN_OR_TITLE } from '@/site/config'; import { Photo } from '..'; +import ImageCaption from './components/ImageCaption'; import ImageContainer from './components/ImageContainer'; import ImagePhotoGrid from './components/ImagePhotoGrid'; @@ -6,10 +8,12 @@ export default function HomeImageResponse({ photos, width, height, + fontFamily, }: { photos: Photo[] width: number height: number + fontFamily: string }) { return ( @@ -20,6 +24,9 @@ export default function HomeImageResponse({ height, }} /> + + {SITE_DOMAIN_OR_TITLE} + ); } diff --git a/src/photo/image-response/components/ImageCaption.tsx b/src/photo/image-response/components/ImageCaption.tsx index 39a8a740..a3a0234a 100644 --- a/src/photo/image-response/components/ImageCaption.tsx +++ b/src/photo/image-response/components/ImageCaption.tsx @@ -28,6 +28,9 @@ export default function ImageCaption({ bottom: 0, left: 0, right: 0, + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', }}> {children} diff --git a/src/photo/index.ts b/src/photo/index.ts index 94bfa5c1..16168697 100644 --- a/src/photo/index.ts +++ b/src/photo/index.ts @@ -1,7 +1,4 @@ -import { - ABSOLUTE_PATH_FOR_HOME_IMAGE, - absolutePathForPhotoImage, -} from '@/site/paths'; +import { ABSOLUTE_PATH_FOR_HOME_IMAGE } from '@/site/paths'; import { formatDateFromPostgresString } from '@/utility/date'; import { formatAperture, @@ -146,8 +143,7 @@ export const getPhotosLimitForQuery = ( }; export const generateOgImageMetaForPhotos = (photos: Photo[]): Metadata => { - if (photos.length >= 6) { - // Show multiple photos once a 3x2 grid is available + if (photos.length > 0) { return { openGraph: { images: ABSOLUTE_PATH_FOR_HOME_IMAGE, @@ -157,21 +153,10 @@ export const generateOgImageMetaForPhotos = (photos: Photo[]): Metadata => { images: ABSOLUTE_PATH_FOR_HOME_IMAGE, }, }; - } else if (photos.length > 0) { - // Otherwise show the first photo - const photo = photos[0]; - return { - openGraph: { - images: absolutePathForPhotoImage(photo), - }, - twitter: { - card: 'summary_large_image', - images: absolutePathForPhotoImage(photo), - }, - }; + } else { + // If there are no photos, refrain from showing an OG image + return {}; } - // If there are no photos, refrain from showing an OG image - return {}; }; const PHOTO_ID_FORWARDING_TABLE: Record = JSON.parse( From 70004bb916b4fe8d0c000fc9592cfafd925bfcb6 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 30 Sep 2023 23:52:25 -0500 Subject: [PATCH 08/15] Stop exporting CSRF_experimental from auth --- src/auth/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/auth/index.ts b/src/auth/index.ts index b9a162f6..f548eb5c 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -13,7 +13,6 @@ declare module 'next-auth' { export const { handlers: { GET, POST }, auth, - CSRF_experimental, } = NextAuth({ providers: [ Credentials({ From 1acda9610c587eecc38789dbb50f919b355ce84e Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 1 Oct 2023 00:00:58 -0500 Subject: [PATCH 09/15] Add title attribute to Apple make symbol --- src/photo/PhotoMakeModel.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/photo/PhotoMakeModel.tsx b/src/photo/PhotoMakeModel.tsx index 99957c58..2e66e3a4 100644 --- a/src/photo/PhotoMakeModel.tsx +++ b/src/photo/PhotoMakeModel.tsx @@ -13,7 +13,10 @@ export default function PhotoMakeModel({ 'uppercase', )}> {photo.make === 'Apple' - ? + ? : photo.make}   {photo.model} From 6e68aa16c532ed1c05e665996baab893a3be22ad Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 1 Oct 2023 22:58:55 -0500 Subject: [PATCH 10/15] Show camera devices, add clear cache button --- src/app/(auth-state)/admin/photos/page.tsx | 18 ++++- src/app/(static)/grid/page.tsx | 30 ++++++-- src/cache/index.ts | 80 ++++++++++++++++------ src/components/AnimateItems.tsx | 3 + src/components/HeaderList.tsx | 29 ++++++++ src/photo/PhotoDevice.tsx | 32 +++++++++ src/photo/PhotoLarge.tsx | 4 +- src/photo/PhotoMakeModel.tsx | 25 ------- src/photo/actions.ts | 8 ++- src/services/postgres.ts | 33 +++++++-- src/site/paths.ts | 12 +++- src/tag/PhotoTag.tsx | 17 +++-- src/utility/string.ts | 6 ++ 13 files changed, 225 insertions(+), 72 deletions(-) create mode 100644 src/components/HeaderList.tsx create mode 100644 src/photo/PhotoDevice.tsx delete mode 100644 src/photo/PhotoMakeModel.tsx diff --git a/src/app/(auth-state)/admin/photos/page.tsx b/src/app/(auth-state)/admin/photos/page.tsx index d0835eb6..85914ac8 100644 --- a/src/app/(auth-state)/admin/photos/page.tsx +++ b/src/app/(auth-state)/admin/photos/page.tsx @@ -9,6 +9,7 @@ import SiteGrid from '@/components/SiteGrid'; import { deletePhotoAction, deleteBlobPhotoAction, + syncCacheAction, } from '@/photo/actions'; import { FaRegEdit } from 'react-icons/fa'; import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus'; @@ -27,6 +28,7 @@ import { getPhotosCountIncludingHiddenCached, } from '@/cache'; import { AiOutlineEyeInvisible } from 'react-icons/ai'; +import { BiTrash } from 'react-icons/bi'; export const runtime = 'edge'; @@ -58,7 +60,21 @@ export default async function AdminPage({ contentMain={
    - +
    +
    + +
    +
    + } + > + Clear Cache + +
    +
    {blobUploadUrls.length > 0 && photos.length; @@ -48,11 +54,25 @@ export default async function GridPage({ {showMorePhotos && }
    } - contentSide={tags && - )} - staggerOnFirstLoadOnly + contentSide={
    + {tags.length > 0 && } + items={tags.map(tag => + )} />} + {devices.length > 0 && } + items={devices.map(({ device, make, model }) => + )} + />} +
    } sideHiddenOnMobile /> : diff --git a/src/cache/index.ts b/src/cache/index.ts index b7d79606..f0949630 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -5,6 +5,7 @@ import { getPhotos, getPhotosCount, getPhotosCountIncludingHidden, + getUniqueDevices, getUniqueTags, } from '@/services/postgres'; import { parseCachedPhotosDates, parseCachedPhotoDates } from '@/photo'; @@ -14,31 +15,45 @@ import { AuthSession } from 'next-auth'; const TAG_PHOTOS = 'photos'; const TAG_PHOTOS_COUNT = 'photos-count'; const TAG_TAGS = 'tags'; +const TAG_DEVICES = 'devices'; const TAG_BLOB = 'blob'; -const getPhotosCacheTags = (options: GetPhotosOptions = {}) => { - const tags = []; - - const { - sortBy, - limit, - offset, - tag, - takenAfterInclusive, - takenBefore, - includeHidden, - } = options; +// eslint-disable-next-line max-len +const getPhotosCacheTagForKey = ( + options: GetPhotosOptions, + key: keyof GetPhotosOptions, +): string | null => { + switch (key) { + // Primitive keys + case 'sortBy': + case 'limit': + case 'offset': + case 'tag': + case 'includeHidden': { + const value = options[key]; + return value ? `${key}-${value}` : null; + } + // Date keys + case 'takenBefore': + case 'takenAfterInclusive': { + const value = options[key]; + return value ? `${key}-${value.toISOString()}` : null; + } + // Complex keys + case 'device': { + const value = options[key]; + return value ? `${key}-${value.make}-${value.model}` : null; + } + } +}; - if (sortBy !== undefined) { tags.push(`sortBy-${sortBy}`); } - if (limit !== undefined) { tags.push(`limit-${limit}`); } - if (offset !== undefined) { tags.push(`offset-${offset}`); } - if (tag !== undefined) { tags.push(`tag-${tag}`); } - // eslint-disable-next-line max-len - if (takenBefore !== undefined) { tags.push(`takenBefore-${takenBefore.toISOString()}`); } - // eslint-disable-next-line max-len - if (takenAfterInclusive !== undefined) { tags.push(`takenAfterInclusive-${takenAfterInclusive.toISOString()}`); } - // eslint-disable-next-line max-len - if (includeHidden !== undefined) { tags.push(`includeHidden-${includeHidden}`); } +const getPhotosCacheTags = (options: GetPhotosOptions = {}) => { + const tags: string[] = []; + + Object.keys(options).forEach(key => { + const tag = getPhotosCacheTagForKey(options, key as keyof GetPhotosOptions); + if (tag) { tags.push(tag); } + }); return tags; }; @@ -48,6 +63,12 @@ const getPhotoCacheTag = (photoId: string) => `photo-${photoId}`; export const revalidatePhotosTag = () => revalidateTag(TAG_PHOTOS); +export const revalidateTagsTag = () => + revalidateTag(TAG_TAGS); + +export const revalidateDevicesTag = () => + revalidateTag(TAG_DEVICES); + export const revalidateBlobTag = () => revalidateTag(TAG_BLOB); @@ -56,6 +77,13 @@ export const revalidatePhotosAndBlobTag = () => { revalidateTag(TAG_BLOB); }; +export const revalidateAllTags = () => { + revalidatePhotosTag(); + revalidateTagsTag(); + revalidateDevicesTag(); + revalidateBlobTag(); +}; + export const getPhotosCached: typeof getPhotos = (...args) => unstable_cache( () => getPhotos(...args), @@ -97,6 +125,14 @@ export const getUniqueTagsCached: typeof getUniqueTags = (...args) => } )(); +export const getUniqueDevicesCached: typeof getUniqueDevices = (...args) => + unstable_cache( + () => getUniqueDevices(...args), + [TAG_PHOTOS, TAG_DEVICES], { + tags: [TAG_PHOTOS, TAG_DEVICES], + } + )(); + export const getBlobUploadUrlsCached: typeof getBlobUploadUrls = (...args) => unstable_cache( () => getBlobUploadUrls(...args), diff --git a/src/components/AnimateItems.tsx b/src/components/AnimateItems.tsx index 6bc5bb4b..98d5c6ed 100644 --- a/src/components/AnimateItems.tsx +++ b/src/components/AnimateItems.tsx @@ -16,6 +16,7 @@ export interface AnimationConfig { interface Props extends AnimationConfig { className?: string + classNameItem?: string items: JSX.Element[] animateFromAppState?: boolean animateOnFirstLoadOnly?: boolean @@ -24,6 +25,7 @@ interface Props extends AnimationConfig { function AnimateItems({ className, + classNameItem, items, type = 'scale', duration = 0.6, @@ -96,6 +98,7 @@ function AnimateItems({ {items.map((item, index) => + {icon} + {icon && <> } + {title} +
    , + ].concat(items)} + classNameItem="text-gray-400 dark:text-gray-500" + /> + ); +} diff --git a/src/photo/PhotoDevice.tsx b/src/photo/PhotoDevice.tsx new file mode 100644 index 00000000..78539abc --- /dev/null +++ b/src/photo/PhotoDevice.tsx @@ -0,0 +1,32 @@ +import { AiFillApple } from 'react-icons/ai'; +import { cc } from '@/utility/css'; + +export default function PhotoDevice({ + make, + model, + hideApple, +}: { + make?: string + model?: string + hideApple?: boolean +}) { + return ( +
    + {!(hideApple && make === 'Apple') && + <> + {make === 'Apple' + ? + : make} +   + } + {model} +
    + ); +} diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index 5e11a715..a9e6c67c 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -6,7 +6,7 @@ import Link from 'next/link'; import { pathForPhoto, pathForPhotoShare } from '@/site/paths'; import PhotoTags from '@/tag/PhotoTags'; import ShareButton from '@/components/ShareButton'; -import PhotoMakeModel from './PhotoMakeModel'; +import PhotoDevice from './PhotoDevice'; export default function PhotoLarge({ photo, @@ -64,7 +64,7 @@ export default function PhotoLarge({ {tagsToShow.length > 0 && } - + )} {renderMiniGrid(<>
      - {photo.make === 'Apple' - ? - : photo.make} -   - {photo.model} - - ); -} diff --git a/src/photo/actions.ts b/src/photo/actions.ts index b5aeb33a..f27e7989 100644 --- a/src/photo/actions.ts +++ b/src/photo/actions.ts @@ -12,8 +12,8 @@ import { deleteBlobPhoto, } from '@/services/blob'; import { + revalidateAllTags, revalidateBlobTag, - revalidatePhotosAndBlobTag, revalidatePhotosTag, } from '@/cache'; import { IS_PRO_MODE } from '@/site/config'; @@ -38,7 +38,7 @@ export async function createPhotoAction(formData: FormData) { await sqlInsertPhoto(photo); - revalidatePhotosAndBlobTag(); + revalidateAllTags(); redirect('/admin/photos'); } @@ -67,3 +67,7 @@ export async function deleteBlobPhotoAction(formData: FormData) { revalidateBlobTag(); }; + +export async function syncCacheAction() { + revalidateAllTags(); +} diff --git a/src/services/postgres.ts b/src/services/postgres.ts index d5bce43e..88a640c3 100644 --- a/src/services/postgres.ts +++ b/src/services/postgres.ts @@ -188,6 +188,17 @@ const sqlGetPhotosByTag = ( LIMIT ${limit} OFFSET ${offset} `; +const sqlGetPhotosByDevice = async ( + limit = PHOTO_DEFAULT_LIMIT, + make: string, + model: string, +) => sql` + SELECT * FROM photos + WHERE make=${make} AND model=${model} + ORDER BY taken_at DESC + LIMIT ${limit} +`; + const sqlGetPhotosTakenAfterDateInclusive = ( takenAt: Date, limit?: number, @@ -225,15 +236,24 @@ const sqlGetPhotosCountIncludingHidden = async () => sql` `.then(({ rows }) => parseInt(rows[0].count, 10)); const sqlGetUniqueTags = async () => sql` - SELECT DISTINCT unnest(tags) FROM photos + SELECT DISTINCT unnest(tags) as tag FROM photos WHERE hidden IS NOT TRUE -`.then(({ rows }) => rows.map(row => row.unnest as string)); + ORDER BY tag ASC +`.then(({ rows }) => rows.map(row => row.tag as string)); + +const sqlGetUniqueDevices = async () => sql` + SELECT DISTINCT make||' '||model as device, make, model FROM photos + WHERE hidden IS NOT TRUE + ORDER BY device ASC +`.then(({ rows }) => + rows as { device: string, make: string, model: string }[]); export type GetPhotosOptions = { sortBy?: 'createdAt' | 'takenAt' | 'priority' limit?: number offset?: number tag?: string + device?: { make: string, model: string } takenBefore?: Date takenAfterInclusive?: Date includeHidden?: boolean @@ -246,9 +266,7 @@ const safelyQueryPhotos = async (callback: () => Promise): Promise => { result = await callback(); } catch (e: any) { if (/relation "photos" does not exist/i.test(e.message)) { - console.log( - 'Creating table "photos" because it did not exist', - ); + console.log('Creating table "photos" because it did not exist'); await sqlCreatePhotosTable(); result = await callback(); } else if (/endpoint is in transition/i.test(e.message)) { @@ -275,6 +293,7 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => { limit, offset, tag, + device, takenBefore, takenAfterInclusive, includeHidden, @@ -291,6 +310,8 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => { getPhotosSql = () => sqlGetPhotosTakenAfterDateInclusive(takenAfterInclusive, limit); } else if (tag) { getPhotosSql = () => sqlGetPhotosByTag(limit, offset, tag); + } else if (device) { + getPhotosSql = () => sqlGetPhotosByDevice(limit, device.make, device.model); } else if (sortBy === 'createdAt') { getPhotosSql = () => sqlGetPhotosSortedByCreatedAt(limit, offset); } else if (sortBy === 'priority') { @@ -316,3 +337,5 @@ export const getPhotosCountIncludingHidden = () => safelyQueryPhotos(sqlGetPhotosCountIncludingHidden); export const getUniqueTags = () => safelyQueryPhotos(sqlGetUniqueTags); + +export const getUniqueDevices = () => safelyQueryPhotos(sqlGetUniqueDevices); diff --git a/src/site/paths.ts b/src/site/paths.ts index 8dc636fd..911c5f83 100644 --- a/src/site/paths.ts +++ b/src/site/paths.ts @@ -1,9 +1,11 @@ import { Photo } from '@/photo'; import { BASE_URL } from './config'; +import { parameterize } from '@/utility/string'; // Prefixes -const PREFIX_PHOTO = '/p'; -const PREFIX_TAG = '/t'; +const PREFIX_PHOTO = '/p'; +const PREFIX_TAG = '/t'; +const PREFIX_DEVICE = '/d'; // Modifiers const SHARE = 'share'; @@ -54,7 +56,11 @@ export const pathForPhotoShare = (photo: PhotoOrPhotoId, tag?: string) => export const pathForPhotoEdit = (photo: PhotoOrPhotoId) => `${PATH_ADMIN_PHOTOS}/${getPhotoId(photo)}/edit`; -export const pathForTag = (tag: string) => `${PREFIX_TAG}/${tag}`; +export const pathForTag = (tag: string) => + `${PREFIX_TAG}/${tag}`; + +export const pathForDevice = (make?: string, model?: string) => + `${PREFIX_DEVICE}/${parameterize(`${make}-${model}`)}`; export const pathForTagShare = (tag: string) => `${pathForTag(tag)}/${SHARE}`; diff --git a/src/tag/PhotoTag.tsx b/src/tag/PhotoTag.tsx index b640fd4a..87bc5c68 100644 --- a/src/tag/PhotoTag.tsx +++ b/src/tag/PhotoTag.tsx @@ -5,8 +5,10 @@ import { cc } from '@/utility/css'; export default function PhotoTag({ tag, + showIcon = true, }: { tag: string + showIcon?: boolean }) { return ( - + {showIcon && + } {tag.replaceAll('-', ' ')} diff --git a/src/utility/string.ts b/src/utility/string.ts index ed8e8ab3..73590a36 100644 --- a/src/utility/string.ts +++ b/src/utility/string.ts @@ -15,3 +15,9 @@ export const capitalizeWords = (string: string) => .split(' ') .map(capitalize) .join(' '); + +export const parameterize = (string: string) => + string + .trim() + .replaceAll(' ', '-') + .toLowerCase(); From af7af534016c91bb55ff0040de2a7c4132a0ece1 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Mon, 2 Oct 2023 11:51:04 -0500 Subject: [PATCH 11/15] Create device photo set view --- src/app/(static)/d/[device]/page.tsx | 71 ++++++++++++++++++++++++++++ src/app/(static)/grid/page.tsx | 3 +- src/device/DeviceHeader.tsx | 26 ++++++++++ src/device/PhotoDevice.tsx | 45 ++++++++++++++++++ src/device/index.ts | 14 ++++++ src/photo/PhotoDevice.tsx | 32 ------------- src/photo/PhotoHeader.tsx | 54 +++++++++++++++++++++ src/photo/PhotoLarge.tsx | 9 +++- src/photo/index.ts | 12 +++++ src/services/postgres.ts | 4 +- src/tag/TagHeader.tsx | 45 ++++-------------- src/tag/index.ts | 11 ++--- 12 files changed, 247 insertions(+), 79 deletions(-) create mode 100644 src/app/(static)/d/[device]/page.tsx create mode 100644 src/device/DeviceHeader.tsx create mode 100644 src/device/PhotoDevice.tsx create mode 100644 src/device/index.ts delete mode 100644 src/photo/PhotoDevice.tsx create mode 100644 src/photo/PhotoHeader.tsx diff --git a/src/app/(static)/d/[device]/page.tsx b/src/app/(static)/d/[device]/page.tsx new file mode 100644 index 00000000..8c56e93c --- /dev/null +++ b/src/app/(static)/d/[device]/page.tsx @@ -0,0 +1,71 @@ +import { getPhotosCached } from '@/cache'; +import SiteGrid from '@/components/SiteGrid'; +import DeviceHeader from '@/device/DeviceHeader'; +import { getMakeModelFromDevice } from '@/device'; +import PhotoGrid from '@/photo/PhotoGrid'; +import { getUniqueDevices } from '@/services/postgres'; +import { generateMetaForTag } from '@/tag'; +import { Metadata } from 'next'; + +interface TagProps { + params: { device: string } +} + +export async function generateStaticParams() { + const devices = await getUniqueDevices(); + return devices.map(device => ({ + params: { device }, + })); +} + +export async function generateMetadata({ + params: { device }, +}: TagProps): Promise { + const photos = await getPhotosCached({ + device: getMakeModelFromDevice(device), + }); + + const { + url, + title, + description, + images, + } = generateMetaForTag(device, photos); + + return { + title, + openGraph: { + title, + description, + images, + url, + }, + twitter: { + images, + description, + card: 'summary_large_image', + }, + description, + }; +} + +export default async function DevicePage({ params: { device } }:TagProps) { + const photos = await getPhotosCached({ + device: getMakeModelFromDevice(device), + }); + + // Harvest original make/model with proper spaces/slashes + const deviceFormatted = photos.length > 0 + ? `${photos[0].make} ${photos[0].model}` + : device; + + return ( + + + + } + /> + ); +} diff --git a/src/app/(static)/grid/page.tsx b/src/app/(static)/grid/page.tsx index fb2d488c..9abea5ff 100644 --- a/src/app/(static)/grid/page.tsx +++ b/src/app/(static)/grid/page.tsx @@ -8,7 +8,7 @@ import HeaderList from '@/components/HeaderList'; import MorePhotos from '@/components/MorePhotos'; import SiteGrid from '@/components/SiteGrid'; import { generateOgImageMetaForPhotos, getPhotosLimitForQuery } from '@/photo'; -import PhotoDevice from '@/photo/PhotoDevice'; +import PhotoDevice from '@/device/PhotoDevice'; import PhotoGrid from '@/photo/PhotoGrid'; import PhotosEmptyState from '@/photo/PhotosEmptyState'; import { MAX_PHOTOS_TO_SHOW_HOME } from '@/photo/image-response'; @@ -69,6 +69,7 @@ export default async function GridPage({ key={device} make={make} model={model} + showIcon={false} hideApple />)} />} diff --git a/src/device/DeviceHeader.tsx b/src/device/DeviceHeader.tsx new file mode 100644 index 00000000..51a2b452 --- /dev/null +++ b/src/device/DeviceHeader.tsx @@ -0,0 +1,26 @@ +import { Photo } from '@/photo'; +import { pathForTagShare } from '@/site/paths'; +import PhotoHeader from '@/photo/PhotoHeader'; +import { descriptionForDevicePhotos, getMakeModelFromDevice } from '.'; +import PhotoDevice from './PhotoDevice'; + +export default function DeviceHeader({ + device, + photos, + selectedPhoto, +}: { + device: string + photos: Photo[] + selectedPhoto?: Photo +}) { + return ( + } + entityVerb="Device" + entityDescription={descriptionForDevicePhotos(photos)} + photos={photos} + selectedPhoto={selectedPhoto} + sharePath={pathForTagShare(device)} + /> + ); +} diff --git a/src/device/PhotoDevice.tsx b/src/device/PhotoDevice.tsx new file mode 100644 index 00000000..0c0a3fa1 --- /dev/null +++ b/src/device/PhotoDevice.tsx @@ -0,0 +1,45 @@ +import { AiFillApple } from 'react-icons/ai'; +import { cc } from '@/utility/css'; +import Link from 'next/link'; +import { pathForDevice } from '@/site/paths'; +import { IoMdCamera } from 'react-icons/io'; + +export default function PhotoDevice({ + make, + model, + showIcon = true, + hideApple = true, +}: { + make?: string + model?: string + showIcon?: boolean + hideApple?: boolean +}) { + console.log({ make, model, showIcon, hideApple }); + return ( + + {showIcon && <> + +   + } + {!(hideApple && make?.toLowerCase() === 'apple') && + <> + {make?.toLowerCase() === 'apple' + ? + : make} +   + } + {model} + + ); +} diff --git a/src/device/index.ts b/src/device/index.ts new file mode 100644 index 00000000..094323f0 --- /dev/null +++ b/src/device/index.ts @@ -0,0 +1,14 @@ +import { Photo, descriptionForPhotoSet } from '@/photo'; + +// Assumes no device makes ('Fujifilm,' 'Apple,' 'Canon', etc.) +// will have dashes in them +export const getMakeModelFromDevice = (device: string) => { + const [make, model] = device.toLowerCase().split(/[-| ](.*)/s); + return { make, model }; +}; + +export const descriptionForDevicePhotos = ( + photos: Photo[], + dateBased?: boolean, +) => + descriptionForPhotoSet(photos, 'device', dateBased); diff --git a/src/photo/PhotoDevice.tsx b/src/photo/PhotoDevice.tsx deleted file mode 100644 index 78539abc..00000000 --- a/src/photo/PhotoDevice.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { AiFillApple } from 'react-icons/ai'; -import { cc } from '@/utility/css'; - -export default function PhotoDevice({ - make, - model, - hideApple, -}: { - make?: string - model?: string - hideApple?: boolean -}) { - return ( -
      - {!(hideApple && make === 'Apple') && - <> - {make === 'Apple' - ? - : make} -   - } - {model} -
      - ); -} diff --git a/src/photo/PhotoHeader.tsx b/src/photo/PhotoHeader.tsx new file mode 100644 index 00000000..3e5958bb --- /dev/null +++ b/src/photo/PhotoHeader.tsx @@ -0,0 +1,54 @@ +import { cc } from '@/utility/css'; +import { Photo, dateRangeForPhotos } from '.'; +import ShareButton from '@/components/ShareButton'; + +export default function PhotoHeader({ + entity, + entityVerb, + entityDescription, + photos, + selectedPhoto, + sharePath, +}: { + entity: JSX.Element + entityVerb: string + entityDescription: string + photos: Photo[] + selectedPhoto?: Photo + sharePath: string +}) { + const { start, end } = dateRangeForPhotos(photos); + + const selectedPhotoIndex = selectedPhoto + ? photos.findIndex(photo => photo.id === selectedPhoto.id) + : undefined; + + return ( +
      + {entity} + + {selectedPhotoIndex !== undefined + ? `${entityVerb} ${selectedPhotoIndex + 1} of ${photos.length}` + : entityDescription} + {selectedPhotoIndex === undefined && + } + + + {start === end + ? start + : <>{start}
      – {end}} +
      +
      + ); +} diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index a9e6c67c..91b42e29 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -6,7 +6,7 @@ import Link from 'next/link'; import { pathForPhoto, pathForPhotoShare } from '@/site/paths'; import PhotoTags from '@/tag/PhotoTags'; import ShareButton from '@/components/ShareButton'; -import PhotoDevice from './PhotoDevice'; +import PhotoDevice from '../device/PhotoDevice'; export default function PhotoLarge({ photo, @@ -64,7 +64,12 @@ export default function PhotoLarge({ {tagsToShow.length > 0 && } - + )} {renderMiniGrid(<>
        export const titleForPhoto = (photo: Photo) => photo.title || 'Untitled'; +export const labelForPhotos = (photos: Photo[]) => + photos.length === 1 ? 'Photo' : 'Photos'; + +export const descriptionForPhotoSet = ( + photos:Photo[], + descriptor: string, + dateBased?: boolean, +) => + dateBased + ? dateRangeForPhotos(photos).description.toUpperCase() + : `${photos.length} ${descriptor} ${labelForPhotos(photos)}`; + export const dateRangeForPhotos = (photos: Photo[]) => { const start = photos[0].takenAtNaiveFormattedShort; const end = photos[photos.length - 1].takenAtNaiveFormattedShort; diff --git a/src/services/postgres.ts b/src/services/postgres.ts index 88a640c3..11d8475d 100644 --- a/src/services/postgres.ts +++ b/src/services/postgres.ts @@ -194,7 +194,9 @@ const sqlGetPhotosByDevice = async ( model: string, ) => sql` SELECT * FROM photos - WHERE make=${make} AND model=${model} + WHERE + LOWER(make)=${make} AND + LOWER(REPLACE(model, ' ', '-'))=${model} ORDER BY taken_at DESC LIMIT ${limit} `; diff --git a/src/tag/TagHeader.tsx b/src/tag/TagHeader.tsx index 0f25aa49..1b6ac981 100644 --- a/src/tag/TagHeader.tsx +++ b/src/tag/TagHeader.tsx @@ -1,9 +1,8 @@ -import { Photo, dateRangeForPhotos } from '@/photo'; -import { cc } from '@/utility/css'; +import { Photo } from '@/photo'; import PhotoTag from './PhotoTag'; import { descriptionForTaggedPhotos } from '.'; -import ShareButton from '@/components/ShareButton'; import { pathForTagShare } from '@/site/paths'; +import PhotoHeader from '@/photo/PhotoHeader'; export default function TagHeader({ tag, @@ -14,38 +13,14 @@ export default function TagHeader({ photos: Photo[] selectedPhoto?: Photo }) { - const { start, end } = dateRangeForPhotos(photos); - - const selectedPhotoIndex = selectedPhoto - ? photos.findIndex(photo => photo.id === selectedPhoto.id) - : undefined; - return ( -
        - - - {selectedPhotoIndex !== undefined - ? `Tagged ${selectedPhotoIndex + 1} of ${photos.length}` - : descriptionForTaggedPhotos(photos)} - {selectedPhotoIndex === undefined && - } - - - {start === end - ? start - : <>{start}
        – {end}} -
        -
        + } + entityVerb="Tagged" + entityDescription={descriptionForTaggedPhotos(photos)} + photos={photos} + selectedPhoto={selectedPhoto} + sharePath={pathForTagShare(tag)} + /> ); } diff --git a/src/tag/index.ts b/src/tag/index.ts index 8b97dc88..f8de8a28 100644 --- a/src/tag/index.ts +++ b/src/tag/index.ts @@ -1,22 +1,17 @@ -import { Photo, dateRangeForPhotos } from '@/photo'; +import { Photo, descriptionForPhotoSet, labelForPhotos } from '@/photo'; import { absolutePathForTag, absolutePathForTagImage } from '@/site/paths'; import { capitalizeWords } from '@/utility/string'; -const labelForPhotos = (photos: Photo[]) => - photos.length === 1 ? 'Photo' : 'Photos'; - export const titleForTag = (tag: string, photos:Photo[]) => [ capitalizeWords(tag.replaceAll('-', ' ')), `(${photos.length} ${labelForPhotos(photos)})`, ].join(' '); export const descriptionForTaggedPhotos = ( - photos:Photo[], + photos: Photo[], dateBased?: boolean, ) => - dateBased - ? dateRangeForPhotos(photos).description.toUpperCase() - : `${photos.length} Tagged ${labelForPhotos(photos)}`; + descriptionForPhotoSet(photos, 'tagged', dateBased); export const generateMetaForTag = (tag: string, photos: Photo[]) => ({ url: absolutePathForTag(tag), From 6c5537725731e5c718cf7b990fbfe0fd865b9ff9 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Tue, 3 Oct 2023 11:23:07 -0500 Subject: [PATCH 12/15] Add robust support for device-based views --- __tests__/path.test.ts | 59 ++++++++-- src/app/(static)/grid/page.tsx | 13 ++- src/app/(static)/p/[photoId]/image/route.tsx | 5 +- .../shot-on/[device]/[photoId]/layout.tsx | 86 +++++++++++++++ .../shot-on/[device]/[photoId]/page.tsx | 3 + .../shot-on/[device]/[photoId]/share/page.tsx | 34 ++++++ .../(static)/shot-on/[device]/image/route.tsx | 45 ++++++++ .../(static)/{d => shot-on}/[device]/page.tsx | 38 +++---- .../(static)/shot-on/[device]/share/page.tsx | 74 +++++++++++++ src/app/(static)/t/[tag]/image/route.tsx | 7 +- src/app/(static)/t/[tag]/share/page.tsx | 2 +- src/components/HeaderList.tsx | 3 +- src/components/IconPathButton.tsx | 11 +- src/components/ShareButton.tsx | 1 + src/device/DeviceHeader.tsx | 14 ++- src/device/DeviceOGTile.tsx | 39 +++++++ src/device/DeviceShareModal.tsx | 23 ++++ src/device/PhotoDevice.tsx | 19 ++-- src/device/index.ts | 40 +++++-- src/device/meta.ts | 26 +++++ src/photo/PhotoDetailPage.tsx | 24 +++- src/photo/PhotoGrid.tsx | 4 + src/photo/PhotoLarge.tsx | 25 +++-- src/photo/PhotoLink.tsx | 5 +- src/photo/PhotoLinks.tsx | 16 ++- src/photo/PhotoShareModal.tsx | 7 +- src/photo/PhotoSmall.tsx | 5 +- .../image-response/DeviceImageResponse.tsx | 44 ++++++++ .../components/ImageCaption.tsx | 37 +++++-- src/services/postgres.ts | 14 ++- src/site/paths.ts | 103 ++++++++++++++---- src/tag/PhotoTag.tsx | 6 +- 32 files changed, 717 insertions(+), 115 deletions(-) create mode 100644 src/app/(static)/shot-on/[device]/[photoId]/layout.tsx create mode 100644 src/app/(static)/shot-on/[device]/[photoId]/page.tsx create mode 100644 src/app/(static)/shot-on/[device]/[photoId]/share/page.tsx create mode 100644 src/app/(static)/shot-on/[device]/image/route.tsx rename src/app/(static)/{d => shot-on}/[device]/page.tsx (51%) create mode 100644 src/app/(static)/shot-on/[device]/share/page.tsx create mode 100644 src/device/DeviceOGTile.tsx create mode 100644 src/device/DeviceShareModal.tsx create mode 100644 src/device/meta.ts create mode 100644 src/photo/image-response/DeviceImageResponse.tsx diff --git a/__tests__/path.test.ts b/__tests__/path.test.ts index 8168e6d1..bd9d54b0 100644 --- a/__tests__/path.test.ts +++ b/__tests__/path.test.ts @@ -2,6 +2,10 @@ import '@testing-library/jest-dom'; import { getEscapePath, getPathComponents, + isPathDevice, + isPathDevicePhoto, + isPathDevicePhotoShare, + isPathDeviceShare, isPathPhoto, isPathPhotoShare, isPathTag, @@ -9,20 +13,30 @@ import { isPathTagPhotoShare, isPathTagShare, } from '@/site/paths'; +import { getMakeModelFromDeviceString } from '@/device'; const PHOTO_ID = 'UsKSGcbt'; const TAG = 'tag-name'; +const DEVICE = 'fujifilm-x-t1'; +const DEVICE_OBJECT = getMakeModelFromDeviceString(DEVICE); const SHARE = 'share'; -const PATH_ROOT = '/'; -const PATH_GRID = '/grid'; -const PATH_ADMIN = '/admin/photos'; -const PATH_PHOTO = `/p/${PHOTO_ID}`; -const PATH_PHOTO_SHARE = `${PATH_PHOTO}/${SHARE}`; -const PATH_TAG = `/t/${TAG}`; -const PATH_TAG_SHARE = `${PATH_TAG}/${SHARE}`; -const PATH_TAG_PHOTO = `${PATH_TAG}/${PHOTO_ID}`; -const PATH_TAG_PHOTO_SHARE = `${PATH_TAG}/${PHOTO_ID}/${SHARE}`; +const PATH_ROOT = '/'; +const PATH_GRID = '/grid'; +const PATH_ADMIN = '/admin/photos'; + +const PATH_PHOTO = `/p/${PHOTO_ID}`; +const PATH_PHOTO_SHARE = `${PATH_PHOTO}/${SHARE}`; + +const PATH_TAG = `/t/${TAG}`; +const PATH_TAG_SHARE = `${PATH_TAG}/${SHARE}`; +const PATH_TAG_PHOTO = `${PATH_TAG}/${PHOTO_ID}`; +const PATH_TAG_PHOTO_SHARE = `${PATH_TAG_PHOTO}/${SHARE}`; + +const PATH_DEVICE = `/shot-on/${DEVICE}`; +const PATH_DEVICE_SHARE = `${PATH_DEVICE}/${SHARE}`; +const PATH_DEVICE_PHOTO = `${PATH_DEVICE}/${PHOTO_ID}`; +const PATH_DEVICE_PHOTO_SHARE = `${PATH_DEVICE_PHOTO}/${SHARE}`; describe('Paths', () => { it('can be classified', () => { @@ -33,6 +47,10 @@ describe('Paths', () => { expect(isPathTagShare(PATH_TAG_SHARE)).toBe(true); expect(isPathTagPhoto(PATH_TAG_PHOTO)).toBe(true); expect(isPathTagPhotoShare(PATH_TAG_PHOTO_SHARE)).toBe(true); + expect(isPathDevice(PATH_DEVICE)).toBe(true); + expect(isPathDeviceShare(PATH_DEVICE_SHARE)).toBe(true); + expect(isPathDevicePhoto(PATH_DEVICE_PHOTO)).toBe(true); + expect(isPathDevicePhotoShare(PATH_DEVICE_PHOTO_SHARE)).toBe(true); // Negative expect(isPathPhoto(PATH_TAG_PHOTO_SHARE)).toBe(false); expect(isPathPhotoShare(PATH_TAG_PHOTO)).toBe(false); @@ -40,6 +58,10 @@ describe('Paths', () => { expect(isPathTagShare(PATH_TAG)).toBe(false); expect(isPathTagPhoto(PATH_PHOTO_SHARE)).toBe(false); expect(isPathTagPhotoShare(PATH_PHOTO)).toBe(false); + expect(isPathDevice(PATH_TAG_SHARE)).toBe(false); + expect(isPathDeviceShare(PATH_TAG)).toBe(false); + expect(isPathDevicePhoto(PATH_PHOTO_SHARE)).toBe(false); + expect(isPathDevicePhotoShare(PATH_PHOTO)).toBe(false); }); it('can be parsed', () => { expect(getPathComponents(PATH_ROOT)).toEqual({}); @@ -63,6 +85,20 @@ describe('Paths', () => { photoId: PHOTO_ID, tag: TAG, }); + expect(getPathComponents(PATH_DEVICE)).toEqual({ + device: DEVICE_OBJECT, + }); + expect(getPathComponents(PATH_DEVICE_SHARE)).toEqual({ + device: DEVICE_OBJECT, + }); + expect(getPathComponents(PATH_DEVICE_PHOTO)).toEqual({ + photoId: PHOTO_ID, + device: DEVICE_OBJECT, + }); + expect(getPathComponents(PATH_DEVICE_PHOTO_SHARE)).toEqual({ + photoId: PHOTO_ID, + device: DEVICE_OBJECT, + }); }); it('can be escaped', () => { // Root views @@ -77,5 +113,10 @@ describe('Paths', () => { expect(getEscapePath(PATH_TAG_SHARE)).toEqual(PATH_TAG); expect(getEscapePath(PATH_TAG_PHOTO)).toEqual(PATH_TAG); expect(getEscapePath(PATH_TAG_PHOTO_SHARE)).toEqual(PATH_TAG_PHOTO); + // Device views + expect(getEscapePath(PATH_DEVICE)).toEqual(PATH_GRID); + expect(getEscapePath(PATH_DEVICE_SHARE)).toEqual(PATH_DEVICE); + expect(getEscapePath(PATH_DEVICE_PHOTO)).toEqual(PATH_DEVICE); + expect(getEscapePath(PATH_DEVICE_PHOTO_SHARE)).toEqual(PATH_DEVICE_PHOTO); }); }); diff --git a/src/app/(static)/grid/page.tsx b/src/app/(static)/grid/page.tsx index 9abea5ff..da635ae6 100644 --- a/src/app/(static)/grid/page.tsx +++ b/src/app/(static)/grid/page.tsx @@ -59,16 +59,19 @@ export default async function GridPage({ title='Tags' icon={} items={tags.map(tag => - )} + )} />} {devices.length > 0 && } - items={devices.map(({ device, make, model }) => + items={devices.map(({ deviceKey, device }) => )} diff --git a/src/app/(static)/p/[photoId]/image/route.tsx b/src/app/(static)/p/[photoId]/image/route.tsx index 1ff41876..eab06594 100644 --- a/src/app/(static)/p/[photoId]/image/route.tsx +++ b/src/app/(static)/p/[photoId]/image/route.tsx @@ -7,7 +7,10 @@ import { ImageResponse } from 'next/server'; export const runtime = 'edge'; -export async function GET(_request: Request, context: any){ +export async function GET( + _: Request, + context: { params: { photoId: string } }, +) { const [ photo, { fontFamily, fonts }, diff --git a/src/app/(static)/shot-on/[device]/[photoId]/layout.tsx b/src/app/(static)/shot-on/[device]/[photoId]/layout.tsx new file mode 100644 index 00000000..71d03728 --- /dev/null +++ b/src/app/(static)/shot-on/[device]/[photoId]/layout.tsx @@ -0,0 +1,86 @@ +import { + descriptionForPhoto, + titleForPhoto, +} from '@/photo'; +import { Metadata } from 'next'; +import { redirect } from 'next/navigation'; +import { + PATH_ROOT, + absolutePathForPhoto, + absolutePathForPhotoImage, +} from '@/site/paths'; +import PhotoDetailPage from '@/photo/PhotoDetailPage'; +import { getPhotoCached, getPhotosCached } from '@/cache'; +import { getPhotos, getUniqueDevices } from '@/services/postgres'; +import { deviceFromPhoto } from '@/device'; + +export async function generateStaticParams() { + const params: { params: { photoId: string, device: string }}[] = []; + + const devices = await getUniqueDevices(); + devices.forEach(async ({ deviceKey, device }) => { + const photos = await getPhotos({ device }); + params.push(...photos.map(photo => ({ + params: { photoId: photo.id, device: deviceKey }, + }))); + }); + + return params; +} + +export async function generateMetadata({ + params: { photoId }, +}: { + params: { photoId: string, device: string } +}): Promise { + const photo = await getPhotoCached(photoId); + + if (!photo) { return {}; } + + const title = titleForPhoto(photo); + const description = descriptionForPhoto(photo); + const images = absolutePathForPhotoImage(photo); + const url = absolutePathForPhoto(photo, undefined, deviceFromPhoto(photo)); + + return { + title, + description, + openGraph: { + title, + images, + description, + url, + }, + twitter: { + title, + description, + images, + card: 'summary_large_image', + }, + }; +} + +export default async function PhotoDevicePage({ + params: { photoId }, + children, +}: { + params: { photoId: string, tag: string } + children: React.ReactNode +}) { + const photo = await getPhotoCached(photoId); + + if (!photo) { redirect(PATH_ROOT); } + + const device = deviceFromPhoto(photo); + + const photos = await getPhotosCached({ device }); + + return <> + {children} + + ; +} diff --git a/src/app/(static)/shot-on/[device]/[photoId]/page.tsx b/src/app/(static)/shot-on/[device]/[photoId]/page.tsx new file mode 100644 index 00000000..67e08591 --- /dev/null +++ b/src/app/(static)/shot-on/[device]/[photoId]/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return null; +} diff --git a/src/app/(static)/shot-on/[device]/[photoId]/share/page.tsx b/src/app/(static)/shot-on/[device]/[photoId]/share/page.tsx new file mode 100644 index 00000000..1bab0fc6 --- /dev/null +++ b/src/app/(static)/shot-on/[device]/[photoId]/share/page.tsx @@ -0,0 +1,34 @@ +import { getPhotoCached } from '@/cache'; +import { deviceFromPhoto } from '@/device'; +import PhotoShareModal from '@/photo/PhotoShareModal'; +import { getPhotos, getUniqueDevices } from '@/services/postgres'; +import { PATH_ROOT } from '@/site/paths'; +import { redirect } from 'next/navigation'; + +export async function generateStaticParams() { + const params: { params: { photoId: string, device: string }}[] = []; + + const devices = await getUniqueDevices(); + devices.forEach(async ({ deviceKey, device }) => { + const photos = await getPhotos({ device }); + params.push(...photos.map(photo => ({ + params: { photoId: photo.id, device: deviceKey }, + }))); + }); + + return params; +} + +export default async function Share({ + params: { photoId }, +}: { + params: { photoId: string } +}) { + const photo = await getPhotoCached(photoId); + + if (!photo) { return redirect(PATH_ROOT); } + + const device = deviceFromPhoto(photo); + + return ; +} diff --git a/src/app/(static)/shot-on/[device]/image/route.tsx b/src/app/(static)/shot-on/[device]/image/route.tsx new file mode 100644 index 00000000..f04ec80f --- /dev/null +++ b/src/app/(static)/shot-on/[device]/image/route.tsx @@ -0,0 +1,45 @@ +import { auth } from '@/auth'; +import { getImageCacheHeadersForAuth, getPhotosCached } from '@/cache'; +import { getMakeModelFromDeviceString } from '@/device'; +import { + IMAGE_OG_SMALL_SIZE, + MAX_PHOTOS_TO_SHOW_PER_TAG, +} from '@/photo/image-response'; +import DeviceImageResponse from '@/photo/image-response/DeviceImageResponse'; +import { getIBMPlexMonoMedium } from '@/site/font'; +import { ImageResponse } from 'next/server'; + +export const runtime = 'edge'; + +export async function GET( + _: Request, + context: { params: { device: string } }, +) { + const device = getMakeModelFromDeviceString(context.params.device); + + const [ + photos, + { fontFamily, fonts }, + headers, + ] = await Promise.all([ + getPhotosCached({ + limit: MAX_PHOTOS_TO_SHOW_PER_TAG, + device, + }), + getIBMPlexMonoMedium(), + getImageCacheHeadersForAuth(await auth()), + ]); + + const { width, height } = IMAGE_OG_SMALL_SIZE; + + return new ImageResponse( + , + { width, height, fonts, headers }, + ); +} diff --git a/src/app/(static)/d/[device]/page.tsx b/src/app/(static)/shot-on/[device]/page.tsx similarity index 51% rename from src/app/(static)/d/[device]/page.tsx rename to src/app/(static)/shot-on/[device]/page.tsx index 8c56e93c..795f87a0 100644 --- a/src/app/(static)/d/[device]/page.tsx +++ b/src/app/(static)/shot-on/[device]/page.tsx @@ -1,36 +1,35 @@ import { getPhotosCached } from '@/cache'; import SiteGrid from '@/components/SiteGrid'; import DeviceHeader from '@/device/DeviceHeader'; -import { getMakeModelFromDevice } from '@/device'; +import { getMakeModelFromDeviceString } from '@/device'; import PhotoGrid from '@/photo/PhotoGrid'; import { getUniqueDevices } from '@/services/postgres'; -import { generateMetaForTag } from '@/tag'; import { Metadata } from 'next'; +import { generateMetaForDevice } from '@/device/meta'; -interface TagProps { +interface DeviceProps { params: { device: string } } export async function generateStaticParams() { const devices = await getUniqueDevices(); - return devices.map(device => ({ - params: { device }, + return devices.map(({ deviceKey }): DeviceProps => ({ + params: { device: deviceKey }, })); } export async function generateMetadata({ - params: { device }, -}: TagProps): Promise { - const photos = await getPhotosCached({ - device: getMakeModelFromDevice(device), - }); + params, +}: DeviceProps): Promise { + const device = getMakeModelFromDeviceString(params.device); + const photos = await getPhotosCached({ device }); const { url, title, description, images, - } = generateMetaForTag(device, photos); + } = generateMetaForDevice(device, photos); return { title, @@ -49,22 +48,17 @@ export async function generateMetadata({ }; } -export default async function DevicePage({ params: { device } }:TagProps) { - const photos = await getPhotosCached({ - device: getMakeModelFromDevice(device), - }); - - // Harvest original make/model with proper spaces/slashes - const deviceFormatted = photos.length > 0 - ? `${photos[0].make} ${photos[0].model}` - : device; +export default async function DevicePage({ params }:DeviceProps) { + const device = getMakeModelFromDeviceString(params.device); + + const photos = await getPhotosCached({ device }); return ( - - + + } /> ); diff --git a/src/app/(static)/shot-on/[device]/share/page.tsx b/src/app/(static)/shot-on/[device]/share/page.tsx new file mode 100644 index 00000000..745fab85 --- /dev/null +++ b/src/app/(static)/shot-on/[device]/share/page.tsx @@ -0,0 +1,74 @@ +import { getPhotosCached } from '@/cache'; +import SiteGrid from '@/components/SiteGrid'; +import { deviceFromPhoto, getMakeModelFromDeviceString } from '@/device'; +import DeviceHeader from '@/device/DeviceHeader'; +import DeviceShareModal from '@/device/DeviceShareModal'; +import { generateMetaForDevice } from '@/device/meta'; +import PhotoGrid from '@/photo/PhotoGrid'; +import { getUniqueDevices } from '@/services/postgres'; +import { Metadata } from 'next'; + +interface DeviceProps { + params: { device: string } +} + +export async function generateStaticParams() { + const devices = await getUniqueDevices(); + return devices.map(({ deviceKey }): DeviceProps => ({ + params: { device: deviceKey }, + })); +} + +export async function generateMetadata({ + params, +}: DeviceProps): Promise { + const device = getMakeModelFromDeviceString(params.device); + + const photos = await getPhotosCached({ device }); + + const { + url, + title, + description, + images, + } = generateMetaForDevice(device, photos); + + return { + title, + openGraph: { + title, + description, + images, + url, + }, + twitter: { + images, + description, + card: 'summary_large_image', + }, + description, + }; +} + +export default async function Share({ + params, +}: { + params: { device: string } +}) { + const deviceFromParams = getMakeModelFromDeviceString(params.device); + + const photos = await getPhotosCached({ device: deviceFromParams }); + + const device = deviceFromPhoto(photos[0]) ?? deviceFromParams; + + return <> + + + + + } + /> + ; +} diff --git a/src/app/(static)/t/[tag]/image/route.tsx b/src/app/(static)/t/[tag]/image/route.tsx index e9175e47..860d258f 100644 --- a/src/app/(static)/t/[tag]/image/route.tsx +++ b/src/app/(static)/t/[tag]/image/route.tsx @@ -10,8 +10,11 @@ import { ImageResponse } from 'next/server'; export const runtime = 'edge'; -export async function GET(_request: Request, context: any) { - const tag = context.params.tag as string; +export async function GET( + _: Request, + context: { params: { tag: string } }, +) { + const tag = context.params.tag; const [ photos, diff --git a/src/app/(static)/t/[tag]/share/page.tsx b/src/app/(static)/t/[tag]/share/page.tsx index 2038d404..c81a936b 100644 --- a/src/app/(static)/t/[tag]/share/page.tsx +++ b/src/app/(static)/t/[tag]/share/page.tsx @@ -54,7 +54,7 @@ export default async function Share({ }) { const photos = await getPhotosCached({ tag }); return <> - + diff --git a/src/components/HeaderList.tsx b/src/components/HeaderList.tsx index 90f50269..fd8d6f46 100644 --- a/src/components/HeaderList.tsx +++ b/src/components/HeaderList.tsx @@ -14,7 +14,8 @@ export default function HeaderList({ diff --git a/src/components/IconPathButton.tsx b/src/components/IconPathButton.tsx index 64d6972b..9aa43036 100644 --- a/src/components/IconPathButton.tsx +++ b/src/components/IconPathButton.tsx @@ -11,12 +11,14 @@ export default function IconPathButton({ prefetch, loaderDelay = 250, shouldScroll = true, + shouldReplace, }: { icon: JSX.Element path: string prefetch?: boolean loaderDelay?: number shouldScroll?: boolean + shouldReplace?: boolean }) { const router = useRouter(); @@ -44,8 +46,13 @@ export default function IconPathButton({ return ( startTransition(() => - router.push(path, { scroll: shouldScroll }))} + onClick={() => startTransition(() => { + if (shouldReplace) { + router.replace(path, { scroll: shouldScroll }); + } else { + router.push(path, { scroll: shouldScroll }); + } + })} isLoading={shouldShowLoader} className={cc( 'translate-y-[-0.5px]', diff --git a/src/components/ShareButton.tsx b/src/components/ShareButton.tsx index 936ab557..08ec476a 100644 --- a/src/components/ShareButton.tsx +++ b/src/components/ShareButton.tsx @@ -20,6 +20,7 @@ export default function ShareButton({ : undefined} />, prefetch, shouldScroll, + shouldReplace: true, }} /> ); } diff --git a/src/device/DeviceHeader.tsx b/src/device/DeviceHeader.tsx index 51a2b452..f11c21c4 100644 --- a/src/device/DeviceHeader.tsx +++ b/src/device/DeviceHeader.tsx @@ -1,26 +1,28 @@ import { Photo } from '@/photo'; -import { pathForTagShare } from '@/site/paths'; +import { pathForDeviceShare } from '@/site/paths'; import PhotoHeader from '@/photo/PhotoHeader'; -import { descriptionForDevicePhotos, getMakeModelFromDevice } from '.'; +import { Device, formatDevice } from '.'; import PhotoDevice from './PhotoDevice'; +import { descriptionForDevicePhotos } from './meta'; export default function DeviceHeader({ - device, + device: deviceFromProps, photos, selectedPhoto, }: { - device: string + device: Device photos: Photo[] selectedPhoto?: Photo }) { + const device = formatDevice(deviceFromProps, photos[0]); return ( } + entity={} entityVerb="Device" entityDescription={descriptionForDevicePhotos(photos)} photos={photos} selectedPhoto={selectedPhoto} - sharePath={pathForTagShare(device)} + sharePath={pathForDeviceShare(device)} /> ); } diff --git a/src/device/DeviceOGTile.tsx b/src/device/DeviceOGTile.tsx new file mode 100644 index 00000000..e68dcbe2 --- /dev/null +++ b/src/device/DeviceOGTile.tsx @@ -0,0 +1,39 @@ +import { Photo } from '@/photo'; +import { absolutePathForDeviceImage, pathForDevice } from '@/site/paths'; +import OGTile from '@/components/OGTile'; +import { Device, titleForDevice } from '.'; +import { descriptionForDevicePhotos } from './meta'; + +export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed'; + +export default function DeviceOGTile({ + device, + photos, + loadingState: loadingStateExternal, + riseOnHover, + onLoad, + onFail, + retryTime, +}: { + device: Device + photos: Photo[] + loadingState?: OGLoadingState + onLoad?: () => void + onFail?: () => void + riseOnHover?: boolean + retryTime?: number +}) { + return ( + + ); +}; diff --git a/src/device/DeviceShareModal.tsx b/src/device/DeviceShareModal.tsx new file mode 100644 index 00000000..5a0b415c --- /dev/null +++ b/src/device/DeviceShareModal.tsx @@ -0,0 +1,23 @@ +import { absolutePathForDevice, pathForDevice } from '@/site/paths'; +import { Photo } from '../photo'; +import ShareModal from '@/components/ShareModal'; +import DeviceOGTile from './DeviceOGTile'; +import { Device } from '.'; + +export default function DeviceShareModal({ + device, + photos, +}: { + device: Device + photos: Photo[] +}) { + return ( + + + + ); +}; diff --git a/src/device/PhotoDevice.tsx b/src/device/PhotoDevice.tsx index 0c0a3fa1..aea0f961 100644 --- a/src/device/PhotoDevice.tsx +++ b/src/device/PhotoDevice.tsx @@ -3,43 +3,42 @@ import { cc } from '@/utility/css'; import Link from 'next/link'; import { pathForDevice } from '@/site/paths'; import { IoMdCamera } from 'react-icons/io'; +import { Device } from '.'; export default function PhotoDevice({ - make, - model, + device, showIcon = true, hideApple = true, }: { - make?: string - model?: string + device: Device showIcon?: boolean hideApple?: boolean }) { - console.log({ make, model, showIcon, hideApple }); return ( {showIcon && <>   } - {!(hideApple && make?.toLowerCase() === 'apple') && + {!(hideApple && device.make?.toLowerCase() === 'apple') && <> - {make?.toLowerCase() === 'apple' + {device.make?.toLowerCase() === 'apple' ? - : make} + : device.make}   } - {model} + {device.model} ); } diff --git a/src/device/index.ts b/src/device/index.ts index 094323f0..43dd424a 100644 --- a/src/device/index.ts +++ b/src/device/index.ts @@ -1,14 +1,40 @@ -import { Photo, descriptionForPhotoSet } from '@/photo'; +import { Photo } from '@/photo'; +import { capitalizeWords, parameterize } from '@/utility/string'; + +export type Device = { + make: string + model: string +}; + +export const createDeviceKey = (make: string, model: string) => + parameterize(`${make}-${model}`); + +export const titleForDevice = ( + { make, model }: Device, + photos:Photo[], +) => [ + 'Shot on', + deviceTextFromPhoto(photos[0]) ?? capitalizeWords(`${make} ${model}`), +].join(' '); // Assumes no device makes ('Fujifilm,' 'Apple,' 'Canon', etc.) // will have dashes in them -export const getMakeModelFromDevice = (device: string) => { +export const getMakeModelFromDeviceString = (device: string): Device => { const [make, model] = device.toLowerCase().split(/[-| ](.*)/s); return { make, model }; }; -export const descriptionForDevicePhotos = ( - photos: Photo[], - dateBased?: boolean, -) => - descriptionForPhotoSet(photos, 'device', dateBased); +// Used to harvest original make/model with proper spaces/hyphens +export const deviceTextFromPhoto = (photo?: Photo) => photo + ? `${photo.make} ${photo.model}` + : undefined; + +export const deviceFromPhoto = (photo?: Photo): Device | undefined => + photo?.make && photo?.model + ? { make: photo.make, model: photo.model } + : undefined; + +export const formatDevice = (device: Device, photo?: Photo): Device => + photo?.make && photo?.model + ? { make: photo.make, model: photo.model } + : device; diff --git a/src/device/meta.ts b/src/device/meta.ts new file mode 100644 index 00000000..9102108e --- /dev/null +++ b/src/device/meta.ts @@ -0,0 +1,26 @@ +import { Photo, descriptionForPhotoSet } from '@/photo'; +import { Device, titleForDevice } from '.'; +import { + absolutePathForDevice, + absolutePathForDeviceImage, +} from '@/site/paths'; + +// Meta functions moved to separate file to avoid +// dependencies (camelcase-keys) found in photo/index.ts +// that cause Jest to crash + +export const descriptionForDevicePhotos = ( + photos: Photo[], + dateBased?: boolean, +) => + descriptionForPhotoSet(photos, 'device', dateBased); + +export const generateMetaForDevice = ( + device: Device, + photos: Photo[] +) => ({ + url: absolutePathForDevice(device), + title: titleForDevice(device, photos), + description: descriptionForDevicePhotos(photos, true), + images: absolutePathForDeviceImage(device), +}); diff --git a/src/photo/PhotoDetailPage.tsx b/src/photo/PhotoDetailPage.tsx index 20bc70a3..750061aa 100644 --- a/src/photo/PhotoDetailPage.tsx +++ b/src/photo/PhotoDetailPage.tsx @@ -6,17 +6,21 @@ import PhotoGrid from './PhotoGrid'; import { cc } from '@/utility/css'; import PhotoLinks from './PhotoLinks'; import TagHeader from '@/tag/TagHeader'; +import { Device } from '@/device'; +import DeviceHeader from '@/device/DeviceHeader'; export default function PhotoDetailPage({ photo, photos, photosGrid, tag, + device, }: { photo: Photo photos: Photo[] photosGrid?: Photo[] tag?: string + device?: Device }) { return (
        @@ -31,6 +35,17 @@ export default function PhotoDetailPage({ selectedPhoto={photo} />} />} + {device && + } + />} , ]} /> @@ -58,7 +75,12 @@ export default function PhotoDetailPage({ 'md:flex md:gap-4', 'user-select-none', )}> - +
        } /> diff --git a/src/photo/PhotoGrid.tsx b/src/photo/PhotoGrid.tsx index aa54697f..f94d9eaa 100644 --- a/src/photo/PhotoGrid.tsx +++ b/src/photo/PhotoGrid.tsx @@ -2,11 +2,13 @@ import { Photo } from '.'; import PhotoSmall from './PhotoSmall'; import { cc } from '@/utility/css'; import AnimateItems from '@/components/AnimateItems'; +import { Device } from '@/device'; export default function PhotoGrid({ photos, selectedPhoto, tag, + device, fast, animate = true, animateOnFirstLoadOnly, @@ -15,6 +17,7 @@ export default function PhotoGrid({ photos: Photo[] selectedPhoto?: Photo tag?: string + device?: Device fast?: boolean animate?: boolean animateOnFirstLoadOnly?: boolean @@ -38,6 +41,7 @@ export default function PhotoGrid({ key={photo.id} photo={photo} tag={tag} + device={device} selected={photo.id === selectedPhoto?.id} />)} /> diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index 91b42e29..abaa8958 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -7,21 +7,28 @@ import { pathForPhoto, pathForPhotoShare } from '@/site/paths'; import PhotoTags from '@/tag/PhotoTags'; import ShareButton from '@/components/ShareButton'; import PhotoDevice from '../device/PhotoDevice'; +import { deviceFromPhoto } from '@/device'; export default function PhotoLarge({ photo, tag, priority, prefetchShare, + shareDevice, shouldScrollOnShare, + showDevice = true, }: { photo: Photo tag?: string priority?: boolean prefetchShare?: boolean + shareDevice?: boolean shouldScrollOnShare?: boolean + showDevice?: boolean }) { const tagsToShow = photo.tags.filter(t => t !== tag); + + const device = deviceFromPhoto(photo); const renderMiniGrid = (children: JSX.Element) =>
        0 && }
        - + {showDevice && device && + } )} {renderMiniGrid(<>
          diff --git a/src/photo/PhotoLink.tsx b/src/photo/PhotoLink.tsx index b881c8ac..ad2984b0 100644 --- a/src/photo/PhotoLink.tsx +++ b/src/photo/PhotoLink.tsx @@ -6,16 +6,19 @@ import Link from 'next/link'; import { AnimationConfig } from '../components/AnimateItems'; import { useAppState } from '@/state'; import { pathForPhoto } from '@/site/paths'; +import { Device } from '@/device'; export default function PhotoLink({ photo, tag, + device, prefetch, nextPhotoAnimation, children, }: { photo?: Photo tag?: string + device?: Device prefetch?: boolean nextPhotoAnimation?: AnimationConfig children: ReactNode @@ -25,7 +28,7 @@ export default function PhotoLink({ return ( photo ? { if (nextPhotoAnimation) { diff --git a/src/photo/PhotoLinks.tsx b/src/photo/PhotoLinks.tsx index ca01ca6f..fc62df2d 100644 --- a/src/photo/PhotoLinks.tsx +++ b/src/photo/PhotoLinks.tsx @@ -7,6 +7,7 @@ import { useRouter } from 'next/navigation'; import { pathForPhoto } from '@/site/paths'; import { useAppState } from '@/state'; import { AnimationConfig } from '@/components/AnimateItems'; +import { Device } from '@/device'; const LISTENER_KEYUP = 'keyup'; @@ -17,10 +18,12 @@ export default function PhotoLinks({ photo, photos, tag, + device, }: { photo: Photo photos: Photo[] tag?: string + device?: Device }) { const router = useRouter(); @@ -36,14 +39,20 @@ export default function PhotoLinks({ case 'J': if (previousPhoto) { setNextPhotoAnimation?.(ANIMATION_RIGHT); - router.push(pathForPhoto(previousPhoto, tag), { scroll: false }); + router.push( + pathForPhoto(previousPhoto, tag, device), + { scroll: false }, + ); } break; case 'ARROWRIGHT': case 'L': if (nextPhoto) { setNextPhotoAnimation?.(ANIMATION_LEFT); - router.push(pathForPhoto(nextPhoto, tag), { scroll: false }); + router.push( + pathForPhoto(nextPhoto, tag, device), + { scroll: false }, + ); } break; }; @@ -56,6 +65,7 @@ export default function PhotoLinks({ previousPhoto, nextPhoto, tag, + device, ]); return ( @@ -64,6 +74,7 @@ export default function PhotoLinks({ photo={previousPhoto} nextPhotoAnimation={ANIMATION_RIGHT} tag={tag} + device={device} prefetch > PREV @@ -72,6 +83,7 @@ export default function PhotoLinks({ photo={nextPhoto} nextPhotoAnimation={ANIMATION_LEFT} tag={tag} + device={device} prefetch > NEXT diff --git a/src/photo/PhotoShareModal.tsx b/src/photo/PhotoShareModal.tsx index a78c5cb7..41004f79 100644 --- a/src/photo/PhotoShareModal.tsx +++ b/src/photo/PhotoShareModal.tsx @@ -2,19 +2,22 @@ import PhotoOGTile from '@/photo/PhotoOGTile'; import { absolutePathForPhoto, pathForPhoto } from '@/site/paths'; import { Photo } from '.'; import ShareModal from '@/components/ShareModal'; +import { Device } from '@/device'; export default function PhotoShareModal({ photo, tag, + device, }: { photo: Photo tag?: string + device?: Device }) { return ( diff --git a/src/photo/PhotoSmall.tsx b/src/photo/PhotoSmall.tsx index a86e1b67..6b5b44e4 100644 --- a/src/photo/PhotoSmall.tsx +++ b/src/photo/PhotoSmall.tsx @@ -3,19 +3,22 @@ import ImageSmall from '@/components/ImageSmall'; import Link from 'next/link'; import { cc } from '@/utility/css'; import { pathForPhoto } from '@/site/paths'; +import { Device } from '@/device'; export default function PhotoSmall({ photo, tag, + device, selected, }: { photo: Photo tag?: string + device?: Device selected?: boolean }) { return ( + + + + + {make.toLowerCase() !== 'apple' && make} + {model} + + + + ); +} diff --git a/src/photo/image-response/components/ImageCaption.tsx b/src/photo/image-response/components/ImageCaption.tsx index a3a0234a..bfb55ae2 100644 --- a/src/photo/image-response/components/ImageCaption.tsx +++ b/src/photo/image-response/components/ImageCaption.tsx @@ -1,17 +1,21 @@ +import { ReactNode } from 'react'; + export default function ImageCaption({ height, - children, fontFamily, + subhead, + children, }: { width: number height: number fontFamily: string - children: React.ReactNode + subhead?: ReactNode + children: ReactNode }) { return (
          - {children} + {subhead && +
          + {subhead} +
          } +
          + {children} +
          ); } diff --git a/src/services/postgres.ts b/src/services/postgres.ts index 11d8475d..35d5c9b1 100644 --- a/src/services/postgres.ts +++ b/src/services/postgres.ts @@ -6,6 +6,8 @@ import { parsePhotoFromDb, Photo, } from '@/photo'; +import { Device, createDeviceKey } from '@/device'; +import { parameterize } from '@/utility/string'; const PHOTO_DEFAULT_LIMIT = 100; @@ -195,8 +197,8 @@ const sqlGetPhotosByDevice = async ( ) => sql` SELECT * FROM photos WHERE - LOWER(make)=${make} AND - LOWER(REPLACE(model, ' ', '-'))=${model} + LOWER(make)=${parameterize(make)} AND + LOWER(REPLACE(model, ' ', '-'))=${parameterize(model)} ORDER BY taken_at DESC LIMIT ${limit} `; @@ -247,15 +249,17 @@ const sqlGetUniqueDevices = async () => sql` SELECT DISTINCT make||' '||model as device, make, model FROM photos WHERE hidden IS NOT TRUE ORDER BY device ASC -`.then(({ rows }) => - rows as { device: string, make: string, model: string }[]); +`.then(({ rows }) => rows.map(({ make, model }) => ({ + deviceKey: createDeviceKey(make, model), + device: { make, model } as Device, + }))); export type GetPhotosOptions = { sortBy?: 'createdAt' | 'takenAt' | 'priority' limit?: number offset?: number tag?: string - device?: { make: string, model: string } + device?: Device takenBefore?: Date takenAfterInclusive?: Date includeHidden?: boolean diff --git a/src/site/paths.ts b/src/site/paths.ts index 911c5f83..af8a8e3d 100644 --- a/src/site/paths.ts +++ b/src/site/paths.ts @@ -1,11 +1,15 @@ import { Photo } from '@/photo'; import { BASE_URL } from './config'; -import { parameterize } from '@/utility/string'; +import { + Device, + createDeviceKey, + getMakeModelFromDeviceString, +} from '@/device'; // Prefixes const PREFIX_PHOTO = '/p'; const PREFIX_TAG = '/t'; -const PREFIX_DEVICE = '/d'; +const PREFIX_DEVICE = '/shot-on'; // Modifiers const SHARE = 'share'; @@ -45,13 +49,23 @@ type PhotoOrPhotoId = Photo | string; const getPhotoId = (photoOrPhotoId: PhotoOrPhotoId) => typeof photoOrPhotoId === 'string' ? photoOrPhotoId : photoOrPhotoId.id; -export const pathForPhoto = (photo: PhotoOrPhotoId, tag?: string) => +export const pathForPhoto = ( + photo: PhotoOrPhotoId, + tag?: string, + device?: Device, +) => tag ? `${pathForTag(tag)}/${getPhotoId(photo)}` - : `${PREFIX_PHOTO}/${getPhotoId(photo)}`; + : device + ? `${pathForDevice(device)}/${getPhotoId(photo)}` + : `${PREFIX_PHOTO}/${getPhotoId(photo)}`; -export const pathForPhotoShare = (photo: PhotoOrPhotoId, tag?: string) => - `${pathForPhoto(photo, tag)}/${SHARE}`; +export const pathForPhotoShare = ( + photo: PhotoOrPhotoId, + tag?: string, + device?: Device, +) => + `${pathForPhoto(photo, tag, device)}/${SHARE}`; export const pathForPhotoEdit = (photo: PhotoOrPhotoId) => `${PATH_ADMIN_PHOTOS}/${getPhotoId(photo)}/edit`; @@ -59,24 +73,37 @@ export const pathForPhotoEdit = (photo: PhotoOrPhotoId) => export const pathForTag = (tag: string) => `${PREFIX_TAG}/${tag}`; -export const pathForDevice = (make?: string, model?: string) => - `${PREFIX_DEVICE}/${parameterize(`${make}-${model}`)}`; - export const pathForTagShare = (tag: string) => `${pathForTag(tag)}/${SHARE}`; -export const absolutePathForPhoto = (photo: PhotoOrPhotoId, tag?: string) => - `${BASE_URL}${pathForPhoto(photo, tag)}`; +export const pathForDevice = ({ make, model }: Device) => + `${PREFIX_DEVICE}/${createDeviceKey(make, model)}`; + +export const pathForDeviceShare = (device: Device) => + `${pathForDevice(device)}/${SHARE}`; + +export const absolutePathForPhoto = ( + photo: PhotoOrPhotoId, + tag?: string, + device?: Device, +) => + `${BASE_URL}${pathForPhoto(photo, tag, device)}`; export const absolutePathForTag = (tag: string) => `${BASE_URL}${pathForTag(tag)}`; +export const absolutePathForDevice= (device: Device) => + `${BASE_URL}${pathForDevice(device)}`; + export const absolutePathForPhotoImage = (photo: PhotoOrPhotoId) => `${absolutePathForPhoto(photo)}/image`; export const absolutePathForTagImage = (tag: string) => `${absolutePathForTag(tag)}/image`; +export const absolutePathForDeviceImage= (device: Device) => + `${absolutePathForDevice(device)}/image`; + // p/[photoId] export const isPathPhoto = (pathname = '') => /^\/p\/[^/]+\/?$/.test(pathname); @@ -85,22 +112,38 @@ export const isPathPhoto = (pathname = '') => export const isPathPhotoShare = (pathname = '') => /^\/p\/[^/]+\/share\/?$/.test(pathname); -// t/[tagId] +// t/[tag] export const isPathTag = (pathname = '') => /^\/t\/[^/]+\/?$/.test(pathname); -// t/[tagId]/share +// t/[tag]/share export const isPathTagShare = (pathname = '') => /^\/t\/[^/]+\/share\/?$/.test(pathname); -// t/[tagId]/[photoId] +// t/[tag]/[photoId] export const isPathTagPhoto = (pathname = '') => /^\/t\/[^/]+\/[^/]+\/?$/.test(pathname); -// t/[tagId]/[photoId]/share +// t/[tag]/[photoId]/share export const isPathTagPhotoShare = (pathname = '') => /^\/t\/[^/]+\/[^/]+\/share\/?$/.test(pathname); +// shot-on/[device] +export const isPathDevice = (pathname = '') => + /^\/shot-on\/[^/]+\/?$/.test(pathname); + +// shot-on/[device]/share +export const isPathDeviceShare = (pathname = '') => + /^\/shot-on\/[^/]+\/share\/?$/.test(pathname); + +// shot-on/[device]/[photoId] +export const isPathDevicePhoto = (pathname = '') => + /^\/shot-on\/[^/]+\/[^/]+\/?$/.test(pathname); + +// shot-on/[device]/[photoId]/share +export const isPathDevicePhotoShare = (pathname = '') => + /^\/shot-on\/[^/]+\/[^/]+\/share\/?$/.test(pathname); + export const isPathGrid = (pathname = '') => pathname.startsWith(PATH_GRID); @@ -117,33 +160,51 @@ export const isPathProtected = (pathname = '') => export const getPathComponents = (pathname = ''): { photoId?: string tag?: string + device?: Device } => { const photoIdFromPhoto = pathname.match(/^\/p\/([^/]+)/)?.[1]; const photoIdFromTag = pathname.match(/^\/t\/[^/]+\/((?!share)[^/]+)/)?.[1]; + // eslint-disable-next-line max-len + const photoIdFromDevice = pathname.match(/^\/shot-on\/[^/]+\/((?!share)[^/]+)/)?.[1]; const tag = pathname.match(/^\/t\/([^/]+)/)?.[1]; + const deviceString = pathname.match(/^\/shot-on\/([^/]+)/)?.[1]; + const device = deviceString + ? getMakeModelFromDeviceString(deviceString) + : undefined; return { photoId: ( photoIdFromPhoto || - photoIdFromTag + photoIdFromTag || + photoIdFromDevice ), tag, + device, }; }; export const getEscapePath = (pathname?: string) => { - const { photoId, tag } = getPathComponents(pathname); + const { photoId, tag, device } = getPathComponents(pathname); if ( (photoId && isPathPhoto(pathname)) || - (tag && isPathTag(pathname)) + (tag && isPathTag(pathname)) || + (device && isPathDevice(pathname)) ) { return PATH_GRID; } else if (photoId && isPathTagPhotoShare(pathname)) { return pathForPhoto(photoId, tag); + } else if (photoId && isPathDevicePhotoShare(pathname)) { + return pathForPhoto(photoId, undefined, device); } else if (photoId && isPathPhotoShare(pathname)) { return pathForPhoto(photoId); - } else if (tag && (isPathTagPhoto(pathname) || isPathTagShare(pathname))) { - return pathForTag(tag); - } else if (tag && isPathTagShare(pathname)) { + } else if (tag && ( + isPathTagPhoto(pathname) || + isPathTagShare(pathname) + )) { return pathForTag(tag); + } else if (device && ( + isPathDevicePhoto(pathname) || + isPathDeviceShare(pathname) + )) { + return pathForDevice(device); } }; diff --git a/src/tag/PhotoTag.tsx b/src/tag/PhotoTag.tsx index 87bc5c68..6d016a74 100644 --- a/src/tag/PhotoTag.tsx +++ b/src/tag/PhotoTag.tsx @@ -12,9 +12,11 @@ export default function PhotoTag({ }) { return ( {showIcon && Date: Tue, 3 Oct 2023 11:30:37 -0500 Subject: [PATCH 13/15] Bump dependencies --- package.json | 14 +-- pnpm-lock.yaml | 306 +++++++++++++++++++++++-------------------------- 2 files changed, 153 insertions(+), 167 deletions(-) diff --git a/package.json b/package.json index 4cd9588f..4c1b66a9 100644 --- a/package.json +++ b/package.json @@ -9,16 +9,16 @@ "analyze": "ANALYZE=true next build" }, "dependencies": { - "@next/bundle-analyzer": "^13.5.3", + "@next/bundle-analyzer": "^13.5.4", "@tailwindcss/forms": "^0.5.6", "@testing-library/jest-dom": "^6.1.3", "@testing-library/react": "^14.0.0", "@types/jest": "^29.5.5", - "@types/node": "^20.7.2", - "@types/react": "18.2.23", + "@types/node": "^20.8.2", + "@types/react": "18.2.24", "@types/react-dom": "18.2.8", - "@typescript-eslint/eslint-plugin": "^6.7.3", - "@typescript-eslint/parser": "^6.7.3", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", "@vercel/analytics": "^1.0.2", "@vercel/blob": "^0.13.0", "@vercel/postgres": "0.5.0", @@ -26,12 +26,12 @@ "camelcase-keys": "^9.1.0", "date-fns": "^2.30.0", "eslint": "8.50.0", - "eslint-config-next": "13.5.3", + "eslint-config-next": "13.5.4", "framer-motion": "^10.16.4", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "nanoid": "^5.0.1", - "next": "^13.5.3", + "next": "^13.5.4", "next-auth": "0.0.0-manual.c885ac1d", "next-themes": "^0.2.1", "postcss": "8.4.31", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3f4fc42f..ca9a683a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@next/bundle-analyzer': - specifier: ^13.5.3 - version: 13.5.3 + specifier: ^13.5.4 + version: 13.5.4 '@tailwindcss/forms': specifier: ^0.5.6 version: 0.5.6(tailwindcss@3.3.3) @@ -21,20 +21,20 @@ dependencies: specifier: ^29.5.5 version: 29.5.5 '@types/node': - specifier: ^20.7.2 - version: 20.7.2 + specifier: ^20.8.2 + version: 20.8.2 '@types/react': - specifier: 18.2.23 - version: 18.2.23 + specifier: 18.2.24 + version: 18.2.24 '@types/react-dom': specifier: 18.2.8 version: 18.2.8 '@typescript-eslint/eslint-plugin': - specifier: ^6.7.3 - version: 6.7.3(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2) + specifier: ^6.7.4 + version: 6.7.4(@typescript-eslint/parser@6.7.4)(eslint@8.50.0)(typescript@5.2.2) '@typescript-eslint/parser': - specifier: ^6.7.3 - version: 6.7.3(eslint@8.50.0)(typescript@5.2.2) + specifier: ^6.7.4 + version: 6.7.4(eslint@8.50.0)(typescript@5.2.2) '@vercel/analytics': specifier: ^1.0.2 version: 1.0.2 @@ -57,14 +57,14 @@ dependencies: specifier: 8.50.0 version: 8.50.0 eslint-config-next: - specifier: 13.5.3 - version: 13.5.3(eslint@8.50.0)(typescript@5.2.2) + specifier: 13.5.4 + version: 13.5.4(eslint@8.50.0)(typescript@5.2.2) framer-motion: specifier: ^10.16.4 version: 10.16.4(react-dom@18.2.0)(react@18.2.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.7.2) + version: 29.7.0(@types/node@20.8.2) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -72,14 +72,14 @@ dependencies: specifier: ^5.0.1 version: 5.0.1 next: - specifier: ^13.5.3 - version: 13.5.3(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) + specifier: ^13.5.4 + version: 13.5.4(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) next-auth: specifier: 0.0.0-manual.c885ac1d - version: 0.0.0-manual.c885ac1d(next@13.5.3)(react@18.2.0) + version: 0.0.0-manual.c885ac1d(next@13.5.4)(react@18.2.0) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@13.5.3)(react-dom@18.2.0)(react@18.2.0) + version: 0.2.1(next@13.5.4)(react-dom@18.2.0)(react@18.2.0) postcss: specifier: 8.4.31 version: 8.4.31 @@ -139,7 +139,7 @@ packages: dependencies: '@panva/hkdf': 1.1.1 cookie: 0.5.0 - jose: 4.14.6 + jose: 4.15.1 oauth4webapi: 2.3.0 preact: 10.11.3 preact-render-to-string: 5.2.3(preact@10.11.3) @@ -573,7 +573,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -594,14 +594,14 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.8.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.7.2) + jest-config: 29.7.0(@types/node@20.8.2) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -629,7 +629,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 jest-mock: 29.7.0 dev: false @@ -656,7 +656,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.7.2 + '@types/node': 20.8.2 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -689,7 +689,7 @@ packages: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.19 - '@types/node': 20.7.2 + '@types/node': 20.8.2 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -777,7 +777,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 20.7.2 + '@types/node': 20.8.2 '@types/yargs': 17.0.24 chalk: 4.1.2 dev: false @@ -818,8 +818,8 @@ packages: '@types/pg': 8.6.6 dev: false - /@next/bundle-analyzer@13.5.3: - resolution: {integrity: sha512-AUHl9hu/0SNo2TCu9awOGY5hJdQHTPThYbjKk3rmjL04GfYAotn5i5pFQGqe209mbCxtu+QnvMEHLXU4GdFi1Q==} + /@next/bundle-analyzer@13.5.4: + resolution: {integrity: sha512-2vgmkuSKyTiyI7NorL+zYerxQRvzmSGbCDr2/kVrbKX28a4UNhbYn8/cQW8z6pvx0EncEFpd0GCUA5r9aRLhJg==} dependencies: webpack-bundle-analyzer: 4.7.0 transitivePeerDependencies: @@ -827,18 +827,18 @@ packages: - utf-8-validate dev: false - /@next/env@13.5.3: - resolution: {integrity: sha512-X4te86vsbjsB7iO4usY9jLPtZ827Mbx+WcwNBGUOIuswuTAKQtzsuoxc/6KLxCMvogKG795MhrR1LDhYgDvasg==} + /@next/env@13.5.4: + resolution: {integrity: sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==} dev: false - /@next/eslint-plugin-next@13.5.3: - resolution: {integrity: sha512-lbZOoEjzSuTtpk9UgV9rOmxYw+PsSfNR+00mZcInqooiDMZ1u+RqT1YQYLsEZPW1kumZoQe5+exkCBtZ2xn0uw==} + /@next/eslint-plugin-next@13.5.4: + resolution: {integrity: sha512-vI94U+D7RNgX6XypSyjeFrOzxGlZyxOplU0dVE5norIfZGn/LDjJYPHdvdsR5vN1eRtl6PDAsOHmycFEOljK5A==} dependencies: glob: 7.1.7 dev: false - /@next/swc-darwin-arm64@13.5.3: - resolution: {integrity: sha512-6hiYNJxJmyYvvKGrVThzo4nTcqvqUTA/JvKim7Auaj33NexDqSNwN5YrrQu+QhZJCIpv2tULSHt+lf+rUflLSw==} + /@next/swc-darwin-arm64@13.5.4: + resolution: {integrity: sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -846,8 +846,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@13.5.3: - resolution: {integrity: sha512-UpBKxu2ob9scbpJyEq/xPgpdrgBgN3aLYlxyGqlYX5/KnwpJpFuIHU2lx8upQQ7L+MEmz+fA1XSgesoK92ppwQ==} + /@next/swc-darwin-x64@13.5.4: + resolution: {integrity: sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -855,8 +855,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@13.5.3: - resolution: {integrity: sha512-5AzM7Yx1Ky+oLY6pHs7tjONTF22JirDPd5Jw/3/NazJ73uGB05NqhGhB4SbeCchg7SlVYVBeRMrMSZwJwq/xoA==} + /@next/swc-linux-arm64-gnu@13.5.4: + resolution: {integrity: sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -864,8 +864,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@13.5.3: - resolution: {integrity: sha512-A/C1shbyUhj7wRtokmn73eBksjTM7fFQoY2v/0rTM5wehpkjQRLOXI8WJsag2uLhnZ4ii5OzR1rFPwoD9cvOgA==} + /@next/swc-linux-arm64-musl@13.5.4: + resolution: {integrity: sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -873,8 +873,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@13.5.3: - resolution: {integrity: sha512-FubPuw/Boz8tKkk+5eOuDHOpk36F80rbgxlx4+xty/U71e3wZZxVYHfZXmf0IRToBn1Crb8WvLM9OYj/Ur815g==} + /@next/swc-linux-x64-gnu@13.5.4: + resolution: {integrity: sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -882,8 +882,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@13.5.3: - resolution: {integrity: sha512-DPw8nFuM1uEpbX47tM3wiXIR0Qa+atSzs9Q3peY1urkhofx44o7E1svnq+a5Q0r8lAcssLrwiM+OyJJgV/oj7g==} + /@next/swc-linux-x64-musl@13.5.4: + resolution: {integrity: sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -891,8 +891,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@13.5.3: - resolution: {integrity: sha512-zBPSP8cHL51Gub/YV8UUePW7AVGukp2D8JU93IHbVDu2qmhFAn9LWXiOOLKplZQKxnIPUkJTQAJDCWBWU4UWUA==} + /@next/swc-win32-arm64-msvc@13.5.4: + resolution: {integrity: sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -900,8 +900,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@13.5.3: - resolution: {integrity: sha512-ONcL/lYyGUj4W37D4I2I450SZtSenmFAvapkJQNIJhrPMhzDU/AdfLkW98NvH1D2+7FXwe7yclf3+B7v28uzBQ==} + /@next/swc-win32-ia32-msvc@13.5.4: + resolution: {integrity: sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -909,8 +909,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@13.5.3: - resolution: {integrity: sha512-2Vz2tYWaLqJvLcWbbTlJ5k9AN6JD7a5CN2pAeIzpbecK8ZF/yobA39cXtv6e+Z8c5UJuVOmaTldEAIxvsIux/Q==} + /@next/swc-win32-x64-msvc@13.5.4: + resolution: {integrity: sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1021,7 +1021,7 @@ packages: chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.5.16 - jest: 29.7.0(@types/node@20.7.2) + jest: 29.7.0(@types/node@20.8.2) lodash: 4.17.21 redent: 3.0.0 dev: false @@ -1081,7 +1081,7 @@ packages: /@types/graceful-fs@4.1.7: resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} dependencies: - '@types/node': 20.7.2 + '@types/node': 20.8.2 dev: false /@types/istanbul-lib-coverage@2.0.4: @@ -1110,7 +1110,7 @@ packages: /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: - '@types/node': 20.7.2 + '@types/node': 20.8.2 '@types/tough-cookie': 4.0.3 parse5: 7.1.2 dev: false @@ -1123,14 +1123,14 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: false - /@types/node@20.7.2: - resolution: {integrity: sha512-RcdC3hOBOauLP+r/kRt27NrByYtDjsXyAuSbR87O6xpsvi763WI+5fbSIvYJrXnt9w4RuxhV6eAXfIs7aaf/FQ==} + /@types/node@20.8.2: + resolution: {integrity: sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==} dev: false /@types/pg@8.6.6: resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} dependencies: - '@types/node': 20.7.2 + '@types/node': 20.8.2 pg-protocol: 1.6.0 pg-types: 2.2.0 dev: false @@ -1142,11 +1142,11 @@ packages: /@types/react-dom@18.2.8: resolution: {integrity: sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw==} dependencies: - '@types/react': 18.2.23 + '@types/react': 18.2.24 dev: false - /@types/react@18.2.23: - resolution: {integrity: sha512-qHLW6n1q2+7KyBEYnrZpcsAmU/iiCh9WGCKgXvMxx89+TYdJWRjZohVIo9XTcoLhfX3+/hP0Pbulu3bCZQ9PSA==} + /@types/react@18.2.24: + resolution: {integrity: sha512-Ee0Jt4sbJxMu1iDcetZEIKQr99J1Zfb6D4F3qfUWoR1JpInkY1Wdg4WwCyBjL257D0+jGqSl1twBjV8iCaC0Aw==} dependencies: '@types/prop-types': 15.7.6 '@types/scheduler': 0.16.3 @@ -1179,8 +1179,8 @@ packages: '@types/yargs-parser': 21.0.0 dev: false - /@typescript-eslint/eslint-plugin@6.7.3(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2): - resolution: {integrity: sha512-vntq452UHNltxsaaN+L9WyuMch8bMd9CqJ3zhzTPXXidwbf5mqqKCVXEuvRZUqLJSTLeWE65lQwyXsRGnXkCTA==} + /@typescript-eslint/eslint-plugin@6.7.4(@typescript-eslint/parser@6.7.4)(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -1191,11 +1191,11 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.8.1 - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) - '@typescript-eslint/scope-manager': 6.7.3 - '@typescript-eslint/type-utils': 6.7.3(eslint@8.50.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.7.3(eslint@8.50.0)(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.7.3 + '@typescript-eslint/parser': 6.7.4(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.7.4 + '@typescript-eslint/type-utils': 6.7.4(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.7.4(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.7.4 debug: 4.3.4 eslint: 8.50.0 graphemer: 1.4.0 @@ -1208,8 +1208,8 @@ packages: - supports-color dev: false - /@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.2.2): - resolution: {integrity: sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==} + /@typescript-eslint/parser@6.7.4(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1218,10 +1218,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.7.3 - '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.7.3 + '@typescript-eslint/scope-manager': 6.7.4 + '@typescript-eslint/types': 6.7.4 + '@typescript-eslint/typescript-estree': 6.7.4(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.7.4 debug: 4.3.4 eslint: 8.50.0 typescript: 5.2.2 @@ -1229,16 +1229,16 @@ packages: - supports-color dev: false - /@typescript-eslint/scope-manager@6.7.3: - resolution: {integrity: sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ==} + /@typescript-eslint/scope-manager@6.7.4: + resolution: {integrity: sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/visitor-keys': 6.7.3 + '@typescript-eslint/types': 6.7.4 + '@typescript-eslint/visitor-keys': 6.7.4 dev: false - /@typescript-eslint/type-utils@6.7.3(eslint@8.50.0)(typescript@5.2.2): - resolution: {integrity: sha512-Fc68K0aTDrKIBvLnKTZ5Pf3MXK495YErrbHb1R6aTpfK5OdSFj0rVN7ib6Tx6ePrZ2gsjLqr0s98NG7l96KSQw==} + /@typescript-eslint/type-utils@6.7.4(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1247,8 +1247,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2) - '@typescript-eslint/utils': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.7.4(typescript@5.2.2) + '@typescript-eslint/utils': 6.7.4(eslint@8.50.0)(typescript@5.2.2) debug: 4.3.4 eslint: 8.50.0 ts-api-utils: 1.0.3(typescript@5.2.2) @@ -1257,13 +1257,13 @@ packages: - supports-color dev: false - /@typescript-eslint/types@6.7.3: - resolution: {integrity: sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw==} + /@typescript-eslint/types@6.7.4: + resolution: {integrity: sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA==} engines: {node: ^16.0.0 || >=18.0.0} dev: false - /@typescript-eslint/typescript-estree@6.7.3(typescript@5.2.2): - resolution: {integrity: sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==} + /@typescript-eslint/typescript-estree@6.7.4(typescript@5.2.2): + resolution: {integrity: sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1271,8 +1271,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/visitor-keys': 6.7.3 + '@typescript-eslint/types': 6.7.4 + '@typescript-eslint/visitor-keys': 6.7.4 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1283,8 +1283,8 @@ packages: - supports-color dev: false - /@typescript-eslint/utils@6.7.3(eslint@8.50.0)(typescript@5.2.2): - resolution: {integrity: sha512-vzLkVder21GpWRrmSR9JxGZ5+ibIUSudXlW52qeKpzUEQhRSmyZiVDDj3crAth7+5tmN1ulvgKaCU2f/bPRCzg==} + /@typescript-eslint/utils@6.7.4(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1292,9 +1292,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) '@types/json-schema': 7.0.13 '@types/semver': 7.5.2 - '@typescript-eslint/scope-manager': 6.7.3 - '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.7.4 + '@typescript-eslint/types': 6.7.4 + '@typescript-eslint/typescript-estree': 6.7.4(typescript@5.2.2) eslint: 8.50.0 semver: 7.5.4 transitivePeerDependencies: @@ -1302,11 +1302,11 @@ packages: - typescript dev: false - /@typescript-eslint/visitor-keys@6.7.3: - resolution: {integrity: sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg==} + /@typescript-eslint/visitor-keys@6.7.4: + resolution: {integrity: sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.7.3 + '@typescript-eslint/types': 6.7.4 eslint-visitor-keys: 3.4.3 dev: false @@ -1885,7 +1885,7 @@ packages: engines: {node: '>= 0.6'} dev: false - /create-jest@29.7.0(@types/node@20.7.2): + /create-jest@29.7.0(@types/node@20.8.2): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -1894,7 +1894,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.7.2) + jest-config: 29.7.0(@types/node@20.8.2) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -2282,8 +2282,8 @@ packages: source-map: 0.6.1 dev: false - /eslint-config-next@13.5.3(eslint@8.50.0)(typescript@5.2.2): - resolution: {integrity: sha512-VN2qbCpq2DMWgs7SVF8KTmc8bVaWz3s4nmcFqRLs7PNBt5AXejOhJuZ4zg2sCEHOvz5RvqdwLeI++NSCV6qHVg==} + /eslint-config-next@13.5.4(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-FzQGIj4UEszRX7fcRSJK6L1LrDiVZvDFW320VVntVKh3BSU8Fb9kpaoxQx0cdFgf3MQXdeSbrCXJ/5Z/NndDkQ==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -2291,13 +2291,13 @@ packages: typescript: optional: true dependencies: - '@next/eslint-plugin-next': 13.5.3 + '@next/eslint-plugin-next': 13.5.4 '@rushstack/eslint-patch': 1.4.0 - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.7.4(eslint@8.50.0)(typescript@5.2.2) eslint: 8.50.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) + eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.50.0) eslint-plugin-react: 7.33.2(eslint@8.50.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.50.0) @@ -2317,7 +2317,7 @@ packages: - supports-color dev: false - /eslint-import-resolver-typescript@3.6.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0): + /eslint-import-resolver-typescript@3.6.0(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0): resolution: {integrity: sha512-QTHR9ddNnn35RTxlaEnx2gCxqFlF2SEN0SE2d17SqwyM7YOSI2GHWRYp5BiRkObTUNYPupC/3Fq2a0PpT+EKpg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -2327,8 +2327,8 @@ packages: debug: 4.3.4 enhanced-resolve: 5.15.0 eslint: 8.50.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) fast-glob: 3.3.1 get-tsconfig: 4.7.0 is-core-module: 2.13.0 @@ -2340,7 +2340,7 @@ packages: - supports-color dev: false - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -2361,16 +2361,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.7.4(eslint@8.50.0)(typescript@5.2.2) debug: 3.2.7 eslint: 8.50.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0) + eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.50.0) transitivePeerDependencies: - supports-color dev: false - /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0): + /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0): resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} engines: {node: '>=4'} peerDependencies: @@ -2380,7 +2380,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.7.4(eslint@8.50.0)(typescript@5.2.2) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -2389,7 +2389,7 @@ packages: doctrine: 2.1.0 eslint: 8.50.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.4)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.50.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -3310,7 +3310,7 @@ packages: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -3331,7 +3331,7 @@ packages: - supports-color dev: false - /jest-cli@29.7.0(@types/node@20.7.2): + /jest-cli@29.7.0(@types/node@20.8.2): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -3345,10 +3345,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.7.2) + create-jest: 29.7.0(@types/node@20.8.2) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.7.2) + jest-config: 29.7.0(@types/node@20.8.2) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -3359,7 +3359,7 @@ packages: - ts-node dev: false - /jest-config@29.7.0(@types/node@20.7.2): + /jest-config@29.7.0(@types/node@20.8.2): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -3374,7 +3374,7 @@ packages: '@babel/core': 7.23.0 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 babel-jest: 29.7.0(@babel/core@7.23.0) chalk: 4.1.2 ci-info: 3.8.0 @@ -3440,7 +3440,7 @@ packages: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.7.2 + '@types/node': 20.8.2 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -3457,7 +3457,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 jest-mock: 29.7.0 jest-util: 29.7.0 dev: false @@ -3473,7 +3473,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.7 - '@types/node': 20.7.2 + '@types/node': 20.8.2 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -3524,7 +3524,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 jest-util: 29.7.0 dev: false @@ -3579,7 +3579,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -3610,7 +3610,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -3662,7 +3662,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -3687,7 +3687,7 @@ packages: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.2 + '@types/node': 20.8.2 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -3699,13 +3699,13 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.7.2 + '@types/node': 20.8.2 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 dev: false - /jest@29.7.0(@types/node@20.7.2): + /jest@29.7.0(@types/node@20.8.2): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -3718,7 +3718,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.7.2) + jest-cli: 29.7.0(@types/node@20.8.2) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -3731,8 +3731,8 @@ packages: hasBin: true dev: false - /jose@4.14.6: - resolution: {integrity: sha512-EqJPEUlZD0/CSUMubKtMaYUOtWe91tZXTWMJZoKSbLk+KtdhNdcvppH8lA9XwVu2V4Ailvsj0GBZJ2ZwDjfesQ==} + /jose@4.15.1: + resolution: {integrity: sha512-CinpaEMmwb/59YG0N6SC3DY1imdTU5iNl08HPWR7NdyxACPeFuQbqjaocEjCDGq04KbnxSqQu702vL3ZTvKe5w==} dev: false /js-tokens@4.0.0: @@ -4039,7 +4039,7 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: false - /next-auth@0.0.0-manual.c885ac1d(next@13.5.3)(react@18.2.0): + /next-auth@0.0.0-manual.c885ac1d(next@13.5.4)(react@18.2.0): resolution: {integrity: sha512-kL5Ead+uIQNjfSWjo/MVxzte+jJSD+N/XIGkYmqyjQmNxE5wDvJ6zuwo+h+QPBnTVf+jmOsOlzr65tPN7OY5fA==} peerDependencies: next: ^13.5.3 @@ -4050,24 +4050,24 @@ packages: optional: true dependencies: '@auth/core': 0.0.0-manual.e9863699 - next: 13.5.3(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.4(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false - /next-themes@0.2.1(next@13.5.3)(react-dom@18.2.0)(react@18.2.0): + /next-themes@0.2.1(next@13.5.4)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} peerDependencies: next: '*' react: '*' react-dom: '*' dependencies: - next: 13.5.3(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.4(@babel/core@7.23.0)(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@13.5.3(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-4Nt4HRLYDW/yRpJ/QR2t1v63UOMS55A38dnWv3UDOWGezuY0ZyFO1ABNbD7mulVzs9qVhgy2+ppjdsANpKP1mg==} + /next@13.5.4(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==} engines: {node: '>=16.14.0'} hasBin: true peerDependencies: @@ -4081,26 +4081,25 @@ packages: sass: optional: true dependencies: - '@next/env': 13.5.3 + '@next/env': 13.5.4 '@swc/helpers': 0.5.2 busboy: 1.6.0 caniuse-lite: 1.0.30001538 - postcss: 8.4.14 + 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.0)(react@18.2.0) watchpack: 2.4.0 - zod: 3.21.4 optionalDependencies: - '@next/swc-darwin-arm64': 13.5.3 - '@next/swc-darwin-x64': 13.5.3 - '@next/swc-linux-arm64-gnu': 13.5.3 - '@next/swc-linux-arm64-musl': 13.5.3 - '@next/swc-linux-x64-gnu': 13.5.3 - '@next/swc-linux-x64-musl': 13.5.3 - '@next/swc-win32-arm64-msvc': 13.5.3 - '@next/swc-win32-ia32-msvc': 13.5.3 - '@next/swc-win32-x64-msvc': 13.5.3 + '@next/swc-darwin-arm64': 13.5.4 + '@next/swc-darwin-x64': 13.5.4 + '@next/swc-linux-arm64-gnu': 13.5.4 + '@next/swc-linux-arm64-musl': 13.5.4 + '@next/swc-linux-x64-gnu': 13.5.4 + '@next/swc-linux-x64-musl': 13.5.4 + '@next/swc-win32-arm64-msvc': 13.5.4 + '@next/swc-win32-ia32-msvc': 13.5.4 + '@next/swc-win32-x64-msvc': 13.5.4 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -4441,15 +4440,6 @@ packages: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} dev: false - /postcss@8.4.14: - resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.6 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: false - /postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} @@ -5517,7 +5507,3 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: false - - /zod@3.21.4: - resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} - dev: false From 69b61d12449c15bfbe8928b35428ff10842444d8 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Tue, 3 Oct 2023 14:29:33 -0500 Subject: [PATCH 14/15] Rename device to camera --- __tests__/path.test.ts | 64 +++++++------- src/app/(static)/grid/page.tsx | 20 ++--- .../[photoId]/layout.tsx | 43 ++++++---- .../{[device] => [camera]}/[photoId]/page.tsx | 0 .../shot-on/[camera]/[photoId]/share/page.tsx | 36 ++++++++ .../{[device] => [camera]}/image/route.tsx | 14 +-- src/app/(static)/shot-on/[camera]/page.tsx | 65 ++++++++++++++ .../(static)/shot-on/[camera]/share/page.tsx | 70 +++++++++++++++ .../shot-on/[device]/[photoId]/share/page.tsx | 34 -------- src/app/(static)/shot-on/[device]/page.tsx | 65 -------------- .../(static)/shot-on/[device]/share/page.tsx | 74 ---------------- src/cache/index.ts | 20 ++--- src/camera/CameraHeader.tsx | 28 ++++++ .../CameraOGTile.tsx} | 20 ++--- src/camera/CameraShareModal.tsx | 23 +++++ .../PhotoCamera.tsx} | 20 ++--- src/camera/index.ts | 31 +++++++ src/camera/meta.ts | 35 ++++++++ src/device/DeviceHeader.tsx | 28 ------ src/device/DeviceShareModal.tsx | 23 ----- src/device/index.ts | 40 --------- src/device/meta.ts | 26 ------ src/photo/PhotoDetailPage.tsx | 20 ++--- src/photo/PhotoGrid.tsx | 8 +- src/photo/PhotoLarge.tsx | 23 ++--- src/photo/PhotoLink.tsx | 8 +- src/photo/PhotoLinks.tsx | 16 ++-- src/photo/PhotoShareModal.tsx | 10 +-- src/photo/PhotoSmall.tsx | 8 +- ...geResponse.tsx => CameraImageResponse.tsx} | 10 +-- src/photo/index.ts | 5 +- src/services/postgres.ts | 24 +++--- src/site/paths.ts | 86 +++++++++---------- src/tag/index.ts | 4 +- 34 files changed, 504 insertions(+), 497 deletions(-) rename src/app/(static)/shot-on/{[device] => [camera]}/[photoId]/layout.tsx (59%) rename src/app/(static)/shot-on/{[device] => [camera]}/[photoId]/page.tsx (100%) create mode 100644 src/app/(static)/shot-on/[camera]/[photoId]/share/page.tsx rename src/app/(static)/shot-on/{[device] => [camera]}/image/route.tsx (73%) create mode 100644 src/app/(static)/shot-on/[camera]/page.tsx create mode 100644 src/app/(static)/shot-on/[camera]/share/page.tsx delete mode 100644 src/app/(static)/shot-on/[device]/[photoId]/share/page.tsx delete mode 100644 src/app/(static)/shot-on/[device]/page.tsx delete mode 100644 src/app/(static)/shot-on/[device]/share/page.tsx create mode 100644 src/camera/CameraHeader.tsx rename src/{device/DeviceOGTile.tsx => camera/CameraOGTile.tsx} (56%) create mode 100644 src/camera/CameraShareModal.tsx rename src/{device/PhotoDevice.tsx => camera/PhotoCamera.tsx} (68%) create mode 100644 src/camera/index.ts create mode 100644 src/camera/meta.ts delete mode 100644 src/device/DeviceHeader.tsx delete mode 100644 src/device/DeviceShareModal.tsx delete mode 100644 src/device/index.ts delete mode 100644 src/device/meta.ts rename src/photo/image-response/{DeviceImageResponse.tsx => CameraImageResponse.tsx} (81%) diff --git a/__tests__/path.test.ts b/__tests__/path.test.ts index bd9d54b0..eb4828bf 100644 --- a/__tests__/path.test.ts +++ b/__tests__/path.test.ts @@ -2,10 +2,10 @@ import '@testing-library/jest-dom'; import { getEscapePath, getPathComponents, - isPathDevice, - isPathDevicePhoto, - isPathDevicePhotoShare, - isPathDeviceShare, + isPathCamera, + isPathCameraPhoto, + isPathCameraPhotoShare, + isPathCameraShare, isPathPhoto, isPathPhotoShare, isPathTag, @@ -13,12 +13,12 @@ import { isPathTagPhotoShare, isPathTagShare, } from '@/site/paths'; -import { getMakeModelFromDeviceString } from '@/device'; +import { getMakeModelFromCameraString } from '@/camera'; const PHOTO_ID = 'UsKSGcbt'; const TAG = 'tag-name'; -const DEVICE = 'fujifilm-x-t1'; -const DEVICE_OBJECT = getMakeModelFromDeviceString(DEVICE); +const CAMERA = 'fujifilm-x-t1'; +const CAMERA_OBJECT = getMakeModelFromCameraString(CAMERA); const SHARE = 'share'; const PATH_ROOT = '/'; @@ -33,10 +33,10 @@ const PATH_TAG_SHARE = `${PATH_TAG}/${SHARE}`; const PATH_TAG_PHOTO = `${PATH_TAG}/${PHOTO_ID}`; const PATH_TAG_PHOTO_SHARE = `${PATH_TAG_PHOTO}/${SHARE}`; -const PATH_DEVICE = `/shot-on/${DEVICE}`; -const PATH_DEVICE_SHARE = `${PATH_DEVICE}/${SHARE}`; -const PATH_DEVICE_PHOTO = `${PATH_DEVICE}/${PHOTO_ID}`; -const PATH_DEVICE_PHOTO_SHARE = `${PATH_DEVICE_PHOTO}/${SHARE}`; +const PATH_CAMERA = `/shot-on/${CAMERA}`; +const PATH_CAMERA_SHARE = `${PATH_CAMERA}/${SHARE}`; +const PATH_CAMERA_PHOTO = `${PATH_CAMERA}/${PHOTO_ID}`; +const PATH_CAMERA_PHOTO_SHARE = `${PATH_CAMERA_PHOTO}/${SHARE}`; describe('Paths', () => { it('can be classified', () => { @@ -47,10 +47,10 @@ describe('Paths', () => { expect(isPathTagShare(PATH_TAG_SHARE)).toBe(true); expect(isPathTagPhoto(PATH_TAG_PHOTO)).toBe(true); expect(isPathTagPhotoShare(PATH_TAG_PHOTO_SHARE)).toBe(true); - expect(isPathDevice(PATH_DEVICE)).toBe(true); - expect(isPathDeviceShare(PATH_DEVICE_SHARE)).toBe(true); - expect(isPathDevicePhoto(PATH_DEVICE_PHOTO)).toBe(true); - expect(isPathDevicePhotoShare(PATH_DEVICE_PHOTO_SHARE)).toBe(true); + expect(isPathCamera(PATH_CAMERA)).toBe(true); + expect(isPathCameraShare(PATH_CAMERA_SHARE)).toBe(true); + expect(isPathCameraPhoto(PATH_CAMERA_PHOTO)).toBe(true); + expect(isPathCameraPhotoShare(PATH_CAMERA_PHOTO_SHARE)).toBe(true); // Negative expect(isPathPhoto(PATH_TAG_PHOTO_SHARE)).toBe(false); expect(isPathPhotoShare(PATH_TAG_PHOTO)).toBe(false); @@ -58,10 +58,10 @@ describe('Paths', () => { expect(isPathTagShare(PATH_TAG)).toBe(false); expect(isPathTagPhoto(PATH_PHOTO_SHARE)).toBe(false); expect(isPathTagPhotoShare(PATH_PHOTO)).toBe(false); - expect(isPathDevice(PATH_TAG_SHARE)).toBe(false); - expect(isPathDeviceShare(PATH_TAG)).toBe(false); - expect(isPathDevicePhoto(PATH_PHOTO_SHARE)).toBe(false); - expect(isPathDevicePhotoShare(PATH_PHOTO)).toBe(false); + expect(isPathCamera(PATH_TAG_SHARE)).toBe(false); + expect(isPathCameraShare(PATH_TAG)).toBe(false); + expect(isPathCameraPhoto(PATH_PHOTO_SHARE)).toBe(false); + expect(isPathCameraPhotoShare(PATH_PHOTO)).toBe(false); }); it('can be parsed', () => { expect(getPathComponents(PATH_ROOT)).toEqual({}); @@ -85,19 +85,19 @@ describe('Paths', () => { photoId: PHOTO_ID, tag: TAG, }); - expect(getPathComponents(PATH_DEVICE)).toEqual({ - device: DEVICE_OBJECT, + expect(getPathComponents(PATH_CAMERA)).toEqual({ + camera: CAMERA_OBJECT, }); - expect(getPathComponents(PATH_DEVICE_SHARE)).toEqual({ - device: DEVICE_OBJECT, + expect(getPathComponents(PATH_CAMERA_SHARE)).toEqual({ + camera: CAMERA_OBJECT, }); - expect(getPathComponents(PATH_DEVICE_PHOTO)).toEqual({ + expect(getPathComponents(PATH_CAMERA_PHOTO)).toEqual({ photoId: PHOTO_ID, - device: DEVICE_OBJECT, + camera: CAMERA_OBJECT, }); - expect(getPathComponents(PATH_DEVICE_PHOTO_SHARE)).toEqual({ + expect(getPathComponents(PATH_CAMERA_PHOTO_SHARE)).toEqual({ photoId: PHOTO_ID, - device: DEVICE_OBJECT, + camera: CAMERA_OBJECT, }); }); it('can be escaped', () => { @@ -113,10 +113,10 @@ describe('Paths', () => { expect(getEscapePath(PATH_TAG_SHARE)).toEqual(PATH_TAG); expect(getEscapePath(PATH_TAG_PHOTO)).toEqual(PATH_TAG); expect(getEscapePath(PATH_TAG_PHOTO_SHARE)).toEqual(PATH_TAG_PHOTO); - // Device views - expect(getEscapePath(PATH_DEVICE)).toEqual(PATH_GRID); - expect(getEscapePath(PATH_DEVICE_SHARE)).toEqual(PATH_DEVICE); - expect(getEscapePath(PATH_DEVICE_PHOTO)).toEqual(PATH_DEVICE); - expect(getEscapePath(PATH_DEVICE_PHOTO_SHARE)).toEqual(PATH_DEVICE_PHOTO); + // Camera views + expect(getEscapePath(PATH_CAMERA)).toEqual(PATH_GRID); + expect(getEscapePath(PATH_CAMERA_SHARE)).toEqual(PATH_CAMERA); + expect(getEscapePath(PATH_CAMERA_PHOTO)).toEqual(PATH_CAMERA); + expect(getEscapePath(PATH_CAMERA_PHOTO_SHARE)).toEqual(PATH_CAMERA_PHOTO); }); }); diff --git a/src/app/(static)/grid/page.tsx b/src/app/(static)/grid/page.tsx index da635ae6..a01890da 100644 --- a/src/app/(static)/grid/page.tsx +++ b/src/app/(static)/grid/page.tsx @@ -1,14 +1,14 @@ import { getPhotosCached, getPhotosCountCached, - getUniqueDevicesCached, + getUniqueCamerasCached, getUniqueTagsCached, } from '@/cache'; import HeaderList from '@/components/HeaderList'; import MorePhotos from '@/components/MorePhotos'; import SiteGrid from '@/components/SiteGrid'; import { generateOgImageMetaForPhotos, getPhotosLimitForQuery } from '@/photo'; -import PhotoDevice from '@/device/PhotoDevice'; +import PhotoCamera from '@/camera/PhotoCamera'; import PhotoGrid from '@/photo/PhotoGrid'; import PhotosEmptyState from '@/photo/PhotosEmptyState'; import { MAX_PHOTOS_TO_SHOW_HOME } from '@/photo/image-response'; @@ -36,12 +36,12 @@ export default async function GridPage({ photos, count, tags, - devices, + cameras, ] = await Promise.all([ getPhotosCached({ limit }), getPhotosCountCached(), getUniqueTagsCached(), - getUniqueDevicesCached(), + getUniqueCamerasCached(), ]); const showMorePhotos = count > photos.length; @@ -65,13 +65,13 @@ export default async function GridPage({ showIcon={false} />)} />} - {devices.length > 0 && 0 && } - items={devices.map(({ deviceKey, device }) => - + )} diff --git a/src/app/(static)/shot-on/[device]/[photoId]/layout.tsx b/src/app/(static)/shot-on/[camera]/[photoId]/layout.tsx similarity index 59% rename from src/app/(static)/shot-on/[device]/[photoId]/layout.tsx rename to src/app/(static)/shot-on/[camera]/[photoId]/layout.tsx index 71d03728..90fbd171 100644 --- a/src/app/(static)/shot-on/[device]/[photoId]/layout.tsx +++ b/src/app/(static)/shot-on/[camera]/[photoId]/layout.tsx @@ -11,17 +11,21 @@ import { } from '@/site/paths'; import PhotoDetailPage from '@/photo/PhotoDetailPage'; import { getPhotoCached, getPhotosCached } from '@/cache'; -import { getPhotos, getUniqueDevices } from '@/services/postgres'; -import { deviceFromPhoto } from '@/device'; +import { getPhotos, getUniqueCameras } from '@/services/postgres'; +import { cameraFromPhoto } from '@/camera'; + +interface PhotoCameraProps { + params: { photoId: string, camera: string } +} export async function generateStaticParams() { - const params: { params: { photoId: string, device: string }}[] = []; + const params: PhotoCameraProps[] = []; - const devices = await getUniqueDevices(); - devices.forEach(async ({ deviceKey, device }) => { - const photos = await getPhotos({ device }); + const cameras = await getUniqueCameras(); + cameras.forEach(async ({ cameraKey, camera }) => { + const photos = await getPhotos({ camera }); params.push(...photos.map(photo => ({ - params: { photoId: photo.id, device: deviceKey }, + params: { photoId: photo.id, camera: cameraKey }, }))); }); @@ -29,10 +33,8 @@ export async function generateStaticParams() { } export async function generateMetadata({ - params: { photoId }, -}: { - params: { photoId: string, device: string } -}): Promise { + params: { photoId, camera }, +}: PhotoCameraProps): Promise { const photo = await getPhotoCached(photoId); if (!photo) { return {}; } @@ -40,7 +42,11 @@ export async function generateMetadata({ const title = titleForPhoto(photo); const description = descriptionForPhoto(photo); const images = absolutePathForPhotoImage(photo); - const url = absolutePathForPhoto(photo, undefined, deviceFromPhoto(photo)); + const url = absolutePathForPhoto( + photo, + undefined, + cameraFromPhoto(photo, camera), + ); return { title, @@ -60,27 +66,26 @@ export async function generateMetadata({ }; } -export default async function PhotoDevicePage({ - params: { photoId }, +export default async function PhotoCameraPage({ + params: { photoId, camera: cameraProp }, children, -}: { - params: { photoId: string, tag: string } +}: PhotoCameraProps & { children: React.ReactNode }) { const photo = await getPhotoCached(photoId); if (!photo) { redirect(PATH_ROOT); } - const device = deviceFromPhoto(photo); + const camera = cameraFromPhoto(photo, cameraProp); - const photos = await getPhotosCached({ device }); + const photos = await getPhotosCached({ camera }); return <> {children} ; } diff --git a/src/app/(static)/shot-on/[device]/[photoId]/page.tsx b/src/app/(static)/shot-on/[camera]/[photoId]/page.tsx similarity index 100% rename from src/app/(static)/shot-on/[device]/[photoId]/page.tsx rename to src/app/(static)/shot-on/[camera]/[photoId]/page.tsx diff --git a/src/app/(static)/shot-on/[camera]/[photoId]/share/page.tsx b/src/app/(static)/shot-on/[camera]/[photoId]/share/page.tsx new file mode 100644 index 00000000..0b3f76d8 --- /dev/null +++ b/src/app/(static)/shot-on/[camera]/[photoId]/share/page.tsx @@ -0,0 +1,36 @@ +import { getPhotoCached } from '@/cache'; +import { cameraFromPhoto } from '@/camera'; +import PhotoShareModal from '@/photo/PhotoShareModal'; +import { getPhotos, getUniqueCameras } from '@/services/postgres'; +import { PATH_ROOT } from '@/site/paths'; +import { redirect } from 'next/navigation'; + +interface PhotoCameraParams { + params: { photoId: string, camera: string } +} + +export async function generateStaticParams() { + const params: PhotoCameraParams[] = []; + + const cameras = await getUniqueCameras(); + cameras.forEach(async ({ cameraKey, camera }) => { + const photos = await getPhotos({ camera }); + params.push(...photos.map(photo => ({ + params: { photoId: photo.id, camera: cameraKey }, + }))); + }); + + return params; +} + +export default async function Share({ + params: { photoId, camera: cameraProp }, +}: PhotoCameraParams) { + const photo = await getPhotoCached(photoId); + + if (!photo) { return redirect(PATH_ROOT); } + + const camera = cameraFromPhoto(photo, cameraProp); + + return ; +} diff --git a/src/app/(static)/shot-on/[device]/image/route.tsx b/src/app/(static)/shot-on/[camera]/image/route.tsx similarity index 73% rename from src/app/(static)/shot-on/[device]/image/route.tsx rename to src/app/(static)/shot-on/[camera]/image/route.tsx index f04ec80f..be0111fa 100644 --- a/src/app/(static)/shot-on/[device]/image/route.tsx +++ b/src/app/(static)/shot-on/[camera]/image/route.tsx @@ -1,11 +1,11 @@ import { auth } from '@/auth'; import { getImageCacheHeadersForAuth, getPhotosCached } from '@/cache'; -import { getMakeModelFromDeviceString } from '@/device'; +import { getMakeModelFromCameraString } from '@/camera'; import { IMAGE_OG_SMALL_SIZE, MAX_PHOTOS_TO_SHOW_PER_TAG, } from '@/photo/image-response'; -import DeviceImageResponse from '@/photo/image-response/DeviceImageResponse'; +import CameraImageResponse from '@/photo/image-response/CameraImageResponse'; import { getIBMPlexMonoMedium } from '@/site/font'; import { ImageResponse } from 'next/server'; @@ -13,9 +13,9 @@ export const runtime = 'edge'; export async function GET( _: Request, - context: { params: { device: string } }, + context: { params: { camera: string } }, ) { - const device = getMakeModelFromDeviceString(context.params.device); + const camera = getMakeModelFromCameraString(context.params.camera); const [ photos, @@ -24,7 +24,7 @@ export async function GET( ] = await Promise.all([ getPhotosCached({ limit: MAX_PHOTOS_TO_SHOW_PER_TAG, - device, + camera: camera, }), getIBMPlexMonoMedium(), getImageCacheHeadersForAuth(await auth()), @@ -33,8 +33,8 @@ export async function GET( const { width, height } = IMAGE_OG_SMALL_SIZE; return new ImageResponse( - ({ + params: { camera: cameraKey }, + })); +} + +export async function generateMetadata({ + params, +}: CameraProps): Promise { + const camera = getMakeModelFromCameraString(params.camera); + const photos = await getPhotosCached({ camera }); + + const { + url, + title, + description, + images, + } = generateMetaForCamera(camera, photos); + + return { + title, + openGraph: { + title, + description, + images, + url, + }, + twitter: { + images, + description, + card: 'summary_large_image', + }, + description, + }; +} + +export default async function CameraPage({ params }:CameraProps) { + const camera = getMakeModelFromCameraString(params.camera); + + const photos = await getPhotosCached({ camera }); + + return ( + + + +
          } + /> + ); +} diff --git a/src/app/(static)/shot-on/[camera]/share/page.tsx b/src/app/(static)/shot-on/[camera]/share/page.tsx new file mode 100644 index 00000000..8511e357 --- /dev/null +++ b/src/app/(static)/shot-on/[camera]/share/page.tsx @@ -0,0 +1,70 @@ +import { getPhotosCached } from '@/cache'; +import SiteGrid from '@/components/SiteGrid'; +import { cameraFromPhoto, getMakeModelFromCameraString } from '@/camera'; +import CameraHeader from '@/camera/CameraHeader'; +import CameraShareModal from '@/camera/CameraShareModal'; +import { generateMetaForCamera } from '@/camera/meta'; +import PhotoGrid from '@/photo/PhotoGrid'; +import { getUniqueCameras } from '@/services/postgres'; +import { Metadata } from 'next'; + +interface CameraProps { + params: { camera: string } +} + +export async function generateStaticParams() { + const camera = await getUniqueCameras(); + return camera.map(({ cameraKey }): CameraProps => ({ + params: { camera: cameraKey }, + })); +} + +export async function generateMetadata({ + params, +}: CameraProps): Promise { + const camera = getMakeModelFromCameraString(params.camera); + + const photos = await getPhotosCached({ camera }); + + const { + url, + title, + description, + images, + } = generateMetaForCamera(camera, photos); + + return { + title, + openGraph: { + title, + description, + images, + url, + }, + twitter: { + images, + description, + card: 'summary_large_image', + }, + description, + }; +} + +export default async function Share({ params }: CameraProps) { + const cameraFromParams = getMakeModelFromCameraString(params.camera); + + const photos = await getPhotosCached({ camera: cameraFromParams }); + + const camera = cameraFromPhoto(photos[0], cameraFromParams); + + return <> + + + + + } + /> + ; +} diff --git a/src/app/(static)/shot-on/[device]/[photoId]/share/page.tsx b/src/app/(static)/shot-on/[device]/[photoId]/share/page.tsx deleted file mode 100644 index 1bab0fc6..00000000 --- a/src/app/(static)/shot-on/[device]/[photoId]/share/page.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { getPhotoCached } from '@/cache'; -import { deviceFromPhoto } from '@/device'; -import PhotoShareModal from '@/photo/PhotoShareModal'; -import { getPhotos, getUniqueDevices } from '@/services/postgres'; -import { PATH_ROOT } from '@/site/paths'; -import { redirect } from 'next/navigation'; - -export async function generateStaticParams() { - const params: { params: { photoId: string, device: string }}[] = []; - - const devices = await getUniqueDevices(); - devices.forEach(async ({ deviceKey, device }) => { - const photos = await getPhotos({ device }); - params.push(...photos.map(photo => ({ - params: { photoId: photo.id, device: deviceKey }, - }))); - }); - - return params; -} - -export default async function Share({ - params: { photoId }, -}: { - params: { photoId: string } -}) { - const photo = await getPhotoCached(photoId); - - if (!photo) { return redirect(PATH_ROOT); } - - const device = deviceFromPhoto(photo); - - return ; -} diff --git a/src/app/(static)/shot-on/[device]/page.tsx b/src/app/(static)/shot-on/[device]/page.tsx deleted file mode 100644 index 795f87a0..00000000 --- a/src/app/(static)/shot-on/[device]/page.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { getPhotosCached } from '@/cache'; -import SiteGrid from '@/components/SiteGrid'; -import DeviceHeader from '@/device/DeviceHeader'; -import { getMakeModelFromDeviceString } from '@/device'; -import PhotoGrid from '@/photo/PhotoGrid'; -import { getUniqueDevices } from '@/services/postgres'; -import { Metadata } from 'next'; -import { generateMetaForDevice } from '@/device/meta'; - -interface DeviceProps { - params: { device: string } -} - -export async function generateStaticParams() { - const devices = await getUniqueDevices(); - return devices.map(({ deviceKey }): DeviceProps => ({ - params: { device: deviceKey }, - })); -} - -export async function generateMetadata({ - params, -}: DeviceProps): Promise { - const device = getMakeModelFromDeviceString(params.device); - const photos = await getPhotosCached({ device }); - - const { - url, - title, - description, - images, - } = generateMetaForDevice(device, photos); - - return { - title, - openGraph: { - title, - description, - images, - url, - }, - twitter: { - images, - description, - card: 'summary_large_image', - }, - description, - }; -} - -export default async function DevicePage({ params }:DeviceProps) { - const device = getMakeModelFromDeviceString(params.device); - - const photos = await getPhotosCached({ device }); - - return ( - - - - } - /> - ); -} diff --git a/src/app/(static)/shot-on/[device]/share/page.tsx b/src/app/(static)/shot-on/[device]/share/page.tsx deleted file mode 100644 index 745fab85..00000000 --- a/src/app/(static)/shot-on/[device]/share/page.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { getPhotosCached } from '@/cache'; -import SiteGrid from '@/components/SiteGrid'; -import { deviceFromPhoto, getMakeModelFromDeviceString } from '@/device'; -import DeviceHeader from '@/device/DeviceHeader'; -import DeviceShareModal from '@/device/DeviceShareModal'; -import { generateMetaForDevice } from '@/device/meta'; -import PhotoGrid from '@/photo/PhotoGrid'; -import { getUniqueDevices } from '@/services/postgres'; -import { Metadata } from 'next'; - -interface DeviceProps { - params: { device: string } -} - -export async function generateStaticParams() { - const devices = await getUniqueDevices(); - return devices.map(({ deviceKey }): DeviceProps => ({ - params: { device: deviceKey }, - })); -} - -export async function generateMetadata({ - params, -}: DeviceProps): Promise { - const device = getMakeModelFromDeviceString(params.device); - - const photos = await getPhotosCached({ device }); - - const { - url, - title, - description, - images, - } = generateMetaForDevice(device, photos); - - return { - title, - openGraph: { - title, - description, - images, - url, - }, - twitter: { - images, - description, - card: 'summary_large_image', - }, - description, - }; -} - -export default async function Share({ - params, -}: { - params: { device: string } -}) { - const deviceFromParams = getMakeModelFromDeviceString(params.device); - - const photos = await getPhotosCached({ device: deviceFromParams }); - - const device = deviceFromPhoto(photos[0]) ?? deviceFromParams; - - return <> - - - - - } - /> - ; -} diff --git a/src/cache/index.ts b/src/cache/index.ts index f0949630..1b6988b8 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -5,7 +5,7 @@ import { getPhotos, getPhotosCount, getPhotosCountIncludingHidden, - getUniqueDevices, + getUniqueCameras, getUniqueTags, } from '@/services/postgres'; import { parseCachedPhotosDates, parseCachedPhotoDates } from '@/photo'; @@ -15,7 +15,7 @@ import { AuthSession } from 'next-auth'; const TAG_PHOTOS = 'photos'; const TAG_PHOTOS_COUNT = 'photos-count'; const TAG_TAGS = 'tags'; -const TAG_DEVICES = 'devices'; +const TAG_CAMERAS = 'cameras'; const TAG_BLOB = 'blob'; // eslint-disable-next-line max-len @@ -40,7 +40,7 @@ const getPhotosCacheTagForKey = ( return value ? `${key}-${value.toISOString()}` : null; } // Complex keys - case 'device': { + case 'camera': { const value = options[key]; return value ? `${key}-${value.make}-${value.model}` : null; } @@ -66,8 +66,8 @@ export const revalidatePhotosTag = () => export const revalidateTagsTag = () => revalidateTag(TAG_TAGS); -export const revalidateDevicesTag = () => - revalidateTag(TAG_DEVICES); +export const revalidateCamerasTag = () => + revalidateTag(TAG_CAMERAS); export const revalidateBlobTag = () => revalidateTag(TAG_BLOB); @@ -80,7 +80,7 @@ export const revalidatePhotosAndBlobTag = () => { export const revalidateAllTags = () => { revalidatePhotosTag(); revalidateTagsTag(); - revalidateDevicesTag(); + revalidateCamerasTag(); revalidateBlobTag(); }; @@ -125,11 +125,11 @@ export const getUniqueTagsCached: typeof getUniqueTags = (...args) => } )(); -export const getUniqueDevicesCached: typeof getUniqueDevices = (...args) => +export const getUniqueCamerasCached: typeof getUniqueCameras = (...args) => unstable_cache( - () => getUniqueDevices(...args), - [TAG_PHOTOS, TAG_DEVICES], { - tags: [TAG_PHOTOS, TAG_DEVICES], + () => getUniqueCameras(...args), + [TAG_PHOTOS, TAG_CAMERAS], { + tags: [TAG_PHOTOS, TAG_CAMERAS], } )(); diff --git a/src/camera/CameraHeader.tsx b/src/camera/CameraHeader.tsx new file mode 100644 index 00000000..c95df7b3 --- /dev/null +++ b/src/camera/CameraHeader.tsx @@ -0,0 +1,28 @@ +import { Photo } from '@/photo'; +import { pathForCameraShare } from '@/site/paths'; +import PhotoHeader from '@/photo/PhotoHeader'; +import { Camera, cameraFromPhoto } from '.'; +import PhotoCamera from './PhotoCamera'; +import { descriptionForCameraPhotos } from './meta'; + +export default function CameraHeader({ + camera: cameraProp, + photos, + selectedPhoto, +}: { + camera: Camera + photos: Photo[] + selectedPhoto?: Photo +}) { + const camera = cameraFromPhoto(photos[0], cameraProp); + return ( + } + entityVerb="Photo" + entityDescription={descriptionForCameraPhotos(photos)} + photos={photos} + selectedPhoto={selectedPhoto} + sharePath={pathForCameraShare(camera)} + /> + ); +} diff --git a/src/device/DeviceOGTile.tsx b/src/camera/CameraOGTile.tsx similarity index 56% rename from src/device/DeviceOGTile.tsx rename to src/camera/CameraOGTile.tsx index e68dcbe2..48f350f9 100644 --- a/src/device/DeviceOGTile.tsx +++ b/src/camera/CameraOGTile.tsx @@ -1,13 +1,13 @@ import { Photo } from '@/photo'; -import { absolutePathForDeviceImage, pathForDevice } from '@/site/paths'; +import { absolutePathForCameraImage, pathForCamera } from '@/site/paths'; import OGTile from '@/components/OGTile'; -import { Device, titleForDevice } from '.'; -import { descriptionForDevicePhotos } from './meta'; +import { Camera, titleForCamera } from '.'; +import { descriptionForCameraPhotos } from './meta'; export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed'; -export default function DeviceOGTile({ - device, +export default function CameraOGTile({ + camera, photos, loadingState: loadingStateExternal, riseOnHover, @@ -15,7 +15,7 @@ export default function DeviceOGTile({ onFail, retryTime, }: { - device: Device + camera: Camera photos: Photo[] loadingState?: OGLoadingState onLoad?: () => void @@ -25,10 +25,10 @@ export default function DeviceOGTile({ }) { return ( + + + ); +}; diff --git a/src/device/PhotoDevice.tsx b/src/camera/PhotoCamera.tsx similarity index 68% rename from src/device/PhotoDevice.tsx rename to src/camera/PhotoCamera.tsx index aea0f961..296df7ed 100644 --- a/src/device/PhotoDevice.tsx +++ b/src/camera/PhotoCamera.tsx @@ -1,22 +1,22 @@ import { AiFillApple } from 'react-icons/ai'; import { cc } from '@/utility/css'; import Link from 'next/link'; -import { pathForDevice } from '@/site/paths'; +import { pathForCamera } from '@/site/paths'; import { IoMdCamera } from 'react-icons/io'; -import { Device } from '.'; +import { Camera } from '.'; -export default function PhotoDevice({ - device, +export default function PhotoCamera({ + camera, showIcon = true, hideApple = true, }: { - device: Device + camera: Camera showIcon?: boolean hideApple?: boolean }) { return (   } - {!(hideApple && device.make?.toLowerCase() === 'apple') && + {!(hideApple && camera.make?.toLowerCase() === 'apple') && <> - {device.make?.toLowerCase() === 'apple' + {camera.make?.toLowerCase() === 'apple' ? - : device.make} + : camera.make}   } - {device.model} + {camera.model} ); } diff --git a/src/camera/index.ts b/src/camera/index.ts new file mode 100644 index 00000000..5f609c28 --- /dev/null +++ b/src/camera/index.ts @@ -0,0 +1,31 @@ +import { Photo } from '@/photo'; +import { parameterize } from '@/utility/string'; + +const CAMERA_PLACEHOLDER: Camera = { make: 'Camera', model: 'Model' }; + +export type Camera = { + make: string + model: string +}; + +export const createCameraKey = (make: string, model: string) => + parameterize(`${make}-${model}`); + +// Assumes no makes ('Fujifilm,' 'Apple,' 'Canon', etc.) have dashes +export const getMakeModelFromCameraString = (camera: string): Camera => { + const [make, model] = camera.toLowerCase().split(/[-| ](.*)/s); + return { make, model }; +}; + +export const cameraFromPhoto = ( + photo: Photo | undefined, + fallback?: Camera | string, +): Camera => + photo?.make && photo?.model + ? { make: photo.make, model: photo.model } + : typeof fallback === 'string' + ? getMakeModelFromCameraString(fallback) + : fallback ?? CAMERA_PLACEHOLDER; + +export const formatCameraText = ({ make, model }: Camera) => + `${make} ${model}`; diff --git a/src/camera/meta.ts b/src/camera/meta.ts new file mode 100644 index 00000000..6abe65a4 --- /dev/null +++ b/src/camera/meta.ts @@ -0,0 +1,35 @@ +import { Photo, descriptionForPhotoSet, photoQuantityText } from '@/photo'; +import { Camera, cameraFromPhoto, formatCameraText } from '.'; +import { + absolutePathForCamera, + absolutePathForCameraImage, +} from '@/site/paths'; + +// Meta functions moved to separate file to avoid +// dependencies (camelcase-keys) found in photo/index.ts +// which cause Jest to crash + +export const titleForCamera = ( + camera: Camera, + photos: Photo[], +) => [ + 'Shot on', + formatCameraText(cameraFromPhoto(photos[0], camera)), + photoQuantityText(photos), +].join(' '); + +export const descriptionForCameraPhotos = ( + photos: Photo[], + dateBased?: boolean, +) => + descriptionForPhotoSet(photos, 'camera', dateBased); + +export const generateMetaForCamera = ( + camera: Camera, + photos: Photo[] +) => ({ + url: absolutePathForCamera(camera), + title: titleForCamera(camera, photos), + description: descriptionForCameraPhotos(photos, true), + images: absolutePathForCameraImage(camera), +}); diff --git a/src/device/DeviceHeader.tsx b/src/device/DeviceHeader.tsx deleted file mode 100644 index f11c21c4..00000000 --- a/src/device/DeviceHeader.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Photo } from '@/photo'; -import { pathForDeviceShare } from '@/site/paths'; -import PhotoHeader from '@/photo/PhotoHeader'; -import { Device, formatDevice } from '.'; -import PhotoDevice from './PhotoDevice'; -import { descriptionForDevicePhotos } from './meta'; - -export default function DeviceHeader({ - device: deviceFromProps, - photos, - selectedPhoto, -}: { - device: Device - photos: Photo[] - selectedPhoto?: Photo -}) { - const device = formatDevice(deviceFromProps, photos[0]); - return ( - } - entityVerb="Device" - entityDescription={descriptionForDevicePhotos(photos)} - photos={photos} - selectedPhoto={selectedPhoto} - sharePath={pathForDeviceShare(device)} - /> - ); -} diff --git a/src/device/DeviceShareModal.tsx b/src/device/DeviceShareModal.tsx deleted file mode 100644 index 5a0b415c..00000000 --- a/src/device/DeviceShareModal.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { absolutePathForDevice, pathForDevice } from '@/site/paths'; -import { Photo } from '../photo'; -import ShareModal from '@/components/ShareModal'; -import DeviceOGTile from './DeviceOGTile'; -import { Device } from '.'; - -export default function DeviceShareModal({ - device, - photos, -}: { - device: Device - photos: Photo[] -}) { - return ( - - - - ); -}; diff --git a/src/device/index.ts b/src/device/index.ts deleted file mode 100644 index 43dd424a..00000000 --- a/src/device/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Photo } from '@/photo'; -import { capitalizeWords, parameterize } from '@/utility/string'; - -export type Device = { - make: string - model: string -}; - -export const createDeviceKey = (make: string, model: string) => - parameterize(`${make}-${model}`); - -export const titleForDevice = ( - { make, model }: Device, - photos:Photo[], -) => [ - 'Shot on', - deviceTextFromPhoto(photos[0]) ?? capitalizeWords(`${make} ${model}`), -].join(' '); - -// Assumes no device makes ('Fujifilm,' 'Apple,' 'Canon', etc.) -// will have dashes in them -export const getMakeModelFromDeviceString = (device: string): Device => { - const [make, model] = device.toLowerCase().split(/[-| ](.*)/s); - return { make, model }; -}; - -// Used to harvest original make/model with proper spaces/hyphens -export const deviceTextFromPhoto = (photo?: Photo) => photo - ? `${photo.make} ${photo.model}` - : undefined; - -export const deviceFromPhoto = (photo?: Photo): Device | undefined => - photo?.make && photo?.model - ? { make: photo.make, model: photo.model } - : undefined; - -export const formatDevice = (device: Device, photo?: Photo): Device => - photo?.make && photo?.model - ? { make: photo.make, model: photo.model } - : device; diff --git a/src/device/meta.ts b/src/device/meta.ts deleted file mode 100644 index 9102108e..00000000 --- a/src/device/meta.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Photo, descriptionForPhotoSet } from '@/photo'; -import { Device, titleForDevice } from '.'; -import { - absolutePathForDevice, - absolutePathForDeviceImage, -} from '@/site/paths'; - -// Meta functions moved to separate file to avoid -// dependencies (camelcase-keys) found in photo/index.ts -// that cause Jest to crash - -export const descriptionForDevicePhotos = ( - photos: Photo[], - dateBased?: boolean, -) => - descriptionForPhotoSet(photos, 'device', dateBased); - -export const generateMetaForDevice = ( - device: Device, - photos: Photo[] -) => ({ - url: absolutePathForDevice(device), - title: titleForDevice(device, photos), - description: descriptionForDevicePhotos(photos, true), - images: absolutePathForDeviceImage(device), -}); diff --git a/src/photo/PhotoDetailPage.tsx b/src/photo/PhotoDetailPage.tsx index 750061aa..f724e655 100644 --- a/src/photo/PhotoDetailPage.tsx +++ b/src/photo/PhotoDetailPage.tsx @@ -6,21 +6,21 @@ import PhotoGrid from './PhotoGrid'; import { cc } from '@/utility/css'; import PhotoLinks from './PhotoLinks'; import TagHeader from '@/tag/TagHeader'; -import { Device } from '@/device'; -import DeviceHeader from '@/device/DeviceHeader'; +import { Camera } from '@/camera'; +import CameraHeader from '@/camera/CameraHeader'; export default function PhotoDetailPage({ photo, photos, photosGrid, tag, - device, + camera, }: { photo: Photo photos: Photo[] photosGrid?: Photo[] tag?: string - device?: Device + camera?: Camera }) { return (
          @@ -35,13 +35,13 @@ export default function PhotoDetailPage({ selectedPhoto={photo} />} />} - {device && + {camera && } @@ -56,9 +56,9 @@ export default function PhotoDetailPage({ tag={tag} priority prefetchShare - shareDevice={device !== undefined} + shareCamera={camera !== undefined} shouldScrollOnShare={false} - showDevice={false} + showCamera={!camera} />, ]} /> @@ -79,7 +79,7 @@ export default function PhotoDetailPage({ photo, photos, tag, - device, + camera, }} />
          } /> diff --git a/src/photo/PhotoGrid.tsx b/src/photo/PhotoGrid.tsx index f94d9eaa..df74603c 100644 --- a/src/photo/PhotoGrid.tsx +++ b/src/photo/PhotoGrid.tsx @@ -2,13 +2,13 @@ import { Photo } from '.'; import PhotoSmall from './PhotoSmall'; import { cc } from '@/utility/css'; import AnimateItems from '@/components/AnimateItems'; -import { Device } from '@/device'; +import { Camera } from '@/camera'; export default function PhotoGrid({ photos, selectedPhoto, tag, - device, + camera, fast, animate = true, animateOnFirstLoadOnly, @@ -17,7 +17,7 @@ export default function PhotoGrid({ photos: Photo[] selectedPhoto?: Photo tag?: string - device?: Device + camera?: Camera fast?: boolean animate?: boolean animateOnFirstLoadOnly?: boolean @@ -41,7 +41,7 @@ export default function PhotoGrid({ key={photo.id} photo={photo} tag={tag} - device={device} + camera={camera} selected={photo.id === selectedPhoto?.id} />)} /> diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index abaa8958..6c07194e 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -6,29 +6,30 @@ import Link from 'next/link'; import { pathForPhoto, pathForPhotoShare } from '@/site/paths'; import PhotoTags from '@/tag/PhotoTags'; import ShareButton from '@/components/ShareButton'; -import PhotoDevice from '../device/PhotoDevice'; -import { deviceFromPhoto } from '@/device'; +import PhotoCamera from '../camera/PhotoCamera'; +import { Camera, cameraFromPhoto } from '@/camera'; export default function PhotoLarge({ photo, tag, priority, prefetchShare, - shareDevice, shouldScrollOnShare, - showDevice = true, + showCamera = true, + shareCamera, }: { photo: Photo tag?: string + camera?: Camera priority?: boolean prefetchShare?: boolean - shareDevice?: boolean shouldScrollOnShare?: boolean - showDevice?: boolean + showCamera?: boolean + shareCamera?: boolean }) { const tagsToShow = photo.tags.filter(t => t !== tag); - const device = deviceFromPhoto(photo); + const camera = cameraFromPhoto(photo); const renderMiniGrid = (children: JSX.Element) =>
          0 && }
          - {showDevice && device && - } @@ -114,7 +115,7 @@ export default function PhotoLarge({ path={pathForPhotoShare( photo, tag, - shareDevice ? device : undefined, + shareCamera ? camera : undefined, )} prefetch={prefetchShare} shouldScroll={shouldScrollOnShare} diff --git a/src/photo/PhotoLink.tsx b/src/photo/PhotoLink.tsx index ad2984b0..d2cd318b 100644 --- a/src/photo/PhotoLink.tsx +++ b/src/photo/PhotoLink.tsx @@ -6,19 +6,19 @@ import Link from 'next/link'; import { AnimationConfig } from '../components/AnimateItems'; import { useAppState } from '@/state'; import { pathForPhoto } from '@/site/paths'; -import { Device } from '@/device'; +import { Camera } from '@/camera'; export default function PhotoLink({ photo, tag, - device, + camera, prefetch, nextPhotoAnimation, children, }: { photo?: Photo tag?: string - device?: Device + camera?: Camera prefetch?: boolean nextPhotoAnimation?: AnimationConfig children: ReactNode @@ -28,7 +28,7 @@ export default function PhotoLink({ return ( photo ? { if (nextPhotoAnimation) { diff --git a/src/photo/PhotoLinks.tsx b/src/photo/PhotoLinks.tsx index fc62df2d..0943f336 100644 --- a/src/photo/PhotoLinks.tsx +++ b/src/photo/PhotoLinks.tsx @@ -7,7 +7,7 @@ import { useRouter } from 'next/navigation'; import { pathForPhoto } from '@/site/paths'; import { useAppState } from '@/state'; import { AnimationConfig } from '@/components/AnimateItems'; -import { Device } from '@/device'; +import { Camera } from '@/camera'; const LISTENER_KEYUP = 'keyup'; @@ -18,12 +18,12 @@ export default function PhotoLinks({ photo, photos, tag, - device, + camera, }: { photo: Photo photos: Photo[] tag?: string - device?: Device + camera?: Camera }) { const router = useRouter(); @@ -40,7 +40,7 @@ export default function PhotoLinks({ if (previousPhoto) { setNextPhotoAnimation?.(ANIMATION_RIGHT); router.push( - pathForPhoto(previousPhoto, tag, device), + pathForPhoto(previousPhoto, tag, camera), { scroll: false }, ); } @@ -50,7 +50,7 @@ export default function PhotoLinks({ if (nextPhoto) { setNextPhotoAnimation?.(ANIMATION_LEFT); router.push( - pathForPhoto(nextPhoto, tag, device), + pathForPhoto(nextPhoto, tag, camera), { scroll: false }, ); } @@ -65,7 +65,7 @@ export default function PhotoLinks({ previousPhoto, nextPhoto, tag, - device, + camera, ]); return ( @@ -74,7 +74,7 @@ export default function PhotoLinks({ photo={previousPhoto} nextPhotoAnimation={ANIMATION_RIGHT} tag={tag} - device={device} + camera={camera} prefetch > PREV @@ -83,7 +83,7 @@ export default function PhotoLinks({ photo={nextPhoto} nextPhotoAnimation={ANIMATION_LEFT} tag={tag} - device={device} + camera={camera} prefetch > NEXT diff --git a/src/photo/PhotoShareModal.tsx b/src/photo/PhotoShareModal.tsx index 41004f79..90a92d18 100644 --- a/src/photo/PhotoShareModal.tsx +++ b/src/photo/PhotoShareModal.tsx @@ -2,22 +2,22 @@ import PhotoOGTile from '@/photo/PhotoOGTile'; import { absolutePathForPhoto, pathForPhoto } from '@/site/paths'; import { Photo } from '.'; import ShareModal from '@/components/ShareModal'; -import { Device } from '@/device'; +import { Camera } from '@/camera'; export default function PhotoShareModal({ photo, tag, - device, + camera, }: { photo: Photo tag?: string - device?: Device + camera?: Camera }) { return ( diff --git a/src/photo/PhotoSmall.tsx b/src/photo/PhotoSmall.tsx index 6b5b44e4..be23c302 100644 --- a/src/photo/PhotoSmall.tsx +++ b/src/photo/PhotoSmall.tsx @@ -3,22 +3,22 @@ import ImageSmall from '@/components/ImageSmall'; import Link from 'next/link'; import { cc } from '@/utility/css'; import { pathForPhoto } from '@/site/paths'; -import { Device } from '@/device'; +import { Camera } from '@/camera'; export default function PhotoSmall({ photo, tag, - device, + camera, selected, }: { photo: Photo tag?: string - device?: Device + camera?: Camera selected?: boolean }) { return ( export const titleForPhoto = (photo: Photo) => photo.title || 'Untitled'; -export const labelForPhotos = (photos: Photo[]) => +const labelForPhotos = (photos: Photo[]) => photos.length === 1 ? 'Photo' : 'Photos'; +export const photoQuantityText = (photos: Photo[]) => + `(${photos.length} ${labelForPhotos(photos)})`; + export const descriptionForPhotoSet = ( photos:Photo[], descriptor: string, diff --git a/src/services/postgres.ts b/src/services/postgres.ts index 35d5c9b1..3c33a745 100644 --- a/src/services/postgres.ts +++ b/src/services/postgres.ts @@ -6,7 +6,7 @@ import { parsePhotoFromDb, Photo, } from '@/photo'; -import { Device, createDeviceKey } from '@/device'; +import { Camera, createCameraKey } from '@/camera'; import { parameterize } from '@/utility/string'; const PHOTO_DEFAULT_LIMIT = 100; @@ -190,7 +190,7 @@ const sqlGetPhotosByTag = ( LIMIT ${limit} OFFSET ${offset} `; -const sqlGetPhotosByDevice = async ( +const sqlGetPhotosByCamera = async ( limit = PHOTO_DEFAULT_LIMIT, make: string, model: string, @@ -245,13 +245,13 @@ const sqlGetUniqueTags = async () => sql` ORDER BY tag ASC `.then(({ rows }) => rows.map(row => row.tag as string)); -const sqlGetUniqueDevices = async () => sql` - SELECT DISTINCT make||' '||model as device, make, model FROM photos +const sqlGetUniqueCameras = async () => sql` + SELECT DISTINCT make||' '||model as camera, make, model FROM photos WHERE hidden IS NOT TRUE - ORDER BY device ASC + ORDER BY camera ASC `.then(({ rows }) => rows.map(({ make, model }) => ({ - deviceKey: createDeviceKey(make, model), - device: { make, model } as Device, + cameraKey: createCameraKey(make, model), + camera: { make, model } as Camera, }))); export type GetPhotosOptions = { @@ -259,7 +259,7 @@ export type GetPhotosOptions = { limit?: number offset?: number tag?: string - device?: Device + camera?: Camera takenBefore?: Date takenAfterInclusive?: Date includeHidden?: boolean @@ -299,7 +299,7 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => { limit, offset, tag, - device, + camera, takenBefore, takenAfterInclusive, includeHidden, @@ -316,8 +316,8 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => { getPhotosSql = () => sqlGetPhotosTakenAfterDateInclusive(takenAfterInclusive, limit); } else if (tag) { getPhotosSql = () => sqlGetPhotosByTag(limit, offset, tag); - } else if (device) { - getPhotosSql = () => sqlGetPhotosByDevice(limit, device.make, device.model); + } else if (camera) { + getPhotosSql = () => sqlGetPhotosByCamera(limit, camera.make, camera.model); } else if (sortBy === 'createdAt') { getPhotosSql = () => sqlGetPhotosSortedByCreatedAt(limit, offset); } else if (sortBy === 'priority') { @@ -344,4 +344,4 @@ export const getPhotosCountIncludingHidden = () => export const getUniqueTags = () => safelyQueryPhotos(sqlGetUniqueTags); -export const getUniqueDevices = () => safelyQueryPhotos(sqlGetUniqueDevices); +export const getUniqueCameras = () => safelyQueryPhotos(sqlGetUniqueCameras); diff --git a/src/site/paths.ts b/src/site/paths.ts index af8a8e3d..53cd18e9 100644 --- a/src/site/paths.ts +++ b/src/site/paths.ts @@ -1,15 +1,15 @@ import { Photo } from '@/photo'; import { BASE_URL } from './config'; import { - Device, - createDeviceKey, - getMakeModelFromDeviceString, -} from '@/device'; + Camera, + createCameraKey, + getMakeModelFromCameraString, +} from '@/camera'; // Prefixes const PREFIX_PHOTO = '/p'; const PREFIX_TAG = '/t'; -const PREFIX_DEVICE = '/shot-on'; +const PREFIX_CAMERA = '/shot-on'; // Modifiers const SHARE = 'share'; @@ -52,20 +52,20 @@ const getPhotoId = (photoOrPhotoId: PhotoOrPhotoId) => export const pathForPhoto = ( photo: PhotoOrPhotoId, tag?: string, - device?: Device, + camera?: Camera, ) => tag ? `${pathForTag(tag)}/${getPhotoId(photo)}` - : device - ? `${pathForDevice(device)}/${getPhotoId(photo)}` + : camera + ? `${pathForCamera(camera)}/${getPhotoId(photo)}` : `${PREFIX_PHOTO}/${getPhotoId(photo)}`; export const pathForPhotoShare = ( photo: PhotoOrPhotoId, tag?: string, - device?: Device, + camera?: Camera, ) => - `${pathForPhoto(photo, tag, device)}/${SHARE}`; + `${pathForPhoto(photo, tag, camera)}/${SHARE}`; export const pathForPhotoEdit = (photo: PhotoOrPhotoId) => `${PATH_ADMIN_PHOTOS}/${getPhotoId(photo)}/edit`; @@ -76,24 +76,24 @@ export const pathForTag = (tag: string) => export const pathForTagShare = (tag: string) => `${pathForTag(tag)}/${SHARE}`; -export const pathForDevice = ({ make, model }: Device) => - `${PREFIX_DEVICE}/${createDeviceKey(make, model)}`; +export const pathForCamera = ({ make, model }: Camera) => + `${PREFIX_CAMERA}/${createCameraKey(make, model)}`; -export const pathForDeviceShare = (device: Device) => - `${pathForDevice(device)}/${SHARE}`; +export const pathForCameraShare = (camera: Camera) => + `${pathForCamera(camera)}/${SHARE}`; export const absolutePathForPhoto = ( photo: PhotoOrPhotoId, tag?: string, - device?: Device, + camera?: Camera, ) => - `${BASE_URL}${pathForPhoto(photo, tag, device)}`; + `${BASE_URL}${pathForPhoto(photo, tag, camera)}`; export const absolutePathForTag = (tag: string) => `${BASE_URL}${pathForTag(tag)}`; -export const absolutePathForDevice= (device: Device) => - `${BASE_URL}${pathForDevice(device)}`; +export const absolutePathForCamera= (camera: Camera) => + `${BASE_URL}${pathForCamera(camera)}`; export const absolutePathForPhotoImage = (photo: PhotoOrPhotoId) => `${absolutePathForPhoto(photo)}/image`; @@ -101,8 +101,8 @@ export const absolutePathForPhotoImage = (photo: PhotoOrPhotoId) => export const absolutePathForTagImage = (tag: string) => `${absolutePathForTag(tag)}/image`; -export const absolutePathForDeviceImage= (device: Device) => - `${absolutePathForDevice(device)}/image`; +export const absolutePathForCameraImage= (camera: Camera) => + `${absolutePathForCamera(camera)}/image`; // p/[photoId] export const isPathPhoto = (pathname = '') => @@ -128,20 +128,20 @@ export const isPathTagPhoto = (pathname = '') => export const isPathTagPhotoShare = (pathname = '') => /^\/t\/[^/]+\/[^/]+\/share\/?$/.test(pathname); -// shot-on/[device] -export const isPathDevice = (pathname = '') => +// shot-on/[camera] +export const isPathCamera = (pathname = '') => /^\/shot-on\/[^/]+\/?$/.test(pathname); -// shot-on/[device]/share -export const isPathDeviceShare = (pathname = '') => +// shot-on/[camera]/share +export const isPathCameraShare = (pathname = '') => /^\/shot-on\/[^/]+\/share\/?$/.test(pathname); -// shot-on/[device]/[photoId] -export const isPathDevicePhoto = (pathname = '') => +// shot-on/[camera]/[photoId] +export const isPathCameraPhoto = (pathname = '') => /^\/shot-on\/[^/]+\/[^/]+\/?$/.test(pathname); -// shot-on/[device]/[photoId]/share -export const isPathDevicePhotoShare = (pathname = '') => +// shot-on/[camera]/[photoId]/share +export const isPathCameraPhotoShare = (pathname = '') => /^\/shot-on\/[^/]+\/[^/]+\/share\/?$/.test(pathname); export const isPathGrid = (pathname = '') => @@ -160,40 +160,40 @@ export const isPathProtected = (pathname = '') => export const getPathComponents = (pathname = ''): { photoId?: string tag?: string - device?: Device + camera?: Camera } => { const photoIdFromPhoto = pathname.match(/^\/p\/([^/]+)/)?.[1]; const photoIdFromTag = pathname.match(/^\/t\/[^/]+\/((?!share)[^/]+)/)?.[1]; // eslint-disable-next-line max-len - const photoIdFromDevice = pathname.match(/^\/shot-on\/[^/]+\/((?!share)[^/]+)/)?.[1]; + const photoIdFromCamera = pathname.match(/^\/shot-on\/[^/]+\/((?!share)[^/]+)/)?.[1]; const tag = pathname.match(/^\/t\/([^/]+)/)?.[1]; - const deviceString = pathname.match(/^\/shot-on\/([^/]+)/)?.[1]; - const device = deviceString - ? getMakeModelFromDeviceString(deviceString) + const cameraString = pathname.match(/^\/shot-on\/([^/]+)/)?.[1]; + const camera = cameraString + ? getMakeModelFromCameraString(cameraString) : undefined; return { photoId: ( photoIdFromPhoto || photoIdFromTag || - photoIdFromDevice + photoIdFromCamera ), tag, - device, + camera, }; }; export const getEscapePath = (pathname?: string) => { - const { photoId, tag, device } = getPathComponents(pathname); + const { photoId, tag, camera } = getPathComponents(pathname); if ( (photoId && isPathPhoto(pathname)) || (tag && isPathTag(pathname)) || - (device && isPathDevice(pathname)) + (camera && isPathCamera(pathname)) ) { return PATH_GRID; } else if (photoId && isPathTagPhotoShare(pathname)) { return pathForPhoto(photoId, tag); - } else if (photoId && isPathDevicePhotoShare(pathname)) { - return pathForPhoto(photoId, undefined, device); + } else if (photoId && isPathCameraPhotoShare(pathname)) { + return pathForPhoto(photoId, undefined, camera); } else if (photoId && isPathPhotoShare(pathname)) { return pathForPhoto(photoId); } else if (tag && ( @@ -201,10 +201,10 @@ export const getEscapePath = (pathname?: string) => { isPathTagShare(pathname) )) { return pathForTag(tag); - } else if (device && ( - isPathDevicePhoto(pathname) || - isPathDeviceShare(pathname) + } else if (camera && ( + isPathCameraPhoto(pathname) || + isPathCameraShare(pathname) )) { - return pathForDevice(device); + return pathForCamera(camera); } }; diff --git a/src/tag/index.ts b/src/tag/index.ts index f8de8a28..0d0d3df2 100644 --- a/src/tag/index.ts +++ b/src/tag/index.ts @@ -1,10 +1,10 @@ -import { Photo, descriptionForPhotoSet, labelForPhotos } from '@/photo'; +import { Photo, descriptionForPhotoSet, photoQuantityText } from '@/photo'; import { absolutePathForTag, absolutePathForTagImage } from '@/site/paths'; import { capitalizeWords } from '@/utility/string'; export const titleForTag = (tag: string, photos:Photo[]) => [ capitalizeWords(tag.replaceAll('-', ' ')), - `(${photos.length} ${labelForPhotos(photos)})`, + photoQuantityText(photos), ].join(' '); export const descriptionForTaggedPhotos = ( From b3162eae86b138fb018b94bc4e56d0e8ff21d72c Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Tue, 3 Oct 2023 15:02:43 -0500 Subject: [PATCH 15/15] Optimize core animations --- src/camera/CameraOGTile.tsx | 4 ++-- src/camera/meta.ts | 2 +- src/components/AnimateItems.tsx | 13 +++++-------- src/photo/index.ts | 8 ++++++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/camera/CameraOGTile.tsx b/src/camera/CameraOGTile.tsx index 48f350f9..a3c58789 100644 --- a/src/camera/CameraOGTile.tsx +++ b/src/camera/CameraOGTile.tsx @@ -1,8 +1,8 @@ import { Photo } from '@/photo'; import { absolutePathForCameraImage, pathForCamera } from '@/site/paths'; import OGTile from '@/components/OGTile'; -import { Camera, titleForCamera } from '.'; -import { descriptionForCameraPhotos } from './meta'; +import { Camera } from '.'; +import { descriptionForCameraPhotos, titleForCamera } from './meta'; export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed'; diff --git a/src/camera/meta.ts b/src/camera/meta.ts index 6abe65a4..1e1c8d3c 100644 --- a/src/camera/meta.ts +++ b/src/camera/meta.ts @@ -22,7 +22,7 @@ export const descriptionForCameraPhotos = ( photos: Photo[], dateBased?: boolean, ) => - descriptionForPhotoSet(photos, 'camera', dateBased); + descriptionForPhotoSet(photos, undefined, dateBased); export const generateMetaForCamera = ( camera: Camera, diff --git a/src/components/AnimateItems.tsx b/src/components/AnimateItems.tsx index 98d5c6ed..c650de48 100644 --- a/src/components/AnimateItems.tsx +++ b/src/components/AnimateItems.tsx @@ -62,16 +62,15 @@ function AnimateItems({ switch (typeResolved) { case 'left': return { opacity: 0, - translateX: distanceOffset, + transform: `translateX(${distanceOffset}px)`, }; case 'right': return { opacity: 0, - translateX: -distanceOffset, + transform: `translateX(${-distanceOffset}px)`, }; default: return { opacity: 0, - scale: scaleOffset, - translateY: distanceOffset, + transform: `translateY(${distanceOffset}px) scale(${scaleOffset})`, }; } }; @@ -99,14 +98,12 @@ function AnimateItems({ export const descriptionForPhotoSet = ( photos:Photo[], - descriptor: string, + descriptor?: string, dateBased?: boolean, ) => dateBased ? dateRangeForPhotos(photos).description.toUpperCase() - : `${photos.length} ${descriptor} ${labelForPhotos(photos)}`; + : [ + photos.length, + descriptor, + labelForPhotos(photos), + ].join(' '); export const dateRangeForPhotos = (photos: Photo[]) => { const start = photos[0].takenAtNaiveFormattedShort;