diff --git a/app/eslint.config.js b/app/eslint.config.js
index f8649435..191fc147 100644
--- a/app/eslint.config.js
+++ b/app/eslint.config.js
@@ -72,6 +72,7 @@ export default tseslint.config(
},
],
"no-console": "warn",
+ "@typescript-eslint/no-deprecated": "warn",
},
},
);
diff --git a/app/package-lock.json b/app/package-lock.json
index 16dc808a..3351c242 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -20,9 +20,8 @@
"react-bootstrap": "^2.10.5",
"react-bootstrap-icons": "^1.11.4",
"react-dom": "^18.3.1",
- "react-router": "^6.28.0",
+ "react-router": "^7.1.0",
"react-router-bootstrap": "^0.26.3",
- "react-router-dom": "^6.28.0",
"react-syntax-highlighter": "^15.6.1",
"swagger-ui-react": "=5.18.2",
"use-interval": "^1.4.0",
@@ -46,7 +45,6 @@
"@types/react-dom": "^18.3.1",
"@types/react-router": "^5.1.20",
"@types/react-router-bootstrap": "^0.26.6",
- "@types/react-router-dom": "^5.3.3",
"@types/react-syntax-highlighter": "^15.5.13",
"@types/swagger-ui-react": "^4.18.3",
"@vitejs/plugin-react-swc": "^3.7.1",
@@ -1039,6 +1037,7 @@
"version": "1.21.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz",
"integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==",
+ "peer": true,
"engines": {
"node": ">=14.0.0"
}
@@ -2125,6 +2124,12 @@
"dev": true,
"peer": true
},
+ "node_modules/@types/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
+ "license": "MIT"
+ },
"node_modules/@types/eslint": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
@@ -2333,17 +2338,6 @@
"@types/react": "*"
}
},
- "node_modules/@types/react-router-dom": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
- "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
- "dev": true,
- "dependencies": {
- "@types/history": "^4.7.11",
- "@types/react": "*",
- "@types/react-router": "*"
- }
- },
"node_modules/@types/react-syntax-highlighter": {
"version": "15.5.13",
"resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz",
@@ -6503,17 +6497,27 @@
}
},
"node_modules/react-router": {
- "version": "6.28.0",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz",
- "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.0.tgz",
+ "integrity": "sha512-VcFhWqkNIcojDRYaUO8qV0Jib52s9ULpCp3nkBbmrvtoCVFRp6tmk3tJ2w9BZauVctA1YRnJlFYDn9iJRuCpGA==",
+ "license": "MIT",
"dependencies": {
- "@remix-run/router": "1.21.0"
+ "@types/cookie": "^0.6.0",
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0",
+ "turbo-stream": "2.4.0"
},
"engines": {
- "node": ">=14.0.0"
+ "node": ">=20.0.0"
},
"peerDependencies": {
- "react": ">=16.8"
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
}
},
"node_modules/react-router-bootstrap": {
@@ -6532,6 +6536,7 @@
"version": "6.28.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz",
"integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==",
+ "peer": true,
"dependencies": {
"@remix-run/router": "1.21.0",
"react-router": "6.28.0"
@@ -6544,6 +6549,31 @@
"react-dom": ">=16.8"
}
},
+ "node_modules/react-router-dom/node_modules/react-router": {
+ "version": "6.28.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz",
+ "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@remix-run/router": "1.21.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router/node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/react-syntax-highlighter": {
"version": "15.6.1",
"resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz",
@@ -6926,6 +6956,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ },
"node_modules/set-function-length": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
@@ -7543,6 +7579,12 @@
"node": "*"
}
},
+ "node_modules/turbo-stream": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
+ "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
+ "license": "ISC"
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/app/package.json b/app/package.json
index 7a7ea547..4da1ef19 100644
--- a/app/package.json
+++ b/app/package.json
@@ -16,9 +16,8 @@
"react-bootstrap": "^2.10.5",
"react-bootstrap-icons": "^1.11.4",
"react-dom": "^18.3.1",
- "react-router": "^6.28.0",
+ "react-router": "^7.1.0",
"react-router-bootstrap": "^0.26.3",
- "react-router-dom": "^6.28.0",
"react-syntax-highlighter": "^15.6.1",
"swagger-ui-react": "=5.18.2",
"use-interval": "^1.4.0",
@@ -68,7 +67,6 @@
"@types/react-dom": "^18.3.1",
"@types/react-router": "^5.1.20",
"@types/react-router-bootstrap": "^0.26.6",
- "@types/react-router-dom": "^5.3.3",
"@types/react-syntax-highlighter": "^15.5.13",
"@types/swagger-ui-react": "^4.18.3",
"@vitejs/plugin-react-swc": "^3.7.1",
diff --git a/app/src/accounts/AccountForm.tsx b/app/src/accounts/AccountForm.tsx
index a56e5943..7d711e94 100644
--- a/app/src/accounts/AccountForm.tsx
+++ b/app/src/accounts/AccountForm.tsx
@@ -3,7 +3,7 @@ import Button from "react-bootstrap/Button";
import FormGroup from "react-bootstrap/FormGroup";
import FormLabel from "react-bootstrap/FormLabel";
import FormControl from "react-bootstrap/FormControl";
-import { Form } from "react-router-dom";
+import { Form } from "react-router";
import { BuildingAdd } from "react-bootstrap-icons";
export default function AccountForm() {
diff --git a/app/src/accounts/AccountList.tsx b/app/src/accounts/AccountList.tsx
index bf105e8e..0d588b12 100644
--- a/app/src/accounts/AccountList.tsx
+++ b/app/src/accounts/AccountList.tsx
@@ -2,7 +2,7 @@ import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import React from "react";
-import { useLoaderData, useAsyncValue, Await } from "react-router-dom";
+import { useLoaderData, useAsyncValue, Await } from "react-router";
import { Account } from "../ApiClient";
import ListGroup from "react-bootstrap/ListGroup";
import { LinkContainer } from "react-router-bootstrap";
diff --git a/app/src/accounts/AccountSummary.tsx b/app/src/accounts/AccountSummary.tsx
index 2eacf7fa..e32e99a7 100644
--- a/app/src/accounts/AccountSummary.tsx
+++ b/app/src/accounts/AccountSummary.tsx
@@ -2,7 +2,7 @@ import Breadcrumb from "react-bootstrap/Breadcrumb";
import Col from "react-bootstrap/Col";
import Row from "react-bootstrap/Row";
import ListGroup from "react-bootstrap/ListGroup";
-import { useFetcher, useParams, useRouteLoaderData } from "react-router-dom";
+import { useFetcher, useParams, useRouteLoaderData } from "react-router";
import {
ChangeEvent,
FormEvent,
diff --git a/app/src/accounts/NextSteps/AggregatorTypeSelection.tsx b/app/src/accounts/NextSteps/AggregatorTypeSelection.tsx
index d1a71325..baae8549 100644
--- a/app/src/accounts/NextSteps/AggregatorTypeSelection.tsx
+++ b/app/src/accounts/NextSteps/AggregatorTypeSelection.tsx
@@ -13,7 +13,7 @@ import {
useParams,
useLoaderData,
useRevalidator,
-} from "react-router-dom";
+} from "react-router";
import ApiClient, {
Aggregator,
NewAggregator,
diff --git a/app/src/accounts/NextSteps/InlineCollectorCredentials.tsx b/app/src/accounts/NextSteps/InlineCollectorCredentials.tsx
index 1e6fa91e..c7678d3a 100644
--- a/app/src/accounts/NextSteps/InlineCollectorCredentials.tsx
+++ b/app/src/accounts/NextSteps/InlineCollectorCredentials.tsx
@@ -1,5 +1,5 @@
import { Button, Col, Row } from "react-bootstrap";
-import { useFetcher, useParams, useRevalidator } from "react-router-dom";
+import { useFetcher, useParams, useRevalidator } from "react-router";
import { ApiToken } from "../../ApiClient";
import React from "react";
import useInterval from "use-interval";
diff --git a/app/src/accounts/NextSteps/index.tsx b/app/src/accounts/NextSteps/index.tsx
index 621e02b3..a5448e66 100644
--- a/app/src/accounts/NextSteps/index.tsx
+++ b/app/src/accounts/NextSteps/index.tsx
@@ -1,6 +1,6 @@
import { Steps } from "primereact/steps";
import { Button, Card, Col, Row } from "react-bootstrap";
-import { useLoaderData } from "react-router-dom";
+import { useLoaderData } from "react-router";
import {
Account,
Aggregator,
diff --git a/app/src/accounts/index.tsx b/app/src/accounts/index.tsx
index c80cefab..72e54d9c 100644
--- a/app/src/accounts/index.tsx
+++ b/app/src/accounts/index.tsx
@@ -1,4 +1,4 @@
-import { RouteObject, defer, redirect } from "react-router-dom";
+import { RouteObject, redirect } from "react-router";
import ApiClient, { NewAccount, UpdateAccount } from "../ApiClient";
import AccountSummary from "./AccountSummary";
import AccountForm from "./AccountForm";
@@ -16,7 +16,7 @@ export default function accounts(
path: "",
element: ,
loader() {
- return defer({ accounts: apiClient.accounts() });
+ return { accounts: apiClient.accounts() };
},
index: true,
},
@@ -43,9 +43,9 @@ export default function accounts(
id: "account",
loader({ params }) {
const { accountId } = params as { accountId: string };
- return defer({
+ return {
account: apiClient.account(accountId),
- });
+ };
},
shouldRevalidate(args) {
return (
@@ -78,14 +78,14 @@ export default function accounts(
index: true,
loader({ params }) {
const { accountId } = params as { accountId: string };
- return defer({
+ return {
apiTokens: apiClient.accountApiTokens(accountId),
tasks: apiClient.accountTasks(accountId),
collectorCredentials:
apiClient.accountCollectorCredentials(accountId),
aggregators: apiClient.accountAggregators(accountId),
account: apiClient.account(accountId),
- });
+ };
},
},
...children,
diff --git a/app/src/admin/index.tsx b/app/src/admin/index.tsx
index d4445c85..13b8dc14 100644
--- a/app/src/admin/index.tsx
+++ b/app/src/admin/index.tsx
@@ -1,4 +1,4 @@
-import { RouteObject } from "react-router-dom";
+import { RouteObject } from "react-router";
import ApiClient from "../ApiClient";
export default function admin(
diff --git a/app/src/aggregators/AggregatorDetail.tsx b/app/src/aggregators/AggregatorDetail.tsx
index 366a4e36..64e7033b 100644
--- a/app/src/aggregators/AggregatorDetail.tsx
+++ b/app/src/aggregators/AggregatorDetail.tsx
@@ -1,4 +1,4 @@
-import { Await, useLoaderData, useParams } from "react-router-dom";
+import { Await, useLoaderData, useParams } from "react-router";
import { Aggregator } from "../ApiClient";
import { AccountBreadcrumbs } from "../util";
import { LinkContainer } from "react-router-bootstrap";
diff --git a/app/src/aggregators/AggregatorForm.tsx b/app/src/aggregators/AggregatorForm.tsx
index c16044b7..854d692a 100644
--- a/app/src/aggregators/AggregatorForm.tsx
+++ b/app/src/aggregators/AggregatorForm.tsx
@@ -18,7 +18,7 @@ import {
useNavigate,
useNavigation,
useParams,
-} from "react-router-dom";
+} from "react-router";
import { ApiClientContext } from "../ApiClientContext";
async function submit(
diff --git a/app/src/aggregators/AggregatorList.tsx b/app/src/aggregators/AggregatorList.tsx
index d412c5c8..762e07d0 100644
--- a/app/src/aggregators/AggregatorList.tsx
+++ b/app/src/aggregators/AggregatorList.tsx
@@ -6,7 +6,7 @@ import { AccountBreadcrumbs, WithAccount } from "../util";
import { CloudUpload } from "react-bootstrap-icons";
import { Suspense } from "react";
import { LinkContainer } from "react-router-bootstrap";
-import { Await, useLoaderData } from "react-router-dom";
+import { Await, useLoaderData } from "react-router";
import { Aggregator } from "../ApiClient";
import { ListGroup } from "react-bootstrap";
import D from "../logo/color/svg/small.svg";
diff --git a/app/src/aggregators/DeleteAggregatorButton.tsx b/app/src/aggregators/DeleteAggregatorButton.tsx
index aa870ada..2aee82d8 100644
--- a/app/src/aggregators/DeleteAggregatorButton.tsx
+++ b/app/src/aggregators/DeleteAggregatorButton.tsx
@@ -1,4 +1,4 @@
-import { useFetcher, useNavigation } from "react-router-dom";
+import { useFetcher, useNavigation } from "react-router";
import React, { useEffect, useState } from "react";
import { Trash } from "react-bootstrap-icons";
import { Button, Modal } from "react-bootstrap";
diff --git a/app/src/aggregators/RenameAggregatorButton.tsx b/app/src/aggregators/RenameAggregatorButton.tsx
index a2ef2b3c..b9443196 100644
--- a/app/src/aggregators/RenameAggregatorButton.tsx
+++ b/app/src/aggregators/RenameAggregatorButton.tsx
@@ -1,4 +1,4 @@
-import { useFetcher } from "react-router-dom";
+import { useFetcher } from "react-router";
import React from "react";
import { Pencil, PencilSquare } from "react-bootstrap-icons";
import {
diff --git a/app/src/aggregators/RotateBearerTokenButton.tsx b/app/src/aggregators/RotateBearerTokenButton.tsx
index 655bc917..2ac7e729 100644
--- a/app/src/aggregators/RotateBearerTokenButton.tsx
+++ b/app/src/aggregators/RotateBearerTokenButton.tsx
@@ -1,4 +1,4 @@
-import { useFetcher } from "react-router-dom";
+import { useFetcher } from "react-router";
import React from "react";
import { ArrowRepeat } from "react-bootstrap-icons";
import {
diff --git a/app/src/aggregators/index.tsx b/app/src/aggregators/index.tsx
index 4b900227..d57b177a 100644
--- a/app/src/aggregators/index.tsx
+++ b/app/src/aggregators/index.tsx
@@ -2,7 +2,7 @@ import Aggregators from "./AggregatorList";
import AggregatorFormPage from "./AggregatorForm";
import AggregatorDetail from "./AggregatorDetail";
import ApiClient from "../ApiClient";
-import { RouteObject, defer, redirect } from "react-router-dom";
+import { RouteObject, redirect } from "react-router";
export default function aggregators(apiClient: ApiClient): RouteObject {
return {
@@ -13,20 +13,20 @@ export default function aggregators(apiClient: ApiClient): RouteObject {
index: true,
element: ,
loader({ params }) {
- return defer({
+ return {
aggregators: apiClient.accountAggregators(
params.accountId as string,
),
- });
+ };
},
},
{
path: ":aggregatorId",
element: ,
loader({ params }) {
- return defer({
+ return {
aggregator: apiClient.aggregator(params.aggregatorId as string),
- });
+ };
},
async action({ params, request }) {
diff --git a/app/src/api-tokens/ApiTokenList.tsx b/app/src/api-tokens/ApiTokenList.tsx
index a32e85fb..d34ef3f1 100644
--- a/app/src/api-tokens/ApiTokenList.tsx
+++ b/app/src/api-tokens/ApiTokenList.tsx
@@ -20,7 +20,7 @@ import {
useFetcher,
useLoaderData,
useNavigation,
-} from "react-router-dom";
+} from "react-router";
import { ApiToken } from "../ApiClient";
import Table from "react-bootstrap/Table";
import React from "react";
diff --git a/app/src/api-tokens/index.tsx b/app/src/api-tokens/index.tsx
index 8d7979d1..49f2df2d 100644
--- a/app/src/api-tokens/index.tsx
+++ b/app/src/api-tokens/index.tsx
@@ -1,4 +1,4 @@
-import { RouteObject, defer } from "react-router-dom";
+import { RouteObject } from "react-router";
import ApiClient from "../ApiClient";
import ApiTokens from "./ApiTokenList";
@@ -11,11 +11,11 @@ export default function apiTokens(apiClient: ApiClient): RouteObject {
index: true,
element: ,
loader({ params }) {
- return defer({
+ return {
apiTokens: apiClient
.accountApiTokens(params.accountId as string)
.then((tokens) => tokens.reverse()),
- });
+ };
},
shouldRevalidate(_) {
diff --git a/app/src/collector-credentials/CollectorCredentialForm.tsx b/app/src/collector-credentials/CollectorCredentialForm.tsx
index 130cc6b7..9dd8ffea 100644
--- a/app/src/collector-credentials/CollectorCredentialForm.tsx
+++ b/app/src/collector-credentials/CollectorCredentialForm.tsx
@@ -14,7 +14,7 @@ import {
Row,
} from "react-bootstrap";
import { KeyFill } from "react-bootstrap-icons";
-import { useFetcher } from "react-router-dom";
+import { useFetcher } from "react-router";
import { formikErrors } from "../ApiClient";
import { CopyCode } from "../util";
diff --git a/app/src/collector-credentials/CollectorCredentialList.tsx b/app/src/collector-credentials/CollectorCredentialList.tsx
index cd555e26..397f0678 100644
--- a/app/src/collector-credentials/CollectorCredentialList.tsx
+++ b/app/src/collector-credentials/CollectorCredentialList.tsx
@@ -12,12 +12,7 @@ import {
XCircle,
} from "react-bootstrap-icons";
import { Suspense, useCallback, useEffect, useState } from "react";
-import {
- Await,
- useFetcher,
- useLoaderData,
- useNavigation,
-} from "react-router-dom";
+import { Await, useFetcher, useLoaderData, useNavigation } from "react-router";
import { CollectorCredential } from "../ApiClient";
import Table from "react-bootstrap/Table";
import React from "react";
diff --git a/app/src/collector-credentials/index.tsx b/app/src/collector-credentials/index.tsx
index 262a628f..aed44ca3 100644
--- a/app/src/collector-credentials/index.tsx
+++ b/app/src/collector-credentials/index.tsx
@@ -1,4 +1,4 @@
-import { RouteObject, defer } from "react-router-dom";
+import { RouteObject } from "react-router";
import ApiClient from "../ApiClient";
import CollectorCredentials from "./CollectorCredentialList";
export default function collectorCredentials(
@@ -12,11 +12,11 @@ export default function collectorCredentials(
index: true,
element: ,
loader({ params }) {
- return defer({
+ return {
collectorCredentials: apiClient.accountCollectorCredentials(
params.accountId as string,
),
- });
+ };
},
id: "collectorCredentials",
diff --git a/app/src/layout/ErrorPage.tsx b/app/src/layout/ErrorPage.tsx
index 5449d45c..ca0358c5 100644
--- a/app/src/layout/ErrorPage.tsx
+++ b/app/src/layout/ErrorPage.tsx
@@ -1,6 +1,6 @@
import { AxiosError } from "axios";
import Alert from "react-bootstrap/Alert";
-import { isRouteErrorResponse, useRouteError } from "react-router-dom";
+import { isRouteErrorResponse, useRouteError } from "react-router";
import ApiClient from "../ApiClient";
import Layout from "./Layout";
import React from "react";
diff --git a/app/src/layout/Header.tsx b/app/src/layout/Header.tsx
index db0f717e..bdead274 100644
--- a/app/src/layout/Header.tsx
+++ b/app/src/layout/Header.tsx
@@ -1,4 +1,4 @@
-import { Await, Link, useAsyncValue, useLoaderData } from "react-router-dom";
+import { Await, Link, useAsyncValue, useLoaderData } from "react-router";
import Container from "react-bootstrap/Container";
import Navbar from "react-bootstrap/Navbar";
import { User } from "../ApiClient";
diff --git a/app/src/layout/Layout.tsx b/app/src/layout/Layout.tsx
index 2e9d3c70..80a61a95 100644
--- a/app/src/layout/Layout.tsx
+++ b/app/src/layout/Layout.tsx
@@ -1,4 +1,4 @@
-import { Outlet } from "react-router-dom";
+import { Outlet } from "react-router";
import Container from "react-bootstrap/Container";
import Header, { HeaderPlaceholder } from "./Header";
diff --git a/app/src/layout/index.tsx b/app/src/layout/index.tsx
index 2347442c..a73cbf3e 100644
--- a/app/src/layout/index.tsx
+++ b/app/src/layout/index.tsx
@@ -1,4 +1,4 @@
-import { RouteObject } from "react-router-dom";
+import { RouteObject } from "react-router";
import ApiClient from "../ApiClient";
import ErrorPage from "./ErrorPage";
import Layout from "./Layout";
diff --git a/app/src/memberships/Memberships.tsx b/app/src/memberships/Memberships.tsx
index 9129690b..a2e4c4bd 100644
--- a/app/src/memberships/Memberships.tsx
+++ b/app/src/memberships/Memberships.tsx
@@ -8,7 +8,7 @@ import {
useRouteLoaderData,
Form,
useSubmit,
-} from "react-router-dom";
+} from "react-router";
import React, { Suspense, useState } from "react";
import { Membership, User } from "../ApiClient";
import { Button, FormControl } from "react-bootstrap";
diff --git a/app/src/memberships/index.tsx b/app/src/memberships/index.tsx
index e2e1b1bd..9e20208b 100644
--- a/app/src/memberships/index.tsx
+++ b/app/src/memberships/index.tsx
@@ -1,4 +1,4 @@
-import { RouteObject, defer } from "react-router-dom";
+import { RouteObject } from "react-router";
import ApiClient from "../ApiClient";
import Memberships from "./Memberships";
@@ -7,9 +7,9 @@ export default function memberships(apiClient: ApiClient): RouteObject {
path: "memberships",
element: ,
loader({ params }) {
- return defer({
+ return {
memberships: apiClient.accountMemberships(params.accountId as string),
- });
+ };
},
shouldRevalidate(_) {
diff --git a/app/src/queue/Queue.tsx b/app/src/queue/Queue.tsx
index c425ed00..3066de77 100644
--- a/app/src/queue/Queue.tsx
+++ b/app/src/queue/Queue.tsx
@@ -11,7 +11,7 @@ import { Outlet, useLoaderData, useRevalidator } from "react-router";
import { QueueJob } from "../ApiClient";
import useInterval from "use-interval";
import { LinkContainer } from "react-router-bootstrap";
-import { useSearchParams } from "react-router-dom";
+import { useSearchParams } from "react-router";
import "@github/relative-time-element";
import { DateTime } from "luxon";
diff --git a/app/src/queue/QueueJob.tsx b/app/src/queue/QueueJob.tsx
index 6fe6ef44..07dd3b1b 100644
--- a/app/src/queue/QueueJob.tsx
+++ b/app/src/queue/QueueJob.tsx
@@ -4,7 +4,7 @@ import { CheckSquare, Stopwatch, XCircle } from "react-bootstrap-icons";
import { useLoaderData } from "react-router";
import { QueueJob } from "../ApiClient";
import { DateTime } from "luxon";
-import { Link } from "react-router-dom";
+import { Link } from "react-router";
export const Component = QueueJobComponent;
diff --git a/app/src/reportWebVitals.ts b/app/src/reportWebVitals.ts
index 61e439e7..7039642a 100644
--- a/app/src/reportWebVitals.ts
+++ b/app/src/reportWebVitals.ts
@@ -2,9 +2,9 @@ import { MetricType } from "web-vitals";
const reportWebVitals = (onPerfEntry?: (metric: MetricType) => void) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
- import("web-vitals").then(({ onCLS, onFID, onFCP, onLCP, onTTFB }) => {
+ import("web-vitals").then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => {
onCLS(onPerfEntry);
- onFID(onPerfEntry);
+ onINP(onPerfEntry);
onFCP(onPerfEntry);
onLCP(onPerfEntry);
onTTFB(onPerfEntry);
diff --git a/app/src/router.tsx b/app/src/router.tsx
index f269d165..487aabeb 100644
--- a/app/src/router.tsx
+++ b/app/src/router.tsx
@@ -1,10 +1,6 @@
import React from "react";
-import {
- createBrowserRouter,
- RouterProvider,
- RouteObject,
- redirect,
-} from "react-router-dom";
+import { createBrowserRouter, RouteObject, redirect } from "react-router";
+import { RouterProvider } from "react-router/dom";
import { ApiClientContext } from "./ApiClientContext";
import { ApiClient } from "./ApiClient";
import layout from "./layout";
@@ -21,21 +17,32 @@ import collectorCredentials from "./collector-credentials";
import swaggerUi from "./swagger-ui";
function buildRouter(apiClient: ApiClient) {
- return createBrowserRouter([
- swaggerUi(),
- layout(apiClient, [
- logout(apiClient),
- root(apiClient),
- admin(apiClient, [queue(apiClient), sharedAggregators(apiClient)]),
- accounts(apiClient, [
- aggregators(apiClient),
- apiTokens(apiClient),
- memberships(apiClient),
- tasks(apiClient),
- collectorCredentials(apiClient),
+ return createBrowserRouter(
+ [
+ swaggerUi(),
+ layout(apiClient, [
+ logout(apiClient),
+ root(apiClient),
+ admin(apiClient, [queue(apiClient), sharedAggregators(apiClient)]),
+ accounts(apiClient, [
+ aggregators(apiClient),
+ apiTokens(apiClient),
+ memberships(apiClient),
+ tasks(apiClient),
+ collectorCredentials(apiClient),
+ ]),
]),
- ]),
- ]);
+ ],
+ {
+ future: {
+ v7_relativeSplatPath: true,
+ v7_fetcherPersist: true,
+ v7_normalizeFormMethod: true,
+ v7_partialHydration: true,
+ v7_skipActionErrorRevalidation: true,
+ },
+ },
+ );
}
export default function Router() {
diff --git a/app/src/shared-aggregators/SharedAggregatorForm.tsx b/app/src/shared-aggregators/SharedAggregatorForm.tsx
index c0bd78b8..f8fbcb5d 100644
--- a/app/src/shared-aggregators/SharedAggregatorForm.tsx
+++ b/app/src/shared-aggregators/SharedAggregatorForm.tsx
@@ -1,7 +1,7 @@
import { FormikHelpers } from "formik";
import ApiClient, { NewAggregator, formikErrors } from "../ApiClient";
import { AggregatorForm } from "../aggregators/AggregatorForm";
-import { useRevalidator } from "react-router-dom";
+import { useRevalidator } from "react-router";
import { ApiClientContext } from "../ApiClientContext";
import React from "react";
diff --git a/app/src/shared-aggregators/SharedAggregatorList.tsx b/app/src/shared-aggregators/SharedAggregatorList.tsx
index 9ac4bb38..3420cea3 100644
--- a/app/src/shared-aggregators/SharedAggregatorList.tsx
+++ b/app/src/shared-aggregators/SharedAggregatorList.tsx
@@ -11,12 +11,7 @@ import {
Placeholder,
Row,
} from "react-bootstrap";
-import {
- Await,
- useFetcher,
- useLoaderData,
- useNavigation,
-} from "react-router-dom";
+import { Await, useFetcher, useLoaderData, useNavigation } from "react-router";
import { Aggregator } from "../ApiClient";
import "@github/relative-time-element";
import { Suspense, useEffect, useState } from "react";
diff --git a/app/src/shared-aggregators/index.tsx b/app/src/shared-aggregators/index.tsx
index c98720fc..54a3b9ac 100644
--- a/app/src/shared-aggregators/index.tsx
+++ b/app/src/shared-aggregators/index.tsx
@@ -1,4 +1,4 @@
-import { RouteObject, defer } from "react-router-dom";
+import { RouteObject } from "react-router";
import ApiClient, { UpdateAggregator } from "../ApiClient";
export default function sharedAggregators(apiClient: ApiClient): RouteObject {
@@ -12,7 +12,7 @@ export default function sharedAggregators(apiClient: ApiClient): RouteObject {
return import("./SharedAggregatorList");
},
async loader() {
- return defer({ aggregators: apiClient.sharedAggregators() });
+ return { aggregators: apiClient.sharedAggregators() };
},
},
{
diff --git a/app/src/swagger-ui.tsx b/app/src/swagger-ui.tsx
index ed6acb55..c9ef2879 100644
--- a/app/src/swagger-ui.tsx
+++ b/app/src/swagger-ui.tsx
@@ -1,4 +1,4 @@
-import { RouteObject } from "react-router-dom";
+import { RouteObject } from "react-router";
export default function swaggerUi(): RouteObject {
return {
diff --git a/app/src/tasks/TaskDetail/ClientConfig.tsx b/app/src/tasks/TaskDetail/ClientConfig.tsx
index 291fdebe..39b7bd3b 100644
--- a/app/src/tasks/TaskDetail/ClientConfig.tsx
+++ b/app/src/tasks/TaskDetail/ClientConfig.tsx
@@ -1,4 +1,4 @@
-import { useLoaderData } from "react-router-dom";
+import { useLoaderData } from "react-router";
import Col from "react-bootstrap/Col";
import { Tab, Tabs } from "react-bootstrap";
import { Task, Aggregator } from "../../ApiClient";
diff --git a/app/src/tasks/TaskDetail/CollectorAuthTokens.tsx b/app/src/tasks/TaskDetail/CollectorAuthTokens.tsx
index fc3a4a9c..e9ae74d2 100644
--- a/app/src/tasks/TaskDetail/CollectorAuthTokens.tsx
+++ b/app/src/tasks/TaskDetail/CollectorAuthTokens.tsx
@@ -1,4 +1,4 @@
-import { useFetcher } from "react-router-dom";
+import { useFetcher } from "react-router";
import Col from "react-bootstrap/Col";
import React from "react";
import { Aggregator, CollectorAuthToken } from "../../ApiClient";
diff --git a/app/src/tasks/TaskDetail/DeleteTaskButton.tsx b/app/src/tasks/TaskDetail/DeleteTaskButton.tsx
index b1dd32a1..9bad9ddf 100644
--- a/app/src/tasks/TaskDetail/DeleteTaskButton.tsx
+++ b/app/src/tasks/TaskDetail/DeleteTaskButton.tsx
@@ -1,4 +1,4 @@
-import { useFetcher, useNavigation } from "react-router-dom";
+import { useFetcher, useNavigation } from "react-router";
import React, { useEffect, useState } from "react";
import { Trash } from "react-bootstrap-icons";
import { Button, Modal } from "react-bootstrap";
diff --git a/app/src/tasks/TaskDetail/DisableTaskButton.tsx b/app/src/tasks/TaskDetail/DisableTaskButton.tsx
index 7524d4db..57549e59 100644
--- a/app/src/tasks/TaskDetail/DisableTaskButton.tsx
+++ b/app/src/tasks/TaskDetail/DisableTaskButton.tsx
@@ -4,7 +4,7 @@ import {
useLoaderData,
useNavigation,
useParams,
-} from "react-router-dom";
+} from "react-router";
import React, { FormEvent, useCallback, useEffect, useState } from "react";
import { Play, SignStop } from "react-bootstrap-icons";
import { Button, Modal } from "react-bootstrap";
diff --git a/app/src/tasks/TaskDetail/Metrics.tsx b/app/src/tasks/TaskDetail/Metrics.tsx
index c0a4d90a..b2ce8b85 100644
--- a/app/src/tasks/TaskDetail/Metrics.tsx
+++ b/app/src/tasks/TaskDetail/Metrics.tsx
@@ -1,4 +1,4 @@
-import { Await, useLoaderData } from "react-router-dom";
+import { Await, useLoaderData } from "react-router";
import Col from "react-bootstrap/Col";
import { Suspense } from "react";
import { Aggregator, Task } from "../../ApiClient";
diff --git a/app/src/tasks/TaskDetail/RenameTaskButton.tsx b/app/src/tasks/TaskDetail/RenameTaskButton.tsx
index 76408b21..18dd23ef 100644
--- a/app/src/tasks/TaskDetail/RenameTaskButton.tsx
+++ b/app/src/tasks/TaskDetail/RenameTaskButton.tsx
@@ -1,4 +1,4 @@
-import { useFetcher } from "react-router-dom";
+import { useFetcher } from "react-router";
import { useCallback, useEffect, useState } from "react";
import { Pencil, PencilSquare } from "react-bootstrap-icons";
import {
diff --git a/app/src/tasks/TaskDetail/TaskPropertyTable.tsx b/app/src/tasks/TaskDetail/TaskPropertyTable.tsx
index 8e69d5eb..97c2233c 100644
--- a/app/src/tasks/TaskDetail/TaskPropertyTable.tsx
+++ b/app/src/tasks/TaskDetail/TaskPropertyTable.tsx
@@ -1,4 +1,4 @@
-import { Await, useParams, useLoaderData, Link } from "react-router-dom";
+import { Await, useParams, useLoaderData, Link } from "react-router";
import Col from "react-bootstrap/Col";
import { Suspense } from "react";
import { Task, Aggregator, CollectorCredential } from "../../ApiClient";
diff --git a/app/src/tasks/TaskDetail/index.tsx b/app/src/tasks/TaskDetail/index.tsx
index 2423668b..f1dcd043 100644
--- a/app/src/tasks/TaskDetail/index.tsx
+++ b/app/src/tasks/TaskDetail/index.tsx
@@ -1,4 +1,4 @@
-import { Await, useParams, useLoaderData } from "react-router-dom";
+import { Await, useParams, useLoaderData } from "react-router";
import Breadcrumb from "react-bootstrap/Breadcrumb";
import React, { Suspense } from "react";
import Row from "react-bootstrap/Row";
diff --git a/app/src/tasks/TaskForm/HelperAggregator.tsx b/app/src/tasks/TaskForm/HelperAggregator.tsx
index 12956d67..2f1e06cd 100644
--- a/app/src/tasks/TaskForm/HelperAggregator.tsx
+++ b/app/src/tasks/TaskForm/HelperAggregator.tsx
@@ -1,4 +1,4 @@
-import { Await, useLoaderData } from "react-router-dom";
+import { Await, useLoaderData } from "react-router";
import FormControl from "react-bootstrap/FormControl";
import FormSelect from "react-bootstrap/FormSelect";
import { Suspense } from "react";
diff --git a/app/src/tasks/TaskForm/LeaderAggregator.tsx b/app/src/tasks/TaskForm/LeaderAggregator.tsx
index 6c120b5a..4daa3b03 100644
--- a/app/src/tasks/TaskForm/LeaderAggregator.tsx
+++ b/app/src/tasks/TaskForm/LeaderAggregator.tsx
@@ -1,4 +1,4 @@
-import { Await, useLoaderData } from "react-router-dom";
+import { Await, useLoaderData } from "react-router";
import FormControl from "react-bootstrap/FormControl";
import FormSelect from "react-bootstrap/FormSelect";
import { Suspense } from "react";
diff --git a/app/src/tasks/TaskForm/QueryType.tsx b/app/src/tasks/TaskForm/QueryType.tsx
index 35847ad1..4f4e7b3a 100644
--- a/app/src/tasks/TaskForm/QueryType.tsx
+++ b/app/src/tasks/TaskForm/QueryType.tsx
@@ -1,4 +1,4 @@
-import { useLoaderData } from "react-router-dom";
+import { useLoaderData } from "react-router";
import React, { ChangeEvent } from "react";
import { Aggregator } from "../../ApiClient";
import FormCheck from "react-bootstrap/FormCheck";
diff --git a/app/src/tasks/TaskForm/VdafType.tsx b/app/src/tasks/TaskForm/VdafType.tsx
index 457cfac9..74d4ca4e 100644
--- a/app/src/tasks/TaskForm/VdafType.tsx
+++ b/app/src/tasks/TaskForm/VdafType.tsx
@@ -1,4 +1,4 @@
-import { useLoaderData } from "react-router-dom";
+import { useLoaderData } from "react-router";
import FormControl from "react-bootstrap/FormControl";
import FormSelect from "react-bootstrap/FormSelect";
import { Aggregator } from "../../ApiClient";
diff --git a/app/src/tasks/TaskForm/index.tsx b/app/src/tasks/TaskForm/index.tsx
index 1db955d1..fdfe3a27 100644
--- a/app/src/tasks/TaskForm/index.tsx
+++ b/app/src/tasks/TaskForm/index.tsx
@@ -3,7 +3,7 @@ import {
useNavigation,
useParams,
NavigateFunction,
-} from "react-router-dom";
+} from "react-router";
import Breadcrumb from "react-bootstrap/Breadcrumb";
import Button from "react-bootstrap/Button";
import Col from "react-bootstrap/Col";
diff --git a/app/src/tasks/TaskList.tsx b/app/src/tasks/TaskList.tsx
index 8637ed1e..fad68283 100644
--- a/app/src/tasks/TaskList.tsx
+++ b/app/src/tasks/TaskList.tsx
@@ -2,7 +2,7 @@ import Breadcrumb from "react-bootstrap/Breadcrumb";
import Col from "react-bootstrap/Col";
import Row from "react-bootstrap/Row";
import ListGroup from "react-bootstrap/ListGroup";
-import { Await, useLoaderData, useAsyncValue } from "react-router-dom";
+import { Await, useLoaderData, useAsyncValue } from "react-router";
import { Suspense } from "react";
import { Task } from "../ApiClient";
import { Alert, Button, Spinner } from "react-bootstrap";
diff --git a/app/src/tasks/index.tsx b/app/src/tasks/index.tsx
index b57b2792..662f3a90 100644
--- a/app/src/tasks/index.tsx
+++ b/app/src/tasks/index.tsx
@@ -2,7 +2,7 @@ import AccountDetailFull from "./TaskList";
import TaskForm from "./TaskForm";
import TaskDetail from "./TaskDetail";
import ApiClient from "../ApiClient";
-import { RouteObject, defer, redirect } from "react-router-dom";
+import { RouteObject, redirect } from "react-router";
export default function tasks(apiClient: ApiClient): RouteObject {
return {
@@ -13,9 +13,9 @@ export default function tasks(apiClient: ApiClient): RouteObject {
index: true,
element: ,
loader({ params }) {
- return defer({
+ return {
tasks: apiClient.accountTasks(params.accountId as string),
- });
+ };
},
},
{
@@ -32,12 +32,12 @@ export default function tasks(apiClient: ApiClient): RouteObject {
const collectorCredential = task.then((t) =>
apiClient.collectorCredential(t.collector_credential_id),
);
- return defer({
+ return {
task,
leaderAggregator,
helperAggregator,
collectorCredential,
- });
+ };
},
async action({ params, request }) {
@@ -68,11 +68,11 @@ export default function tasks(apiClient: ApiClient): RouteObject {
{
path: "collector_auth_tokens",
loader({ params }) {
- return defer({
+ return {
collectorAuthTokens: apiClient.taskCollectorAuthTokens(
params.taskId as string,
),
- });
+ };
},
},
],
@@ -81,14 +81,14 @@ export default function tasks(apiClient: ApiClient): RouteObject {
path: "new",
element: ,
loader({ params }) {
- return defer({
+ return {
aggregators: apiClient.accountAggregators(
params.accountId as string,
),
collectorCredentials: apiClient.accountCollectorCredentials(
params.accountId as string,
),
- });
+ };
},
},
],
diff --git a/app/src/util.tsx b/app/src/util.tsx
index 4eec44cc..4df79717 100644
--- a/app/src/util.tsx
+++ b/app/src/util.tsx
@@ -3,7 +3,7 @@ import Col from "react-bootstrap/Col";
import Row from "react-bootstrap/Row";
import { LinkContainer } from "react-router-bootstrap";
import React, { Suspense, useRef } from "react";
-import { Await, useRouteLoaderData, useLoaderData } from "react-router-dom";
+import { Await, useRouteLoaderData, useLoaderData } from "react-router";
import { Account } from "./ApiClient";
import Placeholder from "react-bootstrap/Placeholder";
import { Button, OverlayTrigger, Tooltip } from "react-bootstrap";
diff --git a/app/tsconfig.json b/app/tsconfig.json
index 3d0a51a8..a4fceaf8 100644
--- a/app/tsconfig.json
+++ b/app/tsconfig.json
@@ -10,7 +10,7 @@
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
- "moduleResolution": "Node",
+ "moduleResolution": "Bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
diff --git a/app/tsconfig.node.json b/app/tsconfig.node.json
index 9d31e2ae..193c3489 100644
--- a/app/tsconfig.node.json
+++ b/app/tsconfig.node.json
@@ -2,7 +2,7 @@
"compilerOptions": {
"composite": true,
"module": "ESNext",
- "moduleResolution": "Node",
+ "moduleResolution": "NodeNext",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]