chore: remove circular dependencies (#17585)

I've been bit in the past by hard to deduce bugs caused by circular
dependencies within TS projects. On a hunch that this could be
contributing to some flaky tests I've used the tool
[dpdm](https://github.com/acrazing/dpdm) to find and remove them.

This PR does the following:
- Move around exports/create new files to remove any non-type circular
depencies
- Add dpdm as a dev dependency and create the `check:circular-depency`
pnpm script
This commit is contained in:
brettkolodny
2025-04-28 16:51:58 -04:00
committed by GitHub
parent 12589026b6
commit b6146dfe8a
42 changed files with 180 additions and 75 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
import { API } from "api/api";
import { cachedQuery } from "api/queries/util";
import type { Region, WorkspaceProxy } from "api/typesGenerated";
import { useAuthenticated } from "contexts/auth/RequireAuth";
import { useAuthenticated } from "hooks";
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
import {
type FC,
+1 -1
View File
@@ -1,4 +1,5 @@
import { renderHook, screen } from "@testing-library/react";
import { useAuthenticated } from "hooks";
import { http, HttpResponse } from "msw";
import type { FC, PropsWithChildren } from "react";
import { QueryClientProvider } from "react-query";
@@ -9,7 +10,6 @@ import {
} from "testHelpers/renderHelpers";
import { server } from "testHelpers/server";
import { AuthContext, type AuthContextValue } from "./AuthProvider";
import { useAuthenticated } from "./RequireAuth";
describe("RequireAuth", () => {
it("redirects to /login if user is not authenticated", async () => {
+1 -26
View File
@@ -6,7 +6,7 @@ import { DashboardProvider as ProductionDashboardProvider } from "modules/dashbo
import { type FC, useEffect } from "react";
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { embedRedirect } from "utils/redirect";
import { type AuthContextValue, useAuthContext } from "./AuthProvider";
import { useAuthContext } from "./AuthProvider";
type RequireAuthProps = Readonly<{
ProxyProvider?: typeof ProductionProxyProvider;
@@ -81,28 +81,3 @@ export const RequireAuth: FC<RequireAuthProps> = ({
</DashboardProvider>
);
};
type RequireKeys<T, R extends keyof T> = Omit<T, R> & {
[K in keyof Pick<T, R>]-?: NonNullable<T[K]>;
};
// We can do some TS magic here but I would rather to be explicit on what
// values are not undefined when authenticated
type AuthenticatedAuthContextValue = RequireKeys<
AuthContextValue,
"user" | "permissions"
>;
export const useAuthenticated = (): AuthenticatedAuthContextValue => {
const auth = useAuthContext();
if (!auth.user) {
throw new Error("User is not authenticated.");
}
if (!auth.permissions) {
throw new Error("Permissions are not available.");
}
return auth as AuthenticatedAuthContextValue;
};