mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-09 05:26:24 +09:00
89 lines
2.3 KiB
TypeScript
89 lines
2.3 KiB
TypeScript
import { type Tree, type AllUserProps } from "@webstudio-is/sdk";
|
|
import { applyPatches, type Patch } from "immer";
|
|
import { prisma } from "./prisma.server";
|
|
import { Project } from "./project.server";
|
|
|
|
export const loadByProject = async (
|
|
project: Project | null,
|
|
env: "production" | "development" = "development"
|
|
) => {
|
|
if (project === null) {
|
|
throw new Error("Project required");
|
|
}
|
|
|
|
const treeId = env === "production" ? project.prodTreeId : project.devTreeId;
|
|
|
|
if (treeId === null) {
|
|
throw new Error("Site needs to be published, production tree ID is null.");
|
|
}
|
|
|
|
return loadByTreeId(treeId);
|
|
};
|
|
|
|
export const loadByTreeId = async (treeId: Tree["id"]) => {
|
|
const instancePropsEntries = await prisma.instanceProps.findMany({
|
|
where: { treeId },
|
|
});
|
|
|
|
return instancePropsEntries.map((tree) => ({
|
|
...tree,
|
|
props: JSON.parse(tree.props),
|
|
}));
|
|
};
|
|
|
|
export const clone = async ({
|
|
previousTreeId,
|
|
nextTreeId,
|
|
}: {
|
|
previousTreeId: string;
|
|
nextTreeId: string;
|
|
}) => {
|
|
const props = await prisma.instanceProps.findMany({
|
|
where: { treeId: previousTreeId },
|
|
});
|
|
if (props.length === 0) return;
|
|
const data = props.map(({ id: _id, treeId: _treeId, ...rest }) => ({
|
|
...rest,
|
|
treeId: nextTreeId,
|
|
}));
|
|
|
|
await prisma.$transaction(
|
|
data.map((prop) =>
|
|
prisma.instanceProps.create({
|
|
data: prop,
|
|
})
|
|
)
|
|
);
|
|
};
|
|
|
|
export const patch = async (
|
|
{ treeId }: { treeId: Tree["id"]; projectId: Project["id"] },
|
|
patches: Array<Patch>
|
|
) => {
|
|
const allProps = await loadByTreeId(treeId);
|
|
|
|
// We should get rid of this by applying patches on the client to the original
|
|
// model instead of the instanceId map.
|
|
// The map is handy for accessing props, but probably should be just cached interface, not the main data structure.
|
|
const allPropsMapByInstanceId = allProps.reduce((acc, prop) => {
|
|
acc[prop.instanceId] = prop;
|
|
return acc;
|
|
}, {} as AllUserProps);
|
|
const nextProps = applyPatches<AllUserProps>(
|
|
allPropsMapByInstanceId,
|
|
patches
|
|
);
|
|
|
|
await Promise.all(
|
|
Object.values(nextProps).map(({ id, instanceId, treeId, props }) =>
|
|
prisma.instanceProps.upsert({
|
|
where: { id: id },
|
|
create: { id: id, instanceId, treeId, props: JSON.stringify(props) },
|
|
update: {
|
|
props: JSON.stringify(props),
|
|
},
|
|
})
|
|
)
|
|
);
|
|
};
|