Merge pull request #16 from sambecker/cache-refactor

Simplify cache strategy
This commit is contained in:
Sam Becker 2023-11-19 00:25:41 -06:00 committed by GitHub
commit 7d45f44672
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 281 additions and 501 deletions

View File

@ -9,35 +9,35 @@
"analyze": "ANALYZE=true next build"
},
"dependencies": {
"@next/bundle-analyzer": "14.0.1",
"@tailwindcss/forms": "^0.5.6",
"@next/bundle-analyzer": "14.0.3",
"@tailwindcss/forms": "^0.5.7",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^14.1.0",
"@testing-library/react": "^14.1.1",
"@types/jest": "^29.5.8",
"@types/node": "^20.9.0",
"@types/node": "^20.9.1",
"@types/react": "18.2.37",
"@types/react-dom": "18.2.15",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"@vercel/analytics": "^1.1.1",
"@vercel/blob": "^0.15.0",
"@vercel/blob": "^0.15.1",
"@vercel/postgres": "0.5.1",
"autoprefixer": "10.4.16",
"camelcase-keys": "^9.1.2",
"date-fns": "^2.30.0",
"eslint": "8.53.0",
"eslint-config-next": "14.0.1",
"framer-motion": "^10.16.4",
"eslint-config-next": "14.0.3",
"framer-motion": "^10.16.5",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"nanoid": "^5.0.3",
"next": "14.0.1",
"next": "14.0.3",
"next-auth": "5.0.0-beta.3",
"next-themes": "^0.2.1",
"postcss": "8.4.31",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.11.0",
"react-icons": "^4.12.0",
"sonner": "^1.2.0",
"tailwindcss": "3.3.5",
"ts-exif-parser": "^0.2.2",

314
pnpm-lock.yaml generated
View File

@ -6,23 +6,23 @@ settings:
dependencies:
'@next/bundle-analyzer':
specifier: 14.0.1
version: 14.0.1
specifier: 14.0.3
version: 14.0.3
'@tailwindcss/forms':
specifier: ^0.5.6
version: 0.5.6(tailwindcss@3.3.5)
specifier: ^0.5.7
version: 0.5.7(tailwindcss@3.3.5)
'@testing-library/jest-dom':
specifier: ^6.1.4
version: 6.1.4(@types/jest@29.5.8)(jest@29.7.0)
'@testing-library/react':
specifier: ^14.1.0
version: 14.1.0(react-dom@18.2.0)(react@18.2.0)
specifier: ^14.1.1
version: 14.1.1(react-dom@18.2.0)(react@18.2.0)
'@types/jest':
specifier: ^29.5.8
version: 29.5.8
'@types/node':
specifier: ^20.9.0
version: 20.9.0
specifier: ^20.9.1
version: 20.9.1
'@types/react':
specifier: 18.2.37
version: 18.2.37
@ -30,17 +30,17 @@ dependencies:
specifier: 18.2.15
version: 18.2.15
'@typescript-eslint/eslint-plugin':
specifier: ^6.10.0
version: 6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.53.0)(typescript@5.2.2)
specifier: ^6.11.0
version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/parser':
specifier: ^6.10.0
version: 6.10.0(eslint@8.53.0)(typescript@5.2.2)
specifier: ^6.11.0
version: 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@vercel/analytics':
specifier: ^1.1.1
version: 1.1.1
'@vercel/blob':
specifier: ^0.15.0
version: 0.15.0
specifier: ^0.15.1
version: 0.15.1
'@vercel/postgres':
specifier: 0.5.1
version: 0.5.1
@ -57,14 +57,14 @@ dependencies:
specifier: 8.53.0
version: 8.53.0
eslint-config-next:
specifier: 14.0.1
version: 14.0.1(eslint@8.53.0)(typescript@5.2.2)
specifier: 14.0.3
version: 14.0.3(eslint@8.53.0)(typescript@5.2.2)
framer-motion:
specifier: ^10.16.4
version: 10.16.4(react-dom@18.2.0)(react@18.2.0)
specifier: ^10.16.5
version: 10.16.5(react-dom@18.2.0)(react@18.2.0)
jest:
specifier: ^29.7.0
version: 29.7.0(@types/node@20.9.0)
version: 29.7.0(@types/node@20.9.1)
jest-environment-jsdom:
specifier: ^29.7.0
version: 29.7.0
@ -72,14 +72,14 @@ dependencies:
specifier: ^5.0.3
version: 5.0.3
next:
specifier: 14.0.1
version: 14.0.1(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0)
specifier: 14.0.3
version: 14.0.3(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0)
next-auth:
specifier: 5.0.0-beta.3
version: 5.0.0-beta.3(next@14.0.1)(react@18.2.0)
version: 5.0.0-beta.3(next@14.0.3)(react@18.2.0)
next-themes:
specifier: ^0.2.1
version: 0.2.1(next@14.0.1)(react-dom@18.2.0)(react@18.2.0)
version: 0.2.1(next@14.0.3)(react-dom@18.2.0)(react@18.2.0)
postcss:
specifier: 8.4.31
version: 8.4.31
@ -90,8 +90,8 @@ dependencies:
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)
specifier: ^4.12.0
version: 4.12.0(react@18.2.0)
sonner:
specifier: ^1.2.0
version: 1.2.0(react-dom@18.2.0)(react@18.2.0)
@ -578,7 +578,7 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
chalk: 4.1.2
jest-message-util: 29.7.0
jest-util: 29.7.0
@ -599,14 +599,14 @@ packages:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 3.9.0
exit: 0.1.2
graceful-fs: 4.2.11
jest-changed-files: 29.7.0
jest-config: 29.7.0(@types/node@20.9.0)
jest-config: 29.7.0(@types/node@20.9.1)
jest-haste-map: 29.7.0
jest-message-util: 29.7.0
jest-regex-util: 29.6.3
@ -634,7 +634,7 @@ packages:
dependencies:
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
jest-mock: 29.7.0
dev: false
@ -661,7 +661,7 @@ packages:
dependencies:
'@jest/types': 29.6.3
'@sinonjs/fake-timers': 10.3.0
'@types/node': 20.9.0
'@types/node': 20.9.1
jest-message-util: 29.7.0
jest-mock: 29.7.0
jest-util: 29.7.0
@ -694,7 +694,7 @@ packages:
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
'@jridgewell/trace-mapping': 0.3.20
'@types/node': 20.9.0
'@types/node': 20.9.1
chalk: 4.1.2
collect-v8-coverage: 1.0.2
exit: 0.1.2
@ -782,7 +782,7 @@ packages:
'@jest/schemas': 29.6.3
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
'@types/node': 20.9.0
'@types/node': 20.9.1
'@types/yargs': 17.0.31
chalk: 4.1.2
dev: false
@ -823,8 +823,8 @@ packages:
'@types/pg': 8.6.6
dev: false
/@next/bundle-analyzer@14.0.1:
resolution: {integrity: sha512-AbZZnj4gZ1ZQFppZxAC9e8+skj0rFiSvY6E6Ut+ydS1r6oizR7PMu/7o02psIm4ekAsmp2O1Eq8IowHQgPWPCQ==}
/@next/bundle-analyzer@14.0.3:
resolution: {integrity: sha512-+UriXNEn2vGR2IxTiiuen45G7lXUbtMh0hgS/UH2o2E4TnScwjEEepqT76pY8fdpa5JEZ+gvBy6aSnrw4G2P2w==}
dependencies:
webpack-bundle-analyzer: 4.7.0
transitivePeerDependencies:
@ -832,18 +832,18 @@ packages:
- utf-8-validate
dev: false
/@next/env@14.0.1:
resolution: {integrity: sha512-Ms8ZswqY65/YfcjrlcIwMPD7Rg/dVjdLapMcSHG26W6O67EJDF435ShW4H4LXi1xKO1oRc97tLXUpx8jpLe86A==}
/@next/env@14.0.3:
resolution: {integrity: sha512-7xRqh9nMvP5xrW4/+L0jgRRX+HoNRGnfJpD+5Wq6/13j3dsdzxO3BCXn7D3hMqsDb+vjZnJq+vI7+EtgrYZTeA==}
dev: false
/@next/eslint-plugin-next@14.0.1:
resolution: {integrity: sha512-bLjJMwXdzvhnQOnxvHoTTUh/+PYk6FF/DCgHi4BXwXCINer+o1ZYfL9aVeezj/oI7wqGJOqwGIXrlBvPbAId3w==}
/@next/eslint-plugin-next@14.0.3:
resolution: {integrity: sha512-j4K0n+DcmQYCVnSAM+UByTVfIHnYQy2ODozfQP+4RdwtRDfobrIvKq1K4Exb2koJ79HSSa7s6B2SA8T/1YR3RA==}
dependencies:
glob: 7.1.7
dev: false
/@next/swc-darwin-arm64@14.0.1:
resolution: {integrity: sha512-JyxnGCS4qT67hdOKQ0CkgFTp+PXub5W1wsGvIq98TNbF3YEIN7iDekYhYsZzc8Ov0pWEsghQt+tANdidITCLaw==}
/@next/swc-darwin-arm64@14.0.3:
resolution: {integrity: sha512-64JbSvi3nbbcEtyitNn2LEDS/hcleAFpHdykpcnrstITFlzFgB/bW0ER5/SJJwUPj+ZPY+z3e+1jAfcczRLVGw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@ -851,8 +851,8 @@ packages:
dev: false
optional: true
/@next/swc-darwin-x64@14.0.1:
resolution: {integrity: sha512-625Z7bb5AyIzswF9hvfZWa+HTwFZw+Jn3lOBNZB87lUS0iuCYDHqk3ujuHCkiyPtSC0xFBtYDLcrZ11mF/ap3w==}
/@next/swc-darwin-x64@14.0.3:
resolution: {integrity: sha512-RkTf+KbAD0SgYdVn1XzqE/+sIxYGB7NLMZRn9I4Z24afrhUpVJx6L8hsRnIwxz3ERE2NFURNliPjJ2QNfnWicQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@ -860,8 +860,8 @@ packages:
dev: false
optional: true
/@next/swc-linux-arm64-gnu@14.0.1:
resolution: {integrity: sha512-iVpn3KG3DprFXzVHM09kvb//4CNNXBQ9NB/pTm8LO+vnnnaObnzFdS5KM+w1okwa32xH0g8EvZIhoB3fI3mS1g==}
/@next/swc-linux-arm64-gnu@14.0.3:
resolution: {integrity: sha512-3tBWGgz7M9RKLO6sPWC6c4pAw4geujSwQ7q7Si4d6bo0l6cLs4tmO+lnSwFp1Tm3lxwfMk0SgkJT7EdwYSJvcg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@ -869,8 +869,8 @@ packages:
dev: false
optional: true
/@next/swc-linux-arm64-musl@14.0.1:
resolution: {integrity: sha512-mVsGyMxTLWZXyD5sen6kGOTYVOO67lZjLApIj/JsTEEohDDt1im2nkspzfV5MvhfS7diDw6Rp/xvAQaWZTv1Ww==}
/@next/swc-linux-arm64-musl@14.0.3:
resolution: {integrity: sha512-v0v8Kb8j8T23jvVUWZeA2D8+izWspeyeDGNaT2/mTHWp7+37fiNfL8bmBWiOmeumXkacM/AB0XOUQvEbncSnHA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@ -878,8 +878,8 @@ packages:
dev: false
optional: true
/@next/swc-linux-x64-gnu@14.0.1:
resolution: {integrity: sha512-wMqf90uDWN001NqCM/auRl3+qVVeKfjJdT9XW+RMIOf+rhUzadmYJu++tp2y+hUbb6GTRhT+VjQzcgg/QTD9NQ==}
/@next/swc-linux-x64-gnu@14.0.3:
resolution: {integrity: sha512-VM1aE1tJKLBwMGtyBR21yy+STfl0MapMQnNrXkxeyLs0GFv/kZqXS5Jw/TQ3TSUnbv0QPDf/X8sDXuMtSgG6eg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@ -887,8 +887,8 @@ packages:
dev: false
optional: true
/@next/swc-linux-x64-musl@14.0.1:
resolution: {integrity: sha512-ol1X1e24w4j4QwdeNjfX0f+Nza25n+ymY0T2frTyalVczUmzkVD7QGgPTZMHfR1aLrO69hBs0G3QBYaj22J5GQ==}
/@next/swc-linux-x64-musl@14.0.3:
resolution: {integrity: sha512-64EnmKy18MYFL5CzLaSuUn561hbO1Gk16jM/KHznYP3iCIfF9e3yULtHaMy0D8zbHfxset9LTOv6cuYKJgcOxg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@ -896,8 +896,8 @@ packages:
dev: false
optional: true
/@next/swc-win32-arm64-msvc@14.0.1:
resolution: {integrity: sha512-WEmTEeWs6yRUEnUlahTgvZteh5RJc4sEjCQIodJlZZ5/VJwVP8p2L7l6VhzQhT4h7KvLx/Ed4UViBdne6zpIsw==}
/@next/swc-win32-arm64-msvc@14.0.3:
resolution: {integrity: sha512-WRDp8QrmsL1bbGtsh5GqQ/KWulmrnMBgbnb+59qNTW1kVi1nG/2ndZLkcbs2GX7NpFLlToLRMWSQXmPzQm4tog==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
@ -905,8 +905,8 @@ packages:
dev: false
optional: true
/@next/swc-win32-ia32-msvc@14.0.1:
resolution: {integrity: sha512-oFpHphN4ygAgZUKjzga7SoH2VGbEJXZa/KL8bHCAwCjDWle6R1SpiGOdUdA8EJ9YsG1TYWpzY6FTbUA+iAJeww==}
/@next/swc-win32-ia32-msvc@14.0.3:
resolution: {integrity: sha512-EKffQeqCrj+t6qFFhIFTRoqb2QwX1mU7iTOvMyLbYw3QtqTw9sMwjykyiMlZlrfm2a4fA84+/aeW+PMg1MjuTg==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
@ -914,8 +914,8 @@ packages:
dev: false
optional: true
/@next/swc-win32-x64-msvc@14.0.1:
resolution: {integrity: sha512-FFp3nOJ/5qSpeWT0BZQ+YE1pSMk4IMpkME/1DwKBwhg4mJLB9L+6EXuJi4JEwaJdl5iN+UUlmUD3IsR1kx5fAg==}
/@next/swc-win32-x64-msvc@14.0.3:
resolution: {integrity: sha512-ERhKPSJ1vQrPiwrs15Pjz/rvDHZmkmvbf/BjPN/UCOI++ODftT0GtasDPi0j+y6PPJi5HsXw+dpRaXUaw4vjuQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@ -978,8 +978,8 @@ packages:
tslib: 2.6.2
dev: false
/@tailwindcss/forms@0.5.6(tailwindcss@3.3.5):
resolution: {integrity: sha512-Fw+2BJ0tmAwK/w01tEFL5TiaJBX1NLT1/YbWgvm7ws3Qcn11kiXxzNTEQDMs5V3mQemhB56l3u0i9dwdzSQldA==}
/@tailwindcss/forms@0.5.7(tailwindcss@3.3.5):
resolution: {integrity: sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==}
peerDependencies:
tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1'
dependencies:
@ -1026,13 +1026,13 @@ packages:
chalk: 3.0.0
css.escape: 1.5.1
dom-accessibility-api: 0.5.16
jest: 29.7.0(@types/node@20.9.0)
jest: 29.7.0(@types/node@20.9.1)
lodash: 4.17.21
redent: 3.0.0
dev: false
/@testing-library/react@14.1.0(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-hcvfZEEyO0xQoZeHmUbuMs7APJCGELpilL7bY+BaJaMP57aWc6q1etFwScnoZDheYjk4ESdlzPdQ33IbsKAK/A==}
/@testing-library/react@14.1.1(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-XN9qioSzyYvfH+O09pzc9HAhZ2dSuTZLh+EmHkp1OKKxe13wAf617EKLuQ5l5S5dlfgPf/p0MHTeRkqO8Xz8qw==}
engines: {node: '>=14'}
peerDependencies:
react: ^18.0.0
@ -1086,7 +1086,7 @@ packages:
/@types/graceful-fs@4.1.9:
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.1
dev: false
/@types/istanbul-lib-coverage@2.0.6:
@ -1115,7 +1115,7 @@ packages:
/@types/jsdom@20.0.1:
resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.1
'@types/tough-cookie': 4.0.5
parse5: 7.1.2
dev: false
@ -1128,8 +1128,8 @@ packages:
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
dev: false
/@types/node@20.9.0:
resolution: {integrity: sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==}
/@types/node@20.9.1:
resolution: {integrity: sha512-HhmzZh5LSJNS5O8jQKpJ/3ZcrrlG6L70hpGqMIAoM9YVD0YBRNWYsfwcXq8VnSjlNpCpgLzMXdiPo+dxcvSmiA==}
dependencies:
undici-types: 5.26.5
dev: false
@ -1137,7 +1137,7 @@ packages:
/@types/pg@8.6.6:
resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.1
pg-protocol: 1.6.0
pg-types: 2.2.0
dev: false
@ -1186,8 +1186,8 @@ packages:
'@types/yargs-parser': 21.0.3
dev: false
/@typescript-eslint/eslint-plugin@6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==}
/@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
@ -1198,11 +1198,11 @@ packages:
optional: true
dependencies:
'@eslint-community/regexpp': 4.10.0
'@typescript-eslint/parser': 6.10.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.10.0
'@typescript-eslint/type-utils': 6.10.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.10.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.10.0
'@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/type-utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4
eslint: 8.53.0
graphemer: 1.4.0
@ -1215,8 +1215,8 @@ packages:
- supports-color
dev: false
/@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==}
/@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
@ -1225,10 +1225,10 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 6.10.0
'@typescript-eslint/types': 6.10.0
'@typescript-eslint/typescript-estree': 6.10.0(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.10.0
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.11.0
'@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4
eslint: 8.53.0
typescript: 5.2.2
@ -1236,16 +1236,16 @@ packages:
- supports-color
dev: false
/@typescript-eslint/scope-manager@6.10.0:
resolution: {integrity: sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==}
/@typescript-eslint/scope-manager@6.11.0:
resolution: {integrity: sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.10.0
'@typescript-eslint/visitor-keys': 6.10.0
'@typescript-eslint/types': 6.11.0
'@typescript-eslint/visitor-keys': 6.11.0
dev: false
/@typescript-eslint/type-utils@6.10.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==}
/@typescript-eslint/type-utils@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
@ -1254,8 +1254,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 6.10.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.10.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
debug: 4.3.4
eslint: 8.53.0
ts-api-utils: 1.0.3(typescript@5.2.2)
@ -1264,13 +1264,13 @@ packages:
- supports-color
dev: false
/@typescript-eslint/types@6.10.0:
resolution: {integrity: sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==}
/@typescript-eslint/types@6.11.0:
resolution: {integrity: sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: false
/@typescript-eslint/typescript-estree@6.10.0(typescript@5.2.2):
resolution: {integrity: sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==}
/@typescript-eslint/typescript-estree@6.11.0(typescript@5.2.2):
resolution: {integrity: sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
typescript: '*'
@ -1278,8 +1278,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 6.10.0
'@typescript-eslint/visitor-keys': 6.10.0
'@typescript-eslint/types': 6.11.0
'@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
@ -1290,8 +1290,8 @@ packages:
- supports-color
dev: false
/@typescript-eslint/utils@6.10.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==}
/@typescript-eslint/utils@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
@ -1299,9 +1299,9 @@ packages:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
'@types/json-schema': 7.0.15
'@types/semver': 7.5.5
'@typescript-eslint/scope-manager': 6.10.0
'@typescript-eslint/types': 6.10.0
'@typescript-eslint/typescript-estree': 6.10.0(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.11.0
'@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
eslint: 8.53.0
semver: 7.5.4
transitivePeerDependencies:
@ -1309,11 +1309,11 @@ packages:
- typescript
dev: false
/@typescript-eslint/visitor-keys@6.10.0:
resolution: {integrity: sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==}
/@typescript-eslint/visitor-keys@6.11.0:
resolution: {integrity: sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.10.0
'@typescript-eslint/types': 6.11.0
eslint-visitor-keys: 3.4.3
dev: false
@ -1327,8 +1327,8 @@ packages:
server-only: 0.0.1
dev: false
/@vercel/blob@0.15.0:
resolution: {integrity: sha512-bWTuln4nkMG7APvcqIA2y5YCYKnmpUdzoITRdJOpDVeRSVoyVFwYOZleb/bj7UWDGfRN7P2JJ2mMMQ2nrpysEQ==}
/@vercel/blob@0.15.1:
resolution: {integrity: sha512-Wo7VU9/tM8kkv7krvxGoDeu/Li0h7PYR/TB1TEiyJZzACruA0jWqj44OGokJQCYN3ZvV5tXHpTAN6pImIBCrUw==}
engines: {node: '>=16.14'}
dependencies:
jest-environment-jsdom: 29.7.0
@ -1895,7 +1895,7 @@ packages:
engines: {node: '>= 0.6'}
dev: false
/create-jest@29.7.0(@types/node@20.9.0):
/create-jest@29.7.0(@types/node@20.9.1):
resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
@ -1904,7 +1904,7 @@ packages:
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.11
jest-config: 29.7.0(@types/node@20.9.0)
jest-config: 29.7.0(@types/node@20.9.1)
jest-util: 29.7.0
prompts: 2.4.2
transitivePeerDependencies:
@ -2293,8 +2293,8 @@ packages:
source-map: 0.6.1
dev: false
/eslint-config-next@14.0.1(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-QfIFK2WD39H4WOespjgf6PLv9Bpsd7KGGelCtmq4l67nGvnlsGpuvj0hIT+aIy6p5gKH+lAChYILsyDlxP52yg==}
/eslint-config-next@14.0.3(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-IKPhpLdpSUyKofmsXUfrvBC49JMUTdeaD8ZIH4v9Vk0sC1X6URTuTJCLtA0Vwuj7V/CQh0oISuSTvNn5//Buew==}
peerDependencies:
eslint: ^7.23.0 || ^8.0.0
typescript: '>=3.3.1'
@ -2302,13 +2302,13 @@ packages:
typescript:
optional: true
dependencies:
'@next/eslint-plugin-next': 14.0.1
'@next/eslint-plugin-next': 14.0.3
'@rushstack/eslint-patch': 1.5.1
'@typescript-eslint/parser': 6.10.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
eslint: 8.53.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.53.0)
eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0)
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.53.0)
eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0)
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.53.0)
eslint-plugin-react: 7.33.2(eslint@8.53.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.53.0)
@ -2328,7 +2328,7 @@ packages:
- supports-color
dev: false
/eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.53.0):
/eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.53.0):
resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
@ -2338,8 +2338,8 @@ packages:
debug: 4.3.4
enhanced-resolve: 5.15.0
eslint: 8.53.0
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0)
eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0)
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0)
eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0)
fast-glob: 3.3.2
get-tsconfig: 4.7.2
is-core-module: 2.13.1
@ -2351,7 +2351,7 @@ packages:
- supports-color
dev: false
/eslint-module-utils@2.8.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0):
/eslint-module-utils@2.8.0(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'}
peerDependencies:
@ -2372,16 +2372,16 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 6.10.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
debug: 3.2.7
eslint: 8.53.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.53.0)
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.53.0)
transitivePeerDependencies:
- supports-color
dev: false
/eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0):
/eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0):
resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==}
engines: {node: '>=4'}
peerDependencies:
@ -2391,7 +2391,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 6.10.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
array-includes: 3.1.7
array.prototype.findlastindex: 1.2.3
array.prototype.flat: 1.3.2
@ -2400,7 +2400,7 @@ packages:
doctrine: 2.1.0
eslint: 8.53.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.10.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0)
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0)
hasown: 2.0.0
is-core-module: 2.13.1
is-glob: 4.0.3
@ -2702,8 +2702,8 @@ packages:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
dev: false
/framer-motion@10.16.4(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-p9V9nGomS3m6/CALXqv6nFGMuFOxbWsmaOrdmhyQimMIlLl3LC7h7l86wge/Js/8cRu5ktutS/zlzgR7eBOtFA==}
/framer-motion@10.16.5(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-GEzVjOYP2MIpV9bT/GbhcsBNoImG3/2X3O/xVNWmktkv9MdJ7P/44zELm/7Fjb+O3v39SmKFnoDQB32giThzpg==}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
@ -3322,7 +3322,7 @@ packages:
'@jest/expect': 29.7.0
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
chalk: 4.1.2
co: 4.6.0
dedent: 1.5.1
@ -3343,7 +3343,7 @@ packages:
- supports-color
dev: false
/jest-cli@29.7.0(@types/node@20.9.0):
/jest-cli@29.7.0(@types/node@20.9.1):
resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
@ -3357,10 +3357,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.9.0)
create-jest: 29.7.0(@types/node@20.9.1)
exit: 0.1.2
import-local: 3.1.0
jest-config: 29.7.0(@types/node@20.9.0)
jest-config: 29.7.0(@types/node@20.9.1)
jest-util: 29.7.0
jest-validate: 29.7.0
yargs: 17.7.2
@ -3371,7 +3371,7 @@ packages:
- ts-node
dev: false
/jest-config@29.7.0(@types/node@20.9.0):
/jest-config@29.7.0(@types/node@20.9.1):
resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
@ -3386,7 +3386,7 @@ packages:
'@babel/core': 7.23.3
'@jest/test-sequencer': 29.7.0
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
babel-jest: 29.7.0(@babel/core@7.23.3)
chalk: 4.1.2
ci-info: 3.9.0
@ -3452,7 +3452,7 @@ packages:
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
'@types/jsdom': 20.0.1
'@types/node': 20.9.0
'@types/node': 20.9.1
jest-mock: 29.7.0
jest-util: 29.7.0
jsdom: 20.0.3
@ -3469,7 +3469,7 @@ packages:
'@jest/environment': 29.7.0
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
jest-mock: 29.7.0
jest-util: 29.7.0
dev: false
@ -3485,7 +3485,7 @@ packages:
dependencies:
'@jest/types': 29.6.3
'@types/graceful-fs': 4.1.9
'@types/node': 20.9.0
'@types/node': 20.9.1
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.11
@ -3536,7 +3536,7 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
jest-util: 29.7.0
dev: false
@ -3591,7 +3591,7 @@ packages:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
chalk: 4.1.2
emittery: 0.13.1
graceful-fs: 4.2.11
@ -3622,7 +3622,7 @@ packages:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
chalk: 4.1.2
cjs-module-lexer: 1.2.3
collect-v8-coverage: 1.0.2
@ -3674,7 +3674,7 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
chalk: 4.1.2
ci-info: 3.9.0
graceful-fs: 4.2.11
@ -3699,7 +3699,7 @@ packages:
dependencies:
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
'@types/node': 20.9.0
'@types/node': 20.9.1
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
@ -3711,13 +3711,13 @@ packages:
resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.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.9.0):
/jest@29.7.0(@types/node@20.9.1):
resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
@ -3730,7 +3730,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.9.0)
jest-cli: 29.7.0(@types/node@20.9.1)
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@ -4052,7 +4052,7 @@ packages:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: false
/next-auth@5.0.0-beta.3(next@14.0.1)(react@18.2.0):
/next-auth@5.0.0-beta.3(next@14.0.3)(react@18.2.0):
resolution: {integrity: sha512-WOKhATBFGeONV+29HzFmspNmL7NXxrsCWLfaDKmAd/4DD1nqXE0BzNFH8t3SJBx7PUDMnB6F7xB76LM/AaV1MQ==}
peerDependencies:
next: ^14
@ -4063,24 +4063,24 @@ packages:
optional: true
dependencies:
'@auth/core': 0.0.0-manual.e9863699
next: 14.0.1(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0)
next: 14.0.3(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
dev: false
/next-themes@0.2.1(next@14.0.1)(react-dom@18.2.0)(react@18.2.0):
/next-themes@0.2.1(next@14.0.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
peerDependencies:
next: '*'
react: '*'
react-dom: '*'
dependencies:
next: 14.0.1(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0)
next: 14.0.3(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/next@14.0.1(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-s4YaLpE4b0gmb3ggtmpmV+wt+lPRuGtANzojMQ2+gmBpgX9w5fTbjsy6dXByBuENsdCX5pukZH/GxdFgO62+pA==}
/next@14.0.3(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-AbYdRNfImBr3XGtvnwOxq8ekVCwbFTv/UJoLwmaX89nk9i051AEY4/HAWzU0YpaTDw8IofUpmuIlvzWF13jxIw==}
engines: {node: '>=18.17.0'}
hasBin: true
peerDependencies:
@ -4094,7 +4094,7 @@ packages:
sass:
optional: true
dependencies:
'@next/env': 14.0.1
'@next/env': 14.0.3
'@swc/helpers': 0.5.2
busboy: 1.6.0
caniuse-lite: 1.0.30001561
@ -4104,15 +4104,15 @@ packages:
styled-jsx: 5.1.1(@babel/core@7.23.3)(react@18.2.0)
watchpack: 2.4.0
optionalDependencies:
'@next/swc-darwin-arm64': 14.0.1
'@next/swc-darwin-x64': 14.0.1
'@next/swc-linux-arm64-gnu': 14.0.1
'@next/swc-linux-arm64-musl': 14.0.1
'@next/swc-linux-x64-gnu': 14.0.1
'@next/swc-linux-x64-musl': 14.0.1
'@next/swc-win32-arm64-msvc': 14.0.1
'@next/swc-win32-ia32-msvc': 14.0.1
'@next/swc-win32-x64-msvc': 14.0.1
'@next/swc-darwin-arm64': 14.0.3
'@next/swc-darwin-x64': 14.0.3
'@next/swc-linux-arm64-gnu': 14.0.3
'@next/swc-linux-arm64-musl': 14.0.3
'@next/swc-linux-x64-gnu': 14.0.3
'@next/swc-linux-x64-musl': 14.0.3
'@next/swc-win32-arm64-msvc': 14.0.3
'@next/swc-win32-ia32-msvc': 14.0.3
'@next/swc-win32-x64-msvc': 14.0.3
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
@ -4576,8 +4576,8 @@ packages:
scheduler: 0.23.0
dev: false
/react-icons@4.11.0(react@18.2.0):
resolution: {integrity: sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA==}
/react-icons@4.12.0(react@18.2.0):
resolution: {integrity: sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==}
peerDependencies:
react: '*'
dependencies:

View File

@ -5,8 +5,6 @@ import { syncCacheAction } from '@/photo/actions';
import SiteChecklist from '@/site/SiteChecklist';
import { BiTrash } from 'react-icons/bi';
export const runtime = 'edge';
export default async function AdminConfigurationPage() {
return (
<SiteGrid

View File

@ -1,5 +1,5 @@
import { redirect } from 'next/navigation';
import { getPhotoCached } from '@/cache';
import { getPhotoNoStore } from '@/cache';
import { PATH_ADMIN } from '@/site/paths';
import PhotoEditPageClient from '@/photo/PhotoEditPageClient';
@ -8,7 +8,7 @@ export default async function PhotoEditPage({
}: {
params: { photoId: string }
}) {
const photo = await getPhotoCached(photoId);
const photo = await getPhotoNoStore(photoId);
if (!photo) { redirect(PATH_ADMIN); }

View File

@ -33,7 +33,7 @@ import IconGrSync from '@/site/IconGrSync';
const DEBUG_PHOTO_BLOBS = false;
export default async function AdminTagsPage({
export default async function AdminPhotosPage({
searchParams,
}: PaginationParams) {
const { offset, limit } = getPaginationForSearchParams(searchParams);

View File

@ -9,8 +9,6 @@ import PhotoLightbox from '@/photo/PhotoLightbox';
const MAX_PHOTO_TO_SHOW = 6;
export const runtime = 'edge';
interface Props {
params: { tag: string }
}

View File

@ -12,9 +12,7 @@ import EditButton from '@/admin/EditButton';
import { pathForAdminTagEdit } from '@/site/paths';
import { cc } from '@/utility/css';
export const runtime = 'edge';
export default async function AdminPhotosPage() {
export default async function AdminTagsPage() {
const tags = await getUniqueTagsHiddenCached();
return (

View File

@ -1,11 +1,9 @@
import { revalidatePhotosAndBlobKeys, revalidateAdminPaths } from '@/cache';
import { revalidateAdminPaths, revalidatePhotosKey } from '@/cache';
import { ACCEPTED_PHOTO_FILE_TYPES } from '@/photo';
import { isUploadPathnameValid } from '@/services/blob';
import { handleUpload, type HandleUploadBody } from '@vercel/blob/client';
import { NextResponse } from 'next/server';
export const runtime = 'edge';
export async function POST(request: Request): Promise<NextResponse> {
const body = (await request.json()) as HandleUploadBody;
@ -25,11 +23,11 @@ export async function POST(request: Request): Promise<NextResponse> {
},
// This argument is required, but doesn't seem to fire
onUploadCompleted: async () => {
revalidatePhotosAndBlobKeys();
revalidatePhotosKey();
revalidateAdminPaths();
},
});
revalidatePhotosAndBlobKeys();
revalidatePhotosKey();
revalidateAdminPaths();
return NextResponse.json(jsonResponse);
} catch (error) {

View File

@ -2,7 +2,7 @@ import BlobUrls from '@/admin/BlobUrls';
import { getBlobUploadUrlsNoStore } from '@/cache';
import SiteGrid from '@/components/SiteGrid';
export default async function UploadsPage() {
export default async function AdminUploadsPage() {
const blobUrls = await getBlobUploadUrlsNoStore();
return (
<SiteGrid

View File

@ -11,7 +11,6 @@ import {
} from '@/site/paths';
import PhotoDetailPage from '@/photo/PhotoDetailPage';
import { getPhotoCached } from '@/cache';
import { getPhotos, getUniqueFilmSimulations } from '@/services/postgres';
import { ReactNode } from 'react';
import { FilmSimulation } from '@/simulation';
import { getPhotosFilmSimulationDataCached } from '@/simulation/data';
@ -20,20 +19,6 @@ interface PhotoFilmSimulationProps {
params: { photoId: string, simulation: FilmSimulation }
}
export async function generateStaticParams() {
const params: PhotoFilmSimulationProps[] = [];
const simulations = await getUniqueFilmSimulations();
simulations.forEach(async ({ simulation }) => {
const photos = await getPhotos({ simulation });
params.push(...photos.map(photo => ({
params: { photoId: photo.id, simulation },
})));
});
return params;
}
export async function generateMetadata({
params: { photoId, simulation },
}: PhotoFilmSimulationProps): Promise<Metadata> {

View File

@ -1,31 +1,14 @@
import { getPhotoCached } from '@/cache';
import PhotoShareModal from '@/photo/PhotoShareModal';
import { getPhotos, getUniqueFilmSimulations } from '@/services/postgres';
import { FilmSimulation } from '@/simulation';
import { PATH_ROOT } from '@/site/paths';
import { redirect } from 'next/navigation';
interface PhotoFilmSimulationProps {
params: { photoId: string, simulation: FilmSimulation }
}
export async function generateStaticParams() {
const params: PhotoFilmSimulationProps[] = [];
const simulations = await getUniqueFilmSimulations();
simulations.forEach(async ({ simulation }) => {
const photos = await getPhotos({ simulation });
params.push(...photos.map(photo => ({
params: { photoId: photo.id, simulation },
})));
});
return params;
}
export default async function Share({
params: { photoId, simulation },
}: PhotoFilmSimulationProps) {
}: {
params: { photoId: string, simulation: FilmSimulation }
}) {
const photo = await getPhotoCached(photoId);
if (!photo) { return redirect(PATH_ROOT); }

View File

@ -10,8 +10,6 @@ import { FilmSimulation } from '@/simulation';
import { getIBMPlexMonoMedium } from '@/site/font';
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET(
_: Request,
context: { params: { simulation: FilmSimulation } },

View File

@ -8,8 +8,6 @@ import {
import { PaginationParams } from '@/site/pagination';
import { Metadata } from 'next';
export const runtime = 'edge';
interface FilmSimulationProps {
params: { simulation: FilmSimulation }
}

View File

@ -9,8 +9,6 @@ import {
import { PaginationParams } from '@/site/pagination';
import { Metadata } from 'next';
export const runtime = 'edge';
interface FilmSimulationProps {
params: { simulation: FilmSimulation }
}

View File

@ -19,8 +19,6 @@ import {
import PhotoGridSidebar from '@/photo/PhotoGridSidebar';
import { SHOW_FILM_SIMULATIONS } from '@/site/config';
export const runtime = 'edge';
export async function generateMetadata(): Promise<Metadata> {
const photos = await getPhotosCached({ limit: MAX_PHOTOS_TO_SHOW_OG });
return generateOgImageMetaForPhotos(photos);

View File

@ -8,8 +8,6 @@ import HomeImageResponse from '@/photo/image-response/HomeImageResponse';
import { getIBMPlexMonoMedium } from '@/site/font';
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET() {
const [
photos,

View File

@ -7,8 +7,6 @@ import {
} from '@/site/pagination';
import { pathForOg } from '@/site/paths';
export const runtime = 'edge';
export default async function GridPage({ searchParams }: PaginationParams) {
const { offset, limit } = getPaginationForSearchParams(searchParams);

View File

@ -5,8 +5,6 @@ import PhotoImageResponse from '@/photo/image-response/PhotoImageResponse';
import { getIBMPlexMonoMedium } from '@/site/font';
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET(
_: Request,
context: { params: { photoId: string } },

View File

@ -12,20 +12,14 @@ import {
} from '@/site/paths';
import PhotoDetailPage from '@/photo/PhotoDetailPage';
import { getPhotoCached, getPhotosCached } from '@/cache';
import { getPhotos } from '@/services/postgres';
export async function generateStaticParams() {
const photos = await getPhotos();
return photos.map(photo => ({
params: { photoId: photo.id },
}));
interface PhotoProps {
params: { photoId: string }
}
export async function generateMetadata({
params: { photoId },
}: {
params: { photoId: string }
}): Promise<Metadata> {
}:PhotoProps): Promise<Metadata> {
const photo = await getPhotoCached(photoId);
if (!photo) { return {}; }
@ -56,10 +50,8 @@ export async function generateMetadata({
export default async function PhotoPage({
params: { photoId },
children,
}: {
params: { photoId: string }
children: React.ReactNode
}) {
}:
PhotoProps & { children: React.ReactNode }) {
const photo = await getPhotoCached(photoId);
if (!photo) { redirect(PATH_ROOT); }

View File

@ -3,8 +3,6 @@ import PhotoShareModal from '@/photo/PhotoShareModal';
import { PATH_ROOT } from '@/site/paths';
import { redirect } from 'next/navigation';
export const runtime = 'edge';
export default async function Share({
params: { photoId },
}: {

View File

@ -13,8 +13,6 @@ import { pathForRoot } from '@/site/paths';
import { Metadata } from 'next';
import { MAX_PHOTOS_TO_SHOW_OG } from '@/photo/image-response';
export const runtime = 'edge';
export async function generateMetadata(): Promise<Metadata> {
const photos = await getPhotosCached({ limit: MAX_PHOTOS_TO_SHOW_OG });
return generateOgImageMetaForPhotos(photos);

View File

@ -15,8 +15,6 @@ import { SHOW_FILM_SIMULATIONS } from '@/site/config';
import { PATH_GRID } from '@/site/paths';
import { Metadata } from 'next';
export const runtime = 'edge';
export async function generateMetadata(): Promise<Metadata> {
const photos = await getPhotosCached({ limit: MAX_PHOTOS_TO_SHOW_OG });
return generateOgImageMetaForPhotos(photos);

View File

@ -11,10 +11,6 @@ import {
} from '@/site/paths';
import PhotoDetailPage from '@/photo/PhotoDetailPage';
import { getPhotoCached } from '@/cache';
import {
getPhotos,
getUniqueCameras,
} from '@/services/postgres';
import { cameraFromPhoto } from '@/camera';
import { getPhotosCameraDataCached } from '@/camera/data';
import { ReactNode } from 'react';
@ -23,20 +19,6 @@ interface PhotoCameraProps {
params: { photoId: string, camera: string }
}
export async function generateStaticParams() {
const params: PhotoCameraProps[] = [];
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 async function generateMetadata({
params: { photoId, camera },
}: PhotoCameraProps): Promise<Metadata> {

View File

@ -1,31 +1,14 @@
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) {
}: {
params: { photoId: string, camera: string }
}) {
const photo = await getPhotoCached(photoId);
if (!photo) { return redirect(PATH_ROOT); }

View File

@ -9,8 +9,6 @@ import CameraImageResponse from '@/photo/image-response/CameraImageResponse';
import { getIBMPlexMonoMedium } from '@/site/font';
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET(
_: Request,
context: { params: { camera: string } },

View File

@ -9,8 +9,6 @@ import {
} from '@/camera/data';
import CameraOverview from '@/camera/CameraOverview';
export const runtime = 'edge';
interface CameraProps {
params: { camera: string },
}

View File

@ -10,8 +10,6 @@ import {
} from '@/camera/data';
import CameraOverview from '@/camera/CameraOverview';
export const runtime = 'edge';
interface CameraProps {
params: { camera: string }
}

View File

@ -11,7 +11,6 @@ import {
} from '@/site/paths';
import PhotoDetailPage from '@/photo/PhotoDetailPage';
import { getPhotoCached } from '@/cache';
import { getPhotos, getUniqueTags } from '@/services/postgres';
import { getPhotosTagDataCached } from '@/tag/data';
import { ReactNode } from 'react';
@ -19,20 +18,6 @@ interface PhotoTagProps {
params: { photoId: string, tag: string }
}
export async function generateStaticParams() {
const params: PhotoTagProps[] = [];
const tags = await getUniqueTags();
tags.forEach(async ({ tag }) => {
const photos = await getPhotos({ tag });
params.push(...photos.map(photo => ({
params: { photoId: photo.id, tag },
})));
});
return params;
}
export async function generateMetadata({
params: { photoId, tag },
}: PhotoTagProps): Promise<Metadata> {

View File

@ -1,30 +1,13 @@
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';
interface PhotoTagProps {
params: { photoId: string, tag: string }
}
export async function generateStaticParams() {
const params: PhotoTagProps[] = [];
const tags = await getUniqueTags();
tags.forEach(async ({ tag }) => {
const photos = await getPhotos({ tag });
params.push(...photos.map(photo => ({
params: { photoId: photo.id, tag },
})));
});
return params;
}
export default async function Share({
params: { photoId, tag },
}: PhotoTagProps) {
}: {
params: { photoId: string, tag: string }
}) {
const photo = await getPhotoCached(photoId);
if (!photo) { return redirect(PATH_ROOT); }

View File

@ -8,8 +8,6 @@ import TagImageResponse from '@/photo/image-response/TagImageResponse';
import { getIBMPlexMonoMedium } from '@/site/font';
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET(
_: Request,
context: { params: { tag: string } },

View File

@ -8,8 +8,6 @@ import {
} from '@/tag/data';
import { Metadata } from 'next';
export const runtime = 'edge';
interface TagProps {
params: { tag: string }
}

View File

@ -9,8 +9,6 @@ import {
} from '@/tag/data';
import { Metadata } from 'next';
export const runtime = 'edge';
interface TagProps {
params: { tag: string }
}

View File

@ -9,8 +9,6 @@ import TemplateImageResponse from
import { getIBMPlexMonoMedium } from '@/site/font';
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET() {
const [
photos,

View File

@ -9,8 +9,6 @@ import TemplateImageResponse from
import { getIBMPlexMonoMedium } from '@/site/font';
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET() {
const [
photos,

View File

@ -4,8 +4,6 @@ import { PATH_ADMIN } from '@/site/paths';
import { cc } from '@/utility/css';
import { redirect } from 'next/navigation';
export const runtime = 'edge';
export default async function SignInPage() {
const session = await auth();

232
src/cache/index.ts vendored
View File

@ -21,22 +21,24 @@ import {
getPhotosFilmSimulationDateRange,
getPhotosFilmSimulationCount,
} from '@/services/postgres';
import { parseCachedPhotosDates, parseCachedPhotoDates } from '@/photo';
import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo';
import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob';
import type { Session } from 'next-auth';
import { Camera, createCameraKey } from '@/camera';
import { PATHS_ADMIN, PATHS_TO_CACHE } from '@/site/paths';
import { FilmSimulation } from '@/simulation';
import { createCameraKey } from '@/camera';
import { PATHS_ADMIN } from '@/site/paths';
// Table key
const KEY_PHOTOS = 'photos';
const KEY_PHOTOS_COUNT = `${KEY_PHOTOS}-count`;
const KEY_PHOTOS_DATE_RANGE = `${KEY_PHOTOS}-date-range`;
const KEY_PHOTO = 'photo';
// Field keys
const KEY_TAGS = 'tags';
const KEY_CAMERAS = 'cameras';
const KEY_FILM_SIMULATIONS = 'film-simulations';
const KEY_BLOB = 'blob';
// Type keys
const KEY_COUNT = 'count';
const KEY_HIDDEN = 'hidden';
const KEY_DATE_RANGE = 'date-range';
// eslint-disable-next-line max-len
const getPhotosCacheKeyForOption = (
options: GetPhotosOptions,
option: keyof GetPhotosOptions,
@ -60,7 +62,7 @@ const getPhotosCacheKeyForOption = (
// Complex keys
case 'camera': {
const value = options[option];
return value ? `${option}-${value.make}-${value.model}` : null;
return value ? `${option}-${createCameraKey(value)}` : null;
}
}
};
@ -79,26 +81,6 @@ const getPhotosCacheKeys = (options: GetPhotosOptions = {}) => {
return tags;
};
const getPhotoCacheKey = (photoId: string) => `photo-${photoId}`;
const getPhotoTagCountKey = (tag: string) =>
`${KEY_PHOTOS_COUNT}-${KEY_TAGS}-${tag}`;
const getPhotoCameraCountKey = (camera: Camera) =>
`${KEY_PHOTOS_COUNT}-${KEY_CAMERAS}-${createCameraKey(camera)}`;
const getPhotoFilmSimulationCountKey = (simulation: FilmSimulation) =>
`${KEY_PHOTOS_COUNT}-${KEY_FILM_SIMULATIONS}-${simulation}`;
const getPhotoTagDateRangeKey = (tag: string) =>
`${KEY_PHOTOS_DATE_RANGE}-${KEY_TAGS}-${tag}`;
const getPhotoCameraDateRangeKey = (camera: Camera) =>
`${KEY_PHOTOS_DATE_RANGE}-${KEY_CAMERAS}-${createCameraKey(camera)}`;
const getPhotoFilmSimulationDateRangeKey = (simulation: FilmSimulation) =>
`${KEY_PHOTOS_DATE_RANGE}-${KEY_FILM_SIMULATIONS}-${simulation}`;
export const revalidatePhotosKey = () =>
revalidateTag(KEY_PHOTOS);
@ -111,16 +93,8 @@ export const revalidateCamerasKey = () =>
export const revalidateFilmSimulationsKey = () =>
revalidateTag(KEY_FILM_SIMULATIONS);
export const revalidateBlobKey = () =>
revalidateTag(KEY_BLOB);
export const revalidatePhotosAndBlobKeys = () => {
revalidatePhotosKey();
revalidateBlobKey();
};
export const revalidateAllKeys = () => {
revalidatePhotosAndBlobKeys();
revalidatePhotosKey();
revalidateTagsKey();
revalidateCamerasKey();
revalidateFilmSimulationsKey();
@ -128,154 +102,114 @@ export const revalidateAllKeys = () => {
export const revalidateAllKeysAndPaths = () => {
revalidateAllKeys();
PATHS_TO_CACHE.forEach(path => revalidatePath(path));
revalidatePath('/', 'layout');
};
export const revalidateAdminPaths = () => {
PATHS_ADMIN.forEach(path => revalidatePath(path));
};
export const getPhotosCached: typeof getPhotos = (...args) =>
unstable_cache(
() => getPhotos(...args),
[KEY_PHOTOS, ...getPhotosCacheKeys(...args)], {
tags: [KEY_PHOTOS, ...getPhotosCacheKeys(...args)],
}
)().then(parseCachedPhotosDates);
// Cache
export const getPhotosCountCached: typeof getPhotosCount = (...args) =>
unstable_cache(
() => getPhotosCount(...args),
[KEY_PHOTOS, KEY_PHOTOS_COUNT], {
tags: [KEY_PHOTOS, KEY_PHOTOS_COUNT],
}
)();
export const getPhotosCached = (
...args: Parameters<typeof getPhotos>
) => unstable_cache(
getPhotos,
[KEY_PHOTOS, ...getPhotosCacheKeys(...args)],
)(...args).then(parseCachedPhotosDates);
export const getPhotosCountIncludingHiddenCached: typeof getPhotosCount =
(...args) =>
unstable_cache(
() => getPhotosCountIncludingHidden(...args),
[KEY_PHOTOS, KEY_PHOTOS_COUNT], {
tags: [KEY_PHOTOS, KEY_PHOTOS_COUNT],
}
)();
export const getPhotosTagCountCached: typeof getPhotosTagCount = (...args) =>
export const getPhotosCountCached =
unstable_cache(
() => getPhotosTagCount(...args),
[KEY_PHOTOS, getPhotoTagCountKey(...args)], {
tags: [KEY_PHOTOS, getPhotoTagCountKey(...args)],
}
)();
getPhotosCount,
[KEY_PHOTOS, KEY_COUNT],
);
// eslint-disable-next-line max-len
export const getPhotosCameraCountCached: typeof getPhotosCameraCount = (...args) =>
export const getPhotosCountIncludingHiddenCached =
unstable_cache(
() => getPhotosCameraCount(...args),
[KEY_PHOTOS, getPhotoCameraCountKey(...args)], {
tags: [KEY_PHOTOS, getPhotoCameraCountKey(...args)],
}
)();
getPhotosCountIncludingHidden,
[KEY_PHOTOS, KEY_COUNT, KEY_HIDDEN],
);
// eslint-disable-next-line max-len
export const getPhotosFilmSimulationCountCached: typeof getPhotosFilmSimulationCount = (...args) =>
export const getPhotosTagCountCached =
unstable_cache(
() => getPhotosFilmSimulationCount(...args),
[KEY_PHOTOS, getPhotoFilmSimulationCountKey(...args)], {
tags: [KEY_PHOTOS, getPhotoFilmSimulationCountKey(...args)],
}
)();
getPhotosTagCount,
[KEY_PHOTOS, KEY_TAGS],
);
// eslint-disable-next-line max-len
export const getPhotosTagDateRangeCached: typeof getPhotosTagDateRange = (...args) =>
export const getPhotosCameraCountCached = (
...args: Parameters<typeof getPhotosCameraCount>
) =>
unstable_cache(
() => getPhotosTagDateRange(...args),
[KEY_PHOTOS, getPhotoTagDateRangeKey(...args)], {
tags: [KEY_PHOTOS, getPhotoTagDateRangeKey(...args)],
}
)();
getPhotosCameraCount,
[KEY_PHOTOS, KEY_COUNT, createCameraKey(...args)],
)(...args);
// eslint-disable-next-line max-len
export const getPhotosCameraDateRangeCached: typeof getPhotosCameraDateRange = (...args) =>
export const getPhotosFilmSimulationCountCached =
unstable_cache(
() => getPhotosCameraDateRange(...args),
[KEY_PHOTOS, getPhotoCameraDateRangeKey(...args)], {
tags: [KEY_PHOTOS, getPhotoCameraDateRangeKey(...args)],
}
)();
getPhotosFilmSimulationCount,
[KEY_PHOTOS, KEY_FILM_SIMULATIONS, KEY_COUNT],
);
// eslint-disable-next-line max-len
export const getPhotosFilmSimulationDateRangeCached: typeof getPhotosFilmSimulationDateRange = (...args) =>
export const getPhotosTagDateRangeCached =
unstable_cache(
() => getPhotosFilmSimulationDateRange(...args),
[KEY_PHOTOS, getPhotoFilmSimulationDateRangeKey(...args)], {
tags: [KEY_PHOTOS, getPhotoFilmSimulationDateRangeKey(...args)],
}
)();
getPhotosTagDateRange,
[KEY_PHOTOS, KEY_TAGS, KEY_DATE_RANGE],
);
export const getPhotoCached: typeof getPhoto = (...args) =>
export const getPhotosCameraDateRangeCached =
unstable_cache(
() => getPhoto(...args),
[KEY_PHOTOS, getPhotoCacheKey(...args)], {
tags: [KEY_PHOTOS, getPhotoCacheKey(...args)],
}
)().then(photo => photo ? parseCachedPhotoDates(photo) : undefined);
getPhotosCameraDateRange,
[KEY_PHOTOS, KEY_CAMERAS, KEY_DATE_RANGE],
);
export const getUniqueTagsCached: typeof getUniqueTags = (...args) =>
export const getPhotosFilmSimulationDateRangeCached =
unstable_cache(
() => getUniqueTags(...args),
[KEY_PHOTOS, KEY_TAGS], {
tags: [KEY_PHOTOS, KEY_TAGS],
}
)();
getPhotosFilmSimulationDateRange,
[KEY_PHOTOS, KEY_FILM_SIMULATIONS, KEY_DATE_RANGE],
);
// eslint-disable-next-line max-len
export const getUniqueTagsHiddenCached: typeof getUniqueTagsHidden = (...args) =>
export const getPhotoCached = (...args: Parameters<typeof getPhoto>) =>
unstable_cache(
() => getUniqueTagsHidden(...args),
[KEY_PHOTOS, KEY_TAGS], {
tags: [KEY_PHOTOS, KEY_TAGS],
}
)();
getPhoto,
[KEY_PHOTOS, KEY_PHOTO]
)(...args).then(photo => photo ? parseCachedPhotoDates(photo) : undefined);
export const getUniqueCamerasCached: typeof getUniqueCameras = (...args) =>
export const getUniqueTagsCached =
unstable_cache(
() => getUniqueCameras(...args),
[KEY_PHOTOS, KEY_CAMERAS], {
tags: [KEY_PHOTOS, KEY_CAMERAS],
}
)();
getUniqueTags,
[KEY_PHOTOS, KEY_TAGS],
);
// eslint-disable-next-line max-len
export const getUniqueFilmSimulationsCached: typeof getUniqueFilmSimulations = (...args) =>
export const getUniqueTagsHiddenCached =
unstable_cache(
() => getUniqueFilmSimulations(...args),
[KEY_PHOTOS, KEY_FILM_SIMULATIONS], {
tags: [KEY_PHOTOS, KEY_FILM_SIMULATIONS],
}
)();
getUniqueTagsHidden,
[KEY_PHOTOS, KEY_TAGS, KEY_HIDDEN]
);
export const getBlobUploadUrlsCached: typeof getBlobUploadUrls = (...args) =>
export const getUniqueCamerasCached =
unstable_cache(
() => getBlobUploadUrls(...args),
[KEY_BLOB, 'uploads'], {
tags: [KEY_BLOB, 'uploads'],
}
)();
getUniqueCameras,
[KEY_PHOTOS, KEY_CAMERAS]
);
export const getUniqueFilmSimulationsCached =
unstable_cache(
getUniqueFilmSimulations,
[KEY_PHOTOS, KEY_FILM_SIMULATIONS],
);
// No Store
export const getPhotoNoStore = (...args: Parameters<typeof getPhoto>) => {
unstable_noStore();
return getPhoto(...args);
};
export const getBlobUploadUrlsNoStore: typeof getBlobUploadUrls = (...args) => {
unstable_noStore();
return getBlobUploadUrls(...args);
};
export const getBlobPhotoUrlsCached: typeof getBlobPhotoUrls = (...args) =>
unstable_cache(
() => getBlobPhotoUrls(...args),
[KEY_BLOB, 'photos'], {
tags: [KEY_BLOB, 'photos'],
}
)();
export const getBlobPhotoUrlsNoStore: typeof getBlobPhotoUrls = (...args) => {
unstable_noStore();
return getBlobPhotoUrls(...args);

View File

@ -21,7 +21,6 @@ import {
import {
revalidateAdminPaths,
revalidateAllKeysAndPaths,
revalidateBlobKey,
revalidatePhotosKey,
} from '@/cache';
import { PATH_ADMIN_PHOTOS, PATH_ADMIN_TAGS } from '@/site/paths';
@ -46,7 +45,7 @@ export async function updatePhotoAction(formData: FormData) {
await sqlUpdatePhoto(photo);
revalidatePhotosKey();
revalidateAllKeysAndPaths();
redirect(PATH_ADMIN_PHOTOS);
}
@ -57,8 +56,7 @@ export async function deletePhotoAction(formData: FormData) {
sqlDeletePhoto(formData.get('id') as string),
]);
revalidatePhotosKey();
revalidateAdminPaths();
revalidateAllKeysAndPaths();
};
export async function deletePhotoTagGloballyAction(formData: FormData) {
@ -84,7 +82,6 @@ export async function renamePhotoTagGloballyAction(formData: FormData) {
export async function deleteBlobPhotoAction(formData: FormData) {
await deleteBlobPhoto(formData.get('url') as string);
revalidateBlobKey();
revalidateAdminPaths();
if (formData.get('redirectToPhotos') === 'true') {

View File

@ -97,7 +97,7 @@ export const parseCachedPhotoDates = (photo: Photo) => ({
takenAt: new Date(photo.takenAt),
updatedAt: new Date(photo.updatedAt),
createdAt: new Date(photo.createdAt),
});
} as Photo);
export const parseCachedPhotosDates = (photos: Photo[]) =>
photos.map(parseCachedPhotoDates);

View File

@ -22,9 +22,10 @@ export const PREFIX_CAMERA = '/shot-on';
export const PREFIX_FILM_SIMULATION = '/film';
// Dynamic paths
const PATH_PHOTO_DYNAMIC = `${PREFIX_PHOTO}/:photoId`;
const PATH_TAG_DYNAMIC = `${PREFIX_TAG}/:tag`;
const PATH_CAMERA_DYNAMIC = `${PREFIX_CAMERA}/:camera`;
const PATH_PHOTO_DYNAMIC = `${PREFIX_PHOTO}/[photoId]`;
const PATH_TAG_DYNAMIC = `${PREFIX_TAG}/[tag]`;
const PATH_CAMERA_DYNAMIC = `${PREFIX_CAMERA}/[camera]`;
const PATH_FILM_SIMULATION_DYNAMIC = `${PREFIX_FILM_SIMULATION}/[simulation]`;
// Admin paths
export const PATH_ADMIN_PHOTOS = `${PATH_ADMIN}/photos`;
@ -55,6 +56,7 @@ export const PATHS_TO_CACHE = [
PATH_PHOTO_DYNAMIC,
PATH_TAG_DYNAMIC,
PATH_CAMERA_DYNAMIC,
PATH_FILM_SIMULATION_DYNAMIC,
...PATHS_ADMIN,
];