Skip to content

Commit 482839e

Browse files
authored
chore: Remove prisma from the Builder app (#4182)
## Description 1. What is this PR about (link the issue and add a short description) ## Steps for reproduction 1. click button 2. expect xyz ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [ ] made a self-review - [ ] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 5de6) - [ ] updated [test cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md) document - [ ] added tests - [ ] if any new env variables are added, added them to `.env` file
1 parent 0765d38 commit 482839e

File tree

14 files changed

+152
-207
lines changed

14 files changed

+152
-207
lines changed

apps/builder/app/builder/features/topbar/domains.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {
1919
ExternalLinkIcon,
2020
CopyIcon,
2121
} from "@webstudio-is/icons";
22-
import type { DomainStatus } from "@webstudio-is/prisma-client";
2322
import { CollapsibleDomainSection } from "./collapsible-domain-section";
2423
import {
2524
startTransition,
@@ -39,6 +38,7 @@ import DomainCheckbox from "./domain-checkbox";
3938
import { CopyToClipboard } from "~/builder/shared/copy-to-clipboard";
4039

4140
export type Domain = Project["domainsVirtual"][number];
41+
type DomainStatus = Project["domainsVirtual"][number]["status"];
4242

4343
const InputEllipsis = styled(InputField, {
4444
"&>input": {

apps/builder/app/dashboard/dashboard.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const user = {
1616
image: null,
1717
username: "Taylor",
1818
teamId: null,
19+
provider: "github",
1920
};
2021

2122
const createRouter = (element: JSX.Element) =>

apps/builder/app/routes/rest.build.$buildId.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const loader = async ({
5454
const user =
5555
project === null || project.userId === null
5656
? undefined
57-
: await getUserById(project.userId);
57+
: await getUserById(context, project.userId);
5858

5959
return {
6060
...pagesCanvasData,

apps/builder/app/routes/rest.current.products.ts

Lines changed: 0 additions & 71 deletions
This file was deleted.

apps/builder/app/services/auth.server.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import env from "~/env/env.server";
1111
import { builderAuthenticator } from "./builder-auth.server";
1212
import { staticEnv } from "~/env/env.static.server";
1313
import type { SessionData } from "./auth.server.utils";
14+
import { createContext } from "~/shared/context.server";
1415

1516
const transformRefToAlias = (input: string) => {
1617
const rawAlias = input.endsWith(".staging") ? input.slice(0, -8) : input;
@@ -32,11 +33,15 @@ export const callbackOrigin =
3233

3334
const strategyCallback = async ({
3435
profile,
36+
request,
3537
}: {
3638
profile: GitHubProfile | GoogleProfile;
39+
request: Request;
3740
}) => {
41+
const context = await createContext(request);
42+
3843
try {
39-
const user = await db.user.createOrLoginWithOAuth(profile);
44+
const user = await db.user.createOrLoginWithOAuth(context, profile);
4045
return { userId: user.id, createdAt: Date.now() };
4146
} catch (error) {
4247
if (error instanceof Error) {
@@ -83,7 +88,7 @@ if (env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) {
8388

8489
if (env.DEV_LOGIN === "true") {
8590
authenticator.use(
86-
new FormStrategy(async ({ form }) => {
91+
new FormStrategy(async ({ form, request }) => {
8792
const secretValue = form.get("secret");
8893

8994
if (secretValue == null) {
@@ -96,7 +101,9 @@ if (env.DEV_LOGIN === "true") {
96101

97102
if (secret === env.AUTH_SECRET?.slice(0, 4)) {
98103
try {
99-
const user = await db.user.createOrLoginWithDev(email);
104+
const context = await createContext(request);
105+
106+
const user = await db.user.createOrLoginWithDev(context, email);
100107
return {
101108
userId: user.id,
102109
createdAt: Date.now(),
@@ -128,9 +135,10 @@ export const findAuthenticatedUser = async (request: Request) => {
128135
if (user == null) {
129136
return null;
130137
}
138+
const context = await createContext(request);
131139

132140
try {
133-
return await getUserById(user.userId);
141+
return await getUserById(context, user.userId);
134142
} catch (error) {
135143
return null;
136144
}
Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { json } from "@remix-run/server-runtime";
2-
import { prisma } from "@webstudio-is/prisma-client";
32
import { parsePages } from "@webstudio-is/project-build/index.server";
43
import { getStaticSiteMapXml } from "@webstudio-is/sdk";
54
import { parseBuilderUrl } from "@webstudio-is/http-client";
65
import { isBuilder } from "../router-utils";
6+
import { createContext } from "../context.server";
77

88
/**
99
* This should be a route in SvelteKit, as it can be fetched server-side without an actual HTTP request.
@@ -22,25 +22,24 @@ export const loader = async ({ request }: { request: Request }) => {
2222
throw new Error("projectId is required");
2323
}
2424

25-
// get pages from the database
26-
const build = await prisma.build.findFirst({
27-
where: {
28-
projectId,
29-
deployment: null,
30-
},
31-
select: {
32-
pages: true,
33-
updatedAt: true,
34-
},
35-
});
36-
37-
if (build === null) {
38-
throw json({ message: "Build not found" }, { status: 404 });
25+
const context = await createContext(request);
26+
27+
const buildResult = await context.postgrest.client
28+
.from("Build")
29+
.select("pages, updatedAt")
30+
.eq("projectId", projectId)
31+
.is("deployment", null)
32+
.single();
33+
34+
if (buildResult.error) {
35+
throw json({ message: buildResult.error.message }, { status: 404 });
3936
}
4037

38+
const build = buildResult.data;
39+
4140
const pages = parsePages(build.pages);
4241

43-
const siteMap = getStaticSiteMapXml(pages, build.updatedAt.toISOString());
42+
const siteMap = getStaticSiteMapXml(pages, build.updatedAt);
4443

4544
return json(siteMap);
4645
};

apps/builder/app/shared/context.server.ts

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { entryApi } from "./entri/entri-api.server";
77
import { getUserPlanFeatures } from "./db/user-plan-features.server";
88
import { staticEnv } from "~/env/env.static.server";
99
import { createClient } from "@webstudio-is/postrest/index.server";
10-
import { prisma } from "@webstudio-is/prisma-client";
1110
import { builderAuthenticator } from "~/services/builder-auth.server";
1211
import { readLoginSessionBloomFilter } from "~/services/session.server";
1312
import type { BloomFilter } from "~/services/bloom-filter.server";
@@ -40,29 +39,24 @@ export const extractAuthFromRequest = async (request: Request) => {
4039
};
4140
};
4241

43-
const createTokenAuthorizationContext = async (authToken: string) => {
44-
const projectOwnerIdByToken = await prisma.authorizationToken.findUnique({
45-
where: {
46-
token: authToken,
47-
},
48-
select: {
49-
project: {
50-
select: {
51-
id: true,
52-
userId: true,
53-
},
54-
},
55-
},
56-
});
42+
const createTokenAuthorizationContext = async (
43+
authToken: string,
44+
postgrest: AppContext["postgrest"]
45+
) => {
46+
const projectOwnerIdByToken = await postgrest.client
47+
.from("AuthorizationToken")
48+
.select("project:Project(id, userId)")
49+
.eq("token", authToken)
50+
.single();
5751

58-
if (projectOwnerIdByToken === null) {
52+
if (projectOwnerIdByToken.error) {
5953
throw new Error(`Project owner can't be found for token ${authToken}`);
6054
}
6155

62-
const ownerId = projectOwnerIdByToken.project.userId;
56+
const ownerId = projectOwnerIdByToken.data.project?.userId ?? null;
6357
if (ownerId === null) {
6458
throw new Error(
65-
`Project ${projectOwnerIdByToken.project.id} has null userId`
59+
`Project ${projectOwnerIdByToken.data.project?.id} has null userId`
6660
);
6761
}
6862

@@ -74,7 +68,8 @@ const createTokenAuthorizationContext = async (authToken: string) => {
7468
};
7569

7670
const createAuthorizationContext = async (
77-
request: Request
71+
request: Request,
72+
postgrest: AppContext["postgrest"]
7873
): Promise<AppContext["authorization"]> => {
7974
const { authToken, isServiceCall, sessionData } =
8075
await extractAuthFromRequest(request);
@@ -87,7 +82,7 @@ const createAuthorizationContext = async (
8782
}
8883

8984
if (authToken != null) {
90-
return await createTokenAuthorizationContext(authToken);
85+
return await createTokenAuthorizationContext(authToken, postgrest);
9186
}
9287

9388
if (sessionData?.userId != null) {
@@ -155,7 +150,8 @@ const createEntriContext = () => {
155150
};
156151

157152
const createUserPlanContext = async (
158-
authorization: AppContext["authorization"]
153+
authorization: AppContext["authorization"],
154+
postgrest: AppContext["postgrest"]
159155
) => {
160156
const ownerId =
161157
authorization.type === "token"
@@ -164,7 +160,9 @@ const createUserPlanContext = async (
164160
? authorization.userId
165161
: undefined;
166162

167-
const planFeatures = ownerId ? await getUserPlanFeatures(ownerId) : undefined;
163+
const planFeatures = ownerId
164+
? await getUserPlanFeatures(ownerId, postgrest)
165+
: undefined;
168166
return planFeatures;
169167
};
170168

@@ -193,18 +191,27 @@ export const createPostrestContext = () => {
193191
* argument buildEnv==="prod" only if we are loading project with production build
194192
*/
195193
export const createContext = async (request: Request): Promise<AppContext> => {
196-
const authorization = await createAuthorizationContext(request);
194+
const postgrest = createPostrestContext();
195+
const authorization = await createAuthorizationContext(request, postgrest);
197196

198197
const domain = createDomainContext();
199198
const deployment = createDeploymentContext(getRequestOrigin(request.url));
200199
const entri = createEntriContext();
201-
const userPlanFeatures = await createUserPlanContext(authorization);
200+
const userPlanFeatures = await createUserPlanContext(
201+
authorization,
202+
postgrest
203+
);
202204
const trpcCache = createTrpcCache();
203-
const postgrest = createPostrestContext();
204205

205206
const createTokenContext = async (authToken: string) => {
206-
const authorization = await createTokenAuthorizationContext(authToken);
207-
const userPlanFeatures = await createUserPlanContext(authorization);
207+
const authorization = await createTokenAuthorizationContext(
208+
authToken,
209+
postgrest
210+
);
211+
const userPlanFeatures = await createUserPlanContext(
212+
authorization,
213+
postgrest
214+
);
208215

209216
return {
210217
authorization,

apps/builder/app/shared/db/canvas.server.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { loadBuildById } from "@webstudio-is/project-build/index.server";
33
import { loadAssetsByProject } from "@webstudio-is/asset-uploader/index.server";
44
import type { AppContext } from "@webstudio-is/trpc-interface/index.server";
55
import { findPageByIdOrPath, getStyleDeclKey } from "@webstudio-is/sdk";
6-
import type { Build } from "@webstudio-is/prisma-client";
76
import { db as projectDb } from "@webstudio-is/project/index.server";
87

98
const getPair = <Item extends { id: string }>(item: Item): [string, Item] => [
@@ -12,7 +11,7 @@ const getPair = <Item extends { id: string }>(item: Item): [string, Item] => [
1211
];
1312

1413
export const loadProductionCanvasData = async (
15-
buildId: Build["id"],
14+
buildId: string,
1615
context: AppContext
1716
): Promise<Data> => {
1817
const build = await loadBuildById(context, buildId);

0 commit comments

Comments
 (0)