mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-09 22:14:29 +09:00
175 lines
4.1 KiB
TypeScript
175 lines
4.1 KiB
TypeScript
import {
|
|
type ChildrenUpdates,
|
|
type Instance,
|
|
type Project,
|
|
type Tree,
|
|
} from "@webstudio-is/sdk";
|
|
import { prisma } from "./prisma.server";
|
|
import {
|
|
insertInstance,
|
|
reparentInstance,
|
|
setInstanceStyle,
|
|
setInstanceChildren,
|
|
deleteInstance as deleteInstanceFromTree,
|
|
createInstance,
|
|
type InstanceInsertionSpec,
|
|
type InstanceReparentingSpec,
|
|
} from "~/shared/tree-utils";
|
|
import type { StyleUpdates } from "~/shared/component";
|
|
import { deleteProps } from "./props.server";
|
|
|
|
const rootConfig = {
|
|
// @todo this should be part of a root primitive in primitives
|
|
component: "Box",
|
|
style: {
|
|
fontFamily: {
|
|
type: "keyword",
|
|
value: "Arial",
|
|
},
|
|
fontSize: {
|
|
type: "unit",
|
|
unit: "px",
|
|
value: 14,
|
|
},
|
|
lineHeight: {
|
|
type: "unit",
|
|
unit: "px",
|
|
value: 20,
|
|
},
|
|
color: {
|
|
type: "keyword",
|
|
value: "#232323",
|
|
},
|
|
minHeight: {
|
|
type: "unit",
|
|
unit: "vh",
|
|
value: 100,
|
|
},
|
|
flexDirection: {
|
|
type: "keyword",
|
|
value: "column",
|
|
},
|
|
},
|
|
} as const;
|
|
|
|
export const create = async (root?: Instance): Promise<Tree> => {
|
|
return (await prisma.tree.create({
|
|
data: { root: root ?? createInstance(rootConfig) },
|
|
})) as Tree;
|
|
};
|
|
|
|
export const loadById = async (id: string): Promise<Tree> => {
|
|
return (await prisma.tree.findUnique({
|
|
where: { id },
|
|
})) as Tree;
|
|
};
|
|
|
|
export const loadByDomain = async (domain: string): Promise<Tree> => {
|
|
const project = await prisma.project.findUnique({
|
|
where: { domain },
|
|
});
|
|
if (project === null) {
|
|
throw new Error(`Unknown domain "${domain}"`);
|
|
}
|
|
if (project.prodTreeId === null) {
|
|
throw new Error(`Site is not published`);
|
|
}
|
|
return await loadById(project.prodTreeId);
|
|
};
|
|
|
|
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 await loadById(treeId);
|
|
};
|
|
|
|
export const insert = async (
|
|
id: string,
|
|
instanceInsertionSpec: InstanceInsertionSpec
|
|
) => {
|
|
// @todo insert without loading the entire tree
|
|
const tree = await loadById(id);
|
|
const { instance: root } = insertInstance(instanceInsertionSpec, tree.root, {
|
|
populate: false,
|
|
});
|
|
await prisma.tree.update({
|
|
data: { root },
|
|
where: { id },
|
|
});
|
|
};
|
|
|
|
export const reparent = async (
|
|
id: string,
|
|
instanceReparentingSpec: InstanceReparentingSpec
|
|
) => {
|
|
// @todo reparent without loading the entire tree
|
|
const tree = await loadById(id);
|
|
const root = reparentInstance(tree.root, instanceReparentingSpec);
|
|
await prisma.tree.update({
|
|
data: { root },
|
|
where: { id },
|
|
});
|
|
};
|
|
|
|
export const updateStyles = async (id: string, styleUpdates: StyleUpdates) => {
|
|
// @todo we need to update without fetching the tree
|
|
const tree = await loadById(id);
|
|
const root = setInstanceStyle(
|
|
tree.root,
|
|
styleUpdates.id,
|
|
styleUpdates.updates
|
|
);
|
|
await prisma.tree.update({
|
|
data: { root },
|
|
where: { id },
|
|
});
|
|
};
|
|
|
|
export const updateChildren = async (
|
|
id: string,
|
|
change: { instanceId: Instance["id"]; updates: ChildrenUpdates }
|
|
) => {
|
|
// @todo we need to update without fetching the tree
|
|
const tree = await loadById(id);
|
|
const root = setInstanceChildren(
|
|
change.instanceId,
|
|
change.updates,
|
|
tree.root
|
|
);
|
|
await prisma.tree.update({
|
|
data: { root },
|
|
where: { id },
|
|
});
|
|
};
|
|
|
|
export const deleteInstance = async (
|
|
treeId: Tree["id"],
|
|
instanceId: Instance["id"]
|
|
) => {
|
|
// @todo we need to delete without fetching the tree
|
|
const tree = await loadById(treeId);
|
|
const root = deleteInstanceFromTree(tree.root, instanceId);
|
|
if (root === null) return;
|
|
await prisma.tree.update({
|
|
data: { root },
|
|
where: { id: treeId },
|
|
});
|
|
await deleteProps({ instanceId, treeId });
|
|
};
|
|
|
|
export const clone = async (id: string) => {
|
|
const tree = await loadById(id);
|
|
return await create(tree.root);
|
|
};
|