diff --git a/README.md b/README.md
index c88da31..c16e467 100644
--- a/README.md
+++ b/README.md
@@ -59,7 +59,6 @@ The following environment variables should be provided when running the server (
| `NODE_SMTP_USERNAME` | SMTP username for sending emails. |
| `NODE_SMTP_PASSWORD` | SMTP password for sending emails. |
| `NODE_SIGHTING_EMAIL` | Email address to send sightings to. |
-| `LOGTAIL_SOURCE_TOKEN` | Token for Better Stack Logs. |
## Development
diff --git a/eslint.config.mjs b/eslint.config.mjs
index b6374fb..69f3259 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,12 +1,31 @@
import globals from 'globals';
-import pluginJs from '@eslint/js';
-import tseslint from 'typescript-eslint';
+import pluginJS from '@eslint/js';
+import pluginTS from 'typescript-eslint';
import pluginReact from 'eslint-plugin-react';
+import pluginReactHooks from 'eslint-plugin-react-hooks';
+import pluginNext from '@next/eslint-plugin-next';
+import pluginJest from 'eslint-plugin-jest';
const recommendedConfigs = [
- pluginJs.configs.recommended,
- ...tseslint.configs.recommended,
+ pluginJS.configs.recommended,
+ ...pluginTS.configs.recommended,
pluginReact.configs.flat.recommended,
+ pluginJest.configs['flat/recommended'],
+
+ // Custom config until packages support flat configs
+ {
+ files: ['src/**/*.{js,ts,jsx,tsx}'],
+ plugins: {
+ 'react-hooks': pluginReactHooks,
+ '@next/next': pluginNext,
+ },
+ rules: {
+ 'react/react-in-jsx-scope': 'off',
+ 'react/prop-types': 'off',
+ ...pluginReactHooks.configs.recommended.rules,
+ ...pluginNext.configs.recommended.rules,
+ },
+ },
];
const customConfigs = [
@@ -15,8 +34,8 @@ const customConfigs = [
},
{
ignores: [
- ".next/",
- "coverage/",
+ '.next/',
+ 'coverage/',
],
},
{
@@ -27,14 +46,11 @@ const customConfigs = [
},
},
{
- languageOptions: { globals: {...globals.browser, ...globals.node} },
- },
- {
- rules: {
- '@typescript-eslint/no-unsafe-function-type': 'off',
- '@typescript-eslint/no-require-imports': 'off',
- 'react/prop-types': 'off',
- 'react/react-in-jsx-scope': 'off',
+ languageOptions: {
+ globals: {
+ ...globals.browser,
+ ...globals.node,
+ },
},
},
];
diff --git a/jest.setup.ts b/jest.setup.ts
index 516cf02..6a8516f 100644
--- a/jest.setup.ts
+++ b/jest.setup.ts
@@ -1,3 +1,5 @@
+/* eslint-disable @typescript-eslint/no-require-imports */
+
process.env.NODE_CONTENTFUL_SPACE_ID = 'mocked-contentful-space-id';
process.env.NODE_CONTENTFUL_ENVIRONMENT = 'mocked-contentful-environment';
process.env.NODE_CONTENTFUL_DELIVERY_API_TOKEN = 'mocked-contentful-delivery-api-token';
diff --git a/next.config.js b/next.config.ts
similarity index 82%
rename from next.config.js
rename to next.config.ts
index 13e1b20..6d149fd 100644
--- a/next.config.js
+++ b/next.config.ts
@@ -1,10 +1,8 @@
-/** @type {import('next').NextConfig} */
+import type { NextConfig } from 'next';
-const { withLogtail } = require('@logtail/next');
+import redirects from './redirects.json';
-const redirects = require('./redirects.json');
-
-const nextConfig = {
+const nextConfig: NextConfig = {
reactStrictMode: true,
poweredByHeader: false,
experimental: {
@@ -50,4 +48,4 @@ const nextConfig = {
},
};
-module.exports = withLogtail(nextConfig);
+module.exports = nextConfig;
diff --git a/package-lock.json b/package-lock.json
index 7058d0a..9d25323 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,19 +9,18 @@
"@contentful/live-preview": "^4.5.13",
"@contentful/rich-text-plain-text-renderer": "^16.2.10",
"@contentful/rich-text-react-renderer": "^15.22.11",
- "@logtail/next": "^0.1.5",
"contentful": "^11.2.0",
"dayjs": "^1.11.13",
"joi": "^17.13.3",
- "next": "^14.2.15",
+ "next": "^15.0.1",
"next-seo": "^6.6.0",
"nodemailer": "^6.9.15",
"react": "^18.3.1",
- "react-markdown": "^9.0.1",
- "sharp": "^0.33.5"
+ "react-markdown": "^9.0.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
+ "@next/eslint-plugin-next": "^15.0.1",
"@testing-library/jest-dom": "^6.6.2",
"@testing-library/react": "^16.0.1",
"@types/jest": "^29.5.14",
@@ -31,7 +30,9 @@
"@types/react": "^18.3.12",
"babel-jest": "^29.7.0",
"eslint": "^9.13.0",
+ "eslint-plugin-jest": "^28.8.3",
"eslint-plugin-react": "^7.37.2",
+ "eslint-plugin-react-hooks": "^5.0.0",
"globals": "^15.11.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
@@ -2122,30 +2123,55 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@logtail/next": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/@logtail/next/-/next-0.1.5.tgz",
- "integrity": "sha512-J8m9jGdcGjYfKEbB1pdQj9iaBq9eNtHtqNcrHStjGI1LPiGREwk+HnnpM12yS6teiwlQepcXJDtQ8fk1QHg+jw==",
+ "node_modules/@next/env": {
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.1.tgz",
+ "integrity": "sha512-lc4HeDUKO9gxxlM5G2knTRifqhsY6yYpwuHspBZdboZe0Gp+rZHBNNSIjmQKDJIdRXiXGyVnSD6gafrbQPvILQ=="
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.1.tgz",
+ "integrity": "sha512-bKWsMaGPbiFAaGqrDJvbE8b4Z0uKicGVcgOI77YM2ui3UfjHMr4emFPrZTLeZVchi7fT1mooG2LxREfUUClIKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-glob": "3.3.1"
+ }
+ },
+ "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "whatwg-fetch": "^3.6.2"
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
},
"engines": {
- "node": ">=15"
- },
- "peerDependencies": {
- "next": "^12.1.4 || ^13 || ^14"
+ "node": ">=8.6.0"
}
},
- "node_modules/@next/env": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz",
- "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ=="
+ "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz",
- "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.1.tgz",
+ "integrity": "sha512-C9k/Xv4sxkQRTA37Z6MzNq3Yb1BJMmSqjmwowoWEpbXTkAdfOwnoKOpAb71ItSzoA26yUTIo6ZhN8rKGu4ExQw==",
"cpu": [
"arm64"
],
@@ -2158,9 +2184,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz",
- "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.1.tgz",
+ "integrity": "sha512-uHl13HXOuq1G7ovWFxCACDJHTSDVbn/sbLv8V1p+7KIvTrYQ5HNoSmKBdYeEKRRCbEmd+OohOgg9YOp8Ux3MBg==",
"cpu": [
"x64"
],
@@ -2173,9 +2199,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz",
- "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.1.tgz",
+ "integrity": "sha512-LvyhvxHOihFTEIbb35KxOc3q8w8G4xAAAH/AQnsYDEnOvwawjL2eawsB59AX02ki6LJdgDaHoTEnC54Gw+82xw==",
"cpu": [
"arm64"
],
@@ -2188,9 +2214,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz",
- "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.1.tgz",
+ "integrity": "sha512-vFmCGUFNyk/A5/BYcQNhAQqPIw01RJaK6dRO+ZEhz0DncoW+hJW1kZ8aH2UvTX27zPq3m85zN5waMSbZEmANcQ==",
"cpu": [
"arm64"
],
@@ -2203,9 +2229,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz",
- "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.1.tgz",
+ "integrity": "sha512-5by7IYq0NCF8rouz6Qg9T97jYU68kaClHPfGpQG2lCZpSYHtSPQF1kjnqBTd34RIqPKMbCa4DqCufirgr8HM5w==",
"cpu": [
"x64"
],
@@ -2218,9 +2244,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz",
- "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.1.tgz",
+ "integrity": "sha512-lmYr6H3JyDNBJLzklGXLfbehU3ay78a+b6UmBGlHls4xhDXBNZfgb0aI67sflrX+cGBnv1LgmWzFlYrAYxS1Qw==",
"cpu": [
"x64"
],
@@ -2233,9 +2259,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz",
- "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.1.tgz",
+ "integrity": "sha512-DS8wQtl6diAj0eZTdH0sefykm4iXMbHT4MOvLwqZiIkeezKpkgPFcEdFlz3vKvXa2R/2UEgMh48z1nEpNhjeOQ==",
"cpu": [
"arm64"
],
@@ -2247,25 +2273,10 @@
"node": ">= 10"
}
},
- "node_modules/@next/swc-win32-ia32-msvc": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz",
- "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==",
- "cpu": [
- "ia32"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz",
- "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.1.tgz",
+ "integrity": "sha512-4Ho2ggvDdMKlZ/0e9HNdZ9ngeaBwtc+2VS5oCeqrbXqOgutX6I4U2X/42VBw0o+M5evn4/7v3zKgGHo+9v/VjA==",
"cpu": [
"x64"
],
@@ -2673,16 +2684,13 @@
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
- "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
- "license": "Apache-2.0"
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
},
"node_modules/@swc/helpers": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
- "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
- "license": "Apache-2.0",
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz",
+ "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==",
"dependencies": {
- "@swc/counter": "^0.1.3",
"tslib": "^2.4.0"
}
},
@@ -4447,8 +4455,7 @@
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
- "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
- "license": "MIT"
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
"node_modules/cliui": {
"version": "8.0.1",
@@ -4488,6 +4495,7 @@
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"license": "MIT",
+ "optional": true,
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
@@ -4510,6 +4518,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "devOptional": true,
"license": "MIT"
},
"node_modules/color-string": {
@@ -4517,6 +4526,7 @@
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"license": "MIT",
+ "optional": true,
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@@ -4527,6 +4537,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
+ "optional": true,
"dependencies": {
"color-name": "~1.1.4"
},
@@ -4538,7 +4549,8 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "license": "MIT"
+ "license": "MIT",
+ "optional": true
},
"node_modules/colord": {
"version": "2.9.3",
@@ -5099,6 +5111,7 @@
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"license": "Apache-2.0",
+ "optional": true,
"engines": {
"node": ">=8"
}
@@ -5519,6 +5532,32 @@
}
}
},
+ "node_modules/eslint-plugin-jest": {
+ "version": "28.8.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz",
+ "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "engines": {
+ "node": "^16.10.0 || ^18.12.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0",
+ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0",
+ "jest": "*"
+ },
+ "peerDependenciesMeta": {
+ "@typescript-eslint/eslint-plugin": {
+ "optional": true
+ },
+ "jest": {
+ "optional": true
+ }
+ }
+ },
"node_modules/eslint-plugin-react": {
"version": "7.37.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz",
@@ -5551,6 +5590,19 @@
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
}
},
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz",
+ "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
"node_modules/eslint-scope": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz",
@@ -6361,6 +6413,7 @@
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
"license": "ISC"
},
"node_modules/graphemer": {
@@ -10708,40 +10761,41 @@
}
},
"node_modules/next": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz",
- "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==",
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/next/-/next-15.0.1.tgz",
+ "integrity": "sha512-PSkFkr/w7UnFWm+EP8y/QpHrJXMqpZzAXpergB/EqLPOh4SGPJXv1wj4mslr2hUZBAS9pX7/9YLIdxTv6fwytw==",
"dependencies": {
- "@next/env": "14.2.15",
- "@swc/helpers": "0.5.5",
+ "@next/env": "15.0.1",
+ "@swc/counter": "0.1.3",
+ "@swc/helpers": "0.5.13",
"busboy": "1.6.0",
"caniuse-lite": "^1.0.30001579",
- "graceful-fs": "^4.2.11",
"postcss": "8.4.31",
- "styled-jsx": "5.1.1"
+ "styled-jsx": "5.1.6"
},
"bin": {
"next": "dist/bin/next"
},
"engines": {
- "node": ">=18.17.0"
+ "node": ">=18.18.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "14.2.15",
- "@next/swc-darwin-x64": "14.2.15",
- "@next/swc-linux-arm64-gnu": "14.2.15",
- "@next/swc-linux-arm64-musl": "14.2.15",
- "@next/swc-linux-x64-gnu": "14.2.15",
- "@next/swc-linux-x64-musl": "14.2.15",
- "@next/swc-win32-arm64-msvc": "14.2.15",
- "@next/swc-win32-ia32-msvc": "14.2.15",
- "@next/swc-win32-x64-msvc": "14.2.15"
+ "@next/swc-darwin-arm64": "15.0.1",
+ "@next/swc-darwin-x64": "15.0.1",
+ "@next/swc-linux-arm64-gnu": "15.0.1",
+ "@next/swc-linux-arm64-musl": "15.0.1",
+ "@next/swc-linux-x64-gnu": "15.0.1",
+ "@next/swc-linux-x64-musl": "15.0.1",
+ "@next/swc-win32-arm64-msvc": "15.0.1",
+ "@next/swc-win32-x64-msvc": "15.0.1",
+ "sharp": "^0.33.5"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
"@playwright/test": "^1.41.2",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
+ "babel-plugin-react-compiler": "*",
+ "react": "^18.2.0 || 19.0.0-rc-69d4b800-20241021",
+ "react-dom": "^18.2.0 || 19.0.0-rc-69d4b800-20241021",
"sass": "^1.3.0"
},
"peerDependenciesMeta": {
@@ -10751,6 +10805,9 @@
"@playwright/test": {
"optional": true
},
+ "babel-plugin-react-compiler": {
+ "optional": true
+ },
"sass": {
"optional": true
}
@@ -12011,6 +12068,7 @@
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
"integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
"hasInstallScript": true,
+ "optional": true,
"dependencies": {
"color": "^4.2.3",
"detect-libc": "^2.0.3",
@@ -12049,6 +12107,7 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"license": "ISC",
+ "optional": true,
"bin": {
"semver": "bin/semver.js"
},
@@ -12109,6 +12168,7 @@
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"license": "MIT",
+ "optional": true,
"dependencies": {
"is-arrayish": "^0.3.1"
}
@@ -12117,7 +12177,8 @@
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
- "license": "MIT"
+ "license": "MIT",
+ "optional": true
},
"node_modules/sisteransi": {
"version": "1.0.5",
@@ -12475,10 +12536,9 @@
}
},
"node_modules/styled-jsx": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
- "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
- "license": "MIT",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
+ "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
"dependencies": {
"client-only": "0.0.1"
},
@@ -12486,7 +12546,7 @@
"node": ">= 12.0.0"
},
"peerDependencies": {
- "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
},
"peerDependenciesMeta": {
"@babel/core": {
@@ -13412,12 +13472,6 @@
"node": ">=12"
}
},
- "node_modules/whatwg-fetch": {
- "version": "3.6.20",
- "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
- "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
- "license": "MIT"
- },
"node_modules/whatwg-mimetype": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
diff --git a/package.json b/package.json
index be15a4d..3ea8c4a 100644
--- a/package.json
+++ b/package.json
@@ -16,19 +16,18 @@
"@contentful/live-preview": "^4.5.13",
"@contentful/rich-text-plain-text-renderer": "^16.2.10",
"@contentful/rich-text-react-renderer": "^15.22.11",
- "@logtail/next": "^0.1.5",
"contentful": "^11.2.0",
"dayjs": "^1.11.13",
"joi": "^17.13.3",
- "next": "^14.2.15",
+ "next": "^15.0.1",
"next-seo": "^6.6.0",
"nodemailer": "^6.9.15",
"react": "^18.3.1",
- "react-markdown": "^9.0.1",
- "sharp": "^0.33.5"
+ "react-markdown": "^9.0.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
+ "@next/eslint-plugin-next": "^15.0.1",
"@testing-library/jest-dom": "^6.6.2",
"@testing-library/react": "^16.0.1",
"@types/jest": "^29.5.14",
@@ -38,7 +37,9 @@
"@types/react": "^18.3.12",
"babel-jest": "^29.7.0",
"eslint": "^9.13.0",
+ "eslint-plugin-jest": "^28.8.3",
"eslint-plugin-react": "^7.37.2",
+ "eslint-plugin-react-hooks": "^5.0.0",
"globals": "^15.11.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
diff --git a/src/components/Filters/Filters.tsx b/src/components/Filters/Filters.tsx
index a8d2cf3..ab457c9 100644
--- a/src/components/Filters/Filters.tsx
+++ b/src/components/Filters/Filters.tsx
@@ -1,7 +1,7 @@
import styles from './Filters.module.scss';
interface UseSearchProps {
- callback: Function,
+ callback: Function, // eslint-disable-line @typescript-eslint/no-unsafe-function-type
label?: string,
defaultValue?: string,
}
@@ -29,7 +29,7 @@ interface DropdownProps {
text: string,
value: string,
}>,
- callback: Function,
+ callback: Function, // eslint-disable-line @typescript-eslint/no-unsafe-function-type
}
const UseDropdown = ({
diff --git a/src/helpers/contentful.spec.ts b/src/helpers/contentful.spec.ts
index 3ba8252..0faab24 100644
--- a/src/helpers/contentful.spec.ts
+++ b/src/helpers/contentful.spec.ts
@@ -7,7 +7,7 @@ jest.mock('contentful', () => ({
}));
beforeAll(() => {
- require('./contentful');
+ require('./contentful'); // eslint-disable-line @typescript-eslint/no-require-imports
});
afterEach(() => {
diff --git a/src/pages/api/catalogues/[catalogue].ts b/src/pages/api/catalogues/[catalogue].ts
index b651372..aecc1b3 100644
--- a/src/pages/api/catalogues/[catalogue].ts
+++ b/src/pages/api/catalogues/[catalogue].ts
@@ -1,15 +1,12 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { NextApiResponse } from 'next';
-import type { LogtailAPIRequest } from '@logtail/next';
-
-import { withLogtail } from '@logtail/next';
+import type { NextApiRequest, NextApiResponse } from 'next';
import { Catalogues } from '@/helpers/constants';
import { getCatalogueList } from '@/helpers/getCatalogue';
const handler = async (
- req: LogtailAPIRequest,
+ req: NextApiRequest,
res: NextApiResponse,
) => {
if (req.method !== 'GET') {
@@ -52,4 +49,4 @@ const handler = async (
return res.json(data);
};
-export default withLogtail(handler);
+export default handler;
diff --git a/src/pages/api/report-sighting.ts b/src/pages/api/report-sighting.ts
index cdb8a45..9b76490 100644
--- a/src/pages/api/report-sighting.ts
+++ b/src/pages/api/report-sighting.ts
@@ -1,7 +1,4 @@
-import type { NextApiResponse } from 'next';
-import type { LogtailAPIRequest } from '@logtail/next';
-
-import { withLogtail } from '@logtail/next';
+import type { NextApiRequest, NextApiResponse } from 'next';
import joi from 'joi';
import nodemailer from 'nodemailer';
@@ -35,7 +32,7 @@ const mailerTransporter = nodemailer.createTransport({
});
const handler = async (
- req: LogtailAPIRequest,
+ req: NextApiRequest,
res: NextApiResponse,
) => {
const { headers, body } = req;
@@ -91,7 +88,7 @@ const handler = async (
html: Object.entries(body).map(([key, value]) => `${key.toUpperCase()}: ${value}`).join('
'),
});
} catch (error) {
- req.log.error('Unable to send email:', { error });
+ console.error('Unable to send email:', { error });
return res.status(500).json({
success: false,
@@ -106,4 +103,4 @@ const handler = async (
});
};
-export default withLogtail(handler);
+export default handler;