wrap into transaction build.create and related functionality

simplify build.create logic, make it easier to add stuff to it
This commit is contained in:
Oleg Isonen committed 2022-12-06 12:43:22 +00:00
1 parent de77e76933
commit 175a62a91e
4 files changed
+90 -70

No files matched your search

+4 -2
View File
@@ -4,6 +4,7 @@ import { applyPatches, type Patch } from "immer";
import {
type Breakpoints as DbBreakpoints,
prisma,
Prisma,
} from "@webstudio-is/prisma-client";
import { type Breakpoint, Breakpoints } from "@webstudio-is/css-data";
@@ -33,9 +34,10 @@ export const createValues = () =>
export const create = async (
buildId: DbBreakpoints["buildId"],
values: Array<Breakpoint>
values: Array<Breakpoint>,
client: Prisma.TransactionClient = prisma
) => {
const breakpoints = await prisma.breakpoints.create({
const breakpoints = await client.breakpoints.create({
data: {
values: JSON.stringify(values),
buildId,
+49 -47
View File
@@ -1,4 +1,4 @@
import { prisma, Build as DbBuild } from "@webstudio-is/prisma-client";
import { prisma, Build as DbBuild, Prisma } from "@webstudio-is/prisma-client";
import { type Breakpoint } from "@webstudio-is/css-data";
import { v4 as uuid } from "uuid";
import * as db from ".";
@@ -156,8 +156,14 @@ export const deletePage = async (buildId: Build["id"], pageId: Page["id"]) => {
});
};
const createPages = async (breakpoints: Array<Breakpoint>) => {
const tree = await db.tree.create(db.tree.createRootInstance(breakpoints));
const createPages = async (
breakpoints: Array<Breakpoint>,
client: Prisma.TransactionClient
) => {
const tree = await db.tree.create(
db.tree.createRootInstance(breakpoints),
client
);
return Pages.parse({
homePage: {
id: uuid(),
@@ -171,26 +177,36 @@ const createPages = async (breakpoints: Array<Breakpoint>) => {
});
};
const clonePage = async (source: Page) => {
const clonePage = async (
source: Page,
client: Prisma.TransactionClient = prisma
) => {
const treeId = source.treeId;
const tree = await db.tree.clone(treeId);
await db.props.clone({ previousTreeId: treeId, nextTreeId: tree.id });
const tree = await db.tree.clone(treeId, client);
await db.props.clone({ previousTreeId: treeId, nextTreeId: tree.id }, client);
return { ...source, id: uuid(), treeId: tree.id };
};
const clonePages = async (source: Pages) => {
const clonePages = async (
source: Pages,
client: Prisma.TransactionClient = prisma
) => {
const clones = [];
for (const page of source.pages) {
clones.push(await clonePage(page));
clones.push(await clonePage(page, client));
}
return Pages.parse({
homePage: await clonePage(source.homePage),
homePage: await clonePage(source.homePage, client),
pages: clones,
});
};
/*
* We create "dev" build in two cases:
* 1. when we create a new project
* 2. when we clone a project
* When create "prod" build when we publish a dev build.
*/
export async function create(
projectId: Build["projectId"],
env: "prod",
@@ -215,52 +231,38 @@ export async function create(
if (count > 0) {
throw new Error("Dev build already exists");
}
const breakpointsValues = sourceBuild
? (await db.breakpoints.load(sourceBuild.id)).values
: db.breakpoints.createValues();
const pages =
sourceBuild === undefined
? await createPages(breakpointsValues)
: await clonePages(sourceBuild.pages);
const build = await prisma.build.create({
data: {
projectId,
pages: JSON.stringify(pages),
isDev: true,
isProd: false,
},
});
await db.breakpoints.create(build.id, breakpointsValues);
return;
}
if (sourceBuild === undefined) {
if (env === "prod" && sourceBuild === undefined) {
throw new Error("Source build required");
}
const breakpointsValues = (await db.breakpoints.load(sourceBuild.id)).values;
const breakpointsValues = sourceBuild
? (await db.breakpoints.load(sourceBuild.id)).values
: db.breakpoints.createValues();
const pages = await clonePages(sourceBuild.pages);
await prisma.$transaction(async (client) => {
const pages =
sourceBuild === undefined
? await createPages(breakpointsValues, client)
: await clonePages(sourceBuild.pages);
const [, build] = await prisma.$transaction([
prisma.build.updateMany({
where: { projectId: projectId, isProd: true },
data: { isProd: false },
}),
prisma.build.create({
if (env === "prod") {
await client.build.updateMany({
where: { projectId: projectId, isProd: true },
data: { isProd: false },
});
}
const build = await client.build.create({
data: {
projectId,
pages: JSON.stringify(pages),
isDev: false,
isProd: true,
isDev: env === "dev",
isProd: env === "dev",
},
}),
]);
});
await db.breakpoints.create(build.id, breakpointsValues);
await db.breakpoints.create(build.id, breakpointsValues, client);
});
}
+20 -13
View File
@@ -8,7 +8,7 @@ import {
UserProps,
} from "@webstudio-is/react-sdk";
import { applyPatches, type Patch } from "immer";
import { prisma } from "@webstudio-is/prisma-client";
import { prisma, Prisma } from "@webstudio-is/prisma-client";
import { formatAsset } from "@webstudio-is/asset-uploader/server";
const baseUserProps = {
@@ -114,14 +114,17 @@ export const deleteByTreeId = async (treeId: Tree["id"]) => {
await prisma.instanceProps.deleteMany({ where: { treeId } });
};
export const clone = async ({
previousTreeId,
nextTreeId,
}: {
previousTreeId: string;
nextTreeId: string;
}) => {
const props = await prisma.instanceProps.findMany({
export const clone = async (
{
previousTreeId,
nextTreeId,
}: {
previousTreeId: string;
nextTreeId: string;
},
client: Prisma.TransactionClient | typeof prisma = prisma
) => {
const props = await client.instanceProps.findMany({
where: { treeId: previousTreeId },
});
if (props.length === 0) return;
@@ -130,13 +133,17 @@ export const clone = async ({
treeId: nextTreeId,
}));
await prisma.$transaction(
const create = async (client: Prisma.TransactionClient) =>
data.map((prop) =>
prisma.instanceProps.create({
client.instanceProps.create({
data: prop,
})
)
);
);
// If our client is not a transaction client, we need to create a transaction
"$transaction" in client
? await client.$transaction(create)
: await create(client);
};
export const patch = async (
+17 -8
View File
@@ -1,6 +1,6 @@
import { type Tree, Instance } from "@webstudio-is/react-sdk";
import { applyPatches, type Patch } from "immer";
import { prisma } from "@webstudio-is/prisma-client";
import { prisma, type Prisma } from "@webstudio-is/prisma-client";
import { Tree as DbTree } from "@prisma/client";
import { utils } from "../index";
import type { Breakpoint } from "@webstudio-is/css-data";
@@ -15,10 +15,13 @@ export const createRootInstance = (breakpoints: Array<Breakpoint>) => {
return utils.tree.populateInstance(instance, defaultBreakpoint.id);
};
export const create = async (root: Instance): Promise<DbTree> => {
export const create = async (
root: Instance,
client: Prisma.TransactionClient = prisma
): Promise<DbTree> => {
Instance.parse(root);
const rootString = JSON.stringify(root);
return await prisma.tree.create({
return await client.tree.create({
data: { root: rootString },
});
};
@@ -27,8 +30,11 @@ export const deleteById = async (treeId: string): Promise<void> => {
await prisma.tree.delete({ where: { id: treeId } });
};
export const loadById = async (treeId: string): Promise<Tree | null> => {
const tree = await prisma.tree.findUnique({
export const loadById = async (
treeId: string,
client: Prisma.TransactionClient = prisma
): Promise<Tree | null> => {
const tree = await client.tree.findUnique({
where: { id: treeId },
});
@@ -42,12 +48,15 @@ export const loadById = async (treeId: string): Promise<Tree | null> => {
};
};
export const clone = async (treeId: string) => {
const tree = await loadById(treeId);
export const clone = async (
treeId: string,
client: Prisma.TransactionClient = prisma
) => {
const tree = await loadById(treeId, client);
if (tree === null) {
throw new Error(`Tree ${treeId} not found`);
}
return await create(tree.root);
return await create(tree.root, client);
};
export const patch = async (