Skip to content

Commit 6ae3f77

Browse files
committed
feat(cloud): connect page
1 parent 9c4a957 commit 6ae3f77

File tree

16 files changed

+114
-58
lines changed

16 files changed

+114
-58
lines changed

frontend/src/app.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ export const router = createRouter({
3535
__APP_TYPE__ === "cloud" ? clerk : (undefined as unknown as Clerk),
3636
queryClient: queryClient,
3737
},
38-
defaultStaleTime: Infinity,
39-
defaultPendingComponent: PageLayout.Root.Skeleton,
4038
defaultPreloadStaleTime: 0,
4139
defaultGcTime: 0,
4240
defaultPreloadGcTime: 0,
41+
defaultStaleTime: Infinity,
42+
scrollRestoration: true,
4343
defaultOnCatch: (error) => {
44+
console.error("Router caught an error:", error);
4445
Sentry.captureException(error);
4546
},
4647
});

frontend/src/app/data-providers/cloud-data-provider.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export const createOrganizationContext = ({
172172
const response = await client.projects.create({
173173
displayName: data.displayName,
174174
name: data.nameId,
175-
organizationId: organization,
175+
org: organization,
176176
});
177177

178178
return response;
@@ -207,7 +207,7 @@ export const createProjectContext = ({
207207
displayName: data.displayName,
208208
org: organization,
209209
});
210-
return response;
210+
return response.namespace;
211211
},
212212
};
213213
},

frontend/src/app/dialogs/create-namespace-frame.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { useMutation, useQueryClient } from "@tanstack/react-query";
2-
import { useNavigate, useParams } from "@tanstack/react-router";
2+
import {
3+
useNavigate,
4+
useParams,
5+
useRouteContext,
6+
} from "@tanstack/react-router";
7+
import { match } from "ts-pattern";
38
import * as CreateNamespaceForm from "@/app/forms/create-namespace-form";
49
import { Flex, Frame } from "@/components";
5-
import { useEngineCompatDataProvider } from "@/components/actors";
610
import { convertStringToId } from "@/lib/utils";
711

812
const useCreateNamespace = () => {
@@ -11,7 +15,18 @@ const useCreateNamespace = () => {
1115

1216
const params = useParams({ strict: false });
1317

14-
const manager = useEngineCompatDataProvider();
18+
const manager = useRouteContext({
19+
from: match(__APP_TYPE__)
20+
.with(
21+
"cloud",
22+
() =>
23+
"/_context/_cloud/orgs/$organization/projects/$project" as const,
24+
)
25+
.with("engine", () => "/_context/_engine/ns/$namespace" as const)
26+
.otherwise(() => {
27+
throw new Error("Not in engine or cloud context");
28+
}),
29+
}).dataProvider;
1530

1631
return useMutation(
1732
manager.createNamespaceMutationOptions({
@@ -26,7 +41,7 @@ const useCreateNamespace = () => {
2641
throw new Error("Missing required parameters");
2742
}
2843
// Navigate to the newly created namespace
29-
navigate({
44+
await navigate({
3045
to: "/orgs/$organization/projects/$project/ns/$namespace",
3146
params: {
3247
organization: params.organization,
@@ -37,7 +52,7 @@ const useCreateNamespace = () => {
3752
return;
3853
}
3954

40-
navigate({
55+
await navigate({
4156
to: "/ns/$namespace",
4257
params: { namespace: data.name },
4358
});

frontend/src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ function HeaderButton({ children, className, ...props }: ButtonProps) {
402402

403403
function ConnectionStatus(): ReactNode {
404404
const endpoint = useSearch({
405-
from: "/_context/_inspector",
405+
from: "/_inspector/",
406406
select: (s) => s.u,
407407
});
408408
const data = useInspectorDataProvider();

frontend/src/components/third-party-providers.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import posthog, { type PostHog } from "posthog-js";
33
import { PostHogProvider } from "posthog-js/react";
44
import type { PropsWithChildren } from "react";
55
import { getConfig, useConfig } from "@/components";
6+
import { cloudEnv, commonEnv } from "@/lib/env";
67

78
export function initThirdPartyProviders(router: unknown, debug: boolean) {
89
const config = getConfig();
@@ -22,19 +23,22 @@ export function initThirdPartyProviders(router: unknown, debug: boolean) {
2223
if (config.sentry) {
2324
const integrations = [
2425
Sentry.tanstackRouterBrowserTracingIntegration(router),
26+
Sentry.browserTracingIntegration(),
2527
];
2628
if (ph) {
2729
integrations.push(
2830
ph.sentryIntegration({
2931
organization: "rivet-gg",
30-
projectId: Number.parseInt(config.sentry.projectId, 10),
32+
projectId: commonEnv().VITE_APP_SENTRY_PROJECT_ID,
3133
}),
3234
);
3335
}
3436

3537
Sentry.init({
36-
dsn: config.sentry.dsn,
38+
dsn: commonEnv().VITE_APP_SENTRY_DSN,
39+
tracesSampleRate: 1.0,
3740
integrations,
41+
tracePropagationTargets: ["localhost", /rivet.gg$/],
3842
});
3943
}
4044
}

frontend/src/lib/env.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
import z from "zod";
22

3-
export const cloudEnvSchema = z.object({
3+
export const commonEnvSchema = z.object({
44
VITE_APP_API_URL: z.string().url(),
5-
VITE_APP_CLOUD_API_URL: z.string().url(),
6-
VITE_CLERK_PUBLISHABLE_KEY: z.string(),
5+
VITE_APP_ASSETS_URL: z.string().url(),
6+
VITE_APP_POSTHOG_API_KEY: z.string().optional(),
7+
VITE_APP_POSTHOG_API_HOST: z.string().url().optional(),
8+
VITE_APP_SENTRY_DSN: z.string().url().optional(),
9+
VITE_APP_SENTRY_PROJECT_ID: z.coerce.number().optional(),
10+
// AVAILABLE ONLY IN CI
11+
SENTRY_AUTH_TOKEN: z.string().optional(),
12+
SENTRY_PROJECT: z.string().optional(),
13+
APP_TYPE: z.enum(["engine", "cloud", "inspector"]).optional(),
714
});
815

9-
export const cloudEnv = () => cloudEnvSchema.parse(import.meta.env);
16+
export const commonEnv = () => commonEnvSchema.parse(import.meta.env);
1017

11-
export const engineEnvSchema = z.object({
12-
VITE_APP_API_URL: z.string().url(),
13-
});
18+
export const engineEnv = () => commonEnvSchema.parse(import.meta.env);
1419

15-
export const engineEnv = () => engineEnvSchema.parse(import.meta.env);
20+
export const cloudEnvSchema = commonEnvSchema.merge(
21+
z.object({
22+
VITE_APP_API_URL: z.string().url(),
23+
VITE_APP_CLOUD_API_URL: z.string().url(),
24+
VITE_CLERK_PUBLISHABLE_KEY: z.string(),
25+
}),
26+
);
27+
28+
export const cloudEnv = () => cloudEnvSchema.parse(import.meta.env);

frontend/src/main.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { App, router } from "./app";
44
import "./index.css";
55
import { initThirdPartyProviders } from "@/components";
66

7-
initThirdPartyProviders(router, import.meta.env.DEV);
7+
initThirdPartyProviders(router, false);
88

99
// biome-ignore lint/style/noNonNullAssertion: it should always be present
1010
const rootElement = document.getElementById("root")!;

frontend/src/routes/__root.tsx

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type { Clerk } from "@clerk/clerk-js";
2+
import * as Sentry from "@sentry/react";
23
import type { QueryClient } from "@tanstack/react-query";
34
import { createRootRouteWithContext, Outlet } from "@tanstack/react-router";
45
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
56
import posthog from "posthog-js";
6-
import { FullscreenLoading } from "@/components";
7+
import { match } from "ts-pattern";
78

89
function RootRoute() {
910
return (
@@ -26,27 +27,40 @@ interface RootRouteContext {
2627

2728
export const Route = createRootRouteWithContext<RootRouteContext>()({
2829
component: RootRoute,
29-
pendingComponent: FullscreenLoading,
3030
beforeLoad: async ({ context }) => {
31-
if (!context.clerk) return;
31+
return match(__APP_TYPE__)
32+
.with("cloud", async () => {
33+
if (!context.clerk) return;
3234

33-
// wait for Clerk
34-
await new Promise((resolve, reject) => {
35-
context.clerk.on("status", (payload) => {
36-
if (payload === "ready") {
37-
posthog.setPersonProperties({
38-
id: context.clerk.user?.id,
39-
email: context.clerk.user?.primaryEmailAddress
40-
?.emailAddress,
41-
});
42-
return resolve(true);
35+
if (context.clerk.status === "ready") {
36+
return;
4337
}
44-
// If the status is not "ready", we don't resolve the promise
45-
// We can also add a timeout to avoid waiting indefinitely
46-
setTimeout(() => {
47-
reject(new Error("Can't confirm identity"));
48-
}, 10000);
38+
39+
// Wait for Clerk
40+
await new Promise((resolve, reject) => {
41+
context.clerk.on("status", (payload) => {
42+
if (payload === "ready") {
43+
Sentry.setUser({
44+
id: context.clerk.user?.id,
45+
email: context.clerk.user?.primaryEmailAddress
46+
?.emailAddress,
47+
});
48+
posthog.setPersonProperties({
49+
id: context.clerk.user?.id,
50+
email: context.clerk.user?.primaryEmailAddress
51+
?.emailAddress,
52+
});
53+
return resolve(true);
54+
}
55+
});
56+
// Timeout to avoid waiting indefinitely
57+
setTimeout(() => {
58+
reject(new Error("Can't confirm identity"));
59+
}, 10000);
60+
});
61+
})
62+
.otherwise(() => {
63+
// No-op for engine and inspector
4964
});
50-
});
5165
},
5266
});

frontend/src/routes/_context/_cloud/orgs.$organization/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import CreateProjectFrameContent from "@/app/dialogs/create-project-frame";
44
import { Card } from "@/components";
55

66
export const Route = createFileRoute("/_context/_cloud/orgs/$organization/")({
7-
beforeLoad: ({ context, params }) => {
7+
beforeLoad: async ({ context, params }) => {
88
return match(__APP_TYPE__)
99
.with("cloud", async () => {
1010
if (!context.clerk?.organization) {
@@ -14,13 +14,15 @@ export const Route = createFileRoute("/_context/_cloud/orgs/$organization/")({
1414
context.dataProvider.currentOrgProjectsQueryOptions(),
1515
);
1616

17+
console.log(result);
18+
1719
const firstProject = result.pages[0].projects[0];
1820

1921
if (firstProject) {
2022
throw redirect({
2123
to: "/orgs/$organization/projects/$project",
2224
replace: true,
23-
reloadDocument: true,
25+
2426
params: {
2527
organization: params.organization,
2628
project: firstProject.name,

frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const Route = createFileRoute(
2222
throw redirect({
2323
to: "/orgs/$organization/projects/$project/ns/$namespace",
2424
replace: true,
25-
reloadDocument: true,
25+
2626
params: {
2727
organization: params.organization,
2828
project: params.project,

0 commit comments

Comments
 (0)