Files
Pien-Studio/packages/editor-core/src/serialization.ts
T

66 lines
1.8 KiB
TypeScript
Raw Normal View History

2026-05-31 03:03:49 +07:00
import {
getLayerAssetRef,
ProjectFileSchema,
type Project,
type ProjectFile,
} from "@pien-studio/types";
2026-05-21 00:02:12 +07:00
import { normalizeProject } from "./normalize";
2026-05-31 03:03:49 +07:00
export function serializeProjectFile(
project: Project,
options?: { checkpointCount?: number },
): string {
const normalized = normalizeProject(project);
2026-05-21 00:02:12 +07:00
const document: ProjectFile = {
format: "pien.project",
2026-05-31 03:03:49 +07:00
version: 2,
2026-05-21 00:02:12 +07:00
exportedAt: new Date().toISOString(),
app: { name: "pien.studio", platform: "web" },
2026-05-31 03:03:49 +07:00
project: normalized,
assets: normalized.layers.flatMap((layer) => {
const asset = getLayerAssetRef(layer);
if (!asset) return [];
if (asset.kind === "stored") {
return [
{
id: asset.id,
kind:
layer.type === "sticker"
? ("sticker" as const)
: ("image" as const),
name: layer.name ?? layer.id,
uri: `asset:${asset.id}`,
},
];
}
return [
{
id: layer.id,
kind:
layer.type === "sticker"
? ("sticker" as const)
: ("image" as const),
name: layer.name ?? layer.id,
uri: asset.uri,
},
];
}),
2026-05-21 00:02:12 +07:00
history: { checkpointCount: options?.checkpointCount ?? 0 },
};
return JSON.stringify(document, null, 2);
}
2026-05-31 03:03:49 +07:00
export function parseProjectFile(
raw: string,
): { ok: true; project: Project } | { ok: false; error: string } {
2026-05-21 00:02:12 +07:00
try {
const data = JSON.parse(raw) as unknown;
const result = ProjectFileSchema.safeParse(data);
2026-05-31 03:03:49 +07:00
if (result.success)
return { ok: true, project: normalizeProject(result.data.project) };
2026-05-21 00:02:12 +07:00
return { ok: false, error: "Invalid project format" };
} catch {
return { ok: false, error: "Invalid JSON" };
}
}