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" };
|
|
|
|
|
}
|
|
|
|
|
}
|