From 350070eb747d023065321f57044f25fc25b30951 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 13:43:26 +0000 Subject: [PATCH 01/10] chore: move useAuthenticated hook to remove circular dependency --- site/src/components/Filter/UserFilter.tsx | 2 +- site/src/contexts/ProxyContext.tsx | 2 +- site/src/contexts/auth/RequireAuth.test.tsx | 2 +- site/src/contexts/auth/RequireAuth.tsx | 27 +---------------- site/src/hooks/index.ts | 1 + site/src/hooks/useAuthenticated.tsx | 29 +++++++++++++++++++ .../src/modules/dashboard/DashboardLayout.tsx | 2 +- .../modules/dashboard/DashboardProvider.tsx | 2 +- .../DeploymentBanner/DeploymentBanner.tsx | 2 +- site/src/modules/dashboard/Navbar/Navbar.tsx | 2 +- .../modules/dashboard/Navbar/ProxyMenu.tsx | 2 +- .../management/DeploymentSettingsLayout.tsx | 2 +- .../modules/management/DeploymentSidebar.tsx | 2 +- .../management/OrganizationSidebar.tsx | 2 +- .../CreateWorkspacePage.tsx | 2 +- .../CreateWorkspacePageExperimental.tsx | 2 +- .../ExternalAuthPage/ExternalAuthPage.tsx | 2 +- .../CreateOrganizationPage.tsx | 2 +- .../OrganizationMembersPage.tsx | 2 +- .../src/pages/TemplatePage/TemplateLayout.tsx | 2 +- .../TemplateVersionPage.tsx | 2 +- .../src/pages/TemplatesPage/TemplatesPage.tsx | 2 +- .../AccountPage/AccountPage.tsx | 2 +- site/src/pages/UserSettingsPage/Layout.tsx | 2 +- .../NotificationsPage/NotificationsPage.tsx | 2 +- .../OAuth2ProviderPage/OAuth2ProviderPage.tsx | 2 +- .../SchedulePage/SchedulePage.tsx | 2 +- .../SecurityPage/SecurityPage.tsx | 2 +- site/src/pages/UsersPage/UsersPage.tsx | 2 +- .../WorkspacePage/WorkspaceReadyPage.tsx | 2 +- .../pages/WorkspacesPage/WorkspacesPage.tsx | 2 +- 31 files changed, 59 insertions(+), 54 deletions(-) create mode 100644 site/src/hooks/useAuthenticated.tsx diff --git a/site/src/components/Filter/UserFilter.tsx b/site/src/components/Filter/UserFilter.tsx index e1c6d0057d021..3dc591cd4a284 100644 --- a/site/src/components/Filter/UserFilter.tsx +++ b/site/src/components/Filter/UserFilter.tsx @@ -5,7 +5,7 @@ import { type SelectFilterOption, SelectFilterSearch, } from "components/Filter/SelectFilter"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import type { FC } from "react"; import { type UseFilterMenuOptions, useFilterMenu } from "./menu"; diff --git a/site/src/contexts/ProxyContext.tsx b/site/src/contexts/ProxyContext.tsx index 1aa749e83edf4..7312afb25fa83 100644 --- a/site/src/contexts/ProxyContext.tsx +++ b/site/src/contexts/ProxyContext.tsx @@ -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, diff --git a/site/src/contexts/auth/RequireAuth.test.tsx b/site/src/contexts/auth/RequireAuth.test.tsx index 02265c1fd7fd5..291d442adbc04 100644 --- a/site/src/contexts/auth/RequireAuth.test.tsx +++ b/site/src/contexts/auth/RequireAuth.test.tsx @@ -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 () => { diff --git a/site/src/contexts/auth/RequireAuth.tsx b/site/src/contexts/auth/RequireAuth.tsx index e558b66c802de..0476d99a168ed 100644 --- a/site/src/contexts/auth/RequireAuth.tsx +++ b/site/src/contexts/auth/RequireAuth.tsx @@ -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 = ({ ); }; - -type RequireKeys = Omit & { - [K in keyof Pick]-?: NonNullable; -}; - -// 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; -}; diff --git a/site/src/hooks/index.ts b/site/src/hooks/index.ts index 522284c6bea1f..94479025d173e 100644 --- a/site/src/hooks/index.ts +++ b/site/src/hooks/index.ts @@ -2,3 +2,4 @@ export * from "./useClickable"; export * from "./useClickableTableRow"; export * from "./useClipboard"; export * from "./usePagination"; +export * from "./useAuthenticated"; diff --git a/site/src/hooks/useAuthenticated.tsx b/site/src/hooks/useAuthenticated.tsx new file mode 100644 index 0000000000000..b03d921843c87 --- /dev/null +++ b/site/src/hooks/useAuthenticated.tsx @@ -0,0 +1,29 @@ +import { + type AuthContextValue, + useAuthContext, +} from "contexts/auth/AuthProvider"; + +type RequireKeys = Omit & { + [K in keyof Pick]-?: NonNullable; +}; + +// 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; +}; diff --git a/site/src/modules/dashboard/DashboardLayout.tsx b/site/src/modules/dashboard/DashboardLayout.tsx index b4ca5a7ae98d6..df3478ab18394 100644 --- a/site/src/modules/dashboard/DashboardLayout.tsx +++ b/site/src/modules/dashboard/DashboardLayout.tsx @@ -3,7 +3,7 @@ import Link from "@mui/material/Link"; import Snackbar from "@mui/material/Snackbar"; import { Button } from "components/Button/Button"; import { Loader } from "components/Loader/Loader"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { AnnouncementBanners } from "modules/dashboard/AnnouncementBanners/AnnouncementBanners"; import { LicenseBanner } from "modules/dashboard/LicenseBanner/LicenseBanner"; import { type FC, type HTMLAttributes, Suspense } from "react"; diff --git a/site/src/modules/dashboard/DashboardProvider.tsx b/site/src/modules/dashboard/DashboardProvider.tsx index c7f7733f153a7..d56e30afaed8b 100644 --- a/site/src/modules/dashboard/DashboardProvider.tsx +++ b/site/src/modules/dashboard/DashboardProvider.tsx @@ -10,7 +10,7 @@ import type { } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata"; import { canViewAnyOrganization } from "modules/permissions"; import { type FC, type PropsWithChildren, createContext } from "react"; diff --git a/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx b/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx index 182682399250f..7fd2a3d0fc170 100644 --- a/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx +++ b/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx @@ -1,6 +1,6 @@ import { health } from "api/queries/debug"; import { deploymentStats } from "api/queries/deployment"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import type { FC } from "react"; import { useQuery } from "react-query"; import { DeploymentBannerView } from "./DeploymentBannerView"; diff --git a/site/src/modules/dashboard/Navbar/Navbar.tsx b/site/src/modules/dashboard/Navbar/Navbar.tsx index 0b7d64de5e290..e573554629193 100644 --- a/site/src/modules/dashboard/Navbar/Navbar.tsx +++ b/site/src/modules/dashboard/Navbar/Navbar.tsx @@ -1,6 +1,6 @@ import { buildInfo } from "api/queries/buildInfo"; import { useProxy } from "contexts/ProxyContext"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata"; import { useDashboard } from "modules/dashboard/useDashboard"; import { canViewDeploymentSettings } from "modules/permissions"; diff --git a/site/src/modules/dashboard/Navbar/ProxyMenu.tsx b/site/src/modules/dashboard/Navbar/ProxyMenu.tsx index abbfbd5fd82f3..86d9b9b53ee84 100644 --- a/site/src/modules/dashboard/Navbar/ProxyMenu.tsx +++ b/site/src/modules/dashboard/Navbar/ProxyMenu.tsx @@ -10,7 +10,7 @@ import { Button } from "components/Button/Button"; import { displayError } from "components/GlobalSnackbar/utils"; import { Latency } from "components/Latency/Latency"; import type { ProxyContextValue } from "contexts/ProxyContext"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { ChevronDownIcon } from "lucide-react"; import { type FC, useRef, useState } from "react"; import { useNavigate } from "react-router-dom"; diff --git a/site/src/modules/management/DeploymentSettingsLayout.tsx b/site/src/modules/management/DeploymentSettingsLayout.tsx index 42e695c80654e..d060deda621fc 100644 --- a/site/src/modules/management/DeploymentSettingsLayout.tsx +++ b/site/src/modules/management/DeploymentSettingsLayout.tsx @@ -6,7 +6,7 @@ import { BreadcrumbSeparator, } from "components/Breadcrumb/Breadcrumb"; import { Loader } from "components/Loader/Loader"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { canViewDeploymentSettings } from "modules/permissions"; import { RequirePermission } from "modules/permissions/RequirePermission"; import { type FC, Suspense } from "react"; diff --git a/site/src/modules/management/DeploymentSidebar.tsx b/site/src/modules/management/DeploymentSidebar.tsx index 7600a075b97e3..b202b46f3d231 100644 --- a/site/src/modules/management/DeploymentSidebar.tsx +++ b/site/src/modules/management/DeploymentSidebar.tsx @@ -1,4 +1,4 @@ -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useDashboard } from "modules/dashboard/useDashboard"; import type { FC } from "react"; import { DeploymentSidebarView } from "./DeploymentSidebarView"; diff --git a/site/src/modules/management/OrganizationSidebar.tsx b/site/src/modules/management/OrganizationSidebar.tsx index 3b6451b0252bc..4f77348eefa93 100644 --- a/site/src/modules/management/OrganizationSidebar.tsx +++ b/site/src/modules/management/OrganizationSidebar.tsx @@ -1,5 +1,5 @@ import { Sidebar as BaseSidebar } from "components/Sidebar/Sidebar"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useOrganizationSettings } from "modules/management/OrganizationSettingsLayout"; import type { FC } from "react"; import { OrganizationSidebarView } from "./OrganizationSidebarView"; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx index fd88e0cc23e72..fa2a5423aef0a 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx @@ -14,7 +14,7 @@ import type { Workspace, } from "api/typesGenerated"; import { Loader } from "components/Loader/Loader"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useEffectEvent } from "hooks/hookPolyfills"; import { useDashboard } from "modules/dashboard/useDashboard"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx index c02529c5d9446..9103c5715b015 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx @@ -12,7 +12,7 @@ import type { Workspace, } from "api/typesGenerated"; import { Loader } from "components/Loader/Loader"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useEffectEvent } from "hooks/hookPolyfills"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; import { diff --git a/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx b/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx index 4256337954020..0523a5da750d4 100644 --- a/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx +++ b/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx @@ -12,7 +12,7 @@ import { } from "components/GitDeviceAuth/GitDeviceAuth"; import { SignInLayout } from "components/SignInLayout/SignInLayout"; import { Welcome } from "components/Welcome/Welcome"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import type { FC } from "react"; import { useMemo } from "react"; import { useQuery, useQueryClient } from "react-query"; diff --git a/site/src/pages/OrganizationSettingsPage/CreateOrganizationPage.tsx b/site/src/pages/OrganizationSettingsPage/CreateOrganizationPage.tsx index 3258461ea79bb..eeb958b040dca 100644 --- a/site/src/pages/OrganizationSettingsPage/CreateOrganizationPage.tsx +++ b/site/src/pages/OrganizationSettingsPage/CreateOrganizationPage.tsx @@ -1,6 +1,6 @@ import { createOrganization } from "api/queries/organizations"; import { displaySuccess } from "components/GlobalSnackbar/utils"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import { RequirePermission } from "modules/permissions/RequirePermission"; import type { FC } from "react"; diff --git a/site/src/pages/OrganizationSettingsPage/OrganizationMembersPage.tsx b/site/src/pages/OrganizationSettingsPage/OrganizationMembersPage.tsx index 5b566efa914aa..68f0098e47f38 100644 --- a/site/src/pages/OrganizationSettingsPage/OrganizationMembersPage.tsx +++ b/site/src/pages/OrganizationSettingsPage/OrganizationMembersPage.tsx @@ -13,7 +13,7 @@ import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"; import { EmptyState } from "components/EmptyState/EmptyState"; import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; import { Stack } from "components/Stack/Stack"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { usePaginatedQuery } from "hooks/usePaginatedQuery"; import { useOrganizationSettings } from "modules/management/OrganizationSettingsLayout"; import { RequirePermission } from "modules/permissions/RequirePermission"; diff --git a/site/src/pages/TemplatePage/TemplateLayout.tsx b/site/src/pages/TemplatePage/TemplateLayout.tsx index 1aa0253da9a33..d81c2156970e3 100644 --- a/site/src/pages/TemplatePage/TemplateLayout.tsx +++ b/site/src/pages/TemplatePage/TemplateLayout.tsx @@ -5,7 +5,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; import { Margins } from "components/Margins/Margins"; import { TabLink, Tabs, TabsList } from "components/Tabs/Tabs"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { type WorkspacePermissions, workspacePermissionChecks, diff --git a/site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx b/site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx index 90c66453c63ee..78fd1f9b60abb 100644 --- a/site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx +++ b/site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx @@ -4,7 +4,7 @@ import { templateVersion, templateVersionByName, } from "api/queries/templates"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { linkToTemplate, useLinks } from "modules/navigation"; import { type FC, useMemo } from "react"; import { Helmet } from "react-helmet-async"; diff --git a/site/src/pages/TemplatesPage/TemplatesPage.tsx b/site/src/pages/TemplatesPage/TemplatesPage.tsx index ce048e178c0ea..b22b0272c10f3 100644 --- a/site/src/pages/TemplatesPage/TemplatesPage.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPage.tsx @@ -1,7 +1,7 @@ import { workspacePermissionsByOrganization } from "api/queries/organizations"; import { templateExamples, templates } from "api/queries/templates"; import { useFilter } from "components/Filter/Filter"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useDashboard } from "modules/dashboard/useDashboard"; import type { FC } from "react"; import { Helmet } from "react-helmet-async"; diff --git a/site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx b/site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx index 34b0ef29b12e3..06f7ebe467a26 100644 --- a/site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx +++ b/site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx @@ -1,7 +1,7 @@ import { groupsForUser } from "api/queries/groups"; import { Stack } from "components/Stack/Stack"; import { useAuthContext } from "contexts/auth/AuthProvider"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useDashboard } from "modules/dashboard/useDashboard"; import type { FC } from "react"; import { useQuery } from "react-query"; diff --git a/site/src/pages/UserSettingsPage/Layout.tsx b/site/src/pages/UserSettingsPage/Layout.tsx index 645545f553257..0745771166ff5 100644 --- a/site/src/pages/UserSettingsPage/Layout.tsx +++ b/site/src/pages/UserSettingsPage/Layout.tsx @@ -1,7 +1,7 @@ import { Loader } from "components/Loader/Loader"; import { Margins } from "components/Margins/Margins"; import { Stack } from "components/Stack/Stack"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { type FC, Suspense } from "react"; import { Helmet } from "react-helmet-async"; import { Outlet } from "react-router-dom"; diff --git a/site/src/pages/UserSettingsPage/NotificationsPage/NotificationsPage.tsx b/site/src/pages/UserSettingsPage/NotificationsPage/NotificationsPage.tsx index a7f9537b1e99d..78acbb9c3b7c2 100644 --- a/site/src/pages/UserSettingsPage/NotificationsPage/NotificationsPage.tsx +++ b/site/src/pages/UserSettingsPage/NotificationsPage/NotificationsPage.tsx @@ -22,7 +22,7 @@ import type { import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; import { Loader } from "components/Loader/Loader"; import { Stack } from "components/Stack/Stack"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { castNotificationMethod, methodIcons, diff --git a/site/src/pages/UserSettingsPage/OAuth2ProviderPage/OAuth2ProviderPage.tsx b/site/src/pages/UserSettingsPage/OAuth2ProviderPage/OAuth2ProviderPage.tsx index 5e499cf263759..5e42a2d95ab13 100644 --- a/site/src/pages/UserSettingsPage/OAuth2ProviderPage/OAuth2ProviderPage.tsx +++ b/site/src/pages/UserSettingsPage/OAuth2ProviderPage/OAuth2ProviderPage.tsx @@ -2,7 +2,7 @@ import { getErrorMessage } from "api/errors"; import { getApps, revokeApp } from "api/queries/oauth2"; import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"; import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { type FC, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "react-query"; import { Section } from "../Section"; diff --git a/site/src/pages/UserSettingsPage/SchedulePage/SchedulePage.tsx b/site/src/pages/UserSettingsPage/SchedulePage/SchedulePage.tsx index 590a439589746..1c3aa2f36eeb5 100644 --- a/site/src/pages/UserSettingsPage/SchedulePage/SchedulePage.tsx +++ b/site/src/pages/UserSettingsPage/SchedulePage/SchedulePage.tsx @@ -5,7 +5,7 @@ import { import { ErrorAlert } from "components/Alert/ErrorAlert"; import { displaySuccess } from "components/GlobalSnackbar/utils"; import { Loader } from "components/Loader/Loader"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import type { FC } from "react"; import { useMutation, useQuery, useQueryClient } from "react-query"; import { Section } from "../Section"; diff --git a/site/src/pages/UserSettingsPage/SecurityPage/SecurityPage.tsx b/site/src/pages/UserSettingsPage/SecurityPage/SecurityPage.tsx index ef09a0aa17742..c33a16c5093eb 100644 --- a/site/src/pages/UserSettingsPage/SecurityPage/SecurityPage.tsx +++ b/site/src/pages/UserSettingsPage/SecurityPage/SecurityPage.tsx @@ -3,7 +3,7 @@ import { authMethods, updatePassword } from "api/queries/users"; import { displaySuccess } from "components/GlobalSnackbar/utils"; import { Loader } from "components/Loader/Loader"; import { Stack } from "components/Stack/Stack"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import type { ComponentProps, FC } from "react"; import { useMutation, useQuery } from "react-query"; import { Section } from "../Section"; diff --git a/site/src/pages/UsersPage/UsersPage.tsx b/site/src/pages/UsersPage/UsersPage.tsx index c8677e3a44f47..f9f59ab22aa8b 100644 --- a/site/src/pages/UsersPage/UsersPage.tsx +++ b/site/src/pages/UsersPage/UsersPage.tsx @@ -17,7 +17,7 @@ import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"; import { useFilter } from "components/Filter/Filter"; import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; import { isNonInitialPage } from "components/PaginationWidget/utils"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { usePaginatedQuery } from "hooks/usePaginatedQuery"; import { useDashboard } from "modules/dashboard/useDashboard"; import { type FC, useState } from "react"; diff --git a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx index e4329ecad78aa..52f026d4992ac 100644 --- a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx @@ -22,8 +22,8 @@ import { import { displayError } from "components/GlobalSnackbar/utils"; import { MemoizedInlineMarkdown } from "components/Markdown/Markdown"; import { Stack } from "components/Stack/Stack"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; import dayjs from "dayjs"; +import { useAuthenticated } from "hooks"; import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata"; import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs"; import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index 85d216e48850d..ba380905adda2 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -3,7 +3,7 @@ import { templates } from "api/queries/templates"; import type { Workspace } from "api/typesGenerated"; import { useFilter } from "components/Filter/Filter"; import { useUserFilterMenu } from "components/Filter/UserFilter"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useAuthenticated } from "hooks"; import { useEffectEvent } from "hooks/hookPolyfills"; import { usePagination } from "hooks/usePagination"; import { useDashboard } from "modules/dashboard/useDashboard"; From cc6df5f6f984cb1419a944b9664cbae8c17aa81f Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 13:50:01 +0000 Subject: [PATCH 02/10] chore: create LoginPage/Language.ts to remove circular dependency --- site/src/pages/LoginPage/Language.ts | 9 +++++++++ site/src/pages/LoginPage/LoginPage.test.tsx | 2 +- site/src/pages/LoginPage/OAuthSignInForm.tsx | 2 +- site/src/pages/LoginPage/PasswordSignInForm.tsx | 2 +- site/src/pages/LoginPage/SignInForm.tsx | 10 ---------- 5 files changed, 12 insertions(+), 13 deletions(-) create mode 100644 site/src/pages/LoginPage/Language.ts diff --git a/site/src/pages/LoginPage/Language.ts b/site/src/pages/LoginPage/Language.ts new file mode 100644 index 0000000000000..199a36bebab41 --- /dev/null +++ b/site/src/pages/LoginPage/Language.ts @@ -0,0 +1,9 @@ +export const Language = { + emailLabel: "Email", + passwordLabel: "Password", + emailInvalid: "Please enter a valid email address.", + emailRequired: "Please enter an email address.", + passwordSignIn: "Sign In", + githubSignIn: "GitHub", + oidcSignIn: "OpenID Connect", +}; diff --git a/site/src/pages/LoginPage/LoginPage.test.tsx b/site/src/pages/LoginPage/LoginPage.test.tsx index 96b394b33d055..1b41232971590 100644 --- a/site/src/pages/LoginPage/LoginPage.test.tsx +++ b/site/src/pages/LoginPage/LoginPage.test.tsx @@ -8,8 +8,8 @@ import { waitForLoaderToBeRemoved, } from "testHelpers/renderHelpers"; import { server } from "testHelpers/server"; +import { Language } from "./Language"; import { LoginPage } from "./LoginPage"; -import { Language } from "./SignInForm"; describe("LoginPage", () => { beforeEach(() => { diff --git a/site/src/pages/LoginPage/OAuthSignInForm.tsx b/site/src/pages/LoginPage/OAuthSignInForm.tsx index b25a9757fe30d..e4872d6600389 100644 --- a/site/src/pages/LoginPage/OAuthSignInForm.tsx +++ b/site/src/pages/LoginPage/OAuthSignInForm.tsx @@ -4,7 +4,7 @@ import Button from "@mui/material/Button"; import { visuallyHidden } from "@mui/utils"; import type { AuthMethods } from "api/typesGenerated"; import { type FC, useId } from "react"; -import { Language } from "./SignInForm"; +import { Language } from "./Language"; const iconStyles = { width: 16, diff --git a/site/src/pages/LoginPage/PasswordSignInForm.tsx b/site/src/pages/LoginPage/PasswordSignInForm.tsx index e2ca4dc5bcfaa..de61c3de6982a 100644 --- a/site/src/pages/LoginPage/PasswordSignInForm.tsx +++ b/site/src/pages/LoginPage/PasswordSignInForm.tsx @@ -7,7 +7,7 @@ import type { FC } from "react"; import { Link as RouterLink } from "react-router-dom"; import { getFormHelpers, onChangeTrimmed } from "utils/formUtils"; import * as Yup from "yup"; -import { Language } from "./SignInForm"; +import { Language } from "./Language"; type PasswordSignInFormProps = { onSubmit: (credentials: { email: string; password: string }) => void; diff --git a/site/src/pages/LoginPage/SignInForm.tsx b/site/src/pages/LoginPage/SignInForm.tsx index dad65fd24f9ab..9411bba182253 100644 --- a/site/src/pages/LoginPage/SignInForm.tsx +++ b/site/src/pages/LoginPage/SignInForm.tsx @@ -7,16 +7,6 @@ import { getApplicationName } from "utils/appearance"; import { OAuthSignInForm } from "./OAuthSignInForm"; import { PasswordSignInForm } from "./PasswordSignInForm"; -export const Language = { - emailLabel: "Email", - passwordLabel: "Password", - emailInvalid: "Please enter a valid email address.", - emailRequired: "Please enter an email address.", - passwordSignIn: "Sign In", - githubSignIn: "GitHub", - oidcSignIn: "OpenID Connect", -}; - const styles = { root: { width: "100%", From 8201297e1f3fe0f5b743b8f17f2afdb959f973e7 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 14:16:02 +0000 Subject: [PATCH 03/10] chore: create ExperimentalFormContext.tsx to remove circular depencency --- site/src/contexts/ExperimentalFormContext.tsx | 5 +++++ .../CreateWorkspaceExperimentRouter.tsx | 7 ++----- .../pages/CreateWorkspacePage/CreateWorkspacePageView.tsx | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 site/src/contexts/ExperimentalFormContext.tsx diff --git a/site/src/contexts/ExperimentalFormContext.tsx b/site/src/contexts/ExperimentalFormContext.tsx new file mode 100644 index 0000000000000..f79665a0e4a01 --- /dev/null +++ b/site/src/contexts/ExperimentalFormContext.tsx @@ -0,0 +1,5 @@ +import { createContext } from "react"; + +export const ExperimentalFormContext = createContext< + { toggleOptedOut: () => void } | undefined +>(undefined); diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx index 377424ca2f9a5..388d51cdb65cc 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx @@ -1,8 +1,9 @@ import { templateByName } from "api/queries/templates"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; +import { ExperimentalFormContext } from "contexts/ExperimentalFormContext"; import { useDashboard } from "modules/dashboard/useDashboard"; -import { type FC, createContext } from "react"; +import type { FC } from "react"; import { useQuery } from "react-query"; import { useParams } from "react-router-dom"; import CreateWorkspacePage from "./CreateWorkspacePage"; @@ -70,7 +71,3 @@ const CreateWorkspaceExperimentRouter: FC = () => { export default CreateWorkspaceExperimentRouter; const optOutKey = (id: string) => `parameters.${id}.optOut`; - -export const ExperimentalFormContext = createContext< - { toggleOptedOut: () => void } | undefined ->(undefined); diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 8f284f7338688..c23cbf9ca0b9a 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -26,6 +26,7 @@ import { Spinner } from "components/Spinner/Spinner"; import { Stack } from "components/Stack/Stack"; import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; +import { ExperimentalFormContext } from "contexts/ExperimentalFormContext"; import { type FormikContextType, useFormik } from "formik"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; import { @@ -47,7 +48,6 @@ import { useValidationSchemaForRichParameters, } from "utils/richParameters"; import * as Yup from "yup"; -import { ExperimentalFormContext } from "./CreateWorkspaceExperimentRouter"; import type { CreateWorkspaceMode, ExternalAuthPollingState, From a78afde8ac6129c9bb638d17d9e282de1a6460c5 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 14:25:42 +0000 Subject: [PATCH 04/10] fix: use correct file path for import --- .../CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx index ab69cebc93f4d..88f492376bac9 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx @@ -13,6 +13,7 @@ import { Spinner } from "components/Spinner/Spinner"; import { Stack } from "components/Stack/Stack"; import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; +import { ExperimentalFormContext } from "contexts/ExperimentalFormContext"; import { type FormikContextType, useFormik } from "formik"; import { useDebouncedFunction } from "hooks/debounce"; import { ArrowLeft, CircleAlert, TriangleAlert } from "lucide-react"; @@ -33,7 +34,6 @@ import { import { getFormHelpers, nameValidator } from "utils/formUtils"; import type { AutofillBuildParameter } from "utils/richParameters"; import * as Yup from "yup"; -import { ExperimentalFormContext } from "./CreateWorkspaceExperimentRouter"; import type { CreateWorkspaceMode, ExternalAuthPollingState, From 77812294dca76b6bc645652f4fb9432e396671e8 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 14:37:44 +0000 Subject: [PATCH 05/10] chore: add dpdm as a dev dependency --- site/package.json | 8 +++- site/pnpm-lock.yaml | 97 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/site/package.json b/site/package.json index 7b5670c36cbee..8a0bce6199e43 100644 --- a/site/package.json +++ b/site/package.json @@ -8,6 +8,7 @@ "build": "NODE_ENV=production pnpm vite build", "check": "biome check --error-on-warnings .", "check:fix": "biome check --error-on-warnings --fix .", + "check:circular-deps": "dpdm --no-tree --no-warning -T ./src/App.tsx", "check:all": "pnpm check && pnpm test", "chromatic": "chromatic", "dev": "vite", @@ -171,6 +172,7 @@ "@vitejs/plugin-react": "4.3.4", "autoprefixer": "10.4.20", "chromatic": "11.25.2", + "dpdm": "3.14.0", "express": "4.21.2", "jest": "29.7.0", "jest-canvas-mock": "2.5.2", @@ -196,7 +198,11 @@ "vite-plugin-checker": "0.8.0", "vite-plugin-turbosnap": "1.0.3" }, - "browserslist": ["chrome 110", "firefox 111", "safari 16.0"], + "browserslist": [ + "chrome 110", + "firefox 111", + "safari 16.0" + ], "resolutions": { "optionator": "0.9.3", "semver": "7.6.2" diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index 913e292f7aba5..15bc6709ef011 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -422,6 +422,9 @@ importers: chromatic: specifier: 11.25.2 version: 11.25.2 + dpdm: + specifier: 3.14.0 + version: 3.14.0 express: specifier: 4.21.2 version: 4.21.2 @@ -3223,6 +3226,14 @@ packages: classnames@2.3.2: resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==, tarball: https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz} + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==, tarball: https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz} + engines: {node: '>=8'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==, tarball: https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz} + engines: {node: '>=6'} + cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==, tarball: https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz} engines: {node: '>= 12'} @@ -3231,6 +3242,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, tarball: https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz} engines: {node: '>=12'} + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==, tarball: https://registry.npmjs.org/clone/-/clone-1.0.4.tgz} + engines: {node: '>=0.8'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==, tarball: https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz} engines: {node: '>=6'} @@ -3491,6 +3506,9 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==, tarball: https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz} engines: {node: '>=0.10.0'} + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==, tarball: https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz} + define-data-property@1.1.1: resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==, tarball: https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz} engines: {node: '>= 0.4'} @@ -3574,6 +3592,10 @@ packages: engines: {node: '>=12'} deprecated: Use your platform's native DOMException instead + dpdm@3.14.0: + resolution: {integrity: sha512-YJzsFSyEtj88q5eTELg3UWU7TVZkG1dpbF4JDQ3t1b07xuzXmdoGeSz9TKOke1mUuOpWlk4q+pBh+aHzD6GBTg==, tarball: https://registry.npmjs.org/dpdm/-/dpdm-3.14.0.tgz} + hasBin: true + dprint-node@1.0.8: resolution: {integrity: sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==, tarball: https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz} @@ -4206,6 +4228,10 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==, tarball: https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz} + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==, tarball: https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz} + engines: {node: '>=8'} + is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==, tarball: https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz} @@ -4261,6 +4287,10 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==, tarball: https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz} engines: {node: '>= 0.4'} + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==, tarball: https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz} + engines: {node: '>=10'} + is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==, tarball: https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz} @@ -4598,6 +4628,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, tarball: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz} + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==, tarball: https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz} + engines: {node: '>=10'} + long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==, tarball: https://registry.npmjs.org/long/-/long-5.2.3.tgz} @@ -5062,6 +5096,10 @@ packages: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==, tarball: https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz} engines: {node: '>= 0.8.0'} + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==, tarball: https://registry.npmjs.org/ora/-/ora-5.4.1.tgz} + engines: {node: '>=10'} + outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==, tarball: https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz} @@ -5606,6 +5644,10 @@ packages: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==, tarball: https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz} hasBin: true + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==, tarball: https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz} + engines: {node: '>=8'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==, tarball: https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -6345,6 +6387,9 @@ packages: walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==, tarball: https://registry.npmjs.org/walker/-/walker-1.0.8.tgz} + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==, tarball: https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz} + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==, tarball: https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz} engines: {node: '>=12'} @@ -9422,6 +9467,12 @@ snapshots: classnames@2.3.2: {} + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-spinners@2.9.2: {} + cli-width@4.1.0: {} cliui@8.0.1: @@ -9430,6 +9481,8 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + clone@1.0.4: {} + clsx@2.1.1: {} cmdk@1.0.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -9667,6 +9720,10 @@ snapshots: deepmerge@4.3.1: {} + defaults@1.0.4: + dependencies: + clone: 1.0.4 + define-data-property@1.1.1: dependencies: get-intrinsic: 1.3.0 @@ -9732,6 +9789,16 @@ snapshots: dependencies: webidl-conversions: 7.0.0 + dpdm@3.14.0: + dependencies: + chalk: 4.1.2 + fs-extra: 11.2.0 + glob: 10.4.5 + ora: 5.4.1 + tslib: 2.8.1 + typescript: 5.6.3 + yargs: 17.7.2 + dprint-node@1.0.8: dependencies: detect-libc: 1.0.3 @@ -10473,6 +10540,8 @@ snapshots: is-hexadecimal@2.0.1: {} + is-interactive@1.0.0: {} + is-map@2.0.2: {} is-node-process@1.2.0: {} @@ -10522,6 +10591,8 @@ snapshots: dependencies: which-typed-array: 1.1.18 + is-unicode-supported@0.1.0: {} + is-weakmap@2.0.1: {} is-weakset@2.0.2: @@ -11096,6 +11167,11 @@ snapshots: lodash@4.17.21: {} + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + long@5.2.3: {} longest-streak@3.1.0: {} @@ -11829,6 +11905,18 @@ snapshots: type-check: 0.4.0 optional: true + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + outvariant@1.4.3: {} p-limit@2.3.0: @@ -12441,6 +12529,11 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + reusify@1.0.4: {} rimraf@3.0.2: @@ -13233,6 +13326,10 @@ snapshots: dependencies: makeerror: 1.0.12 + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + webidl-conversions@7.0.0: {} webpack-sources@3.2.3: {} From d945f7bd6a295b6f235ac4b04015fa8961158a52 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 14:51:09 +0000 Subject: [PATCH 06/10] chore: format --- site/package.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/site/package.json b/site/package.json index 8a0bce6199e43..9f17505110897 100644 --- a/site/package.json +++ b/site/package.json @@ -198,11 +198,7 @@ "vite-plugin-checker": "0.8.0", "vite-plugin-turbosnap": "1.0.3" }, - "browserslist": [ - "chrome 110", - "firefox 111", - "safari 16.0" - ], + "browserslist": ["chrome 110", "firefox 111", "safari 16.0"], "resolutions": { "optionator": "0.9.3", "semver": "7.6.2" From e06717806338316b892fa110edf32442e0ce4cac Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 16:51:40 +0000 Subject: [PATCH 07/10] chore: alphabetize exports --- site/src/hooks/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/hooks/index.ts b/site/src/hooks/index.ts index 94479025d173e..901fee8a50ded 100644 --- a/site/src/hooks/index.ts +++ b/site/src/hooks/index.ts @@ -1,5 +1,5 @@ +export * from "./useAuthenticated"; export * from "./useClickable"; export * from "./useClickableTableRow"; export * from "./useClipboard"; export * from "./usePagination"; -export * from "./useAuthenticated"; From 64e6b3db3232481cc845ab145eb8da06769464f4 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 19:19:53 +0000 Subject: [PATCH 08/10] refactor: co-locate context --- .../CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx | 2 +- site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx | 2 +- .../CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx | 2 +- .../CreateWorkspacePage}/ExperimentalFormContext.tsx | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename site/src/{contexts => pages/CreateWorkspacePage}/ExperimentalFormContext.tsx (100%) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx index 388d51cdb65cc..9af0c404626f5 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx @@ -1,7 +1,7 @@ import { templateByName } from "api/queries/templates"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; -import { ExperimentalFormContext } from "contexts/ExperimentalFormContext"; +import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { useDashboard } from "modules/dashboard/useDashboard"; import type { FC } from "react"; import { useQuery } from "react-query"; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index c23cbf9ca0b9a..55cde2bd9127a 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -26,7 +26,7 @@ import { Spinner } from "components/Spinner/Spinner"; import { Stack } from "components/Stack/Stack"; import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; -import { ExperimentalFormContext } from "contexts/ExperimentalFormContext"; +import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { type FormikContextType, useFormik } from "formik"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; import { diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx index 88f492376bac9..37f66dcadbf1b 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx @@ -13,7 +13,7 @@ import { Spinner } from "components/Spinner/Spinner"; import { Stack } from "components/Stack/Stack"; import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; -import { ExperimentalFormContext } from "contexts/ExperimentalFormContext"; +import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { type FormikContextType, useFormik } from "formik"; import { useDebouncedFunction } from "hooks/debounce"; import { ArrowLeft, CircleAlert, TriangleAlert } from "lucide-react"; diff --git a/site/src/contexts/ExperimentalFormContext.tsx b/site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx similarity index 100% rename from site/src/contexts/ExperimentalFormContext.tsx rename to site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx From dca8d8fd95ce7178c4480cf9a155dc8cadd4cc73 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 19:46:22 +0000 Subject: [PATCH 09/10] fix: format --- .../CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx | 2 +- site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx | 2 +- .../CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx index 9af0c404626f5..3ebc194cc61b0 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspaceExperimentRouter.tsx @@ -1,13 +1,13 @@ import { templateByName } from "api/queries/templates"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; -import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { useDashboard } from "modules/dashboard/useDashboard"; import type { FC } from "react"; import { useQuery } from "react-query"; import { useParams } from "react-router-dom"; import CreateWorkspacePage from "./CreateWorkspacePage"; import CreateWorkspacePageExperimental from "./CreateWorkspacePageExperimental"; +import { ExperimentalFormContext } from "./ExperimentalFormContext"; const CreateWorkspaceExperimentRouter: FC = () => { const { experiments } = useDashboard(); diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 55cde2bd9127a..6c561cf1322f0 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -26,7 +26,6 @@ import { Spinner } from "components/Spinner/Spinner"; import { Stack } from "components/Stack/Stack"; import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; -import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { type FormikContextType, useFormik } from "formik"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; import { @@ -52,6 +51,7 @@ import type { CreateWorkspaceMode, ExternalAuthPollingState, } from "./CreateWorkspacePage"; +import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWorkspacePermissions } from "./permissions"; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx index 37f66dcadbf1b..c8a119fb70186 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx @@ -13,7 +13,6 @@ import { Spinner } from "components/Spinner/Spinner"; import { Stack } from "components/Stack/Stack"; import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; -import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { type FormikContextType, useFormik } from "formik"; import { useDebouncedFunction } from "hooks/debounce"; import { ArrowLeft, CircleAlert, TriangleAlert } from "lucide-react"; @@ -38,6 +37,7 @@ import type { CreateWorkspaceMode, ExternalAuthPollingState, } from "./CreateWorkspacePage"; +import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWorkspacePermissions } from "./permissions"; From 5b711a385100a4e0437f5fc76da3bcb16851dda0 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Mon, 28 Apr 2025 20:00:39 +0000 Subject: [PATCH 10/10] chore: add circular-deps lint to lint command and CI --- site/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/package.json b/site/package.json index 9f17505110897..8a08e837dc8a5 100644 --- a/site/package.json +++ b/site/package.json @@ -8,14 +8,14 @@ "build": "NODE_ENV=production pnpm vite build", "check": "biome check --error-on-warnings .", "check:fix": "biome check --error-on-warnings --fix .", - "check:circular-deps": "dpdm --no-tree --no-warning -T ./src/App.tsx", "check:all": "pnpm check && pnpm test", "chromatic": "chromatic", "dev": "vite", "format": "biome format --write .", "format:check": "biome format .", - "lint": "pnpm run lint:check && pnpm run lint:types", + "lint": "pnpm run lint:check && pnpm run lint:types && pnpm run lint:circular-deps", "lint:check": " biome lint --error-on-warnings .", + "lint:circular-deps": "dpdm --no-tree --no-warning -T ./src/App.tsx", "lint:fix": " biome lint --error-on-warnings --write .", "lint:types": "tsc -p .", "playwright:install": "playwright install --with-deps chromium",