@@ -98,12 +103,12 @@ function TopBar() {
function LoadingIndicator() {
const n = useSearch({
- from: "/_layout",
+ from: "/_context",
select: (state) => state.n,
});
const filters = useFiltersValue({ includeEphemeral: false });
const { isLoading } = useInfiniteQuery(
- useManager().actorsListQueryOptions({ n, filters }),
+ useDataProvider().actorsListQueryOptions({ n, filters }),
);
if (isLoading) {
return
;
@@ -114,10 +119,10 @@ function LoadingIndicator() {
function List() {
const filters = useFiltersValue({ includeEphemeral: false });
const { actorId, n } = useSearch({
- from: "/_layout",
+ from: "/_context",
});
const { data: actorIds = [] } = useInfiniteQuery(
- useManager().actorsListQueryOptions({ n, filters }),
+ useDataProvider().actorsListQueryOptions({ n, filters }),
);
return (
@@ -135,7 +140,7 @@ function List() {
function ActorIdPrefiller() {
const { n, actorId } = useSearch({
- from: "/_layout",
+ from: "/_context",
select: (state) => ({
n: state.n,
actorId: state.actorId,
@@ -143,7 +148,7 @@ function ActorIdPrefiller() {
});
const filters = useFiltersValue({ includeEphemeral: false });
const { data } = useSuspenseInfiniteQuery(
- useManager().actorsListQueryOptions({
+ useDataProvider().actorsListQueryOptions({
n,
filters,
}),
@@ -164,13 +169,13 @@ function ActorIdPrefiller() {
function Pagination() {
const n = useSearch({
- from: "/_layout",
+ from: "/_context",
select: (state) => state.n,
});
const filters = useFiltersValue({ includeEphemeral: false });
const { hasNextPage, isFetchingNextPage, fetchNextPage, data } =
useSuspenseInfiniteQuery(
- useManager().actorsListPaginationQueryOptions({
+ useDataProvider().actorsListPaginationQueryOptions({
n,
filters,
}),
@@ -190,7 +195,7 @@ function Pagination() {
export function ListSkeleton() {
return (
- {Array(ACTORS_PER_PAGE)
+ {Array(RECORDS_PER_PAGE)
.fill(null)
.map((_, i) => (
@@ -202,18 +207,18 @@ export function ListSkeleton() {
function EmptyState({ count }: { count: number }) {
const navigate = useNavigate();
const names = useSearch({
- from: "/_layout",
+ from: "/_context",
select: (state) => state.n,
});
const { copy, links } = useActorsView();
const { remove, pick } = useActorsFilters();
const { data: availableNamesCount = 0 } = useInfiniteQuery(
- useManager().buildsCountQueryOptions(),
+ useDataProvider().buildsCountQueryOptions(),
);
const filtersCount = useSearch({
- from: "/_layout",
+ from: "/_context",
select: (state) =>
Object.values(pick(state, { includeEphemeral: false })).length,
});
diff --git a/frontend/src/components/actors/actors-sidebar-toggle-button.tsx b/frontend/src/components/actors/actors-sidebar-toggle-button.tsx
deleted file mode 100644
index 24a6a75e2e..0000000000
--- a/frontend/src/components/actors/actors-sidebar-toggle-button.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { faSidebar, Icon } from "@rivet-gg/icons";
-import { Button } from "@/components";
-import { useActorsLayout } from "./actors-layout-context";
-
-export function ActorsSidebarToggleButton() {
- const { setFolded, isFolded } = useActorsLayout();
-
- if (!isFolded) {
- return null;
- }
- return (
-
-
-
- );
-}
diff --git a/frontend/src/components/actors/build-select.tsx b/frontend/src/components/actors/build-select.tsx
index ab53bd2140..c25361e242 100644
--- a/frontend/src/components/actors/build-select.tsx
+++ b/frontend/src/components/actors/build-select.tsx
@@ -1,7 +1,7 @@
import { useInfiniteQuery } from "@tanstack/react-query";
import { useMemo } from "react";
import { Combobox } from "@/components";
-import { useManager } from "./manager-context";
+import { useDataProvider } from "./data-provider";
interface BuildSelectProps {
onValueChange: (value: string) => void;
@@ -9,25 +9,14 @@ interface BuildSelectProps {
}
export function BuildSelect({ onValueChange, value }: BuildSelectProps) {
- const { data = [] } = useInfiniteQuery(useManager().buildsQueryOptions());
+ const { data = [] } = useInfiniteQuery(
+ useDataProvider().buildsQueryOptions(),
+ );
const builds = useMemo(() => {
return data.map((build) => {
return {
- label: (
-
-
-
- {build.tags?.name || build.name}
-
- {build.createdAt ? (
-
- Created: {build.createdAt.toLocaleString()}
-
- ) : null}
-
-
- ),
+ label: build.name,
value: build.name,
build,
};
diff --git a/frontend/src/components/actors/console/actor-console-message.tsx b/frontend/src/components/actors/console/actor-console-message.tsx
index 71acc39cb0..3f875ab3dc 100644
--- a/frontend/src/components/actors/console/actor-console-message.tsx
+++ b/frontend/src/components/actors/console/actor-console-message.tsx
@@ -20,7 +20,7 @@ interface ActorConsoleMessageProps {
| "warn"
| "info"
| "debug";
- timestamp?: Date;
+ timestamp?: string | Date;
className?: string;
children: ReactNode;
}
diff --git a/frontend/src/components/actors/console/actor-console.tsx b/frontend/src/components/actors/console/actor-console.tsx
index 6bdb5bd6a8..02e0c328e2 100644
--- a/frontend/src/components/actors/console/actor-console.tsx
+++ b/frontend/src/components/actors/console/actor-console.tsx
@@ -4,7 +4,7 @@ import { AnimatePresence, motion } from "framer-motion";
import { useState } from "react";
import { Button, cn } from "@/components";
import { useActor } from "../actor-queries-context";
-import { useManager } from "../manager-context";
+import { useDataProvider } from "../data-provider";
import type { ActorId } from "../queries";
import { useActorWorkerStatus } from "../worker/actor-worker-context";
import { ActorWorkerStatus } from "../worker/actor-worker-status";
@@ -19,7 +19,7 @@ export function ActorConsole({ actorId }: ActorConsoleProps) {
const [isOpen, setOpen] = useState(false);
const status = useActorWorkerStatus();
- const managerQueries = useManager();
+ const managerQueries = useDataProvider();
const actorQueries = useActor();
const { data: { destroyedAt, sleepingAt } = {} } = useQuery(
managerQueries.actorWorkerQueryOptions(actorId),
diff --git a/frontend/src/components/actors/create-actor-button.tsx b/frontend/src/components/actors/create-actor-button.tsx
index 253e445483..15c344aaff 100644
--- a/frontend/src/components/actors/create-actor-button.tsx
+++ b/frontend/src/components/actors/create-actor-button.tsx
@@ -3,19 +3,19 @@ import { useInfiniteQuery } from "@tanstack/react-query";
import { useNavigate } from "@tanstack/react-router";
import { Button, type ButtonProps, WithTooltip } from "@/components";
import { useActorsView } from "./actors-view-context-provider";
-import { useManager } from "./manager-context";
+import { useDataProvider } from "./data-provider";
export function CreateActorButton(props: ButtonProps) {
const navigate = useNavigate();
- const manager = useManager();
- const { data } = useInfiniteQuery(useManager().buildsQueryOptions());
+ const provider = useDataProvider();
+ const { data } = useInfiniteQuery(useDataProvider().buildsQueryOptions());
const { copy } = useActorsView();
const canCreate = data && data.length > 0;
- if (!manager.features.canCreateActors) {
+ if (!provider.features.canCreateActors) {
return null;
}
diff --git a/frontend/src/components/actors/current-environment-version-title.tsx b/frontend/src/components/actors/current-environment-version-title.tsx
deleted file mode 100644
index e38d15afec..0000000000
--- a/frontend/src/components/actors/current-environment-version-title.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { useSuspenseQuery } from "@tanstack/react-query";
-import {
- projectEnvironmentQueryOptions,
- projectVersionQueryOptions,
-} from "../queries";
-import { EnvironmentVersionTitle } from "./environment-version-title";
-
-interface CurrentEnvironmentVersionTitleProps {
- environmentId: string;
- projectId: string;
-}
-
-export function CurrentEnvironmentVersionTitle({
- environmentId,
- projectId,
-}: CurrentEnvironmentVersionTitleProps) {
- const {
- data: { namespace: environment },
- } = useSuspenseQuery(
- projectEnvironmentQueryOptions({ projectId, environmentId }),
- );
-
- const { data: version } = useSuspenseQuery(
- projectVersionQueryOptions({
- projectId,
- versionId: environment.versionId,
- }),
- );
-
- return (
-
- );
-}
diff --git a/frontend/src/components/actors/data-provider.tsx b/frontend/src/components/actors/data-provider.tsx
new file mode 100644
index 0000000000..2d35fdf8b0
--- /dev/null
+++ b/frontend/src/components/actors/data-provider.tsx
@@ -0,0 +1,63 @@
+import {
+ type RegisteredRouter,
+ type RouteIds,
+ useRouteContext,
+} from "@tanstack/react-router";
+import { match } from "ts-pattern";
+
+export const useDataProvider = () =>
+ useRouteContext({
+ from: match(__APP_TYPE__)
+ .with("cloud", () => {
+ return "/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace" as const;
+ })
+ .with("engine", () => {
+ return "/_context/_engine/ns/$namespace" as const;
+ })
+ .with("inspector", () => {
+ return "/_context/_inspector" as const;
+ })
+ .exhaustive(),
+ }).dataProvider;
+
+export const useEngineDataProvider = () => {
+ return useRouteContext({
+ from: "/_context/_engine",
+ }).dataProvider;
+};
+
+export const useInspectorDataProvider = () => {
+ return useRouteContext({
+ from: "/_context/_inspector",
+ }).dataProvider;
+};
+
+type OnlyCloudRouteIds = Extract<
+ RouteIds
,
+ `/_context/_cloud/${string}`
+>;
+
+export const useCloudDataProvider = ({
+ from = "/_context/_cloud/orgs/$organization",
+}: {
+ from?: OnlyCloudRouteIds;
+} = {}) => {
+ return useRouteContext({
+ from,
+ }).dataProvider;
+};
+
+export const useEngineCompatDataProvider = () => {
+ return useRouteContext({
+ from: match(__APP_TYPE__)
+ .with("cloud", () => {
+ return "/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace" as const;
+ })
+ .with("engine", () => {
+ return "/_context/_engine/ns/$namespace" as const;
+ })
+ .otherwise(() => {
+ throw new Error("Not in an engine-like context");
+ }),
+ }).dataProvider;
+};
diff --git a/frontend/src/components/actors/database/database-table.tsx b/frontend/src/components/actors/database/database-table.tsx
index bbf4a39efc..5c34cab452 100644
--- a/frontend/src/components/actors/database/database-table.tsx
+++ b/frontend/src/components/actors/database/database-table.tsx
@@ -32,6 +32,14 @@ import {
TableRow,
} from "@/components";
+declare module "@tanstack/react-table" {
+ interface ColumnMeta {
+ type: string;
+ notNull: boolean;
+ default: any;
+ }
+}
+
interface DatabaseTableProps {
columns: any[];
data: any[];
@@ -52,7 +60,6 @@ export function DatabaseTable({
enableRowSelection = true,
enableSorting = true,
- enableCellExpanding = true,
enableColumnResizing = true,
}: DatabaseTableProps) {
const columns = useMemo(() => {
@@ -61,14 +68,12 @@ export function DatabaseTable({
const [rowSelection, setRowSelection] = useState({});
const [sorting, setSorting] = useState([]);
- const [expanded, setExpanded] = useState({});
const table = useTable({
columns,
data,
enableRowSelection,
enableSorting,
- enableCellExpanding,
enableColumnResizing,
getCoreRowModel: getCoreRowModel(),
getExpandedRowModel: getExpandedRowModel(),
@@ -81,7 +86,6 @@ export function DatabaseTable({
state: {
sorting,
rowSelection,
- expanded,
},
});
@@ -220,7 +224,7 @@ export function DatabaseTable({
);
}
-const ch = createColumnHelper();
+const ch = createColumnHelper>();
function createColumns(
columns: Columns,
@@ -269,7 +273,7 @@ function createColumns(
),
})
: null,
- ].filter(Boolean),
+ ].filter((v): v is NonNullable => v !== null),
...columns.map((col) =>
ch.accessor(col.name, {
header: (info) => (
diff --git a/frontend/src/components/actors/dialogs/create-actor-dialog.tsx b/frontend/src/components/actors/dialogs/create-actor-dialog.tsx
index 535b2f97a1..d51af9d41b 100644
--- a/frontend/src/components/actors/dialogs/create-actor-dialog.tsx
+++ b/frontend/src/components/actors/dialogs/create-actor-dialog.tsx
@@ -1,12 +1,12 @@
import { useMutation } from "@tanstack/react-query";
import { useSearch } from "@tanstack/react-router";
+import type { DialogContentProps } from "@/components/hooks";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
-import type { NamespaceNameId } from "@/queries/manager-engine";
import {
DialogDescription,
DialogFooter,
@@ -15,13 +15,12 @@ import {
} from "../../ui/dialog";
import { Flex } from "../../ui/flex";
import { useActorsView } from "../actors-view-context-provider";
+import { useDataProvider } from "../data-provider";
import * as ActorCreateForm from "../form/actor-create-form";
-import type { DialogContentProps } from "../hooks";
-import { useManager } from "../manager-context";
import { CrashPolicy } from "../queries";
interface ContentProps extends DialogContentProps {
- namespace: NamespaceNameId;
+ namespace: string;
}
export default function CreateActorDialog({
@@ -29,10 +28,10 @@ export default function CreateActorDialog({
namespace,
}: ContentProps) {
const { mutateAsync } = useMutation(
- useManager().createActorMutationOptions(),
+ useDataProvider().createActorMutationOptions(),
);
const name = useSearch({
- from: "/_layout",
+ from: "/_context",
select: (state) => state.n?.[0],
});
@@ -45,8 +44,8 @@ export default function CreateActorDialog({
name: values.name,
input: values.input ? JSON.parse(values.input) : undefined,
key: values.key,
- crashPolicy: values.crashPolicy,
- runnerNameSelector: values.runnerNameSelector,
+ crashPolicy: values.crashPolicy || CrashPolicy.Destroy,
+ runnerNameSelector: values.runnerNameSelector || "default",
});
onClose?.();
}}
diff --git a/frontend/src/components/actors/dialogs/go-to-actor-dialog.tsx b/frontend/src/components/actors/dialogs/go-to-actor-dialog.tsx
index 3baf32d185..941aeffb87 100644
--- a/frontend/src/components/actors/dialogs/go-to-actor-dialog.tsx
+++ b/frontend/src/components/actors/dialogs/go-to-actor-dialog.tsx
@@ -1,8 +1,8 @@
+import { DialogContentProps } from "@/components/hooks";
import { Button } from "../../ui/button";
import { DialogFooter, DialogHeader, DialogTitle } from "../../ui/dialog";
import { useActorsView } from "../actors-view-context-provider";
import * as GoToActorForm from "../form/go-to-actor-form";
-import type { DialogContentProps } from "../hooks";
interface ContentProps extends DialogContentProps {
onSubmit?: (actorId: string) => void;
diff --git a/frontend/src/components/actors/dynamic-servers-feature-card.tsx b/frontend/src/components/actors/dynamic-servers-feature-card.tsx
deleted file mode 100644
index a021d59242..0000000000
--- a/frontend/src/components/actors/dynamic-servers-feature-card.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { Link as RouterLink } from "@tanstack/react-router";
-import {
- Card,
- CardContent,
- CardHeader,
- CardTitle,
- Link,
- Text,
-} from "@/components";
-
-export function DynamicServersFeatureCard() {
- return (
-
-
- Legacy Lobbies and Environments
-
-
-
- Dynamic servers and builds are the new way to manage your
- project servers. However, if you're looking for lobbies and
- namespaces, you can switch back to the old interface in the{" "}
-
-
- User Settings
-
-
- .
-
-
-
- );
-}
diff --git a/frontend/src/components/actors/environment-select.tsx b/frontend/src/components/actors/environment-select.tsx
deleted file mode 100644
index 46d5a1d141..0000000000
--- a/frontend/src/components/actors/environment-select.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { faCirclePlus, Icon } from "@rivet-gg/icons";
-import { useSuspenseQuery } from "@tanstack/react-query";
-import { type ComponentProps, useCallback } from "react";
-import {
- Flex,
- Select,
- SelectContent,
- SelectItem,
- SelectSeparator,
- SelectTrigger,
- SelectValue,
-} from "@/components";
-import { projectEnvironmentsQueryOptions } from "@/domains/project/queries";
-
-interface EnvironmentSelectProps extends ComponentProps {
- projectId: string;
- showCreateEnvironment?: boolean;
- onCreateClick?: () => void;
- variant?: ComponentProps["variant"];
-}
-
-export function EnvironmentSelect({
- showCreateEnvironment,
- onCreateClick,
- onValueChange,
- projectId,
- variant,
- ...props
-}: EnvironmentSelectProps) {
- const { data } = useSuspenseQuery(
- projectEnvironmentsQueryOptions(projectId),
- );
-
- const handleValueChange = useCallback(
- (value: string) => {
- if (value === "create") {
- onCreateClick?.();
- return;
- }
- onValueChange?.(value);
- },
- [onCreateClick, onValueChange],
- );
-
- return (
-
- );
-}
diff --git a/frontend/src/components/actors/environment-version-title.tsx b/frontend/src/components/actors/environment-version-title.tsx
deleted file mode 100644
index 81aec17a58..0000000000
--- a/frontend/src/components/actors/environment-version-title.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Badge, Flex } from "@/components";
-
-interface EnvironmentVersionTitleProps {
- environment: string;
- version: string;
-}
-
-export function EnvironmentVersionTitle({
- environment,
- version,
-}: EnvironmentVersionTitleProps) {
- return (
-
- {environment}
- {version}
-
- );
-}
diff --git a/frontend/src/components/actors/form/actor-create-form.tsx b/frontend/src/components/actors/form/actor-create-form.tsx
index 5bc179362a..813de8b46c 100644
--- a/frontend/src/components/actors/form/actor-create-form.tsx
+++ b/frontend/src/components/actors/form/actor-create-form.tsx
@@ -3,10 +3,6 @@ import { useEffect, useRef } from "react";
import { type UseFormReturn, useFormContext } from "react-hook-form";
import z from "zod";
import { CodePreview, Input, Label } from "@/components";
-import {
- type NamespaceNameId,
- runnerNamesQueryOptions,
-} from "@/queries/manager-engine";
import { JsonCode } from "../../code-mirror";
import { createSchemaForm } from "../../lib/create-schema-form";
import {
@@ -43,16 +39,12 @@ export const formSchema = z
key: z.string(),
input: jsonValid.optional(),
// tags: tagsFormSchema.shape.tags,
+
+ region: z.string(),
+ runnerNameSelector: z.string(),
+ crashPolicy: z.nativeEnum(CrashPolicyEnum),
})
- .and(
- __APP_TYPE__ === "engine"
- ? z.object({
- region: z.string(),
- runnerNameSelector: z.string(),
- crashPolicy: z.nativeEnum(CrashPolicyEnum),
- })
- : z.object({}),
- );
+ .partial({ region: true, runnerNameSelector: true, crashPolicy: true });
export type FormValues = z.infer;
export type SubmitHandler = (
@@ -101,7 +93,7 @@ export const CrashPolicy = () => {
@@ -161,11 +153,7 @@ export const JsonInput = () => {
);
};
-export const RunnerNameSelector = ({
- namespace,
-}: {
- namespace: NamespaceNameId;
-}) => {
+export const RunnerNameSelector = ({ namespace }: { namespace: string }) => {
const { control } = useFormContext();
return (
@@ -179,7 +167,7 @@ export const RunnerNameSelector = ({
@@ -224,11 +212,7 @@ export const ActorPreview = () => {
);
};
-export const PrefillRunnerName = ({
- namespace,
-}: {
- namespace: NamespaceNameId;
-}) => {
+export const PrefillRunnerName = ({ namespace }: { namespace: string }) => {
const prefilled = useRef(false);
const { watch } = useFormContext();
diff --git a/frontend/src/components/actors/get-started.tsx b/frontend/src/components/actors/get-started.tsx
deleted file mode 100644
index 9471f354cb..0000000000
--- a/frontend/src/components/actors/get-started.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import { faActors, faFunction, faServer, Icon } from "@rivet-gg/icons";
-import { motion } from "framer-motion";
-import type { ComponentProps } from "react";
-import { DocsSheet } from "../docs-sheet";
-import { cn } from "../lib/utils";
-import { Button } from "../ui/button";
-
-export function ActorsResources() {
- return (
- <>
-
-
-
-
-
- >
- );
-}
-
-const linkVariants = {
- hidden: {
- opacity: 0,
- },
- show: {
- opacity: 1,
- },
-};
-
-interface ExampleLinkProps {
- title: string;
- description?: string;
- icon: ComponentProps["icon"];
- href: string;
- size?: "sm" | "md" | "lg";
-}
-
-function ExampleLink({
- title,
- description,
- icon,
- href,
- size = "lg",
-}: ExampleLinkProps) {
- return (
-
-
-
- );
-}
diff --git a/frontend/src/components/actors/getting-started.tsx b/frontend/src/components/actors/getting-started.tsx
deleted file mode 100644
index 63f60d6afa..0000000000
--- a/frontend/src/components/actors/getting-started.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { faActors, Icon } from "@rivet-gg/icons";
-import { useActorsView } from "./actors-view-context-provider";
-import { ActorsResources } from "./get-started";
-
-export function GettingStarted() {
- const { copy } = useActorsView();
- return (
-
-
-
-
- {copy.gettingStarted.title}
-
-
- {copy.gettingStarted.description}
-
-
-
-
- );
-}
diff --git a/frontend/src/components/actors/go-to-actor-button.tsx b/frontend/src/components/actors/go-to-actor-button.tsx
index 34e7769988..2480455750 100644
--- a/frontend/src/components/actors/go-to-actor-button.tsx
+++ b/frontend/src/components/actors/go-to-actor-button.tsx
@@ -12,6 +12,7 @@ export function GoToActorButton(props: ButtonProps) {
variant="ghost"
onClick={() => {
navigate({
+ to: ".",
search: (prev) => ({ ...prev, modal: "go-to-actor" }),
});
}}
diff --git a/frontend/src/components/actors/group-project-select.tsx b/frontend/src/components/actors/group-project-select.tsx
deleted file mode 100644
index e71869a577..0000000000
--- a/frontend/src/components/actors/group-project-select.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { faCirclePlus, Icon } from "@rivet-gg/icons";
-import { useSuspenseQuery } from "@tanstack/react-query";
-import { type ComponentProps, useCallback } from "react";
-import {
- Flex,
- Select,
- SelectContent,
- SelectItem,
- SelectSeparator,
- SelectTrigger,
- SelectValue,
-} from "@/components";
-import { groupProjectsQueryOptions } from "@/domains/project/queries";
-
-interface GroupProjectSelectProps extends ComponentProps {
- groupId: string;
- showCreateProject?: boolean;
- onCreateClick?: () => void;
- variant?: ComponentProps["variant"];
-}
-
-export function GroupProjectSelect({
- groupId,
- showCreateProject,
- onCreateClick,
- onValueChange,
- variant,
- ...props
-}: GroupProjectSelectProps) {
- const { data } = useSuspenseQuery(groupProjectsQueryOptions(groupId));
-
- const handleValueChange = useCallback(
- (value: string) => {
- if (value === "create") {
- onCreateClick?.();
- return;
- }
- onValueChange?.(value);
- },
- [onCreateClick, onValueChange],
- );
-
- return (
-
- );
-}
diff --git a/frontend/src/components/actors/guard-connectable-inspector.tsx b/frontend/src/components/actors/guard-connectable-inspector.tsx
index 52226eb5a4..4f1100da5a 100644
--- a/frontend/src/components/actors/guard-connectable-inspector.tsx
+++ b/frontend/src/components/actors/guard-connectable-inspector.tsx
@@ -4,10 +4,6 @@ import { useMatch } from "@tanstack/react-router";
import { createContext, type ReactNode, useContext, useMemo } from "react";
import { useInspectorCredentials } from "@/app/credentials-context";
import { createInspectorActorContext } from "@/queries/actor-inspector";
-import {
- type NamespaceNameId,
- runnerByNameQueryOptions,
-} from "@/queries/manager-engine";
import { DiscreteCopyButton } from "../copy-area";
import { getConfig } from "../lib/config";
import { ls } from "../lib/utils";
@@ -15,7 +11,7 @@ import { Button } from "../ui/button";
import { useFiltersValue } from "./actor-filters-context";
import { ActorProvider } from "./actor-queries-context";
import { Info } from "./actor-state-tab";
-import { useManager } from "./manager-context";
+import { useDataProvider, useEngineCompatDataProvider } from "./data-provider";
import type { ActorId } from "./queries";
const InspectorGuardContext = createContext(null);
@@ -35,7 +31,7 @@ export function GuardConnectableInspector({
const {
data: { destroyedAt, sleepingAt, pendingAllocationAt, startedAt } = {},
} = useQuery({
- ...useManager().actorQueryOptions(actorId),
+ ...useDataProvider().actorQueryOptions(actorId),
refetchInterval: 1000,
});
@@ -131,14 +127,14 @@ function ActorInspectorProvider({ children }: { children: ReactNode }) {
function useActorRunner({ actorId }: { actorId: ActorId }) {
const { data: actor } = useSuspenseQuery(
- useManager().actorQueryOptions(actorId),
+ useDataProvider().actorQueryOptions(actorId),
);
const match = useMatch({
from:
__APP_TYPE__ === "engine"
- ? "/_layout/ns/$namespace"
- : "/_layout/orgs/$organization/projects/$project/ns/$namespace/",
+ ? "/_context/_engine/ns/$namespace"
+ : "/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/",
shouldThrow: false,
});
@@ -147,9 +143,9 @@ function useActorRunner({ actorId }: { actorId: ActorId }) {
}
const { data: runner } = useQuery({
- ...runnerByNameQueryOptions({
+ ...useEngineCompatDataProvider().runnerByNameQueryOptions({
runnerName: actor.runner,
- namespace: match.params.namespace as NamespaceNameId,
+ namespace: match.params.namespace,
}),
refetchInterval: 1000,
});
diff --git a/frontend/src/components/actors/hooks/index.ts b/frontend/src/components/actors/hooks/index.ts
deleted file mode 100644
index 14c4d0400f..0000000000
--- a/frontend/src/components/actors/hooks/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./use-dialog";
diff --git a/frontend/src/components/actors/hooks/use-websocket.ts b/frontend/src/components/actors/hooks/use-websocket.ts
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/frontend/src/components/actors/index.ts b/frontend/src/components/actors/index.ts
index f690e14fc4..bdf87a9973 100644
--- a/frontend/src/components/actors/index.ts
+++ b/frontend/src/components/actors/index.ts
@@ -6,13 +6,10 @@ export * from "./actor-status-indicator";
export * from "./actor-status-label";
export * from "./actor-tags";
export * from "./actors-actor-details";
-export * from "./actors-layout";
export * from "./actors-layout-context";
export * from "./actors-list-preview";
export * from "./actors-view-context-provider";
export * from "./console/actor-console-message";
export * from "./console/actor-inspector";
-export * from "./getting-started";
-export * from "./hooks/index";
-export * from "./manager-context";
+export * from "./data-provider";
export * from "./queries";
diff --git a/frontend/src/components/actors/matchmaker-lobby-config-settings-card.tsx b/frontend/src/components/actors/matchmaker-lobby-config-settings-card.tsx
deleted file mode 100644
index 52e564ad1e..0000000000
--- a/frontend/src/components/actors/matchmaker-lobby-config-settings-card.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import { useSuspenseQuery } from "@tanstack/react-query";
-import {
- Card,
- CardContent,
- CardFooter,
- CardHeader,
- CardTitle,
- Flex,
-} from "@/components";
-import * as MatchmakerLobbyConfigForm from "@/domains/project/forms/matchmaker-lobby-config-form";
-import { useMatchmakerLobbyConfigFormHandler } from "../hooks/use-matchmaker-lobby-config-form-handler";
-import { projectEnvironmentQueryOptions } from "../queries";
-
-interface MatchMakerLobbyConfigSettingsCardProps {
- projectId: string;
- environmentId: string;
-}
-
-export function MatchMakerLobbyConfigSettingsCard({
- environmentId,
- projectId,
-}: MatchMakerLobbyConfigSettingsCardProps) {
- const { data } = useSuspenseQuery(
- projectEnvironmentQueryOptions({ projectId, environmentId }),
- );
-
- const handleSubmit = useMatchmakerLobbyConfigFormHandler({
- environmentId,
- projectId,
- });
-
- return (
-
-
-
- Config
-
-
-
-
-
-
-
-
-
- Save
-
-
-
-
- );
-}
diff --git a/frontend/src/components/actors/project-logo-settings-card.tsx b/frontend/src/components/actors/project-logo-settings-card.tsx
deleted file mode 100644
index a2a6185e39..0000000000
--- a/frontend/src/components/actors/project-logo-settings-card.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import {
- Card,
- CardContent,
- CardFooter,
- CardHeader,
- CardTitle,
-} from "@/components";
-import * as GroupImageForm from "@/domains/project/forms/project-logo-form";
-import { useProjectLogoUploadMutation } from "../queries";
-
-interface ProjectLogoSettingsCardProps {
- projectId: string;
-}
-
-export function ProjectLogoSettingsCard({
- projectId,
-}: ProjectLogoSettingsCardProps) {
- const { mutateAsync } = useProjectLogoUploadMutation(projectId);
- return (
- {
- try {
- await mutateAsync({ file: values.logo });
- } catch {
- form.setError("logo", {
- type: "manual",
- message: "An error occurred while uploading the image",
- });
- }
- }}
- defaultValues={{ logo: undefined }}
- >
-
-
- Project Logo
-
-
-
-
-
- Save
-
-
-
- );
-}
diff --git a/frontend/src/components/actors/project-select.tsx b/frontend/src/components/actors/project-select.tsx
deleted file mode 100644
index 0560643252..0000000000
--- a/frontend/src/components/actors/project-select.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import { faCirclePlus, Icon } from "@rivet-gg/icons";
-import { useSuspenseQuery } from "@tanstack/react-query";
-import { type ComponentProps, Fragment, useCallback } from "react";
-import {
- Flex,
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectLabel,
- SelectSeparator,
- SelectTrigger,
- SelectValue,
-} from "@/components";
-import { GroupAvatar } from "@/domains/group/components/group-avatar";
-import { projectsByGroupQueryOptions } from "@/domains/project/queries";
-
-interface ProjectSelectProps extends ComponentProps {
- showCreateProject?: boolean;
- onCreateClick?: () => void;
-}
-
-export function ProjectSelect({
- showCreateProject,
- onCreateClick,
- onValueChange,
- ...props
-}: ProjectSelectProps) {
- const { data } = useSuspenseQuery(projectsByGroupQueryOptions());
-
- const handleValueChange = useCallback(
- (value: string) => {
- if (value === "create") {
- onCreateClick?.();
- return;
- }
- onValueChange?.(value);
- },
- [onCreateClick, onValueChange],
- );
-
- return (
-
- );
-}
diff --git a/frontend/src/components/actors/project-table-actions.tsx b/frontend/src/components/actors/project-table-actions.tsx
deleted file mode 100644
index 064f2f5e0d..0000000000
--- a/frontend/src/components/actors/project-table-actions.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { faEllipsisH, Icon } from "@rivet-gg/icons";
-import {
- Button,
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@/components";
-
-export function ProjectTableActions() {
- return (
-
-
-
-
-
- Manage
-
-
- );
-}
diff --git a/frontend/src/components/actors/project-tile.tsx b/frontend/src/components/actors/project-tile.tsx
deleted file mode 100644
index 835d613b2b..0000000000
--- a/frontend/src/components/actors/project-tile.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { Rivet } from "@rivet-gg/api";
-import { AssetImage, Flex, Text } from "@/components";
-import { BillingPlanBadge } from "./billing/billing-plan-badge";
-
-interface ProjectTileProps
- extends Pick<
- Rivet.game.GameSummary,
- "gameId" | "displayName" | "logoUrl"
- > {}
-
-export function ProjectTile({
- gameId: projectId,
- displayName,
- logoUrl,
-}: ProjectTileProps) {
- return (
-
-
- {displayName}
-
-
- );
-}
diff --git a/frontend/src/components/actors/queries/actor.ts b/frontend/src/components/actors/queries/actor.ts
index ae76eb0340..cc5c759a6a 100644
--- a/frontend/src/components/actors/queries/actor.ts
+++ b/frontend/src/components/actors/queries/actor.ts
@@ -30,7 +30,6 @@ export const useActorStatePatchMutation = (
const queryClient = useQueryClient();
const queries = useActor();
return useMutation({
- // biome-ignore lint/suspicious/noExplicitAny: its really any
mutationFn: async (data: any) => {
const client = queries.createActorInspector(actorId);
@@ -45,7 +44,6 @@ export const useActorStatePatchMutation = (
if (!oldState || !isPatchable(data)) {
response = await client.state.$patch({
// its okay, we know the type
- // @ts-expect-error
json: { replace: data },
});
} else {
@@ -65,7 +63,7 @@ export const useActorStatePatchMutation = (
onSuccess: (data) => {
queryClient.setQueryData(
queries.actorStateQueryOptions(actorId).queryKey,
- data,
+ () => ({ enabled: true, state: data }),
);
},
...options,
diff --git a/frontend/src/components/actors/queries/index.ts b/frontend/src/components/actors/queries/index.ts
index ca557fc41e..693c8993a0 100644
--- a/frontend/src/components/actors/queries/index.ts
+++ b/frontend/src/components/actors/queries/index.ts
@@ -86,13 +86,6 @@ export type Region = {
name: string;
};
-export type Namespace = {
- id: string;
- name: string;
- displayName: string;
- createdAt: string;
-};
-
export * from "./actor";
export type ActorStatus =
diff --git a/frontend/src/components/actors/region-select.tsx b/frontend/src/components/actors/region-select.tsx
index cfc4ade905..4431e260ca 100644
--- a/frontend/src/components/actors/region-select.tsx
+++ b/frontend/src/components/actors/region-select.tsx
@@ -1,7 +1,7 @@
import { useInfiniteQuery } from "@tanstack/react-query";
import { Combobox } from "@/components";
import { ActorRegion } from "./actor-region";
-import { useManager } from "./manager-context";
+import { useDataProvider } from "./data-provider";
interface RegionSelectProps {
onValueChange: (value: string) => void;
@@ -14,7 +14,7 @@ export function RegionSelect({ onValueChange, value }: RegionSelectProps) {
fetchNextPage,
isLoading,
isFetchingNextPage,
- } = useInfiniteQuery(useManager().regionsQueryOptions());
+ } = useInfiniteQuery(useDataProvider().regionsQueryOptions());
const regions = [
{
diff --git a/frontend/src/components/actors/runner-select.tsx b/frontend/src/components/actors/runner-select.tsx
index c8f8d0908d..d06fda989a 100644
--- a/frontend/src/components/actors/runner-select.tsx
+++ b/frontend/src/components/actors/runner-select.tsx
@@ -1,15 +1,12 @@
import { useInfiniteQuery } from "@tanstack/react-query";
import { useMemo, useState } from "react";
import { Combobox } from "@/components";
-import {
- type NamespaceNameId,
- runnerNamesQueryOptions,
-} from "@/queries/manager-engine";
+import { useEngineCompatDataProvider } from "./data-provider";
interface RunnerSelectProps {
onValueChange: (value: string) => void;
value: string;
- namespace: NamespaceNameId;
+ namespace: string;
}
export function RunnerSelect({
@@ -23,7 +20,9 @@ export function RunnerSelect({
fetchNextPage,
isLoading,
isFetchingNextPage,
- } = useInfiniteQuery(runnerNamesQueryOptions({ namespace }));
+ } = useInfiniteQuery(
+ useEngineCompatDataProvider().runnerNamesQueryOptions({ namespace }),
+ );
const [newRunner, setNewRunner] = useState(null);
diff --git a/frontend/src/components/actors/worker/actor-worker-context.tsx b/frontend/src/components/actors/worker/actor-worker-context.tsx
index 6a3038e940..a5a589f4da 100644
--- a/frontend/src/components/actors/worker/actor-worker-context.tsx
+++ b/frontend/src/components/actors/worker/actor-worker-context.tsx
@@ -11,7 +11,7 @@ import {
import { getConfig } from "@/components/lib/config";
import { assertNonNullable, ls } from "../../lib/utils";
import { useActor } from "../actor-queries-context";
-import { useManager } from "../manager-context";
+import { useDataProvider } from "../data-provider";
import { ActorFeature, type ActorId } from "../queries";
import { ActorWorkerContainer } from "./actor-worker-container";
@@ -42,7 +42,7 @@ export const ActorWorkerContextProvider = ({
startedAt,
sleepingAt,
} = {},
- } = useQuery(useManager().actorWorkerQueryOptions(actorId));
+ } = useQuery(useDataProvider().actorWorkerQueryOptions(actorId));
const enabled =
(features?.includes(ActorFeature.Console) &&
!destroyedAt &&
diff --git a/frontend/src/components/code-mirror/index.tsx b/frontend/src/components/code-mirror/index.tsx
index bdadd2bf68..a995fd6330 100644
--- a/frontend/src/components/code-mirror/index.tsx
+++ b/frontend/src/components/code-mirror/index.tsx
@@ -37,7 +37,7 @@ export const JsonCode = forwardRef(
const value = state.doc.toString();
if (value.trim() === "") return [];
- return diagnostics;
+ return [...diagnostics];
},
}),
...extensions,
diff --git a/frontend/src/components/code-preview/code-preview.tsx b/frontend/src/components/code-preview/code-preview.tsx
index 5cb00c2f29..bba87a961b 100644
--- a/frontend/src/components/code-preview/code-preview.tsx
+++ b/frontend/src/components/code-preview/code-preview.tsx
@@ -3,6 +3,7 @@ import {
createHighlighterCore,
createOnigurumaEngine,
type HighlighterCore,
+ type ThemeInput,
} from "shiki";
import { Skeleton } from "../ui/skeleton";
import theme from "./theme.json";
@@ -21,7 +22,7 @@ export function CodePreview({ code, language }: CodePreviewProps) {
async function createHighlighter() {
highlighter.current ??= await createHighlighterCore({
- themes: [theme],
+ themes: [theme as ThemeInput],
langs: [import("@shikijs/langs/typescript")],
engine: createOnigurumaEngine(import("shiki/wasm")),
});
diff --git a/frontend/src/components/dialogs/feedback-dialog.tsx b/frontend/src/components/dialogs/feedback-dialog.tsx
index 20197b36d0..a9946ffccf 100644
--- a/frontend/src/components/dialogs/feedback-dialog.tsx
+++ b/frontend/src/components/dialogs/feedback-dialog.tsx
@@ -3,7 +3,7 @@ import { faDiscord, Icon } from "@rivet-gg/icons";
import { usePostHog } from "posthog-js/react";
import { useState } from "react";
import * as FeedbackForm from "../forms/feedback-form";
-import type { DialogContentProps } from "../hooks/use-dialog";
+import type { DialogContentProps } from "../hooks";
import { FEEDBACK_FORM_ID } from "../lib/constants";
import { Button } from "../ui/button";
import { DialogFooter, DialogHeader, DialogTitle } from "../ui/dialog";
diff --git a/frontend/src/components/hooks/index.ts b/frontend/src/components/hooks/index.ts
index b4641096d6..56c9ff0c31 100644
--- a/frontend/src/components/hooks/index.ts
+++ b/frontend/src/components/hooks/index.ts
@@ -1 +1,3 @@
+export * as Frame from "./isomorphic-frame";
export * from "./use-breakpoint";
+export * from "./use-dialog";
diff --git a/frontend/src/components/hooks/isomorphic-frame.tsx b/frontend/src/components/hooks/isomorphic-frame.tsx
new file mode 100644
index 0000000000..890fb71e98
--- /dev/null
+++ b/frontend/src/components/hooks/isomorphic-frame.tsx
@@ -0,0 +1,37 @@
+import { createContext, useContext } from "react";
+import {
+ CardContent,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+ DialogContent,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components";
+
+export const IsInModalContext = createContext(false);
+
+export const Header = (props: React.ComponentProps) => {
+ const isInModal = useContext(IsInModalContext);
+ return isInModal ? : ;
+};
+
+export const Title = (props: React.ComponentProps) => {
+ const isInModal = useContext(IsInModalContext);
+ return isInModal ? : ;
+};
+
+export const Content = (props: React.HTMLAttributes) => {
+ const isInModal = useContext(IsInModalContext);
+ return isInModal ? (
+
+ ) : (
+
+ );
+};
+
+export const Footer = (props: React.ComponentProps) => {
+ const isInModal = useContext(IsInModalContext);
+ return isInModal ? : ;
+};
diff --git a/frontend/src/components/actors/hooks/use-dialog.tsx b/frontend/src/components/hooks/use-dialog.tsx
similarity index 85%
rename from frontend/src/components/actors/hooks/use-dialog.tsx
rename to frontend/src/components/hooks/use-dialog.tsx
index 7c6cd19a0a..e2d5267d58 100644
--- a/frontend/src/components/actors/hooks/use-dialog.tsx
+++ b/frontend/src/components/hooks/use-dialog.tsx
@@ -15,7 +15,8 @@ import {
DialogContent,
type DialogProps,
DialogTitle,
-} from "../../ui/dialog";
+} from "../ui/dialog";
+import { IsInModalContext } from "./isomorphic-frame";
export interface DialogContentProps {
onClose?: () => void;
@@ -27,7 +28,7 @@ interface DialogConfig {
export const createDialogHook = <
// biome-ignore lint/suspicious/noExplicitAny: we don't know the type of the component, so we use any
- Component extends Promise<{ default: ComponentType }>,
+ Component extends () => Promise<{ default: ComponentType }>,
>(
component: Component,
opts: DialogConfig = {},
@@ -35,11 +36,11 @@ export const createDialogHook = <
const DialogImpl = ({
dialogProps,
...props
- }: ComponentProps["default"]> & {
+ }: ComponentProps>["default"]> & {
dialogProps?: DialogProps;
}) => {
// biome-ignore lint/correctness/useExhaustiveDependencies: component here is a static value, won't change over time
- const Content = useMemo(() => lazy(() => component), []);
+ const Content = useMemo(() => lazy(component), []);
return (
),
@@ -194,9 +199,13 @@ export const createDataDialogHook = <
export function useDialog() {}
-useDialog.GoToActor = createDialogHook(import("../dialogs/go-to-actor-dialog"));
+useDialog.GoToActor = createDialogHook(
+ () => import("../actors/dialogs/go-to-actor-dialog"),
+);
-useDialog.Feedback = createDialogHook(import("../../dialogs/feedback-dialog"));
+useDialog.Feedback = createDialogHook(
+ () => import("../dialogs/feedback-dialog"),
+);
useDialog.CreateActor = createDialogHook(
- import("../dialogs/create-actor-dialog"),
+ () => import("../actors/dialogs/create-actor-dialog"),
);
diff --git a/frontend/src/components/json/index.tsx b/frontend/src/components/json/index.tsx
index 8e2f4491d4..0599f7a2ef 100644
--- a/frontend/src/components/json/index.tsx
+++ b/frontend/src/components/json/index.tsx
@@ -434,7 +434,7 @@ function ObjectValue({
{key}:
{" "}
(
diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx
index fe8fd4b677..17736a8daa 100644
--- a/frontend/src/components/ui/button.tsx
+++ b/frontend/src/components/ui/button.tsx
@@ -30,7 +30,7 @@ const buttonVariants = cva(
size: {
default: "h-10 px-4 py-2 gap-1.5 [&_svg]:size-[1em]",
xs: "h-5 rounded-md px-2 text-xs gap-0.5 [&_svg]:size-2",
- sm: "h-7 rounded-md px-2 text-xs [&_svg]:size-3 gap-1.5",
+ sm: "h-7 rounded-md px-2 text-sm [&_svg]:size-3.5 gap-1.5",
lg: "h-11 rounded-md px-8 gap-2 [&_svg]:size-[1em]",
icon: "h-10 w-10 gap-1.5 [&_svg]:size-[1em]",
"icon-sm": "h-7 w-7 text-xs [&_svg]:size-3 gap-1.5",
diff --git a/frontend/src/components/ui/combobox.tsx b/frontend/src/components/ui/combobox.tsx
index 345d0a759c..f6ca7e3c56 100644
--- a/frontend/src/components/ui/combobox.tsx
+++ b/frontend/src/components/ui/combobox.tsx
@@ -64,7 +64,6 @@ export const Combobox =
diff --git a/frontend/src/components/ui/select.tsx b/frontend/src/components/ui/select.tsx
index c6e28ef74a..6606bac576 100644
--- a/frontend/src/components/ui/select.tsx
+++ b/frontend/src/components/ui/select.tsx
@@ -5,6 +5,7 @@ import {
faCheck,
faChevronDown,
faChevronUp,
+ // @ts-expect-error
faSelect,
Icon,
} from "@rivet-gg/icons";
diff --git a/frontend/src/lib/env.ts b/frontend/src/lib/env.ts
index 89dc93e950..1fc0c61630 100644
--- a/frontend/src/lib/env.ts
+++ b/frontend/src/lib/env.ts
@@ -7,3 +7,9 @@ export const cloudEnvSchema = z.object({
});
export const cloudEnv = () => cloudEnvSchema.parse(import.meta.env);
+
+export const engineEnvSchema = z.object({
+ VITE_APP_API_URL: z.string().url(),
+});
+
+export const engineEnv = () => engineEnvSchema.parse(import.meta.env);
diff --git a/frontend/src/queries/manager-cloud.ts b/frontend/src/queries/manager-cloud.ts
deleted file mode 100644
index 047da7fb03..0000000000
--- a/frontend/src/queries/manager-cloud.ts
+++ /dev/null
@@ -1,498 +0,0 @@
-import {
- type Rivet as CloudRivet,
- RivetClient as CloudRivetClient,
-} from "@rivet-gg/cloud";
-import { ActorFeature } from "@rivetkit/core/inspector";
-import { type Rivet, RivetClient } from "@rivetkit/engine-api-full";
-import {
- infiniteQueryOptions,
- queryOptions,
- skipToken,
-} from "@tanstack/react-query";
-import z from "zod";
-import { getConfig } from "@/components";
-import type {
- Actor,
- ActorId,
- CrashPolicy,
- ManagerContext,
-} from "@/components/actors";
-import {
- ACTORS_PER_PAGE,
- ActorQueryOptionsSchema,
- createDefaultManagerContext,
-} from "@/components/actors/manager-context";
-import { clerk } from "@/lib/auth";
-import { cloudEnv } from "@/lib/env";
-import { queryClient } from "./global";
-
-const client = new RivetClient({
- baseUrl: () => getConfig().apiUrl,
- environment: "",
-});
-
-const cloudClient = new CloudRivetClient({
- baseUrl: () => cloudEnv().VITE_APP_CLOUD_API_URL,
- environment: "",
- token: async () => {
- return (await clerk.session?.getToken()) || "";
- },
-});
-
-export { cloudClient as managerCloudClient };
-
-export const createCloudManagerContext = ({
- namespace,
- project,
-}: {
- namespace: string;
- project: string;
-}) => {
- const def = createDefaultManagerContext();
-
- const namespacesQueryOptions = (project: string) => {
- return infiniteQueryOptions({
- queryKey: [project, "namespaces"],
- initialPageParam: undefined as string | undefined,
- queryFn: async ({ pageParam, signal: abortSignal }) => {
- const data = await cloudClient.namespaces.list(
- project,
- {
- limit: ACTORS_PER_PAGE,
- cursor: pageParam ?? undefined,
- },
- { abortSignal },
- );
- return {
- pagination: data.pagination,
- namespaces: data.namespaces.map((ns) => ({
- id: ns.id,
- name: ns.name,
- displayName: ns.displayName,
- createdAt: ns.createdAt,
- })),
- };
- },
- getNextPageParam: (lastPage) => {
- if (lastPage.namespaces.length < ACTORS_PER_PAGE) {
- return undefined;
- }
- return lastPage.pagination.cursor;
- },
- select: (data) => data.pages.flatMap((page) => page.namespaces),
- });
- };
-
- return {
- ...def,
- features: {
- canCreateActors: true,
- canDeleteActors: true,
- },
- managerStatusQueryOptions() {
- return queryOptions({
- ...def.managerStatusQueryOptions(),
- enabled: true,
- queryFn: async () => {
- return true;
- },
- });
- },
- regionsQueryOptions() {
- return infiniteQueryOptions({
- ...def.regionsQueryOptions(),
- enabled: true,
- queryFn: async () => {
- const data = await client.datacenters.list();
- return {
- regions: data.datacenters.map((dc) => ({
- id: dc.name,
- name: dc.name,
- })),
- pagination: data.pagination,
- };
- },
- });
- },
- regionQueryOptions(regionId: string) {
- return queryOptions({
- ...def.regionQueryOptions(regionId),
- queryKey: ["region", regionId],
- queryFn: async ({ client }) => {
- const regions = await client.ensureInfiniteQueryData(
- this.regionsQueryOptions(),
- );
-
- for (const page of regions.pages) {
- for (const region of page.regions) {
- if (region.id === regionId) {
- return region;
- }
- }
- }
-
- throw new Error(`Region not found: ${regionId}`);
- },
- });
- },
- actorQueryOptions(actorId) {
- return queryOptions({
- ...def.actorQueryOptions(actorId),
- queryKey: [namespace, "actor", actorId],
- enabled: true,
- queryFn: async ({ signal: abortSignal }) => {
- const data = await client.actorsGet(
- actorId,
- { namespace },
- { abortSignal },
- );
-
- return transformActor(data.actor);
- },
- });
- },
- actorsQueryOptions(opts) {
- return infiniteQueryOptions({
- ...def.actorsQueryOptions(opts),
- queryKey: [namespace, "actors", opts],
- enabled: true,
- initialPageParam: undefined,
- queryFn: async ({
- signal: abortSignal,
- pageParam,
- queryKey: [, , _opts],
- }) => {
- const { success, data: opts } =
- ActorQueryOptionsSchema.safeParse(_opts || {});
-
- if (
- (opts?.n?.length === 0 || !opts?.n) &&
- (opts?.filters?.id?.value?.length === 0 ||
- !opts?.filters?.id?.value ||
- opts?.filters.key?.value?.length === 0 ||
- !opts?.filters.key?.value)
- ) {
- // If there are no names specified, we can return an empty result
- return {
- actors: [],
- pagination: {
- cursor: undefined,
- },
- };
- }
-
- const data = await client.actorsList(
- {
- namespace,
- cursor: pageParam ?? undefined,
- actorIds: opts?.filters?.id?.value?.join(","),
- key: opts?.filters?.key?.value?.join(","),
- includeDestroyed:
- success &&
- (opts?.filters?.showDestroyed?.value.includes(
- "true",
- ) ||
- opts?.filters?.showDestroyed?.value.includes(
- "1",
- )),
- limit: ACTORS_PER_PAGE,
- name: opts?.filters?.id?.value
- ? undefined
- : opts?.n?.join(","),
- },
- { abortSignal },
- );
-
- return {
- ...data,
- actors: data.actors.map((actor) =>
- transformActor(actor),
- ),
- };
- },
- getNextPageParam: (lastPage) => {
- if (lastPage.actors.length < ACTORS_PER_PAGE) {
- return undefined;
- }
- return lastPage.pagination.cursor;
- },
- });
- },
- buildsQueryOptions() {
- return infiniteQueryOptions({
- ...def.buildsQueryOptions(),
- queryKey: [namespace, "builds"],
- enabled: true,
- queryFn: async ({ signal: abortSignal, pageParam }) => {
- const data = await client.actorsListNames(
- {
- namespace,
- cursor: pageParam ?? undefined,
- limit: ACTORS_PER_PAGE,
- },
- { abortSignal },
- );
-
- return {
- pagination: data.pagination,
- builds: Object.keys(data.names)
- .sort()
- .map((build) => ({
- id: build,
- name: build,
- })),
- };
- },
- getNextPageParam: (lastPage) => {
- if (lastPage.builds.length < ACTORS_PER_PAGE) {
- return undefined;
- }
- return lastPage.pagination.cursor;
- },
- });
- },
- createActorMutationOptions() {
- return {
- ...def.createActorMutationOptions(),
- mutationKey: [namespace, "actors"],
- mutationFn: async (data) => {
- const response = await client.actorsCreate({
- namespace,
- name: data.name,
- key: data.key,
- crashPolicy: data.crashPolicy,
- runnerNameSelector: data.runnerNameSelector,
- input: JSON.stringify(data.input),
- });
-
- return response.actor.actorId;
- },
- onSuccess: () => {},
- };
- },
- actorDestroyMutationOptions(actorId) {
- return {
- ...def.actorDestroyMutationOptions(actorId),
- mutationFn: async () => {
- await client.actorsDelete(actorId);
- },
- };
- },
- namespacesQueryOptions() {
- return namespacesQueryOptions(project);
- },
- projectNamespacesQueryOptions(projectId) {
- return namespacesQueryOptions(projectId);
- },
- createNamespaceMutationOptions(opts) {
- return {
- ...opts,
- mutationKey: [project, "namespaces"],
- mutationFn: async (data) => {
- return await cloudClient.namespaces.create(project, data);
- },
- };
- },
- } satisfies ManagerContext;
-};
-
-export const NamespaceNameId = z.string().brand();
-export type NamespaceNameId = z.infer
;
-
-export const projectsQueryOptions = (opts: { organization: string }) => {
- return infiniteQueryOptions({
- queryKey: [opts, "projects"],
- initialPageParam: undefined as string | undefined,
- queryFn: async ({ signal: abortSignal, pageParam }) => {
- const data = await cloudClient.projects.list(
- {
- org: opts.organization,
- cursor: pageParam ?? undefined,
- limit: ACTORS_PER_PAGE,
- },
- {
- abortSignal,
- },
- );
- return data;
- },
- getNextPageParam: (lastPage) => {
- if (lastPage.projects.length < ACTORS_PER_PAGE) {
- return undefined;
- }
- return lastPage.pagination.cursor;
- },
- select: (data) => data.pages.flatMap((page) => page.projects),
- });
-};
-
-export const projectQueryOptions = (opts: { project: string }) => {
- return queryOptions({
- queryKey: ["project", opts.project],
- enabled: !!opts.project,
- queryFn: async ({ signal: abortSignal }) => {
- const data = await cloudClient.projects.get(opts.project, {
- abortSignal,
- });
- return data;
- },
- });
-};
-
-export const organizationQueryOptions = (opts: { org: string }) => {
- return queryOptions({
- queryKey: ["organization", opts.org],
- queryFn: async () => {
- return clerk.getOrganization(opts.org);
- },
- });
-};
-
-export const runnersQueryOptions = (opts: { namespace: NamespaceNameId }) => {
- return infiniteQueryOptions({
- queryKey: [opts.namespace, "runners"],
- initialPageParam: undefined as string | undefined,
- queryFn: async ({ pageParam, signal: abortSignal }) => {
- const data = await client.runners.list(
- {
- namespace: opts.namespace,
- cursor: pageParam ?? undefined,
- limit: ACTORS_PER_PAGE,
- },
- { abortSignal },
- );
- return data;
- },
- getNextPageParam: (lastPage) => {
- if (lastPage.runners.length < ACTORS_PER_PAGE) {
- return undefined;
- }
- return lastPage.pagination.cursor;
- },
- select: (data) => data.pages.flatMap((page) => page.runners),
- });
-};
-
-export const runnerQueryOptions = (opts: {
- namespace: NamespaceNameId;
- runnerId: string;
-}) => {
- return queryOptions({
- queryKey: [opts.namespace, "runner", opts.runnerId],
- enabled: !!opts.runnerId,
- queryFn: async ({ signal: abortSignal }) => {
- const data = await client.runners.get(
- opts.runnerId,
- { namespace: opts.namespace },
- {
- abortSignal,
- },
- );
- return data.runner;
- },
- });
-};
-
-export const runnerNamesQueryOptions = (opts: {
- namespace: NamespaceNameId;
-}) => {
- return infiniteQueryOptions({
- queryKey: [opts.namespace, "runner", "names"],
- initialPageParam: undefined as string | undefined,
- queryFn: async ({ signal: abortSignal, pageParam }) => {
- const data = await client.runners.listNames(
- {
- namespace: opts.namespace,
- cursor: pageParam ?? undefined,
- limit: ACTORS_PER_PAGE,
- },
- {
- abortSignal,
- },
- );
- return data;
- },
- getNextPageParam: (lastPage) => {
- if (lastPage.names.length < ACTORS_PER_PAGE) {
- return undefined;
- }
- return lastPage.pagination.cursor;
- },
- select: (data) => data.pages.flatMap((page) => page.names),
- });
-};
-
-export const namespaceQueryOptions = ({
- project,
- namespace,
-}: {
- project: string;
- namespace: string;
-}) => {
- return queryOptions({
- queryKey: [project, "namespace", namespace],
- enabled: !!namespace,
- queryFn: namespace
- ? async ({ signal: abortSignal }) => {
- const data = await cloudClient.namespaces.get(
- project,
- namespace,
- {
- abortSignal,
- },
- );
- return data;
- }
- : skipToken,
- });
-};
-
-function transformActor(a: Rivet.Actor): Actor {
- return {
- id: a.actorId as ActorId,
- name: a.name,
- key: a.key ? a.key : undefined,
- connectableAt: a.connectableTs
- ? new Date(a.connectableTs).toISOString()
- : undefined,
- region: a.datacenter,
- createdAt: new Date(a.createTs).toISOString(),
- startedAt: a.startTs ? new Date(a.startTs).toISOString() : undefined,
- destroyedAt: a.destroyTs
- ? new Date(a.destroyTs).toISOString()
- : undefined,
- sleepingAt: a.sleepTs ? new Date(a.sleepTs).toISOString() : undefined,
- pendingAllocationAt: a.pendingAllocationTs
- ? new Date(a.pendingAllocationTs).toISOString()
- : undefined,
- crashPolicy: a.crashPolicy as CrashPolicy,
- runner: a.runnerNameSelector,
- features: [
- ActorFeature.Config,
- ActorFeature.Connections,
- ActorFeature.State,
- ActorFeature.Console,
- ActorFeature.Database,
- ActorFeature.EventsMonitoring,
- ],
- };
-}
-
-export function createProjectMutationOptions({
- onSuccess,
-}: {
- onSuccess?: (data: CloudRivet.Project) => void;
-} = {}) {
- return {
- mutationKey: ["projects"],
- mutationFn: async (data: { displayName: string; nameId: string }) => {
- const response = await cloudClient.projects.create({
- displayName: data.displayName,
- name: data.nameId,
- });
-
- return response;
- },
- onSuccess,
- };
-}
diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts
index 00a2f83986..e870324744 100644
--- a/frontend/src/routeTree.gen.ts
+++ b/frontend/src/routeTree.gen.ts
@@ -9,262 +9,450 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
-import { Route as LayoutRouteImport } from './routes/_layout'
-import { Route as LayoutIndexRouteImport } from './routes/_layout/index'
-import { Route as LayoutNamespacesRouteImport } from './routes/_layout/namespaces'
-import { Route as LayoutNsNamespaceRouteImport } from './routes/_layout/ns.$namespace'
-import { Route as LayoutOrgsOrganizationIndexRouteImport } from './routes/_layout/orgs.$organization/index'
-import { Route as LayoutNsNamespaceIndexRouteImport } from './routes/_layout/ns.$namespace/index'
-import { Route as LayoutNsNamespaceRunnersRouteImport } from './routes/_layout/ns.$namespace/runners'
-import { Route as LayoutOrgsOrganizationProjectsProjectIndexRouteImport } from './routes/_layout/orgs.$organization/projects.$project/index'
-import { Route as LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRouteImport } from './routes/_layout/orgs.$organization/projects.$project/ns.$namespace/index'
-import { Route as LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRouteImport } from './routes/_layout/orgs.$organization/projects.$project/ns.$namespace/connect'
-
-const LayoutRoute = LayoutRouteImport.update({
- id: '/_layout',
+import { Route as ContextRouteImport } from './routes/_context'
+import { Route as ContextIndexRouteImport } from './routes/_context/index'
+import { Route as ContextInspectorRouteImport } from './routes/_context/_inspector'
+import { Route as ContextEngineRouteImport } from './routes/_context/_engine'
+import { Route as ContextCloudRouteImport } from './routes/_context/_cloud'
+import { Route as ContextInspectorInspectRouteImport } from './routes/_context/_inspector/inspect'
+import { Route as ContextEngineNsNamespaceRouteImport } from './routes/_context/_engine/ns.$namespace'
+import { Route as ContextCloudOrgsOrganizationRouteImport } from './routes/_context/_cloud/orgs.$organization'
+import { Route as ContextEngineNsNamespaceIndexRouteImport } from './routes/_context/_engine/ns.$namespace/index'
+import { Route as ContextCloudOrgsOrganizationIndexRouteImport } from './routes/_context/_cloud/orgs.$organization/index'
+import { Route as ContextEngineNsNamespaceRunnersRouteImport } from './routes/_context/_engine/ns.$namespace/runners'
+import { Route as ContextCloudOrgsOrganizationProjectsProjectRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project'
+import { Route as ContextCloudOrgsOrganizationProjectsProjectIndexRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/index'
+import { Route as ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace'
+import { Route as ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/index'
+import { Route as ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/connect'
+
+const ContextRoute = ContextRouteImport.update({
+ id: '/_context',
getParentRoute: () => rootRouteImport,
} as any)
-const LayoutIndexRoute = LayoutIndexRouteImport.update({
+const ContextIndexRoute = ContextIndexRouteImport.update({
id: '/',
path: '/',
- getParentRoute: () => LayoutRoute,
+ getParentRoute: () => ContextRoute,
} as any)
-const LayoutNamespacesRoute = LayoutNamespacesRouteImport.update({
- id: '/namespaces',
- path: '/namespaces',
- getParentRoute: () => LayoutRoute,
+const ContextInspectorRoute = ContextInspectorRouteImport.update({
+ id: '/_inspector',
+ getParentRoute: () => ContextRoute,
} as any)
-const LayoutNsNamespaceRoute = LayoutNsNamespaceRouteImport.update({
- id: '/ns/$namespace',
- path: '/ns/$namespace',
- getParentRoute: () => LayoutRoute,
+const ContextEngineRoute = ContextEngineRouteImport.update({
+ id: '/_engine',
+ getParentRoute: () => ContextRoute,
} as any)
-const LayoutOrgsOrganizationIndexRoute =
- LayoutOrgsOrganizationIndexRouteImport.update({
- id: '/orgs/$organization/',
- path: '/orgs/$organization/',
- getParentRoute: () => LayoutRoute,
- } as any)
-const LayoutNsNamespaceIndexRoute = LayoutNsNamespaceIndexRouteImport.update({
- id: '/',
- path: '/',
- getParentRoute: () => LayoutNsNamespaceRoute,
+const ContextCloudRoute = ContextCloudRouteImport.update({
+ id: '/_cloud',
+ getParentRoute: () => ContextRoute,
} as any)
-const LayoutNsNamespaceRunnersRoute =
- LayoutNsNamespaceRunnersRouteImport.update({
+const ContextInspectorInspectRoute = ContextInspectorInspectRouteImport.update({
+ id: '/inspect',
+ path: '/inspect',
+ getParentRoute: () => ContextInspectorRoute,
+} as any)
+const ContextEngineNsNamespaceRoute =
+ ContextEngineNsNamespaceRouteImport.update({
+ id: '/ns/$namespace',
+ path: '/ns/$namespace',
+ getParentRoute: () => ContextEngineRoute,
+ } as any)
+const ContextCloudOrgsOrganizationRoute =
+ ContextCloudOrgsOrganizationRouteImport.update({
+ id: '/orgs/$organization',
+ path: '/orgs/$organization',
+ getParentRoute: () => ContextCloudRoute,
+ } as any)
+const ContextEngineNsNamespaceIndexRoute =
+ ContextEngineNsNamespaceIndexRouteImport.update({
+ id: '/',
+ path: '/',
+ getParentRoute: () => ContextEngineNsNamespaceRoute,
+ } as any)
+const ContextCloudOrgsOrganizationIndexRoute =
+ ContextCloudOrgsOrganizationIndexRouteImport.update({
+ id: '/',
+ path: '/',
+ getParentRoute: () => ContextCloudOrgsOrganizationRoute,
+ } as any)
+const ContextEngineNsNamespaceRunnersRoute =
+ ContextEngineNsNamespaceRunnersRouteImport.update({
id: '/runners',
path: '/runners',
- getParentRoute: () => LayoutNsNamespaceRoute,
+ getParentRoute: () => ContextEngineNsNamespaceRoute,
} as any)
-const LayoutOrgsOrganizationProjectsProjectIndexRoute =
- LayoutOrgsOrganizationProjectsProjectIndexRouteImport.update({
- id: '/orgs/$organization/projects/$project/',
- path: '/orgs/$organization/projects/$project/',
- getParentRoute: () => LayoutRoute,
+const ContextCloudOrgsOrganizationProjectsProjectRoute =
+ ContextCloudOrgsOrganizationProjectsProjectRouteImport.update({
+ id: '/projects/$project',
+ path: '/projects/$project',
+ getParentRoute: () => ContextCloudOrgsOrganizationRoute,
} as any)
-const LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRoute =
- LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRouteImport.update({
- id: '/orgs/$organization/projects/$project/ns/$namespace/',
- path: '/orgs/$organization/projects/$project/ns/$namespace/',
- getParentRoute: () => LayoutRoute,
+const ContextCloudOrgsOrganizationProjectsProjectIndexRoute =
+ ContextCloudOrgsOrganizationProjectsProjectIndexRouteImport.update({
+ id: '/',
+ path: '/',
+ getParentRoute: () => ContextCloudOrgsOrganizationProjectsProjectRoute,
} as any)
-const LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRoute =
- LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRouteImport.update({
- id: '/orgs/$organization/projects/$project/ns/$namespace/connect',
- path: '/orgs/$organization/projects/$project/ns/$namespace/connect',
- getParentRoute: () => LayoutRoute,
+const ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute =
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteImport.update({
+ id: '/ns/$namespace',
+ path: '/ns/$namespace',
+ getParentRoute: () => ContextCloudOrgsOrganizationProjectsProjectRoute,
} as any)
+const ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRoute =
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRouteImport.update(
+ {
+ id: '/',
+ path: '/',
+ getParentRoute: () =>
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute,
+ } as any,
+ )
+const ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute =
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRouteImport.update(
+ {
+ id: '/connect',
+ path: '/connect',
+ getParentRoute: () =>
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute,
+ } as any,
+ )
export interface FileRoutesByFullPath {
- '/namespaces': typeof LayoutNamespacesRoute
- '/': typeof LayoutIndexRoute
- '/ns/$namespace': typeof LayoutNsNamespaceRouteWithChildren
- '/ns/$namespace/runners': typeof LayoutNsNamespaceRunnersRoute
- '/ns/$namespace/': typeof LayoutNsNamespaceIndexRoute
- '/orgs/$organization': typeof LayoutOrgsOrganizationIndexRoute
- '/orgs/$organization/projects/$project': typeof LayoutOrgsOrganizationProjectsProjectIndexRoute
- '/orgs/$organization/projects/$project/ns/$namespace/connect': typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRoute
- '/orgs/$organization/projects/$project/ns/$namespace': typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRoute
+ '/': typeof ContextIndexRoute
+ '/inspect': typeof ContextInspectorInspectRoute
+ '/orgs/$organization': typeof ContextCloudOrgsOrganizationRouteWithChildren
+ '/ns/$namespace': typeof ContextEngineNsNamespaceRouteWithChildren
+ '/ns/$namespace/runners': typeof ContextEngineNsNamespaceRunnersRoute
+ '/orgs/$organization/': typeof ContextCloudOrgsOrganizationIndexRoute
+ '/ns/$namespace/': typeof ContextEngineNsNamespaceIndexRoute
+ '/orgs/$organization/projects/$project': typeof ContextCloudOrgsOrganizationProjectsProjectRouteWithChildren
+ '/orgs/$organization/projects/$project/': typeof ContextCloudOrgsOrganizationProjectsProjectIndexRoute
+ '/orgs/$organization/projects/$project/ns/$namespace': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren
+ '/orgs/$organization/projects/$project/ns/$namespace/connect': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute
+ '/orgs/$organization/projects/$project/ns/$namespace/': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRoute
}
export interface FileRoutesByTo {
- '/namespaces': typeof LayoutNamespacesRoute
- '/': typeof LayoutIndexRoute
- '/ns/$namespace/runners': typeof LayoutNsNamespaceRunnersRoute
- '/ns/$namespace': typeof LayoutNsNamespaceIndexRoute
- '/orgs/$organization': typeof LayoutOrgsOrganizationIndexRoute
- '/orgs/$organization/projects/$project': typeof LayoutOrgsOrganizationProjectsProjectIndexRoute
- '/orgs/$organization/projects/$project/ns/$namespace/connect': typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRoute
- '/orgs/$organization/projects/$project/ns/$namespace': typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRoute
+ '/': typeof ContextIndexRoute
+ '/inspect': typeof ContextInspectorInspectRoute
+ '/ns/$namespace/runners': typeof ContextEngineNsNamespaceRunnersRoute
+ '/orgs/$organization': typeof ContextCloudOrgsOrganizationIndexRoute
+ '/ns/$namespace': typeof ContextEngineNsNamespaceIndexRoute
+ '/orgs/$organization/projects/$project': typeof ContextCloudOrgsOrganizationProjectsProjectIndexRoute
+ '/orgs/$organization/projects/$project/ns/$namespace/connect': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute
+ '/orgs/$organization/projects/$project/ns/$namespace': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
- '/_layout': typeof LayoutRouteWithChildren
- '/_layout/namespaces': typeof LayoutNamespacesRoute
- '/_layout/': typeof LayoutIndexRoute
- '/_layout/ns/$namespace': typeof LayoutNsNamespaceRouteWithChildren
- '/_layout/ns/$namespace/runners': typeof LayoutNsNamespaceRunnersRoute
- '/_layout/ns/$namespace/': typeof LayoutNsNamespaceIndexRoute
- '/_layout/orgs/$organization/': typeof LayoutOrgsOrganizationIndexRoute
- '/_layout/orgs/$organization/projects/$project/': typeof LayoutOrgsOrganizationProjectsProjectIndexRoute
- '/_layout/orgs/$organization/projects/$project/ns/$namespace/connect': typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRoute
- '/_layout/orgs/$organization/projects/$project/ns/$namespace/': typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRoute
+ '/_context': typeof ContextRouteWithChildren
+ '/_context/_cloud': typeof ContextCloudRouteWithChildren
+ '/_context/_engine': typeof ContextEngineRouteWithChildren
+ '/_context/_inspector': typeof ContextInspectorRouteWithChildren
+ '/_context/': typeof ContextIndexRoute
+ '/_context/_inspector/inspect': typeof ContextInspectorInspectRoute
+ '/_context/_cloud/orgs/$organization': typeof ContextCloudOrgsOrganizationRouteWithChildren
+ '/_context/_engine/ns/$namespace': typeof ContextEngineNsNamespaceRouteWithChildren
+ '/_context/_engine/ns/$namespace/runners': typeof ContextEngineNsNamespaceRunnersRoute
+ '/_context/_cloud/orgs/$organization/': typeof ContextCloudOrgsOrganizationIndexRoute
+ '/_context/_engine/ns/$namespace/': typeof ContextEngineNsNamespaceIndexRoute
+ '/_context/_cloud/orgs/$organization/projects/$project': typeof ContextCloudOrgsOrganizationProjectsProjectRouteWithChildren
+ '/_context/_cloud/orgs/$organization/projects/$project/': typeof ContextCloudOrgsOrganizationProjectsProjectIndexRoute
+ '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren
+ '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/connect': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute
+ '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths:
- | '/namespaces'
| '/'
+ | '/inspect'
+ | '/orgs/$organization'
| '/ns/$namespace'
| '/ns/$namespace/runners'
+ | '/orgs/$organization/'
| '/ns/$namespace/'
- | '/orgs/$organization'
| '/orgs/$organization/projects/$project'
- | '/orgs/$organization/projects/$project/ns/$namespace/connect'
+ | '/orgs/$organization/projects/$project/'
| '/orgs/$organization/projects/$project/ns/$namespace'
+ | '/orgs/$organization/projects/$project/ns/$namespace/connect'
+ | '/orgs/$organization/projects/$project/ns/$namespace/'
fileRoutesByTo: FileRoutesByTo
to:
- | '/namespaces'
| '/'
+ | '/inspect'
| '/ns/$namespace/runners'
- | '/ns/$namespace'
| '/orgs/$organization'
+ | '/ns/$namespace'
| '/orgs/$organization/projects/$project'
| '/orgs/$organization/projects/$project/ns/$namespace/connect'
| '/orgs/$organization/projects/$project/ns/$namespace'
id:
| '__root__'
- | '/_layout'
- | '/_layout/namespaces'
- | '/_layout/'
- | '/_layout/ns/$namespace'
- | '/_layout/ns/$namespace/runners'
- | '/_layout/ns/$namespace/'
- | '/_layout/orgs/$organization/'
- | '/_layout/orgs/$organization/projects/$project/'
- | '/_layout/orgs/$organization/projects/$project/ns/$namespace/connect'
- | '/_layout/orgs/$organization/projects/$project/ns/$namespace/'
+ | '/_context'
+ | '/_context/_cloud'
+ | '/_context/_engine'
+ | '/_context/_inspector'
+ | '/_context/'
+ | '/_context/_inspector/inspect'
+ | '/_context/_cloud/orgs/$organization'
+ | '/_context/_engine/ns/$namespace'
+ | '/_context/_engine/ns/$namespace/runners'
+ | '/_context/_cloud/orgs/$organization/'
+ | '/_context/_engine/ns/$namespace/'
+ | '/_context/_cloud/orgs/$organization/projects/$project'
+ | '/_context/_cloud/orgs/$organization/projects/$project/'
+ | '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace'
+ | '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/connect'
+ | '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
- LayoutRoute: typeof LayoutRouteWithChildren
+ ContextRoute: typeof ContextRouteWithChildren
}
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
- '/_layout': {
- id: '/_layout'
+ '/_context': {
+ id: '/_context'
path: ''
fullPath: ''
- preLoaderRoute: typeof LayoutRouteImport
+ preLoaderRoute: typeof ContextRouteImport
parentRoute: typeof rootRouteImport
}
- '/_layout/': {
- id: '/_layout/'
+ '/_context/': {
+ id: '/_context/'
path: '/'
fullPath: '/'
- preLoaderRoute: typeof LayoutIndexRouteImport
- parentRoute: typeof LayoutRoute
+ preLoaderRoute: typeof ContextIndexRouteImport
+ parentRoute: typeof ContextRoute
}
- '/_layout/namespaces': {
- id: '/_layout/namespaces'
- path: '/namespaces'
- fullPath: '/namespaces'
- preLoaderRoute: typeof LayoutNamespacesRouteImport
- parentRoute: typeof LayoutRoute
+ '/_context/_inspector': {
+ id: '/_context/_inspector'
+ path: ''
+ fullPath: ''
+ preLoaderRoute: typeof ContextInspectorRouteImport
+ parentRoute: typeof ContextRoute
+ }
+ '/_context/_engine': {
+ id: '/_context/_engine'
+ path: ''
+ fullPath: ''
+ preLoaderRoute: typeof ContextEngineRouteImport
+ parentRoute: typeof ContextRoute
+ }
+ '/_context/_cloud': {
+ id: '/_context/_cloud'
+ path: ''
+ fullPath: ''
+ preLoaderRoute: typeof ContextCloudRouteImport
+ parentRoute: typeof ContextRoute
+ }
+ '/_context/_inspector/inspect': {
+ id: '/_context/_inspector/inspect'
+ path: '/inspect'
+ fullPath: '/inspect'
+ preLoaderRoute: typeof ContextInspectorInspectRouteImport
+ parentRoute: typeof ContextInspectorRoute
}
- '/_layout/ns/$namespace': {
- id: '/_layout/ns/$namespace'
+ '/_context/_engine/ns/$namespace': {
+ id: '/_context/_engine/ns/$namespace'
path: '/ns/$namespace'
fullPath: '/ns/$namespace'
- preLoaderRoute: typeof LayoutNsNamespaceRouteImport
- parentRoute: typeof LayoutRoute
+ preLoaderRoute: typeof ContextEngineNsNamespaceRouteImport
+ parentRoute: typeof ContextEngineRoute
}
- '/_layout/orgs/$organization/': {
- id: '/_layout/orgs/$organization/'
+ '/_context/_cloud/orgs/$organization': {
+ id: '/_context/_cloud/orgs/$organization'
path: '/orgs/$organization'
fullPath: '/orgs/$organization'
- preLoaderRoute: typeof LayoutOrgsOrganizationIndexRouteImport
- parentRoute: typeof LayoutRoute
+ preLoaderRoute: typeof ContextCloudOrgsOrganizationRouteImport
+ parentRoute: typeof ContextCloudRoute
}
- '/_layout/ns/$namespace/': {
- id: '/_layout/ns/$namespace/'
+ '/_context/_engine/ns/$namespace/': {
+ id: '/_context/_engine/ns/$namespace/'
path: '/'
fullPath: '/ns/$namespace/'
- preLoaderRoute: typeof LayoutNsNamespaceIndexRouteImport
- parentRoute: typeof LayoutNsNamespaceRoute
+ preLoaderRoute: typeof ContextEngineNsNamespaceIndexRouteImport
+ parentRoute: typeof ContextEngineNsNamespaceRoute
}
- '/_layout/ns/$namespace/runners': {
- id: '/_layout/ns/$namespace/runners'
+ '/_context/_cloud/orgs/$organization/': {
+ id: '/_context/_cloud/orgs/$organization/'
+ path: '/'
+ fullPath: '/orgs/$organization/'
+ preLoaderRoute: typeof ContextCloudOrgsOrganizationIndexRouteImport
+ parentRoute: typeof ContextCloudOrgsOrganizationRoute
+ }
+ '/_context/_engine/ns/$namespace/runners': {
+ id: '/_context/_engine/ns/$namespace/runners'
path: '/runners'
fullPath: '/ns/$namespace/runners'
- preLoaderRoute: typeof LayoutNsNamespaceRunnersRouteImport
- parentRoute: typeof LayoutNsNamespaceRoute
+ preLoaderRoute: typeof ContextEngineNsNamespaceRunnersRouteImport
+ parentRoute: typeof ContextEngineNsNamespaceRoute
}
- '/_layout/orgs/$organization/projects/$project/': {
- id: '/_layout/orgs/$organization/projects/$project/'
- path: '/orgs/$organization/projects/$project'
+ '/_context/_cloud/orgs/$organization/projects/$project': {
+ id: '/_context/_cloud/orgs/$organization/projects/$project'
+ path: '/projects/$project'
fullPath: '/orgs/$organization/projects/$project'
- preLoaderRoute: typeof LayoutOrgsOrganizationProjectsProjectIndexRouteImport
- parentRoute: typeof LayoutRoute
+ preLoaderRoute: typeof ContextCloudOrgsOrganizationProjectsProjectRouteImport
+ parentRoute: typeof ContextCloudOrgsOrganizationRoute
+ }
+ '/_context/_cloud/orgs/$organization/projects/$project/': {
+ id: '/_context/_cloud/orgs/$organization/projects/$project/'
+ path: '/'
+ fullPath: '/orgs/$organization/projects/$project/'
+ preLoaderRoute: typeof ContextCloudOrgsOrganizationProjectsProjectIndexRouteImport
+ parentRoute: typeof ContextCloudOrgsOrganizationProjectsProjectRoute
}
- '/_layout/orgs/$organization/projects/$project/ns/$namespace/': {
- id: '/_layout/orgs/$organization/projects/$project/ns/$namespace/'
- path: '/orgs/$organization/projects/$project/ns/$namespace'
+ '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace': {
+ id: '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace'
+ path: '/ns/$namespace'
fullPath: '/orgs/$organization/projects/$project/ns/$namespace'
- preLoaderRoute: typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRouteImport
- parentRoute: typeof LayoutRoute
+ preLoaderRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteImport
+ parentRoute: typeof ContextCloudOrgsOrganizationProjectsProjectRoute
+ }
+ '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/': {
+ id: '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/'
+ path: '/'
+ fullPath: '/orgs/$organization/projects/$project/ns/$namespace/'
+ preLoaderRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRouteImport
+ parentRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute
}
- '/_layout/orgs/$organization/projects/$project/ns/$namespace/connect': {
- id: '/_layout/orgs/$organization/projects/$project/ns/$namespace/connect'
- path: '/orgs/$organization/projects/$project/ns/$namespace/connect'
+ '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/connect': {
+ id: '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/connect'
+ path: '/connect'
fullPath: '/orgs/$organization/projects/$project/ns/$namespace/connect'
- preLoaderRoute: typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRouteImport
- parentRoute: typeof LayoutRoute
+ preLoaderRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRouteImport
+ parentRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute
}
}
}
-interface LayoutNsNamespaceRouteChildren {
- LayoutNsNamespaceRunnersRoute: typeof LayoutNsNamespaceRunnersRoute
- LayoutNsNamespaceIndexRoute: typeof LayoutNsNamespaceIndexRoute
+interface ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteChildren {
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRoute
}
-const LayoutNsNamespaceRouteChildren: LayoutNsNamespaceRouteChildren = {
- LayoutNsNamespaceRunnersRoute: LayoutNsNamespaceRunnersRoute,
- LayoutNsNamespaceIndexRoute: LayoutNsNamespaceIndexRoute,
+const ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteChildren: ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteChildren =
+ {
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute:
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute,
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRoute:
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceIndexRoute,
+ }
+
+const ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren =
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute._addFileChildren(
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteChildren,
+ )
+
+interface ContextCloudOrgsOrganizationProjectsProjectRouteChildren {
+ ContextCloudOrgsOrganizationProjectsProjectIndexRoute: typeof ContextCloudOrgsOrganizationProjectsProjectIndexRoute
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren
+}
+
+const ContextCloudOrgsOrganizationProjectsProjectRouteChildren: ContextCloudOrgsOrganizationProjectsProjectRouteChildren =
+ {
+ ContextCloudOrgsOrganizationProjectsProjectIndexRoute:
+ ContextCloudOrgsOrganizationProjectsProjectIndexRoute,
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute:
+ ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren,
+ }
+
+const ContextCloudOrgsOrganizationProjectsProjectRouteWithChildren =
+ ContextCloudOrgsOrganizationProjectsProjectRoute._addFileChildren(
+ ContextCloudOrgsOrganizationProjectsProjectRouteChildren,
+ )
+
+interface ContextCloudOrgsOrganizationRouteChildren {
+ ContextCloudOrgsOrganizationIndexRoute: typeof ContextCloudOrgsOrganizationIndexRoute
+ ContextCloudOrgsOrganizationProjectsProjectRoute: typeof ContextCloudOrgsOrganizationProjectsProjectRouteWithChildren
}
-const LayoutNsNamespaceRouteWithChildren =
- LayoutNsNamespaceRoute._addFileChildren(LayoutNsNamespaceRouteChildren)
-
-interface LayoutRouteChildren {
- LayoutNamespacesRoute: typeof LayoutNamespacesRoute
- LayoutIndexRoute: typeof LayoutIndexRoute
- LayoutNsNamespaceRoute: typeof LayoutNsNamespaceRouteWithChildren
- LayoutOrgsOrganizationIndexRoute: typeof LayoutOrgsOrganizationIndexRoute
- LayoutOrgsOrganizationProjectsProjectIndexRoute: typeof LayoutOrgsOrganizationProjectsProjectIndexRoute
- LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRoute: typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRoute
- LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRoute: typeof LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRoute
+const ContextCloudOrgsOrganizationRouteChildren: ContextCloudOrgsOrganizationRouteChildren =
+ {
+ ContextCloudOrgsOrganizationIndexRoute:
+ ContextCloudOrgsOrganizationIndexRoute,
+ ContextCloudOrgsOrganizationProjectsProjectRoute:
+ ContextCloudOrgsOrganizationProjectsProjectRouteWithChildren,
+ }
+
+const ContextCloudOrgsOrganizationRouteWithChildren =
+ ContextCloudOrgsOrganizationRoute._addFileChildren(
+ ContextCloudOrgsOrganizationRouteChildren,
+ )
+
+interface ContextCloudRouteChildren {
+ ContextCloudOrgsOrganizationRoute: typeof ContextCloudOrgsOrganizationRouteWithChildren
+}
+
+const ContextCloudRouteChildren: ContextCloudRouteChildren = {
+ ContextCloudOrgsOrganizationRoute:
+ ContextCloudOrgsOrganizationRouteWithChildren,
+}
+
+const ContextCloudRouteWithChildren = ContextCloudRoute._addFileChildren(
+ ContextCloudRouteChildren,
+)
+
+interface ContextEngineNsNamespaceRouteChildren {
+ ContextEngineNsNamespaceRunnersRoute: typeof ContextEngineNsNamespaceRunnersRoute
+ ContextEngineNsNamespaceIndexRoute: typeof ContextEngineNsNamespaceIndexRoute
+}
+
+const ContextEngineNsNamespaceRouteChildren: ContextEngineNsNamespaceRouteChildren =
+ {
+ ContextEngineNsNamespaceRunnersRoute: ContextEngineNsNamespaceRunnersRoute,
+ ContextEngineNsNamespaceIndexRoute: ContextEngineNsNamespaceIndexRoute,
+ }
+
+const ContextEngineNsNamespaceRouteWithChildren =
+ ContextEngineNsNamespaceRoute._addFileChildren(
+ ContextEngineNsNamespaceRouteChildren,
+ )
+
+interface ContextEngineRouteChildren {
+ ContextEngineNsNamespaceRoute: typeof ContextEngineNsNamespaceRouteWithChildren
+}
+
+const ContextEngineRouteChildren: ContextEngineRouteChildren = {
+ ContextEngineNsNamespaceRoute: ContextEngineNsNamespaceRouteWithChildren,
+}
+
+const ContextEngineRouteWithChildren = ContextEngineRoute._addFileChildren(
+ ContextEngineRouteChildren,
+)
+
+interface ContextInspectorRouteChildren {
+ ContextInspectorInspectRoute: typeof ContextInspectorInspectRoute
+}
+
+const ContextInspectorRouteChildren: ContextInspectorRouteChildren = {
+ ContextInspectorInspectRoute: ContextInspectorInspectRoute,
+}
+
+const ContextInspectorRouteWithChildren =
+ ContextInspectorRoute._addFileChildren(ContextInspectorRouteChildren)
+
+interface ContextRouteChildren {
+ ContextCloudRoute: typeof ContextCloudRouteWithChildren
+ ContextEngineRoute: typeof ContextEngineRouteWithChildren
+ ContextInspectorRoute: typeof ContextInspectorRouteWithChildren
+ ContextIndexRoute: typeof ContextIndexRoute
}
-const LayoutRouteChildren: LayoutRouteChildren = {
- LayoutNamespacesRoute: LayoutNamespacesRoute,
- LayoutIndexRoute: LayoutIndexRoute,
- LayoutNsNamespaceRoute: LayoutNsNamespaceRouteWithChildren,
- LayoutOrgsOrganizationIndexRoute: LayoutOrgsOrganizationIndexRoute,
- LayoutOrgsOrganizationProjectsProjectIndexRoute:
- LayoutOrgsOrganizationProjectsProjectIndexRoute,
- LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRoute:
- LayoutOrgsOrganizationProjectsProjectNsNamespaceConnectRoute,
- LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRoute:
- LayoutOrgsOrganizationProjectsProjectNsNamespaceIndexRoute,
+const ContextRouteChildren: ContextRouteChildren = {
+ ContextCloudRoute: ContextCloudRouteWithChildren,
+ ContextEngineRoute: ContextEngineRouteWithChildren,
+ ContextInspectorRoute: ContextInspectorRouteWithChildren,
+ ContextIndexRoute: ContextIndexRoute,
}
-const LayoutRouteWithChildren =
- LayoutRoute._addFileChildren(LayoutRouteChildren)
+const ContextRouteWithChildren =
+ ContextRoute._addFileChildren(ContextRouteChildren)
const rootRouteChildren: RootRouteChildren = {
- LayoutRoute: LayoutRouteWithChildren,
+ ContextRoute: ContextRouteWithChildren,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
diff --git a/frontend/src/routes/__root.tsx b/frontend/src/routes/__root.tsx
index 5f05b309cb..7625e808c6 100644
--- a/frontend/src/routes/__root.tsx
+++ b/frontend/src/routes/__root.tsx
@@ -1,10 +1,9 @@
-import { ClerkProvider } from "@clerk/clerk-react";
-import { dark } from "@clerk/themes";
+import type { Clerk } from "@clerk/clerk-js";
+import type { QueryClient } from "@tanstack/react-query";
import { createRootRouteWithContext, Outlet } from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
-import { match } from "ts-pattern";
+import posthog from "posthog-js";
import { FullscreenLoading } from "@/components";
-import { clerk } from "@/lib/auth";
function RootRoute() {
return (
@@ -17,28 +16,37 @@ function RootRoute() {
);
}
-function CloudRootRoute() {
- const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;
-
- if (!PUBLISHABLE_KEY) {
- throw new Error("Add your Clerk Publishable Key to the .env file");
- }
-
- return (
-
-
-
- );
+interface RootRouteContext {
+ /**
+ * Only available in cloud mode
+ */
+ clerk: Clerk;
+ queryClient: QueryClient;
}
-export const Route = createRootRouteWithContext()({
- component: match(__APP_TYPE__)
- .with("cloud", () => CloudRootRoute)
- .otherwise(() => RootRoute),
+export const Route = createRootRouteWithContext()({
+ component: RootRoute,
pendingComponent: FullscreenLoading,
- wrapInSuspense: true,
+ beforeLoad: async ({ context }) => {
+ if (!context.clerk) return;
+
+ // wait for Clerk
+ await new Promise((resolve, reject) => {
+ context.clerk.on("status", (payload) => {
+ if (payload === "ready") {
+ posthog.setPersonProperties({
+ id: context.clerk.user?.id,
+ email: context.clerk.user?.primaryEmailAddress
+ ?.emailAddress,
+ });
+ return resolve(true);
+ }
+ // If the status is not "ready", we don't resolve the promise
+ // We can also add a timeout to avoid waiting indefinitely
+ setTimeout(() => {
+ reject(new Error("Can't confirm identity"));
+ }, 10000);
+ });
+ });
+ },
});
diff --git a/frontend/src/routes/_context.tsx b/frontend/src/routes/_context.tsx
new file mode 100644
index 0000000000..e121d3a2a8
--- /dev/null
+++ b/frontend/src/routes/_context.tsx
@@ -0,0 +1,53 @@
+import { createFileRoute, Outlet } from "@tanstack/react-router";
+import { zodValidator } from "@tanstack/zod-adapter";
+import { match } from "ts-pattern";
+import z from "zod";
+import { createGlobalContext as createGlobalCloudContext } from "@/app/data-providers/cloud-data-provider";
+import { createGlobalContext as createGlobalEngineContext } from "@/app/data-providers/engine-data-provider";
+import { createGlobalContext as createGlobalInspectorContext } from "@/app/data-providers/inspector-data-provider";
+
+const searchSchema = z
+ .object({
+ modal: z
+ .enum(["go-to-actor", "feedback", "create-ns", "create-project"])
+ .or(z.string())
+ .optional(),
+ utm_source: z.string().optional(),
+ actorId: z.string().optional(),
+ tab: z.string().optional(),
+ n: z.array(z.string()).optional(),
+ u: z.string().optional(),
+ t: z.string().optional(),
+ })
+ .and(z.record(z.string(), z.any()));
+
+export const Route = createFileRoute("/_context")({
+ component: RouteComponent,
+ validateSearch: zodValidator(searchSchema),
+ context: ({ location: { search }, context }) => {
+ return match(__APP_TYPE__)
+ .with("engine", () => ({
+ dataProvider: createGlobalEngineContext(),
+ __type: "engine" as const,
+ }))
+ .with("cloud", () => ({
+ dataProvider: createGlobalCloudContext({
+ clerk: context.clerk,
+ }),
+ __type: "cloud" as const,
+ }))
+ .with("inspector", () => ({
+ dataProvider: createGlobalInspectorContext({
+ url: (search as z.infer).u || "",
+ token: (search as z.infer).t || "",
+ }),
+ __type: "inspector" as const,
+ }))
+ .exhaustive();
+ },
+ loaderDeps: (route) => ({ token: route.search.t, url: route.search.u }),
+});
+
+function RouteComponent() {
+ return ;
+}
diff --git a/frontend/src/routes/_context/_cloud.tsx b/frontend/src/routes/_context/_cloud.tsx
new file mode 100644
index 0000000000..c3622ad7fb
--- /dev/null
+++ b/frontend/src/routes/_context/_cloud.tsx
@@ -0,0 +1,78 @@
+import {
+ createFileRoute,
+ notFound,
+ Outlet,
+ useNavigate,
+ useSearch,
+} from "@tanstack/react-router";
+import { match } from "ts-pattern";
+import { useDialog } from "@/app/use-dialog";
+import { ModalRenderer } from "@/components/modal-renderer";
+
+export const Route = createFileRoute("/_context/_cloud")({
+ component: RouteComponent,
+ beforeLoad: () => {
+ return match(__APP_TYPE__)
+ .with("cloud", async () => {})
+ .otherwise(() => {
+ throw notFound();
+ });
+ },
+});
+
+function RouteComponent() {
+ return (
+ <>
+
+
+
+ >
+ );
+}
+
+function CloudModals() {
+ const navigate = useNavigate();
+ const search = useSearch({ from: "/_context" });
+
+ const CreateProjectDialog = useDialog.CreateProject.Dialog;
+ const CreateNamespaceDialog = useDialog.CreateNamespace.Dialog;
+
+ return (
+ <>
+ {
+ if (!value) {
+ navigate({
+ to: ".",
+ search: (old) => ({
+ ...old,
+ modal: undefined,
+ }),
+ });
+ }
+ },
+ }}
+ />
+ {
+ if (!value) {
+ navigate({
+ to: ".",
+ search: (old) => ({
+ ...old,
+ modal: undefined,
+ }),
+ });
+ }
+ },
+ }}
+ />
+ >
+ );
+}
diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization.tsx
new file mode 100644
index 0000000000..9a96652ae5
--- /dev/null
+++ b/frontend/src/routes/_context/_cloud/orgs.$organization.tsx
@@ -0,0 +1,26 @@
+import { createFileRoute, Outlet } from "@tanstack/react-router";
+import { match } from "ts-pattern";
+import { createOrganizationContext } from "@/app/data-providers/cloud-data-provider";
+
+export const Route = createFileRoute("/_context/_cloud/orgs/$organization")({
+ component: RouteComponent,
+ context: ({ context, params }) => {
+ return match(context)
+ .with({ __type: "cloud" }, (context) => ({
+ dataProvider: {
+ ...context.dataProvider,
+ ...createOrganizationContext({
+ ...context.dataProvider,
+ organization: params.organization,
+ }),
+ },
+ }))
+ .otherwise(() => {
+ throw new Error("Invalid context type for this route");
+ });
+ },
+});
+
+function RouteComponent() {
+ return ;
+}
diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization/index.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/index.tsx
new file mode 100644
index 0000000000..a54e109ae8
--- /dev/null
+++ b/frontend/src/routes/_context/_cloud/orgs.$organization/index.tsx
@@ -0,0 +1,47 @@
+import { createFileRoute, notFound, redirect } from "@tanstack/react-router";
+import { match } from "ts-pattern";
+import CreateProjectFrameContent from "@/app/dialogs/create-project-frame";
+import { Card } from "@/components";
+
+export const Route = createFileRoute("/_context/_cloud/orgs/$organization/")({
+ beforeLoad: ({ context, params }) => {
+ return match(__APP_TYPE__)
+ .with("cloud", async () => {
+ if (!context.clerk?.organization) {
+ throw notFound();
+ }
+ const result = await context.queryClient.fetchInfiniteQuery(
+ context.dataProvider.currentOrgProjectsQueryOptions(),
+ );
+
+ const firstProject = result.pages[0].projects[0];
+
+ if (firstProject) {
+ throw redirect({
+ to: "/orgs/$organization/projects/$project",
+ replace: true,
+ reloadDocument: true,
+ params: {
+ organization: params.organization,
+ project: firstProject.name,
+ },
+ });
+ }
+ })
+ .otherwise(() => {
+ throw notFound();
+ });
+ },
+
+ component: RouteComponent,
+});
+
+function RouteComponent() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project.tsx
new file mode 100644
index 0000000000..6f6d1bd694
--- /dev/null
+++ b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project.tsx
@@ -0,0 +1,29 @@
+import { createFileRoute, Outlet } from "@tanstack/react-router";
+import { match } from "ts-pattern";
+import { createProjectContext } from "@/app/data-providers/cloud-data-provider";
+
+export const Route = createFileRoute(
+ "/_context/_cloud/orgs/$organization/projects/$project",
+)({
+ component: RouteComponent,
+ context: ({ context, params }) => {
+ return match(context)
+ .with({ __type: "cloud" }, (context) => ({
+ dataProvider: {
+ ...context.dataProvider,
+ ...createProjectContext({
+ ...context.dataProvider,
+ organization: params.organization,
+ project: params.project,
+ }),
+ },
+ }))
+ .otherwise(() => {
+ throw new Error("Invalid context type for this route");
+ });
+ },
+});
+
+function RouteComponent() {
+ return ;
+}
diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/index.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/index.tsx
new file mode 100644
index 0000000000..9c285297b2
--- /dev/null
+++ b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/index.tsx
@@ -0,0 +1,49 @@
+import { createFileRoute, notFound, redirect } from "@tanstack/react-router";
+import { match } from "ts-pattern";
+import CreateNamespacesFrameContent from "@/app/dialogs/create-namespace-frame";
+import { Card } from "@/components";
+
+export const Route = createFileRoute(
+ "/_context/_cloud/orgs/$organization/projects/$project/",
+)({
+ beforeLoad: ({ context, params }) => {
+ return match(__APP_TYPE__)
+ .with("cloud", async () => {
+ if (!context.clerk?.organization) {
+ throw notFound();
+ }
+ const result = await context.queryClient.fetchInfiniteQuery(
+ context.dataProvider.currentProjectNamespacesQueryOptions(),
+ );
+
+ const firstNamespace = result.pages[0].namespaces[0];
+
+ if (firstNamespace) {
+ throw redirect({
+ to: "/orgs/$organization/projects/$project/ns/$namespace",
+ replace: true,
+ reloadDocument: true,
+ params: {
+ organization: params.organization,
+ project: params.project,
+ namespace: firstNamespace.name,
+ },
+ });
+ }
+ })
+ .otherwise(() => {
+ throw notFound();
+ });
+ },
+ component: RouteComponent,
+});
+
+function RouteComponent() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace.tsx
new file mode 100644
index 0000000000..64b1a28a07
--- /dev/null
+++ b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace.tsx
@@ -0,0 +1,29 @@
+import { createFileRoute } from "@tanstack/react-router";
+import { match } from "ts-pattern";
+import { createNamespaceContext } from "@/app/data-providers/cloud-data-provider";
+import { RouteLayout } from "@/app/route-layout";
+
+export const Route = createFileRoute(
+ "/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace",
+)({
+ component: RouteComponent,
+ context: ({ context, params }) => {
+ return match(context)
+ .with({ __type: "cloud" }, (ctx) => ({
+ dataProvider: {
+ ...ctx.dataProvider,
+ ...createNamespaceContext({
+ ...ctx.dataProvider,
+ namespace: params.namespace,
+ }),
+ },
+ }))
+ .otherwise(() => {
+ throw new Error("Invalid context type for this route");
+ });
+ },
+});
+
+function RouteComponent() {
+ return ;
+}
diff --git a/frontend/src/routes/_layout/orgs.$organization/projects.$project/ns.$namespace/connect.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/connect.tsx
similarity index 83%
rename from frontend/src/routes/_layout/orgs.$organization/projects.$project/ns.$namespace/connect.tsx
rename to frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/connect.tsx
index 8db37544dd..c871124127 100644
--- a/frontend/src/routes/_layout/orgs.$organization/projects.$project/ns.$namespace/connect.tsx
+++ b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/connect.tsx
@@ -2,7 +2,7 @@ import { createFileRoute, notFound } from "@tanstack/react-router";
import { match } from "ts-pattern";
export const Route = createFileRoute(
- "/_layout/orgs/$organization/projects/$project/ns/$namespace/connect",
+ "/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/connect",
)({
component: match(__APP_TYPE__)
.with("cloud", () => RouteComponent)
@@ -17,5 +17,5 @@ function RouteComponent() {
Hello
"/_layout/orgs/$organization/projects/$project/ns/$namespace/connect"!
- );
+ )
}
diff --git a/frontend/src/routes/_layout/orgs.$organization/projects.$project/ns.$namespace/index.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/index.tsx
similarity index 52%
rename from frontend/src/routes/_layout/orgs.$organization/projects.$project/ns.$namespace/index.tsx
rename to frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/index.tsx
index d6c631ddc4..095828eb19 100644
--- a/frontend/src/routes/_layout/orgs.$organization/projects.$project/ns.$namespace/index.tsx
+++ b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/index.tsx
@@ -1,26 +1,16 @@
import { useSuspenseInfiniteQuery } from "@tanstack/react-query";
-import {
- createFileRoute,
- Navigate,
- notFound,
- useSearch,
-} from "@tanstack/react-router";
-import { match } from "ts-pattern";
+import { createFileRoute, Navigate, useSearch } from "@tanstack/react-router";
import { Actors } from "@/app/actors";
-import { useManager } from "@/components/actors";
+import { useDataProvider } from "@/components/actors";
export const Route = createFileRoute(
- "/_layout/orgs/$organization/projects/$project/ns/$namespace/",
+ "/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/",
)({
- component: match(__APP_TYPE__)
- .with("cloud", () => RouteComponent)
- .otherwise(() => () => {
- throw notFound();
- }),
+ component: RouteComponent,
});
export function RouteComponent() {
- const { actorId, n } = useSearch({ from: "/_layout" });
+ const { actorId, n } = Route.useSearch();
return (
<>
@@ -32,7 +22,7 @@ export function RouteComponent() {
function BuildPrefiller() {
const { data } = useSuspenseInfiniteQuery(
- useManager().buildsQueryOptions(),
+ useDataProvider().buildsQueryOptions(),
);
if (data[0]) {
diff --git a/frontend/src/routes/_context/_engine.tsx b/frontend/src/routes/_context/_engine.tsx
new file mode 100644
index 0000000000..3a14bc98c8
--- /dev/null
+++ b/frontend/src/routes/_context/_engine.tsx
@@ -0,0 +1,58 @@
+import {
+ createFileRoute,
+ notFound,
+ Outlet,
+ useNavigate,
+ useSearch,
+} from "@tanstack/react-router";
+import { match } from "ts-pattern";
+import { useDialog } from "@/app/use-dialog";
+import { ModalRenderer } from "@/components/modal-renderer";
+
+export const Route = createFileRoute("/_context/_engine")({
+ component: RouteComponent,
+ beforeLoad: () => {
+ return match(__APP_TYPE__)
+ .with("engine", () => {})
+ .otherwise(() => {
+ throw notFound();
+ });
+ },
+});
+
+function RouteComponent() {
+ return (
+ <>
+
+ >
+ );
+}
+
+function EngineModals() {
+ const navigate = useNavigate();
+ const search = useSearch({ from: "/_context" });
+
+ const CreateNamespaceDialog = useDialog.CreateNamespace.Dialog;
+
+ return (
+