@hyperframes/studio-server 0.8.141 → 0.8.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-DSVQ2U7J.js → chunk-32IH7WBY.js} +36 -14
- package/dist/chunk-32IH7WBY.js.map +1 -0
- package/dist/{chunk-QP7LKFU2.js → chunk-6EFY2WPN.js} +2 -2
- package/dist/{chunk-5VCIZYUE.js → chunk-AYKLBPP2.js} +3 -3
- package/dist/{chunk-CLWFZQUU.js → chunk-JJ4N3PXT.js} +4 -1
- package/dist/chunk-JJ4N3PXT.js.map +1 -0
- package/dist/{chunk-74JVVCWL.js → chunk-RN33UALN.js} +16 -18
- package/dist/chunk-RN33UALN.js.map +1 -0
- package/dist/helpers/loudness.js +4 -1
- package/dist/helpers/mediaCodecMap.js +1 -1
- package/dist/helpers/mediaProxyPreview.js +3 -3
- package/dist/helpers/proxyTranscoder.js +2 -2
- package/dist/helpers/sourceMutation.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +279 -72
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-74JVVCWL.js.map +0 -1
- package/dist/chunk-CLWFZQUU.js.map +0 -1
- package/dist/chunk-DSVQ2U7J.js.map +0 -1
- /package/dist/{chunk-QP7LKFU2.js.map → chunk-6EFY2WPN.js.map} +0 -0
- /package/dist/{chunk-5VCIZYUE.js.map → chunk-AYKLBPP2.js.map} +0 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/createStudioApi.ts","../src/routes/projects.ts","../src/routes/files.ts","../src/helpers/mime.ts","../src/helpers/compositionInputs.ts","../src/helpers/subComposition.ts","../src/helpers/compositionInsertion.ts","../src/helpers/waveform.ts","../src/helpers/mediaValidation.ts","../src/helpers/backupJournal.ts","../src/helpers/projectDirMissing.ts","../src/helpers/applyFileMutations.ts","../src/helpers/studioFontFace.ts","../src/routes/gsapMutationCapabilities.ts","../src/helpers/requestSubPath.ts","../src/routes/preview.ts","../src/helpers/previewReads.ts","../src/helpers/variablesPayload.ts","../src/helpers/previewVariables.ts","../src/helpers/lazyPreviewImages.ts","../src/routes/lint.ts","../src/routes/render.ts","../src/routes/imageThumbnail.ts","../src/routes/thumbnailGenerationCoordinator.ts","../src/routes/thumbnail.ts","../src/routes/waveform.ts","../src/routes/freezeFrame.ts","../src/helpers/freezeFrame.ts","../src/routes/loudness.ts","../src/routes/peaks.ts","../src/helpers/peakMap.ts","../src/routes/fonts.ts","../src/routes/registry.ts","../src/routes/selection.ts","../src/routes/media.ts","../src/routes/globalAssets.ts","../src/routes/history.ts","../src/helpers/duplicateElement.ts","../src/helpers/previewDocumentStore.ts","../src/helpers/thumbnailOutput.ts","../src/helpers/backgroundRemovalJob.ts"],"sourcesContent":["import { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"./types.js\";\nimport { registerProjectRoutes } from \"./routes/projects.js\";\nimport { registerFileRoutes } from \"./routes/files.js\";\nimport { registerPreviewRoutes } from \"./routes/preview.js\";\nimport { registerLintRoutes } from \"./routes/lint.js\";\nimport { registerRenderRoutes } from \"./routes/render.js\";\nimport { registerImageThumbnailRoutes } from \"./routes/imageThumbnail.js\";\nimport { registerThumbnailRoutes } from \"./routes/thumbnail.js\";\nimport { registerWaveformRoutes } from \"./routes/waveform.js\";\nimport { registerFreezeFrameRoutes } from \"./routes/freezeFrame.js\";\nimport { registerLoudnessRoutes } from \"./routes/loudness.js\";\nimport { registerPeakRoutes } from \"./routes/peaks.js\";\nimport { registerFontRoutes } from \"./routes/fonts.js\";\nimport { registerRegistryRoutes } from \"./routes/registry.js\";\nimport { registerSelectionRoutes } from \"./routes/selection.js\";\nimport { registerMediaRoutes } from \"./routes/media.js\";\nimport { registerGlobalAssetRoutes } from \"./routes/globalAssets.js\";\nimport { registerHistoryRoutes } from \"./routes/history.js\";\nimport { replaceWithProjectDirMissing } from \"./helpers/projectDirMissing.js\";\nimport { folderGone, isProjectRootMissing } from \"./helpers/safePath.js\";\n\n/**\n * Create a Hono sub-app with all studio API routes.\n *\n * Both the vite dev server and CLI embedded server mount this app\n * under /api, each providing their own adapter for host-specific behavior.\n */\nexport function createStudioApi(adapter: StudioApiAdapter): Hono {\n const api = new Hono();\n api.use(async function answerProjectDirMissingAfterErrorHandlers(c, next) {\n const hostHeaders = new Headers(c.res.headers);\n await next();\n if (isProjectRootMissing(c.error)) replaceWithProjectDirMissing(c, hostHeaders);\n });\n api.use(\"/projects/:id/*\", async function answerProjectDirMissingForVanishedFolder(c, next) {\n const hostHeaders = new Headers(c.res.headers);\n const dirBeforeRoute = await Promise.resolve()\n .then(() => adapter.resolveProject(c.req.param(\"id\")))\n .then(\n (project) => project?.dir,\n () => undefined,\n );\n await next();\n if (c.res.status >= 403 && dirBeforeRoute && folderGone(dirBeforeRoute))\n replaceWithProjectDirMissing(c, hostHeaders);\n });\n api.use(\"/projects/:id/*\", async function forgetSignatureAfterWrite(c, next) {\n await next();\n if (c.req.method === \"GET\" || c.req.method === \"HEAD\") return;\n const project = await Promise.resolve()\n .then(() => adapter.resolveProject(c.req.param(\"id\")))\n .catch(() => null);\n if (project) adapter.invalidateProjectSignature?.(project.dir);\n });\n api.use(\"/projects/:id/*\", async function openHistorySoNoWriteBecomesItsBaseline(c, next) {\n if (c.req.method !== \"GET\" && c.req.method !== \"HEAD\" && adapter.history) {\n await Promise.resolve()\n .then(() => adapter.resolveProject(c.req.param(\"id\")))\n .then((project) => project && adapter.history?.(project))\n .catch(() => null);\n }\n await next();\n });\n\n registerProjectRoutes(api, adapter);\n registerFileRoutes(api, adapter);\n registerPreviewRoutes(api, adapter);\n registerLintRoutes(api, adapter);\n registerRenderRoutes(api, adapter);\n registerThumbnailRoutes(api, adapter);\n registerImageThumbnailRoutes(api, adapter);\n registerSelectionRoutes(api, adapter);\n registerMediaRoutes(api, adapter);\n registerWaveformRoutes(api, adapter);\n registerFreezeFrameRoutes(api, adapter);\n registerLoudnessRoutes(api, adapter);\n registerPeakRoutes(api, adapter);\n registerFontRoutes(api);\n registerRegistryRoutes(api, adapter);\n registerGlobalAssetRoutes(api);\n registerHistoryRoutes(api, adapter);\n\n return api;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isInHiddenOrVendorDir, isPrivateProjectPath, walkDir } from \"../helpers/safePath.js\";\nimport { isCompositionSource } from \"../helpers/hfIdPersist.js\";\nimport { resolveProjectSignature } from \"../helpers/projectSignature.js\";\n\nasync function filterCompositionFiles(projectDir: string, files: string[]): Promise<string[]> {\n const htmlFiles = files.filter((f) => f.endsWith(\".html\") && !isInHiddenOrVendorDir(f));\n const checks = await Promise.all(\n htmlFiles.map(async (f) => {\n try {\n const content = await readFile(join(projectDir, f), \"utf-8\");\n return isCompositionSource(content);\n } catch {\n return false;\n }\n }),\n );\n return htmlFiles.filter((_, i) => checks[i]);\n}\n\nexport function registerProjectRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // List all projects\n api.get(\"/projects\", async (c) => {\n const projects = await adapter.listProjects();\n return c.json({ projects });\n });\n\n // Resolve session to project (multi-project mode)\n api.get(\"/resolve-session/:sessionId\", async (c) => {\n if (!adapter.resolveSession) {\n return c.json({ error: \"not available\" }, 404);\n }\n const { sessionId } = c.req.param();\n const result = await adapter.resolveSession(sessionId);\n if (!result) return c.json({ error: \"Session not found\" }, 404);\n return c.json(result);\n });\n\n // Current content signature for a project: a cheap poll target for clients that refresh when files change on disk.\n api.get(\"/projects/:id/signature\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n return c.json({ signature: resolveProjectSignature(adapter, project.dir) });\n });\n\n // Project file tree\n api.get(\"/projects/:id\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const files = walkDir(project.dir).filter((file) => !isPrivateProjectPath(file));\n const compositions = await filterCompositionFiles(project.dir, files);\n return c.json({ id: project.id, dir: project.dir, title: project.title, files, compositions });\n });\n}\n","// fallow-ignore-file code-duplication\n// executeGsapMutationRecast and executeGsapMutationAcorn are intentionally\n// parallel — two writers, same switch-case interface. Structural duplication\n// is load-bearing (both paths must remain testable in isolation).\nimport type { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport {\n closeSync,\n existsSync,\n lstatSync,\n openSync,\n readFileSync,\n readlinkSync,\n unlinkSync,\n rmSync,\n statSync,\n fstatSync,\n renameSync,\n readdirSync,\n realpathSync,\n type Dirent,\n} from \"node:fs\";\nimport { resolve, dirname, join } from \"node:path\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isAudioFile } from \"../helpers/mime.js\";\nimport { lengthIsTimeline } from \"../helpers/compositionInputs.js\";\nimport { createFileAtomically, replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\nimport { generateWaveformCache } from \"../helpers/waveform.js\";\nimport { validateUploadedMediaBuffer } from \"../helpers/mediaValidation.js\";\nimport {\n folderGone,\n isInHiddenOrVendorDir,\n isPrivateProjectFile,\n isSafePath,\n mkdirWithinProject,\n pinWithinProject,\n resolveWithinProject,\n walkDir,\n} from \"../helpers/safePath.js\";\nimport { backupPathForResponse, snapshotBeforeWrite } from \"../helpers/backupJournal.js\";\nimport { projectDirMissing } from \"../helpers/projectDirMissing.js\";\nimport {\n createWriteToken,\n fileContentVersion,\n recordFileWriteReceipt,\n} from \"../helpers/fileVersion.js\";\nimport { applyFileMutations, FileChangedError } from \"../helpers/applyFileMutations.js\";\nimport {\n findUnsafeDomPatchValues,\n findUnsafeMutationValues,\n type UnsafeMutationValue,\n} from \"../helpers/finiteMutation.js\";\nimport type { GsapAnimation } from \"@hyperframes/parsers\";\nimport { classifyPropertyGroup } from \"@hyperframes/parsers/gsap-constants\";\nimport { findTimelineScript, parseGsapScriptAcorn } from \"@hyperframes/parsers/gsap-parser-acorn\";\nimport { unrollComputedTimeline } from \"@hyperframes/parsers\";\nimport {\n updateAnimationInScript,\n addAnimationToScript,\n removeAnimationFromScript,\n addKeyframeToScript,\n removeKeyframeFromScript,\n moveKeyframeInScript,\n resizeKeyframedTweenInScript,\n updateKeyframeInScript,\n convertToKeyframesFromScript,\n removeAllKeyframesFromScript,\n materializeKeyframesFromScript,\n unrollDynamicAnimations,\n setArcPathInScript,\n updateArcSegmentInScript,\n updateMotionPathPointInScript,\n addMotionPathPointInScript,\n removeMotionPathPointInScript,\n addMotionPathToScript,\n removeArcPathFromScript,\n addAnimationWithKeyframesToScript,\n replaceTweenWithKeyframesInScript,\n splitAnimationsInScript,\n splitIntoPropertyGroupsFromScript,\n retimeClipTweensInScript,\n type ClipTweenRetime,\n dedupePositionWritesInScript,\n syncPositionHoldsBeforeKeyframes,\n trimTrailingKeyframeSpans,\n clipQueryRoot,\n} from \"@hyperframes/parsers/gsap-writer-acorn\";\nimport {\n removeElementFromHtml,\n removeElementsFromHtml,\n patchElementInHtml,\n probeElementInSource,\n probeElementsInSource,\n splitElementInHtml,\n relinkSplitHalvesInHtml,\n wrapElementsInHtml,\n unwrapElementsFromHtml,\n isHTMLElement,\n type PatchOperation,\n type ElementRebase,\n} from \"../helpers/sourceMutation.js\";\nimport { ensureStudioFontFaceCss, isStudioFontFaceCss } from \"../helpers/studioFontFace.js\";\nimport { parseHTML } from \"linkedom\";\nimport { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport {\n CompositionInsertionError,\n insertCompositionIntoSource,\n} from \"../helpers/compositionInsertion.js\";\nimport { resolveGsapWriter } from \"./gsapMutationCapabilities.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\nimport {\n hasCompositionOutsideTemplates,\n insertBeforeCloseTag,\n} from \"@hyperframes/core/compiler/html-document\";\n\n// ── Server cutover flag ─────────────────────────────────────────────────────\n\n/**\n * Writer selection is deliberately independent from the Studio SDK cutover.\n * Recast remains the default until the capability report has no parity blockers.\n */\n/**\n * Lazy-load gsapParser for write ops (recast-backed) — the default server writer.\n * The read path uses the browser-safe acorn parser; this loader is only needed\n * for the recast write path (the default until the migration gate graduates).\n */\nasync function loadGsapParser() {\n return import(\"@hyperframes/parsers/gsap-parser-recast\");\n}\n\n// ── Shared helpers ──────────────────────────────────────────────────────────\n\n/**\n * Resolve the project and file path from the request, validating safety.\n * Returns null (and sends an error response) if anything is invalid.\n */\ninterface RouteContext {\n req: {\n param: (name: string) => string;\n url: string;\n query: (name: string) => string | undefined;\n header: (name: string) => string | undefined;\n };\n header: (name: string, value: string) => void;\n json: (data: unknown, status?: number) => Response;\n}\n\ninterface ResolvedGsapFile {\n project: { dir: string };\n filePath: string;\n absPath: string;\n}\n\n/**\n * True only for a symlink that itself lives inside the project, whose target\n * (once resolved against the link's own directory) also names a location\n * inside the project, and does not exist anywhere — not for one that exists\n * (that stays a real containment failure) and not for a plain missing path\n * (the ordinary case `resolveWithinProject` already covers).\n *\n * Both containment checks matter, not just the second: a request can name a\n * path lexically *outside* the project (reached via `..`) that happens to be\n * a dangling symlink out there, or a real in-project symlink that points\n * *outside* the project at a target that may or may not exist. Labeling\n * either of those \"not found\" would leak, to anyone who can hit the route,\n * whether an out-of-project path exists — the containment check exists\n * precisely so that answer never depends on what's outside the project.\n * `isSafePath` fails closed on a dangling in-project symlink by design (a\n * write through it could later resolve outside the project once something\n * creates the target) — this does not loosen that; it only tells the caller\n * *why* the containment check refused, so the response can say \"not found\"\n * instead of a path-traversal-shaped \"forbidden\" for a case that scans as\n * broken plumbing, not an attack.\n */\nfunction isDanglingSymlinkInProject(projectDir: string, lexicalPath: string): boolean {\n if (!isSafePath(projectDir, dirname(lexicalPath))) return false;\n let stats;\n try {\n stats = lstatSync(lexicalPath);\n } catch {\n return false;\n }\n if (!stats.isSymbolicLink()) return false;\n const target = resolve(dirname(lexicalPath), readlinkSync(lexicalPath));\n if (!isSafePath(projectDir, target)) return false;\n try {\n statSync(lexicalPath);\n return false;\n } catch {\n return true;\n }\n}\n\n/** Resolve project + safe absolute path for any project-scoped route. */\nasync function resolveProjectPath(\n c: RouteContext,\n adapter: StudioApiAdapter,\n route: string,\n opts?: { mustExist?: boolean; pin?: boolean },\n) {\n const id = c.req.param(\"id\");\n const project = await adapter.resolveProject(id);\n if (!project) {\n return { error: c.json({ error: \"not found\" }, 404) } as const;\n }\n\n // The CLI host's `resolveProject` is static (`id === projectId ? project : null`),\n // so it keeps answering with this project even after its folder is renamed\n // or deleted out from under a running `preview` — mount-time validation\n // (`/api/projects/:id`) still passes, so nothing upstream catches this.\n // Every subsequent read then failed closed inside `isSafePath` (its\n // `realpathSync(base)` throws when the base itself is gone) and reported as\n // `403 forbidden` — indistinguishable from a real path-traversal attempt.\n // Checked here, once, so every route built on this shares the fix.\n if (folderGone(project.dir)) {\n return { error: projectDirMissing(c) } as const;\n }\n\n const filePath = requestSubPath(c.req.url, `projects/:id/${route}`);\n if (filePath.includes(\"\\0\")) {\n return { error: c.json({ error: \"forbidden\", why: \"nul\" }, 403) } as const;\n }\n\n // An edit pins its target; create-only writes use `wx`, and a delete or rename acts on a link itself.\n const absPath = (opts?.pin ? pinWithinProject : resolveWithinProject)(project.dir, filePath);\n if (!absPath) {\n if (isDanglingSymlinkInProject(project.dir, resolve(project.dir, filePath))) {\n return { error: c.json({ error: \"not found\", why: \"dangling_symlink\" }, 404) } as const;\n }\n return { error: c.json({ error: \"forbidden\", why: \"outside_project\" }, 403) } as const;\n }\n\n if (opts?.mustExist && !existsSync(absPath)) {\n return { error: c.json({ error: \"not found\" }, 404) } as const;\n }\n\n return { project, filePath, absPath } as const;\n}\n\nfunction resolveProjectFile(\n c: RouteContext,\n adapter: StudioApiAdapter,\n opts?: { mustExist?: boolean; pin?: boolean },\n) {\n return resolveProjectPath(c, adapter, \"files\", opts);\n}\n\nfunction resolveFileMutationContext(c: RouteContext, adapter: StudioApiAdapter, operation: string) {\n return resolveProjectPath(c, adapter, `file-mutations/${operation}`, { pin: true });\n}\n\ntype MutationTarget = {\n id?: string | null;\n hfId?: string;\n selector?: string;\n selectorIndex?: number;\n};\n\ninterface ElementPatchRequest {\n target: MutationTarget;\n operations: PatchOperation[];\n}\n\ninterface ElementPatchBatchRequest {\n sourceFile: string;\n patches: ElementPatchRequest[];\n}\n\ninterface ElementPatchBatchFileResult {\n sourceFile: string;\n changed: boolean;\n matched: boolean[];\n before: string;\n after: string;\n backupPath?: string | null;\n}\n\ninterface AtomicCutTarget {\n target: MutationTarget;\n originalId?: string;\n splitTime: number;\n elementStart: number;\n elementDuration: number;\n playbackStart?: number;\n playbackRate?: number;\n isComposition?: boolean;\n track?: number;\n}\n\ninterface AtomicCutFileRequest {\n path: string;\n expectedVersion: string;\n targets: AtomicCutTarget[];\n}\n\nfunction isOptionalInteger(value: unknown): value is number | undefined {\n return value === undefined || Number.isInteger(value);\n}\n\nfunction isAtomicCutTarget(value: unknown): value is AtomicCutTarget {\n if (!value || typeof value !== \"object\") return false;\n const target = value as Partial<AtomicCutTarget>;\n return (\n !!target.target &&\n typeof target.target === \"object\" &&\n Number.isFinite(target.splitTime) &&\n Number.isFinite(target.elementStart) &&\n Number.isFinite(target.elementDuration) &&\n Number(target.elementDuration) > 0 &&\n isOptionalInteger(target.track)\n );\n}\n\nfunction isAtomicCutFileRequest(value: unknown): value is AtomicCutFileRequest {\n if (!value || typeof value !== \"object\") return false;\n const file = value as Partial<AtomicCutFileRequest>;\n return (\n typeof file.path === \"string\" &&\n file.path.length > 0 &&\n typeof file.expectedVersion === \"string\" &&\n Array.isArray(file.targets) &&\n file.targets.length > 0 &&\n file.targets.every(isAtomicCutTarget)\n );\n}\n\nlet atomicCutTail: Promise<unknown> = Promise.resolve();\n\n/** Serialize cut actions so a rapid second gesture observes the first one's bytes. */\nfunction serializeAtomicCut<T>(task: () => Promise<T>): Promise<T> {\n const next = atomicCutTail.then(task, task);\n atomicCutTail = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n}\n\nfunction isElementPatchRequest(value: unknown): value is ElementPatchRequest {\n if (typeof value !== \"object\" || value === null) return false;\n if (!(\"target\" in value) || typeof value.target !== \"object\" || value.target === null) {\n return false;\n }\n return \"operations\" in value && Array.isArray(value.operations) && value.operations.length > 0;\n}\n\nfunction isElementPatchBatchRequest(value: unknown): value is ElementPatchBatchRequest {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"sourceFile\" in value &&\n typeof value.sourceFile === \"string\" &&\n value.sourceFile.length > 0 &&\n \"patches\" in value &&\n Array.isArray(value.patches) &&\n value.patches.length > 0 &&\n value.patches.every(isElementPatchRequest)\n );\n}\n\nfunction findUnsafeElementPatchBatchValues(\n batches: readonly ElementPatchBatchRequest[],\n): UnsafeMutationValue[] {\n return batches.flatMap((batch) =>\n batch.patches.flatMap((patch) => findUnsafeDomPatchValues(patch)),\n );\n}\n\nfunction foldElementPatches(\n originalContent: string,\n patches: ElementPatchRequest[],\n): { content: string; matched: boolean[] } {\n let content = originalContent;\n const matched: boolean[] = [];\n for (const patch of patches) {\n const result = patchElementInHtml(content, patch.target, patch.operations);\n content = result.html;\n matched.push(result.matched);\n }\n return { content, matched };\n}\n\nconst PATCH_CONFLICT_ATTEMPTS = 3;\n\nconst ID_ATTRIBUTE = /[\\s\"'/]id\\s*=\\s*(?=(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))/gi;\n\n/** Every id in the project's HTML files: sub-compositions share one preview document. */\nfunction projectHtmlIds(projectDir: string): Set<string> {\n const ids = new Set<string>();\n for (const rel of walkDir(projectDir)) {\n if (!rel.endsWith(\".html\") || isInHiddenOrVendorDir(rel)) continue;\n let html: string;\n try {\n html = readFileSync(join(projectDir, rel), \"utf-8\");\n } catch {\n continue;\n }\n for (const m of html.matchAll(ID_ATTRIBUTE)) ids.add(m[1] ?? m[2] ?? m[3] ?? \"\");\n }\n return ids;\n}\n\ntype ElementPatchCommitResult =\n | { error: \"duplicate\" | \"forbidden\" | \"not-found\" | \"conflict\"; sourceFile: string }\n | { durable: boolean; files: ElementPatchBatchFileResult[] };\n\n/**\n * The single commit owner for element patch batches. All files are resolved,\n * read, and folded before the first write; any unmatched target refuses the\n * whole request, and a write from elsewhere mid-fold refolds before it answers 409.\n * Studio Server is single-process; within it the final snapshots/writes are\n * synchronous, so another route cannot interleave once the commit begins. A\n * multi-process deployment needs a shared per-project file lock instead.\n */\nexport function commitElementPatchBatches(\n projectDir: string,\n batches: ElementPatchBatchRequest[],\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void = (path, content) =>\n replaceFileAtomically(path, content, statSync(path).mode),\n requestToken?: string,\n): ElementPatchCommitResult {\n for (let attempt = 1; ; attempt += 1) {\n try {\n return foldAndCommitElementPatchBatches(projectDir, batches, writeFile, requestToken);\n } catch (error) {\n if (!(error instanceof FileChangedError)) throw error;\n if (attempt === PATCH_CONFLICT_ATTEMPTS)\n return { error: \"conflict\", sourceFile: error.sourceFile };\n }\n }\n}\n\nfunction foldAndCommitElementPatchBatches(\n projectDir: string,\n batches: ElementPatchBatchRequest[],\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void,\n requestToken: string | undefined,\n): ElementPatchCommitResult {\n const resolvedPaths = new Set<string>();\n const prepared: Array<{\n sourceFile: string;\n absPath: string;\n before: string;\n matched: boolean[];\n after: string;\n }> = [];\n\n for (const batch of batches) {\n const absPath = pinWithinProject(projectDir, batch.sourceFile);\n if (!absPath) return { error: \"forbidden\", sourceFile: batch.sourceFile };\n if (resolvedPaths.has(absPath)) return { error: \"duplicate\", sourceFile: batch.sourceFile };\n resolvedPaths.add(absPath);\n\n let before: string;\n try {\n before = readFileSync(absPath, \"utf-8\");\n } catch {\n return { error: \"not-found\", sourceFile: batch.sourceFile };\n }\n const folded = foldElementPatches(before, batch.patches);\n prepared.push({\n sourceFile: batch.sourceFile,\n absPath,\n before,\n matched: folded.matched,\n after: folded.content,\n });\n }\n\n const durable = prepared.every((file) => file.matched.every(Boolean));\n if (!durable) {\n return {\n durable: false,\n files: prepared.map((file) => ({\n sourceFile: file.sourceFile,\n changed: false,\n matched: file.matched,\n before: file.before,\n after: file.before,\n })),\n };\n }\n\n const applied = applyFileMutations(\n projectDir,\n prepared.map(({ sourceFile, absPath, before, after }) => ({\n sourceFile,\n absPath,\n before,\n after,\n })),\n requestToken,\n writeFile,\n );\n const files: ElementPatchBatchFileResult[] = applied.map((file, index) => ({\n sourceFile: file.sourceFile,\n changed: file.changed,\n matched: prepared[index]?.matched ?? [],\n before: file.before,\n after: file.after,\n backupPath: file.backupPath ?? undefined,\n }));\n return { durable: true, files };\n}\n\nfunction commitElementPatchBatchesWithReceipts(\n c: RouteContext,\n projectDir: string,\n batches: ElementPatchBatchRequest[],\n): ReturnType<typeof commitElementPatchBatches> {\n return commitElementPatchBatches(\n projectDir,\n batches,\n undefined,\n c.req.header(\"X-Hyperframes-Write-Token\"),\n );\n}\n\n/**\n * Record the receipt that claims a mutation result.\n *\n * The file watcher broadcasts every write, including the ones Studio itself just\n * asked for. The receipt is what lets the client tell its own echo from an agent\n * or an editor writing the file behind its back: without one, the client treats\n * its own edit as an external change and does a full preview reload, which blanks\n * the stage for a few hundred milliseconds right after the user typed. Every\n * mutation route records through here so no route can forget.\n */\nfunction writeFileWithReceipt(\n c: RouteContext,\n filePath: string,\n absPath: string,\n html: string,\n): { version: string; writeToken: string } {\n const overwrote = readFileSync(absPath);\n replaceFileAtomically(absPath, html, statSync(absPath).mode);\n // The synchronous write cannot yield before its receipt is recorded; keep this block await-free.\n const version = fileContentVersion(html);\n const writeToken = createWriteToken(c.req.header(\"X-Hyperframes-Write-Token\"));\n recordFileWriteReceipt(absPath, { path: filePath, version, writeToken, overwrote });\n return { version, writeToken };\n}\n\nfunction writeMutationResult(\n c: RouteContext,\n projectDir: string,\n filePath: string,\n absPath: string,\n html: string,\n original: string,\n): { backupPath: string | null; version: string } | Response {\n const backup = snapshotBeforeWrite(projectDir, absPath);\n if (backup.error) return c.json({ error: `backup failed: ${backup.error}` }, 500);\n if (readFileSync(absPath, \"utf-8\") !== original) {\n return c.json({ error: \"file changed\", conflict: true, path: filePath }, 409);\n }\n const { version } = writeFileWithReceipt(c, filePath, absPath, html);\n return { backupPath: backupPathForResponse(projectDir, backup.backupPath), version };\n}\n\n/** Write `next` to `absPath` only if it differs from `original`, returning a standardized change response. */\nfunction writeIfChanged(\n c: RouteContext,\n projectDir: string,\n filePath: string,\n absPath: string,\n original: string,\n next: string,\n): Response {\n if (next === original) {\n return c.json({ ok: true, changed: false, content: original, path: filePath });\n }\n const mutationResult = writeMutationResult(c, projectDir, filePath, absPath, next, original);\n if (mutationResult instanceof Response) return mutationResult;\n const { backupPath } = mutationResult;\n return c.json({\n ok: true,\n changed: true,\n content: next,\n path: filePath,\n backupPath,\n });\n}\n\nfunction rejectUnsafeMutationValues(\n c: RouteContext,\n unsafeFields: UnsafeMutationValue[],\n): Response {\n return c.json(\n {\n error: \"mutation contains unsafe values\",\n fields: unsafeFields.map((field) => field.path),\n unsafeValues: unsafeFields,\n },\n 400,\n );\n}\n\nfunction elementPatchBatchCommitErrorResponse(\n c: RouteContext,\n error: Extract<ElementPatchCommitResult, { error: unknown }>[\"error\"],\n sourceFile: string,\n): Response {\n if (error === \"conflict\")\n return c.json({ error: \"file changed\", conflict: true, sourceFile }, 409);\n if (error === \"not-found\") return c.json({ error, sourceFile }, 404);\n if (error === \"forbidden\") return c.json({ error, sourceFile }, 403);\n return c.json({ error: \"duplicate source file\", sourceFile }, 400);\n}\n\n/**\n * Parse the request body and validate that `target` is present.\n * Returns `{ error }` if missing, or `{ target, body }` for the full parsed body.\n */\nasync function parseMutationBody<T extends { target?: MutationTarget }>(\n c: RouteContext & { req: { json(): Promise<unknown> } },\n): Promise<{ error: Response } | { target: MutationTarget; body: T }> {\n const body = (await (c.req as { json(): Promise<unknown> }).json().catch(() => null)) as T | null;\n if (!body?.target) {\n return { error: c.json({ error: \"target required\" }, 400) };\n }\n return { target: body.target, body };\n}\n\n/** Ensure the parent directory of a path exists, never recreating a project folder that is gone. */\nfunction ensureDir(projectDir: string, filePath: string) {\n mkdirWithinProject(projectDir, dirname(filePath));\n}\n\n/**\n * Generate a copy name: foo.html → foo (copy).html → foo (copy 2).html\n */\nfunction generateCopyPath(projectDir: string, originalPath: string): string {\n const ext = originalPath.includes(\".\") ? \".\" + originalPath.split(\".\").pop() : \"\";\n const base = ext ? originalPath.slice(0, -ext.length) : originalPath;\n\n // If already a copy, increment the number\n const copyMatch = base.match(/ \\(copy(?: (\\d+))?\\)$/);\n const cleanBase = copyMatch ? base.slice(0, -copyMatch[0].length) : base;\n let num = copyMatch ? (copyMatch[1] ? parseInt(copyMatch[1]) + 1 : 2) : 1;\n\n let candidate = num === 1 ? `${cleanBase} (copy)${ext}` : `${cleanBase} (copy ${num})${ext}`;\n while (existsSync(resolve(projectDir, candidate))) {\n num++;\n candidate = `${cleanBase} (copy ${num})${ext}`;\n }\n\n return candidate;\n}\n\n/**\n * Walk a directory recursively and return all file paths matching a filter.\n */\nfunction walkFiles(dir: string, filter: (name: string) => boolean): string[] {\n const results: string[] = [];\n for (const entry of readableEntries(dir)) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (\n entry.name === \"node_modules\" ||\n entry.name === \".thumbnails\" ||\n entry.name === \"renders\" ||\n entry.name === \".transcode-cache\"\n )\n continue;\n results.push(...walkFiles(full, filter));\n } else if (filter(entry.name)) {\n results.push(full);\n }\n }\n return results;\n}\n\nconst SKIPPED_ENTRY = new Set([\"EACCES\", \"EPERM\", \"ENOENT\"]);\n\nfunction skippable(error: unknown): boolean {\n return error instanceof Error && SKIPPED_ENTRY.has((error as NodeJS.ErrnoException).code ?? \"\");\n}\n\nfunction readableEntries(dir: string): Dirent[] {\n try {\n return readdirSync(dir, { withFileTypes: true });\n } catch (error) {\n if (skippable(error)) return [];\n throw error;\n }\n}\n\nfunction readableText(file: string): string | null {\n try {\n return readFileSync(file, \"utf-8\");\n } catch (error) {\n if (skippable(error)) return null;\n throw error;\n }\n}\n\nconst escapeRegExp = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nconst SEPARATOR = String.raw`\\\\{0,2}[\\\\/]`;\nconst REFERENCE_START = String.raw`(?<![\\w./\\\\+-])`;\nconst FILE_END = String.raw`(?![\\w-]|\\.\\w)`;\n\nfunction referencePattern(oldPath: string, isDirectory: boolean): RegExp {\n const name = oldPath.split(\"/\").map(escapeRegExp).join(SEPARATOR);\n const end = isDirectory ? `(?=${SEPARATOR})` : FILE_END;\n return new RegExp(\n String.raw`${REFERENCE_START}(?<lead>(?:\\.{1,2}${SEPARATOR}|${SEPARATOR}){0,4})${name}${end}`,\n \"g\",\n );\n}\n\n// A match inside the longer path of a file or folder that exists (`a.png&b.png`, `other assets/`) is that path's.\n// Existing paths are indexed by the text after the old path, then the text before it, so a match costs a few lookups.\nexport function referenceRewriter(\n oldPath: string,\n newPath: string,\n isDirectory: boolean,\n existing: readonly string[] = [],\n): (text: string) => string {\n const pattern = referencePattern(oldPath, isDirectory);\n const around = new Map<string, Map<number, Set<string>>>();\n const afterLengths = new Set<number>();\n let window = 0;\n for (const path of existing) {\n if (path.length <= oldPath.length) continue;\n for (const start of occurrences(path, oldPath)) {\n const [before, after] = [path.slice(0, start), path.slice(start + oldPath.length)];\n const befores = around.get(after) ?? around.set(after, new Map()).get(after)!;\n (befores.get(before.length) ?? befores.set(before.length, new Set()).get(before.length)!).add(\n before,\n );\n afterLengths.add(after.length);\n window = Math.max(window, path.length * 3);\n }\n }\n const normalized = (text: string) => text.replace(/\\\\{0,2}[\\\\/]/g, \"/\");\n return (text) =>\n text.replace(pattern, (...args) => {\n const [match, offset] = [args[0] as string, args.at(-3) as number];\n const { lead } = args.at(-1) as { lead: string };\n const at = offset + lead.length;\n const head = normalized(text.slice(Math.max(0, at - window), at));\n const tail = normalized(text.slice(offset + match.length, offset + match.length + window));\n const inLonger = [...afterLengths].some((after) => {\n const befores = tail.length >= after && around.get(tail.slice(0, after));\n return (\n befores &&\n [...befores].some(\n ([length, set]) => head.length >= length && set.has(head.slice(head.length - length)),\n )\n );\n });\n return inLonger ? match : `${lead}${newPath}`;\n });\n}\n\nfunction occurrences(text: string, part: string): number[] {\n const at: number[] = [];\n for (let i = text.indexOf(part); i >= 0; i = text.indexOf(part, i + 1)) at.push(i);\n return at;\n}\n\nfunction projectPaths(\n root: string,\n dir = root,\n prefix = \"\",\n ancestors: ReadonlySet<string> = new Set(),\n): string[] {\n return readableEntries(dir).flatMap((entry) => {\n const [path, full] = [`${prefix}${entry.name}`, join(dir, entry.name)];\n const real = entry.name === \"node_modules\" ? null : directoryReal(entry, full);\n if (real === null || ancestors.has(real) || !isSafePath(root, full)) return [path];\n return [path, ...projectPaths(root, full, `${path}/`, new Set([...ancestors, real]))];\n });\n}\n\n// A directory's real path, through a link, or null for anything else: aliases are paths too.\nfunction directoryReal(entry: Dirent, full: string): string | null {\n try {\n return entry.isDirectory() || (entry.isSymbolicLink() && statSync(full).isDirectory())\n ? realpathSync(full)\n : null;\n } catch {\n return null;\n }\n}\n\n/**\n * After a rename, update all references to the old path in project files.\n * Scans HTML, CSS, JS, and JSON files for the old path and replaces it where it names that path.\n */\nfunction updateReferences(\n projectDir: string,\n oldPath: string,\n newPath: string,\n isDirectory: boolean,\n): number {\n const textFiles = walkFiles(projectDir, (name) =>\n /\\.(html|css|js|jsx|ts|tsx|json|mjs|cjs|md|mdx)$/i.test(name),\n );\n\n const rewrite = referenceRewriter(oldPath, newPath, isDirectory, projectPaths(projectDir));\n let updatedCount = 0;\n for (const file of textFiles) {\n if (!isSafePath(projectDir, file) || isPrivateProjectFile(projectDir, file)) continue;\n const content = readableText(file);\n if (content === null) continue;\n\n const updated = rewrite(content);\n if (updated !== content) {\n replaceFileAtomically(file, updated, statSync(file).mode);\n updatedCount++;\n }\n }\n return updatedCount;\n}\n\n// ── GSAP script extraction ──────────────────────────────────────────────────\n\n/**\n * Mint the HTML's ids (so a tween saved on a served id writes that id too), parse it with\n * linkedom, locate the inline `<script>` holding GSAP timeline code, and return its text and\n * a function that replaces that script block and serialises back to HTML.\n */\nfunction extractGsapScriptBlock(html: string): {\n scriptText: string;\n document: Document;\n root: ParentNode;\n replaceScript: (newText: string) => string;\n} | null {\n const { document } = parseHTML(ensureHfIds(html));\n const scripts = [\n ...document.querySelectorAll(\"script:not([src])\"),\n ...Array.from(document.querySelectorAll(\"template\")).flatMap((tmpl) =>\n Array.from(tmpl.querySelectorAll(\"script:not([src])\")),\n ),\n ];\n const script = findTimelineScript(scripts);\n if (!script) return null;\n return {\n scriptText: script.textContent || \"\",\n document,\n root: clipQueryRoot(script),\n replaceScript(newText: string): string {\n script.textContent = newText;\n return document.toString();\n },\n };\n}\n\n/**\n * Remove every GSAP animation that targets `selector` from an HTML string's\n * inline script. Used after unwrapping a group so its leftover `gsap.set(\"#id\")`\n * (the wrapper is gone) doesn't throw \"target not found\" on every preview run.\n */\nfunction stripGsapAnimationsForSelector(html: string, selector: string): string {\n const block = extractGsapScriptBlock(html);\n if (!block) return html;\n const parsed = parseGsapScriptAcorn(block.scriptText);\n const matching = parsed.animations.filter((a) => a.targetSelector === selector);\n if (matching.length === 0) return html;\n let script = block.scriptText;\n // Reverse so earlier removals don't shift the spans of later ones.\n for (const anim of [...matching].reverse()) {\n script = removeAnimationFromScript(script, anim.id);\n }\n return block.replaceScript(script);\n}\n\n/**\n * Bake a group's STATIC GSAP transform into each member BEFORE the group is\n * stripped on ungroup. Moving a group is stored as `gsap.set(\"#group-1\",{x,y,…})`;\n * without distributing it to the members they snap back to their creation-time\n * positions. Translation (x/y/z) is an exact per-axis add; rotation/scale are\n * composed about the group's centre (the pivot) so off-centre members don't drift.\n * Animated group transforms (keyframes/tweens) are NOT baked — left to be stripped.\n */\nfunction bakeGroupTransformIntoMembers(\n html: string,\n groupId: string,\n members: Array<{ id: string; cx: number; cy: number }>,\n groupCenter: { cx: number; cy: number },\n): string {\n const block = extractGsapScriptBlock(html);\n if (!block) return html;\n const parsed = parseGsapScriptAcorn(block.scriptText);\n const groupSel = `#${groupId}`;\n const groupSets = parsed.animations.filter(\n (a) => a.targetSelector === groupSel && a.method === \"set\",\n );\n if (groupSets.length === 0) return html;\n // Merge the group's sets (later per-prop wins) → its effective static transform.\n const gt: Record<string, number> = {};\n for (const s of groupSets) {\n for (const [k, v] of Object.entries(s.properties)) if (typeof v === \"number\") gt[k] = v;\n }\n const gx = gt.x ?? 0;\n const gy = gt.y ?? 0;\n const gz = gt.z ?? 0;\n const grot = gt.rotation ?? 0;\n const gscale = gt.scale ?? 1;\n // Identity across ALL axes (incl. the extras baked below) — else a group whose\n // only transform is e.g. scaleX would skip the bake and silently drop it.\n const isScaleAxis = (k: string) => k === \"scale\" || k === \"scaleX\" || k === \"scaleY\";\n const groupIsIdentity = Object.entries(gt).every(([k, v]) =>\n isScaleAxis(k) ? v === 1 : v === 0,\n );\n if (groupIsIdentity) return html;\n\n const rad = (grot * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const round3 = (n: number) => Math.round(n * 1000) / 1000;\n\n let script = block.scriptText;\n for (const m of members) {\n const memberSel = `#${m.id}`;\n const sets = parsed.animations.filter(\n (a) => a.targetSelector === memberSel && a.method === \"set\",\n );\n // Effective member transform (merge its sets — last per-prop wins).\n const mProps: Record<string, number | string> = {};\n for (const s of sets) Object.assign(mProps, s.properties);\n const mx = typeof mProps.x === \"number\" ? mProps.x : 0;\n const my = typeof mProps.y === \"number\" ? mProps.y : 0;\n // Compose the group transform onto the member's centre, then back to an offset.\n const dx = m.cx + mx - groupCenter.cx;\n const dy = m.cy + my - groupCenter.cy;\n const visX = groupCenter.cx + gscale * (cos * dx - sin * dy) + gx;\n const visY = groupCenter.cy + gscale * (sin * dx + cos * dy) + gy;\n const newProps: Record<string, number | string> = {\n ...mProps,\n x: round3(visX - m.cx),\n y: round3(visY - m.cy),\n };\n if (gz !== 0) newProps.z = (typeof mProps.z === \"number\" ? mProps.z : 0) + gz;\n if (grot !== 0) {\n newProps.rotation = round3(\n (typeof mProps.rotation === \"number\" ? mProps.rotation : 0) + grot,\n );\n }\n if (gscale !== 1) {\n newProps.scale = round3((typeof mProps.scale === \"number\" ? mProps.scale : 1) * gscale);\n }\n // Bake any REMAINING group transform axis so nothing is silently dropped on\n // ungroup. The pivot-composed axes (x/y/z/rotation/scale) are handled above;\n // these extras (scaleX/Y, rotationX/Y/Z, skewX/Y, transformPerspective) compose\n // about the member's own origin — exact for a member at the group centre, a\n // close approximation otherwise (groups rarely carry these).\n const pivoted = new Set([\"x\", \"y\", \"z\", \"rotation\", \"scale\"]);\n for (const [k, v] of Object.entries(gt)) {\n if (pivoted.has(k) || typeof v !== \"number\") continue;\n if (k === \"scaleX\" || k === \"scaleY\") {\n if (v !== 1) newProps[k] = round3((typeof mProps[k] === \"number\" ? mProps[k] : 1) * v);\n } else if (k === \"transformPerspective\") {\n // Adopt the group's lens only if the member has none of its own — never\n // silently overwrite a member's existing perspective.\n if (typeof mProps[k] !== \"number\") newProps[k] = v;\n } else if (v !== 0) {\n newProps[k] = round3((typeof mProps[k] === \"number\" ? mProps[k] : 0) + v);\n }\n }\n\n // Strip ALL the member's existing sets and write ONE fresh gsap.set at position\n // 0. The baked transform is the member's static base — writing it to an arbitrary\n // \"last\" set could land it at a non-zero timeline position, or leave stale earlier\n // sets that override it. Reverse-remove so spans don't shift, then add fresh.\n for (const s of [...sets].reverse()) {\n script = removeAnimationFromScript(script, s.id);\n }\n script = addAnimationToScript(script, {\n targetSelector: memberSel,\n method: \"set\",\n position: 0,\n properties: newProps,\n global: true,\n }).script;\n }\n return block.replaceScript(script);\n}\n\nfunction stripStudioEditsFromTarget(document: Document, selector: string): number {\n if (!selector) return 0;\n let stripped = 0;\n try {\n for (const el of document.querySelectorAll(selector)) {\n if (!isHTMLElement(el)) continue;\n const htmlEl = el;\n let touched = false;\n // Manual path offset (--hf-studio-offset / translate) — a GSAP position tween\n // now owns position, so the stale offset channel must go.\n if (el.getAttribute(\"data-hf-studio-path-offset\")) {\n const originalTranslate = el.getAttribute(\"data-hf-studio-original-inline-translate\");\n htmlEl.style.removeProperty(\"--hf-studio-offset-x\");\n htmlEl.style.removeProperty(\"--hf-studio-offset-y\");\n if (originalTranslate) {\n htmlEl.style.setProperty(\"translate\", originalTranslate);\n } else {\n htmlEl.style.removeProperty(\"translate\");\n }\n el.removeAttribute(\"data-hf-studio-path-offset\");\n el.removeAttribute(\"data-hf-studio-original-translate\");\n el.removeAttribute(\"data-hf-studio-original-inline-translate\");\n touched = true;\n }\n // Manual rotation (--hf-studio-rotation / rotate) — likewise, a GSAP rotation\n // set/tween now owns rotation, so clear the legacy CSS-var channel.\n if (el.getAttribute(\"data-hf-studio-rotation\")) {\n const originalRotate = el.getAttribute(\"data-hf-studio-original-inline-rotate\");\n const originalOrigin = el.getAttribute(\"data-hf-studio-original-rotation-transform-origin\");\n htmlEl.style.removeProperty(\"--hf-studio-rotation\");\n if (originalRotate) {\n htmlEl.style.setProperty(\"rotate\", originalRotate);\n } else {\n htmlEl.style.removeProperty(\"rotate\");\n }\n if (originalOrigin) {\n htmlEl.style.setProperty(\"transform-origin\", originalOrigin);\n } else {\n htmlEl.style.removeProperty(\"transform-origin\");\n }\n el.removeAttribute(\"data-hf-studio-rotation\");\n el.removeAttribute(\"data-hf-studio-rotation-draft\");\n el.removeAttribute(\"data-hf-studio-original-rotate\");\n el.removeAttribute(\"data-hf-studio-original-inline-rotate\");\n el.removeAttribute(\"data-hf-studio-original-rotation-transform-origin\");\n touched = true;\n }\n if (touched) stripped++;\n }\n } catch {\n // Invalid selector — skip silently.\n }\n return stripped;\n}\n\n// A studio path-offset (--hf-studio-offset / data-hf-studio-path-offset) and a GSAP\n// position tween both drive translate — keeping both stacks the offsets (a gesture or\n// drag recorded over a stale offset plays shoved off-position). When a committed tween\n// writes a position property, the tween owns position, so the stale offset must go.\nfunction keyframesWritePosition(\n keyframes: Array<{ properties: Record<string, number | string> }>,\n): boolean {\n return keyframes.some((kf) =>\n Object.keys(kf.properties).some((k) => classifyPropertyGroup(k) === \"position\"),\n );\n}\n\n// A studio rotation edit (--hf-studio-rotation / data-hf-studio-rotation) and a GSAP\n// rotation tween both drive rotate — keeping both stacks them. When a committed keyframe\n// set writes a rotation property, the tween owns rotation, so the stale CSS-var channel\n// must go (the position twin of this is `keyframesWritePosition`).\nfunction keyframesWriteRotation(\n keyframes: Array<{ properties: Record<string, number | string> }>,\n): boolean {\n return keyframes.some((kf) =>\n Object.keys(kf.properties).some((k) => classifyPropertyGroup(k) === \"rotation\"),\n );\n}\n\nfunction lastKeyframeOpacity(kfs: GsapAnimation[\"keyframes\"]): number | string | undefined {\n if (!kfs) return undefined;\n for (let i = kfs.keyframes.length - 1; i >= 0; i--) {\n if (\"opacity\" in kfs.keyframes[i]!.properties) return kfs.keyframes[i]!.properties.opacity;\n }\n return undefined;\n}\n\nfunction resolveFinalOpacity(anim: GsapAnimation): number | null {\n if (anim.method === \"from\") return null;\n const raw = anim.keyframes ? lastKeyframeOpacity(anim.keyframes) : anim.properties.opacity;\n if (raw == null) return null;\n if (typeof raw === \"string\" && /^[+\\-*]=/.test(raw)) return null;\n const num = Number(raw);\n return Number.isFinite(num) && num !== 0 ? num : null;\n}\n\nfunction bakeVisibilityOnDelete(document: Document, anim: GsapAnimation): void {\n const opacity = resolveFinalOpacity(anim);\n if (opacity === null) return;\n try {\n for (const el of document.querySelectorAll(anim.targetSelector)) {\n if (isHTMLElement(el)) el.style.setProperty(\"opacity\", String(opacity));\n }\n } catch {\n // Invalid selector — skip silently.\n }\n}\n\n// ── GSAP mutation types ─────────────────────────────────────────────────────\n\nexport type GsapMutationRequest =\n | {\n type: \"update-property\";\n animationId: string;\n property: string;\n value: number | string;\n }\n | {\n // Merge MULTIPLE properties into an animation in ONE call. A per-property\n // loop on a `set` can shift its group-derived id mid-way (e.g. adding `scale`\n // to a rotation set), 404-ing the next update; this lands them all at once.\n type: \"update-properties\";\n animationId: string;\n properties: Record<string, number | string>;\n }\n | {\n type: \"update-from-property\";\n animationId: string;\n property: string;\n value: number | string;\n }\n | {\n type: \"update-meta\";\n animationId: string;\n updates: {\n duration?: number;\n ease?: string;\n easeEach?: string;\n position?: number;\n resetKeyframeEases?: boolean;\n };\n }\n | {\n type: \"add\";\n targetSelector: string;\n method: \"to\" | \"from\" | \"set\" | \"fromTo\";\n position: number;\n duration?: number;\n ease?: string;\n properties: Record<string, number | string>;\n fromProperties?: Record<string, number | string>;\n /** Emit a base `gsap.set` (off-timeline, no keyframe marker) instead of `tl.set`. */\n global?: boolean;\n }\n | { type: \"delete\"; animationId: string; stripStudioEdits?: boolean }\n | {\n type: \"add-property\";\n animationId: string;\n property: string;\n defaultValue: number | string;\n }\n | {\n type: \"add-from-property\";\n animationId: string;\n property: string;\n defaultValue: number | string;\n }\n | { type: \"remove-property\"; animationId: string; property: string }\n | { type: \"remove-from-property\"; animationId: string; property: string }\n | {\n type: \"add-keyframe\";\n animationId: string;\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n backfillDefaults?: Record<string, number | string>;\n }\n | { type: \"remove-keyframe\"; animationId: string; percentage: number }\n | {\n type: \"move-keyframe\";\n animationId: string;\n fromPercentage: number;\n toPercentage: number;\n }\n | {\n // Boundary drag-to-retime: grow/shift a keyframed tween's window and re-key\n // its existing keyframes in place (preserves _auto / per-keyframe ease /\n // easeEach / outer ease, unlike the array-rebuild replace-with-keyframes).\n type: \"resize-keyframed-tween\";\n animationId: string;\n position: number;\n duration: number;\n pctRemap: Array<{ from: number; to: number }>;\n }\n | {\n type: \"update-keyframe\";\n animationId: string;\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n }\n | {\n type: \"convert-to-keyframes\";\n animationId: string;\n resolvedFromValues?: Record<string, number | string>;\n /** Duration (s) to give a converted static `set`, which has none. */\n duration?: number;\n }\n | { type: \"remove-all-keyframes\"; animationId: string }\n | {\n type: \"materialize-keyframes\";\n animationId: string;\n keyframes: Array<{\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n }>;\n easeEach?: string;\n resolvedSelector?: string;\n allElements?: Array<{\n selector: string;\n keyframes: Array<{ percentage: number; properties: Record<string, number | string> }>;\n easeEach?: string;\n }>;\n }\n | {\n type: \"set-arc-path\";\n animationId: string;\n enabled: boolean;\n autoRotate?: boolean | number;\n segments?: Array<{\n curviness: number;\n cp1?: { x: number; y: number };\n cp2?: { x: number; y: number };\n }>;\n }\n | {\n type: \"update-arc-segment\";\n animationId: string;\n segmentIndex: number;\n curviness?: number;\n cp1?: { x: number; y: number };\n cp2?: { x: number; y: number };\n }\n | {\n type: \"update-motion-path-point\";\n animationId: string;\n pointIndex: number;\n x: number;\n y: number;\n }\n | { type: \"add-motion-path-point\"; animationId: string; index: number; x: number; y: number }\n | { type: \"remove-motion-path-point\"; animationId: string; index: number }\n | {\n type: \"add-motion-path\";\n targetSelector: string;\n position: number;\n duration: number;\n x: number;\n y: number;\n ease?: string;\n }\n | { type: \"remove-arc-path\"; animationId: string }\n | {\n type: \"add-with-keyframes\";\n targetSelector: string;\n position: number;\n duration: number;\n keyframes: Array<{\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n auto?: boolean;\n }>;\n ease?: string;\n easeEach?: string;\n }\n | {\n type: \"replace-with-keyframes\";\n animationId: string;\n targetSelector: string;\n position: number;\n duration: number;\n keyframes: Array<{\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n auto?: boolean;\n }>;\n ease?: string;\n easeEach?: string;\n }\n | {\n type: \"split-animations\";\n originalId: string;\n newId: string;\n splitTime: number;\n elementStart: number;\n elementDuration: number;\n }\n | {\n type: \"split-into-property-groups\";\n animationId: string;\n }\n | {\n type: \"delete-all-for-selector\";\n targetSelector: string;\n }\n | {\n // Enforce \"exactly one position write per element\": keep `keepAnimationId`\n // (the write the commit is editing) and strip every other pure-position\n // write for the selector. Self-heals files that already have duplicates.\n type: \"consolidate-position-writes\";\n targetSelector: string;\n keepAnimationId?: string;\n }\n | {\n // Rewrite all top-level helper/loop constructs into literal tweens so\n // computed keyframes become directly editable (visual no-op).\n type: \"unroll-timeline\";\n }\n | {\n type: \"shift-positions\";\n targetSelector: string;\n delta: number;\n }\n | {\n // Batched shift: fold shiftPositionsInScript over N selectors in one write.\n // Lets a multi-clip timeline move (ripple / insert) shift every affected\n // clip's tweens atomically instead of one racing server round-trip per clip.\n type: \"shift-positions-batch\";\n shifts: Array<{ targetSelector: string; delta: number }>;\n }\n | {\n type: \"scale-positions\";\n targetSelector: string;\n oldStart: number;\n oldDuration: number;\n newStart: number;\n newDuration: number;\n };\n\n// ── GSAP mutation executor ──────────────────────────────────────────────────\n\ntype GsapMutationResult = string | { script: string; skippedSelectors: string[] };\n\nfunction replaceInPlaceUnlessSetOrUnknown(\n scriptText: string,\n body: Extract<GsapMutationRequest, { type: \"replace-with-keyframes\" }>,\n): string {\n const edit = { ...body, easeEach: resolveReplacementEaseEach(scriptText, body) };\n const inPlace = replaceTweenWithKeyframesInScript(scriptText, body.animationId, edit);\n if (inPlace !== null) return inPlace;\n const script = removeAnimationFromScript(scriptText, body.animationId);\n return addAnimationWithKeyframesToScript(\n script,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n edit.easeEach,\n ).script;\n}\n\nfunction resolveReplacementEaseEach(\n scriptText: string,\n request: { animationId: string; easeEach?: string },\n): string | undefined {\n if (request.easeEach !== undefined) return request.easeEach;\n const original = parseGsapScriptAcorn(scriptText).animations.find(\n (animation) => animation.id === request.animationId,\n );\n if (!original?.arcPath?.enabled) return undefined;\n return original?.keyframes?.easeEach ?? original?.ease;\n}\n\n// Mutations that can change a position tween's first keyframe (value/existence/timing)\n// and therefore require the pre-keyframe hold-`set`s to be re-synced afterwards.\n// `syncPositionHoldsBeforeKeyframes` rebuilds all `hf-hold` sets from scratch: it acts\n// on every tween whose 0% keyframe carries a position prop and\n// whose start is > 0. So any mutation that creates such a tween, retargets it, or moves\n// its start across the t=0 boundary must trigger a re-sync.\nconst HOLD_SYNC_MUTATION_TYPES = new Set<string>([\n \"add-keyframe\",\n \"update-keyframe\",\n \"remove-keyframe\",\n \"move-keyframe\",\n \"resize-keyframed-tween\",\n \"remove-all-keyframes\",\n \"add-with-keyframes\",\n \"replace-with-keyframes\",\n \"convert-to-keyframes\",\n \"materialize-keyframes\",\n \"update-motion-path-point\",\n \"add-motion-path-point\",\n \"remove-motion-path-point\",\n // Authors a fresh motionPath tween whose parsed first keyframe is (0,0); if it lands\n // at position > 0 the element snaps home at t=0 without a pre-tween hold-`set`.\n \"add-motion-path\",\n // Can move a tween's `position` (start) across the t=0 boundary, which flips whether a\n // keyframed position tween needs a hold (started at 0 → moved later, or vice versa).\n \"update-meta\",\n // Time-shift / time-scale tweens, which can move a keyframed position tween's start\n // across t=0, flipping hold need; stale holds are not repositioned by these ops.\n \"shift-positions\",\n \"shift-positions-batch\",\n \"scale-positions\",\n // Retargets keyframed position tweens to a cloned element's selector; the old hold is\n // keyed to the prior selector, so holds must be rebuilt for the new target.\n \"split-animations\",\n \"delete\",\n \"delete-all-for-selector\",\n]);\n\nasync function executeGsapMutation(\n body: GsapMutationRequest,\n block: NonNullable<ReturnType<typeof extractGsapScriptBlock>>,\n respond: (data: unknown, status?: number) => Response,\n writer: \"recast\" | \"acorn\",\n): Promise<GsapMutationResult | Response> {\n // Keep writer selection explicit at the route boundary so a batch cannot\n // switch implementations between operations.\n if (writer === \"recast\") {\n return executeGsapMutationRecast(body, block, respond);\n }\n return executeGsapMutationAcorn(body, block, respond);\n}\n\nfunction validateGsapMutationRequest(\n c: RouteContext,\n body: GsapMutationRequest | null,\n): Response | null {\n if (!body || typeof body !== \"object\" || !(\"type\" in body) || !body.type) {\n return c.json({ error: \"mutation type required\" }, 400);\n }\n if (containsRawGsapExpression(body)) {\n return c.json({ error: \"raw JavaScript expressions are not accepted\" }, 400);\n }\n const unsafeFields = findUnsafeMutationValues(body);\n if (unsafeFields.length > 0) return rejectUnsafeMutationValues(c, unsafeFields);\n if (\n body.type === \"shift-positions-batch\" &&\n (!(\"shifts\" in body) || !Array.isArray(body.shifts))\n ) {\n return c.json({ error: \"shift-positions-batch requires a `shifts` array\" }, 400);\n }\n return null;\n}\n\nfunction containsRawGsapExpression(value: unknown): boolean {\n if (typeof value === \"string\") return value.startsWith(\"__raw:\");\n if (Array.isArray(value)) return value.some(containsRawGsapExpression);\n if (!value || typeof value !== \"object\") return false;\n return Object.values(value).some(containsRawGsapExpression);\n}\n\nasync function prepareGsapMutationScript(\n c: RouteContext,\n res: ResolvedGsapFile,\n firstMutation: GsapMutationRequest,\n): Promise<\n | Response\n | {\n html: string;\n beforeHtml: string;\n block: NonNullable<ReturnType<typeof extractGsapScriptBlock>>;\n }\n> {\n const beforeHtml = readFileSync(res.absPath, \"utf-8\");\n let html = beforeHtml;\n let block = extractGsapScriptBlock(html);\n if (!block && (firstMutation.type === \"add\" || firstMutation.type === \"add-with-keyframes\")) {\n const compId = html.match(/data-composition-id=\"([^\"]+)\"/)?.[1] ?? \"main\";\n const { GSAP_CDN } = await import(\"@hyperframes/core\");\n const bootstrap = [\n `<script src=\"${GSAP_CDN}\"></script>`,\n \"<script>\",\n \"window.__timelines = window.__timelines || {};\",\n \"const tl = gsap.timeline({ paused: true });\",\n `window.__timelines[\"${compId}\"] = tl;`,\n \"</script>\",\n ].join(\"\\n\");\n const [first, second] = hasCompositionOutsideTemplates(html)\n ? ([\"body\", \"template\"] as const)\n : ([\"template\", \"body\"] as const);\n html =\n insertBeforeCloseTag(html, first, `${bootstrap}\\n`) ??\n insertBeforeCloseTag(html, second, `${bootstrap}\\n`) ??\n `${html}\\n${bootstrap}`;\n block = extractGsapScriptBlock(html);\n }\n if (\n !block &&\n (firstMutation.type === \"shift-positions\" ||\n firstMutation.type === \"scale-positions\" ||\n firstMutation.type === \"shift-positions-batch\")\n ) {\n return c.json({\n ok: true,\n changed: false,\n mutated: false,\n parsed: { animations: [], timelineVar: \"tl\", preamble: \"\", postamble: \"\" },\n before: html,\n after: html,\n scriptText: \"\",\n path: res.filePath,\n backupPath: null,\n });\n }\n if (!block) return c.json({ error: \"no GSAP script found in file\" }, 400);\n return { html, beforeHtml, block };\n}\n\ntype RetimeSlot = ClipTweenRetime | \"no-op\";\n\nfunction retimeRuns(mutations: readonly GsapMutationRequest[]): Map<number, RetimeSlot[]> {\n const runs = new Map<number, RetimeSlot[]>();\n let start = -1;\n mutations.forEach((mutation, index) => {\n const retime = clipRetimeOf(mutation);\n if (!retime) return void (start = -1);\n if (start < 0) runs.set((start = index), []);\n runs.get(start)!.push(retime);\n });\n return runs;\n}\n\n// The one owner of the clip-retime no-op rules; a no-op keeps its slot so flags line up.\nfunction clipRetimeOf(mutation: GsapMutationRequest): RetimeSlot | null {\n if (mutation.type === \"shift-positions\") {\n const { targetSelector, delta } = mutation;\n return targetSelector && Number.isFinite(delta) && delta !== 0\n ? { kind: \"shift\", targetSelector, delta }\n : \"no-op\";\n }\n if (mutation.type !== \"scale-positions\") return null;\n const { targetSelector, oldStart, oldDuration, newStart, newDuration } = mutation;\n const finite = [oldStart, oldDuration, newStart, newDuration].every(Number.isFinite);\n if (!targetSelector || !finite || oldDuration <= 0 || newDuration <= 0) return \"no-op\";\n if (oldStart === newStart && oldDuration === newDuration) return \"no-op\";\n return { kind: \"scale\", targetSelector, oldStart, oldDuration, newStart, newDuration };\n}\n\nfunction retimeRun(script: string, run: readonly RetimeSlot[], root: ParentNode | undefined) {\n const live = run.filter((slot): slot is ClipTweenRetime => slot !== \"no-op\");\n const retimed = retimeClipTweensInScript(script, live, root);\n const synced = syncPositionHoldsBeforeKeyframes(retimed.script, script);\n let next = 0;\n const changed = run.map((slot) => slot !== \"no-op\" && retimed.changed[next++]!);\n if (synced !== retimed.script) changed[changed.length - 1] = true;\n return { script: synced, changed: synced === script ? changed.map(() => false) : changed };\n}\n\nasync function applyGsapMutations(\n c: RouteContext,\n res: ResolvedGsapFile,\n mutations: GsapMutationRequest[],\n): Promise<Response> {\n const firstMutation = mutations[0];\n if (!firstMutation) return c.json({ error: \"mutations array required\" }, 400);\n const prepared = await prepareGsapMutationScript(c, res, firstMutation);\n if (prepared instanceof Response) return prepared;\n const { html, beforeHtml, block } = prepared;\n let lengthIsAuthored: boolean | undefined;\n\n const initialScript = block.scriptText;\n const skippedSelectors = new Set<string>();\n const respond = (data: unknown, status?: number) =>\n status ? c.json(data, status) : c.json(data);\n let writer: \"recast\" | \"acorn\";\n try {\n writer = resolveGsapWriter({\n HYPERFRAMES_GSAP_WRITER: process.env[\"HYPERFRAMES_GSAP_WRITER\"],\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);\n }\n\n const mutationChanges: boolean[] = [];\n const retimes = writer === \"acorn\" ? retimeRuns(mutations) : new Map<number, RetimeSlot[]>();\n for (let index = 0; index < mutations.length; index++) {\n const run = retimes.get(index);\n if (run) {\n const retimed = retimeRun(block.scriptText, run, block.root);\n mutationChanges.push(...retimed.changed);\n block.scriptText = retimed.script;\n index += run.length - 1;\n continue;\n }\n const mutation = mutations[index]!;\n const previousScript = block.scriptText;\n const result = await executeGsapMutation(mutation, block, respond, writer);\n if (result instanceof Response) return result;\n let newScript = typeof result === \"string\" ? result : result.script;\n if (typeof result !== \"string\") {\n for (const selector of result.skippedSelectors) skippedSelectors.add(selector);\n }\n if (HOLD_SYNC_MUTATION_TYPES.has(mutation.type)) {\n lengthIsAuthored ??= !lengthIsTimeline(res.project.dir, res.filePath);\n if (lengthIsAuthored) newScript = trimTrailingKeyframeSpans(previousScript, newScript);\n newScript =\n writer === \"acorn\"\n ? syncPositionHoldsBeforeKeyframes(newScript, previousScript)\n : (await loadGsapParser()).syncPositionHoldsBeforeKeyframes(newScript, previousScript);\n }\n mutationChanges.push(newScript !== previousScript);\n block.scriptText = newScript;\n }\n\n const changed = block.scriptText !== initialScript;\n const newHtml = changed ? block.replaceScript(block.scriptText) : html;\n let backupPath: string | null = null;\n // Parsing can await lazy imports. Revalidate before EVERY successful response,\n // including semantic no-ops: a stale no-op response would otherwise claim\n // the old bytes and let the client keep a preview that missed a successor.\n if (readFileSync(res.absPath, \"utf-8\") !== beforeHtml) {\n return c.json({ error: \"file changed during GSAP mutation\", conflict: true }, 409);\n }\n if (changed) {\n const mutationResult = writeMutationResult(\n c,\n res.project.dir,\n res.filePath,\n res.absPath,\n newHtml,\n beforeHtml,\n );\n if (mutationResult instanceof Response) return mutationResult;\n backupPath = mutationResult.backupPath;\n }\n\n const responsePayload: Record<string, unknown> = {\n ok: true,\n changed,\n mutated: changed,\n mutationChanges,\n parsed: parseGsapScriptAcorn(block.scriptText),\n before: beforeHtml,\n after: newHtml,\n scriptText: block.scriptText,\n path: res.filePath,\n version: fileContentVersion(newHtml),\n backupPath,\n };\n if (skippedSelectors.size > 0) responsePayload.skippedSelectors = [...skippedSelectors];\n c.header(\"ETag\", responsePayload.version as string);\n return c.json(responsePayload);\n}\n\nfunction executeGsapMutationAcorn(\n body: GsapMutationRequest,\n block: NonNullable<ReturnType<typeof extractGsapScriptBlock>>,\n respond: (data: unknown, status?: number) => Response,\n): GsapMutationResult | Response {\n function requireAnimation(\n scriptText: string,\n animationId: string,\n ): { anim: GsapAnimation } | { err: Response } {\n const parsed = parseGsapScriptAcorn(scriptText);\n const anim = parsed.animations.find((a) => a.id === animationId);\n if (!anim) return { err: respond({ error: \"animation not found\" }, 404) };\n return { anim };\n }\n\n function requireFromToAnimation(\n scriptText: string,\n animationId: string,\n ): { anim: GsapAnimation } | { err: Response } {\n const result = requireAnimation(scriptText, animationId);\n if (\"err\" in result) return result;\n if (result.anim.method !== \"fromTo\")\n return { err: respond({ error: \"animation is not a fromTo\" }, 400) };\n return result;\n }\n\n switch (body.type) {\n case \"update-property\":\n case \"add-property\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const val = body.type === \"update-property\" ? body.value : body.defaultValue;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: { ...r.anim.properties, [body.property]: val },\n });\n }\n case \"update-properties\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: { ...r.anim.properties, ...body.properties },\n });\n }\n case \"update-from-property\":\n case \"add-from-property\": {\n const r = requireFromToAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const val = body.type === \"update-from-property\" ? body.value : body.defaultValue;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n fromProperties: { ...(r.anim.fromProperties ?? {}), [body.property]: val },\n });\n }\n case \"update-meta\": {\n return updateAnimationInScript(block.scriptText, body.animationId, body.updates);\n }\n case \"add\": {\n if (body.fromProperties && body.method !== \"fromTo\") {\n return respond({ error: \"fromProperties is only valid for method=fromTo\" }, 400);\n }\n if (\n Object.keys(body.properties).some((key) => {\n const group = classifyPropertyGroup(key);\n return group === \"position\" || group === \"rotation\";\n })\n ) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n const result = addAnimationToScript(block.scriptText, {\n targetSelector: body.targetSelector,\n method: body.method,\n position: body.position,\n duration: body.duration,\n ease: body.ease,\n properties: body.properties,\n fromProperties: body.fromProperties,\n ...(body.global ? { global: true } : {}),\n });\n return result.script;\n }\n case \"delete\": {\n const delTarget = requireAnimation(block.scriptText, body.animationId);\n if (!(\"err\" in delTarget) && body.stripStudioEdits) {\n stripStudioEditsFromTarget(block.document, delTarget.anim.targetSelector);\n bakeVisibilityOnDelete(block.document, delTarget.anim);\n }\n return removeAnimationFromScript(block.scriptText, body.animationId);\n }\n case \"delete-all-for-selector\": {\n const parsed = parseGsapScriptAcorn(block.scriptText);\n const matching = parsed.animations.filter((a) => a.targetSelector === body.targetSelector);\n if (matching.length === 0) return block.scriptText;\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n let script = block.scriptText;\n for (const anim of matching.reverse()) {\n script = removeAnimationFromScript(script, anim.id);\n }\n return script;\n }\n case \"consolidate-position-writes\": {\n if (!body.targetSelector) return block.scriptText;\n return dedupePositionWritesInScript(\n block.scriptText,\n body.targetSelector,\n body.keepAnimationId,\n );\n }\n case \"remove-property\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const filtered = { ...r.anim.properties };\n delete filtered[body.property];\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: filtered,\n });\n }\n case \"remove-from-property\": {\n const r = requireFromToAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const filtered = { ...(r.anim.fromProperties ?? {}) };\n delete filtered[body.property];\n return updateAnimationInScript(block.scriptText, body.animationId, {\n fromProperties: filtered,\n });\n }\n case \"add-keyframe\": {\n return addKeyframeToScript(\n block.scriptText,\n body.animationId,\n body.percentage,\n body.properties,\n body.ease,\n body.backfillDefaults,\n );\n }\n case \"remove-keyframe\": {\n return removeKeyframeFromScript(block.scriptText, body.animationId, body.percentage);\n }\n case \"move-keyframe\": {\n return moveKeyframeInScript(\n block.scriptText,\n body.animationId,\n body.fromPercentage,\n body.toPercentage,\n );\n }\n case \"resize-keyframed-tween\": {\n return resizeKeyframedTweenInScript(\n block.scriptText,\n body.animationId,\n body.position,\n body.duration,\n body.pctRemap,\n );\n }\n case \"update-keyframe\": {\n return updateKeyframeInScript(\n block.scriptText,\n body.animationId,\n body.percentage,\n body.properties,\n body.ease,\n );\n }\n case \"convert-to-keyframes\": {\n return convertToKeyframesFromScript(\n block.scriptText,\n body.animationId,\n body.resolvedFromValues,\n body.duration,\n );\n }\n case \"remove-all-keyframes\": {\n const preCollapse = requireAnimation(block.scriptText, body.animationId);\n if (!(\"err\" in preCollapse)) {\n bakeVisibilityOnDelete(block.document, preCollapse.anim);\n }\n return removeAllKeyframesFromScript(block.scriptText, body.animationId);\n }\n case \"materialize-keyframes\": {\n if (body.allElements && body.allElements.length > 0) {\n return unrollDynamicAnimations(block.scriptText, body.animationId, body.allElements);\n }\n return materializeKeyframesFromScript(\n block.scriptText,\n body.animationId,\n body.keyframes,\n body.easeEach,\n body.resolvedSelector,\n );\n }\n case \"set-arc-path\": {\n return setArcPathInScript(block.scriptText, body.animationId, {\n enabled: body.enabled,\n autoRotate: body.autoRotate ?? false,\n segments: body.segments ?? [],\n });\n }\n case \"update-arc-segment\": {\n return updateArcSegmentInScript(block.scriptText, body.animationId, body.segmentIndex, {\n ...(body.curviness !== undefined ? { curviness: body.curviness } : {}),\n ...(body.cp1 ? { cp1: body.cp1 } : {}),\n ...(body.cp2 ? { cp2: body.cp2 } : {}),\n });\n }\n case \"update-motion-path-point\": {\n return updateMotionPathPointInScript(block.scriptText, body.animationId, body.pointIndex, {\n x: body.x,\n y: body.y,\n });\n }\n case \"add-motion-path-point\": {\n return addMotionPathPointInScript(block.scriptText, body.animationId, body.index, {\n x: body.x,\n y: body.y,\n });\n }\n case \"remove-motion-path-point\": {\n return removeMotionPathPointInScript(block.scriptText, body.animationId, body.index);\n }\n case \"add-motion-path\": {\n return addMotionPathToScript(\n block.scriptText,\n body.targetSelector,\n body.position,\n body.duration,\n { x: body.x, y: body.y },\n body.ease,\n ).script;\n }\n case \"remove-arc-path\": {\n return removeArcPathFromScript(block.scriptText, body.animationId);\n }\n case \"add-with-keyframes\": {\n if (keyframesWritePosition(body.keyframes) || keyframesWriteRotation(body.keyframes)) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n const result = addAnimationWithKeyframesToScript(\n block.scriptText,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n body.easeEach,\n );\n return result.script;\n }\n case \"replace-with-keyframes\": {\n if (keyframesWritePosition(body.keyframes) || keyframesWriteRotation(body.keyframes)) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n return replaceInPlaceUnlessSetOrUnknown(block.scriptText, body);\n }\n case \"split-animations\": {\n if (\n typeof body.originalId !== \"string\" ||\n !body.originalId ||\n typeof body.newId !== \"string\" ||\n !body.newId ||\n typeof body.splitTime !== \"number\" ||\n !Number.isFinite(body.splitTime) ||\n typeof body.elementStart !== \"number\" ||\n !Number.isFinite(body.elementStart) ||\n typeof body.elementDuration !== \"number\" ||\n !Number.isFinite(body.elementDuration) ||\n body.elementDuration <= 0\n ) {\n return respond(\n {\n error:\n \"split-animations requires originalId, newId (non-empty strings), splitTime, elementStart (finite numbers), and elementDuration (positive number)\",\n },\n 400,\n );\n }\n return splitAnimationsInScript(block.scriptText, {\n originalId: body.originalId,\n newId: body.newId,\n splitTime: body.splitTime,\n elementStart: body.elementStart,\n elementDuration: body.elementDuration,\n });\n }\n case \"split-into-property-groups\": {\n const result = splitIntoPropertyGroupsFromScript(block.scriptText, body.animationId);\n return result.script;\n }\n case \"unroll-timeline\": {\n return unrollComputedTimeline(block.scriptText);\n }\n case \"shift-positions-batch\": {\n const shifts = body.shifts\n .filter((s) => s.targetSelector && Number.isFinite(s.delta) && s.delta !== 0)\n .map((s) => ({ kind: \"shift\" as const, targetSelector: s.targetSelector, delta: s.delta }));\n return retimeClipTweensInScript(block.scriptText, shifts, block.root).script;\n }\n case \"shift-positions\":\n case \"scale-positions\": {\n const retime = clipRetimeOf(body);\n return retime && retime !== \"no-op\"\n ? retimeClipTweensInScript(block.scriptText, [retime], block.root).script\n : block.scriptText;\n }\n default:\n return respond({ error: `unknown mutation type: ${(body as { type: string }).type}` }, 400);\n }\n}\n\nasync function executeGsapMutationRecast(\n body: GsapMutationRequest,\n block: NonNullable<ReturnType<typeof extractGsapScriptBlock>>,\n respond: (data: unknown, status?: number) => Response,\n): Promise<GsapMutationResult | Response> {\n const parser = await loadGsapParser();\n const {\n updateAnimationInScript,\n addAnimationToScript,\n removeAnimationFromScript,\n addKeyframeToScript,\n removeKeyframeFromScript,\n moveKeyframeInScript,\n resizeKeyframedTweenInScript,\n updateKeyframeInScript,\n convertToKeyframesInScript,\n removeAllKeyframesFromScript,\n materializeKeyframesInScript,\n unrollDynamicAnimations,\n setArcPathInScript,\n updateArcSegmentInScript,\n updateMotionPathPointInScript,\n addMotionPathPointInScript,\n removeMotionPathPointInScript,\n addMotionPathToScript,\n removeArcPathFromScript,\n addAnimationWithKeyframesToScript,\n splitAnimationsInScript,\n splitIntoPropertyGroups,\n dedupePositionWritesInScript,\n } = parser;\n\n function requireAnimation(\n scriptText: string,\n animationId: string,\n ): { anim: GsapAnimation } | { err: Response } {\n const parsed = parseGsapScriptAcorn(scriptText);\n const anim = parsed.animations.find((a) => a.id === animationId);\n if (!anim) return { err: respond({ error: \"animation not found\" }, 404) };\n return { anim };\n }\n\n function requireFromToAnimation(\n scriptText: string,\n animationId: string,\n ): { anim: GsapAnimation } | { err: Response } {\n const result = requireAnimation(scriptText, animationId);\n if (\"err\" in result) return result;\n if (result.anim.method !== \"fromTo\")\n return { err: respond({ error: \"animation is not a fromTo\" }, 400) };\n return result;\n }\n\n switch (body.type) {\n case \"update-property\":\n case \"add-property\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const val = body.type === \"update-property\" ? body.value : body.defaultValue;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: { ...r.anim.properties, [body.property]: val },\n });\n }\n case \"update-properties\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: { ...r.anim.properties, ...body.properties },\n });\n }\n case \"update-from-property\":\n case \"add-from-property\": {\n const r = requireFromToAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const val = body.type === \"update-from-property\" ? body.value : body.defaultValue;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n fromProperties: { ...(r.anim.fromProperties ?? {}), [body.property]: val },\n });\n }\n case \"update-meta\": {\n return updateAnimationInScript(block.scriptText, body.animationId, body.updates);\n }\n case \"add\": {\n if (body.fromProperties && body.method !== \"fromTo\") {\n return respond({ error: \"fromProperties is only valid for method=fromTo\" }, 400);\n }\n // A new position/rotation animation owns that channel — strip the matching\n // legacy studio CSS var (--hf-studio-offset / --hf-studio-rotation) so it can't\n // double with the tween, matching add-with-keyframes/replace-with-keyframes.\n if (\n Object.keys(body.properties).some((k) => {\n const group = classifyPropertyGroup(k);\n return group === \"position\" || group === \"rotation\";\n })\n ) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n const result = addAnimationToScript(block.scriptText, {\n targetSelector: body.targetSelector,\n method: body.method,\n position: body.position,\n duration: body.duration,\n ease: body.ease,\n properties: body.properties,\n fromProperties: body.fromProperties,\n ...(body.global ? { global: true } : {}),\n });\n return result.script;\n }\n case \"delete\": {\n const delTarget = requireAnimation(block.scriptText, body.animationId);\n if (!(\"err\" in delTarget) && body.stripStudioEdits) {\n stripStudioEditsFromTarget(block.document, delTarget.anim.targetSelector);\n bakeVisibilityOnDelete(block.document, delTarget.anim);\n }\n return removeAnimationFromScript(block.scriptText, body.animationId);\n }\n case \"delete-all-for-selector\": {\n const parsed = parseGsapScriptAcorn(block.scriptText);\n const matching = parsed.animations.filter((a) => a.targetSelector === body.targetSelector);\n if (matching.length === 0) return block.scriptText;\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n let script = block.scriptText;\n for (const anim of matching.reverse()) {\n script = removeAnimationFromScript(script, anim.id);\n }\n return script;\n }\n case \"consolidate-position-writes\": {\n if (!body.targetSelector) return block.scriptText;\n return dedupePositionWritesInScript(\n block.scriptText,\n body.targetSelector,\n body.keepAnimationId,\n );\n }\n case \"remove-property\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const filtered = { ...r.anim.properties };\n delete filtered[body.property];\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: filtered,\n });\n }\n case \"remove-from-property\": {\n const r = requireFromToAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const filtered = { ...(r.anim.fromProperties ?? {}) };\n delete filtered[body.property];\n return updateAnimationInScript(block.scriptText, body.animationId, {\n fromProperties: filtered,\n });\n }\n case \"add-keyframe\": {\n return addKeyframeToScript(\n block.scriptText,\n body.animationId,\n body.percentage,\n body.properties,\n body.ease,\n body.backfillDefaults,\n );\n }\n case \"remove-keyframe\": {\n return removeKeyframeFromScript(block.scriptText, body.animationId, body.percentage);\n }\n case \"move-keyframe\": {\n return moveKeyframeInScript(\n block.scriptText,\n body.animationId,\n body.fromPercentage,\n body.toPercentage,\n );\n }\n case \"resize-keyframed-tween\": {\n return resizeKeyframedTweenInScript(\n block.scriptText,\n body.animationId,\n body.position,\n body.duration,\n body.pctRemap,\n );\n }\n case \"update-keyframe\": {\n return updateKeyframeInScript(\n block.scriptText,\n body.animationId,\n body.percentage,\n body.properties,\n body.ease,\n );\n }\n case \"convert-to-keyframes\": {\n return convertToKeyframesInScript(\n block.scriptText,\n body.animationId,\n body.resolvedFromValues,\n body.duration,\n );\n }\n case \"remove-all-keyframes\": {\n const preCollapse = requireAnimation(block.scriptText, body.animationId);\n if (!(\"err\" in preCollapse)) {\n bakeVisibilityOnDelete(block.document, preCollapse.anim);\n }\n return removeAllKeyframesFromScript(block.scriptText, body.animationId);\n }\n case \"materialize-keyframes\": {\n if (body.allElements && body.allElements.length > 0) {\n return unrollDynamicAnimations(block.scriptText, body.animationId, body.allElements);\n }\n return materializeKeyframesInScript(\n block.scriptText,\n body.animationId,\n body.keyframes,\n body.easeEach,\n body.resolvedSelector,\n );\n }\n case \"set-arc-path\": {\n return setArcPathInScript(block.scriptText, body.animationId, {\n enabled: body.enabled,\n autoRotate: body.autoRotate ?? false,\n segments: body.segments ?? [],\n });\n }\n case \"update-arc-segment\": {\n return updateArcSegmentInScript(block.scriptText, body.animationId, body.segmentIndex, {\n ...(body.curviness !== undefined ? { curviness: body.curviness } : {}),\n ...(body.cp1 ? { cp1: body.cp1 } : {}),\n ...(body.cp2 ? { cp2: body.cp2 } : {}),\n });\n }\n case \"update-motion-path-point\": {\n return updateMotionPathPointInScript(block.scriptText, body.animationId, body.pointIndex, {\n x: body.x,\n y: body.y,\n });\n }\n case \"add-motion-path-point\": {\n return addMotionPathPointInScript(block.scriptText, body.animationId, body.index, {\n x: body.x,\n y: body.y,\n });\n }\n case \"remove-motion-path-point\": {\n return removeMotionPathPointInScript(block.scriptText, body.animationId, body.index);\n }\n case \"add-motion-path\": {\n const result = addMotionPathToScript(\n block.scriptText,\n body.targetSelector,\n body.position,\n body.duration,\n { x: body.x, y: body.y },\n body.ease,\n );\n return result.script;\n }\n case \"remove-arc-path\": {\n return removeArcPathFromScript(block.scriptText, body.animationId);\n }\n case \"add-with-keyframes\": {\n if (keyframesWritePosition(body.keyframes) || keyframesWriteRotation(body.keyframes)) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n const result = addAnimationWithKeyframesToScript(\n block.scriptText,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n body.easeEach,\n );\n return result.script;\n }\n case \"replace-with-keyframes\": {\n if (keyframesWritePosition(body.keyframes) || keyframesWriteRotation(body.keyframes)) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n return replaceInPlaceUnlessSetOrUnknown(block.scriptText, body);\n }\n case \"split-animations\": {\n if (\n typeof body.originalId !== \"string\" ||\n !body.originalId ||\n typeof body.newId !== \"string\" ||\n !body.newId ||\n typeof body.splitTime !== \"number\" ||\n !Number.isFinite(body.splitTime) ||\n typeof body.elementStart !== \"number\" ||\n !Number.isFinite(body.elementStart) ||\n typeof body.elementDuration !== \"number\" ||\n !Number.isFinite(body.elementDuration) ||\n body.elementDuration <= 0\n ) {\n return respond(\n {\n error:\n \"split-animations requires originalId, newId (non-empty strings), splitTime, elementStart (finite numbers), and elementDuration (positive number)\",\n },\n 400,\n );\n }\n return splitAnimationsInScript(block.scriptText, {\n originalId: body.originalId,\n newId: body.newId,\n splitTime: body.splitTime,\n elementStart: body.elementStart,\n elementDuration: body.elementDuration,\n });\n }\n case \"split-into-property-groups\": {\n const result = splitIntoPropertyGroups(block.scriptText, body.animationId);\n return result.script;\n }\n case \"unroll-timeline\": {\n return unrollComputedTimeline(block.scriptText);\n }\n case \"shift-positions\": {\n const { targetSelector, delta } = body;\n if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;\n const { shiftPositionsInScript } = parser;\n return shiftPositionsInScript(block.scriptText, targetSelector, delta, block.root);\n }\n case \"shift-positions-batch\": {\n const { shiftPositionsInScript } = parser;\n let script = block.scriptText;\n for (const s of body.shifts) {\n if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;\n script = shiftPositionsInScript(script, s.targetSelector, s.delta, block.root);\n }\n return script;\n }\n case \"scale-positions\": {\n const { targetSelector, oldStart, oldDuration, newStart, newDuration } = body;\n if (\n !targetSelector ||\n !Number.isFinite(oldStart) ||\n !Number.isFinite(oldDuration) ||\n !Number.isFinite(newStart) ||\n !Number.isFinite(newDuration) ||\n oldDuration <= 0 ||\n newDuration <= 0\n )\n return block.scriptText;\n if (oldStart === newStart && oldDuration === newDuration) return block.scriptText;\n const { scalePositionsInScript } = parser;\n return scalePositionsInScript(\n block.scriptText,\n targetSelector,\n oldStart,\n oldDuration,\n newStart,\n newDuration,\n block.root,\n );\n }\n default:\n return respond({ error: `unknown mutation type: ${(body as { type: string }).type}` }, 400);\n }\n}\n\ninterface FoldedAtomicCutFile {\n path: string;\n absPath: string;\n before: string;\n after: string;\n splitCount: number;\n skippedSelectors: string[];\n}\n\n/** Fold every split and optional GSAP retarget for one file without touching disk. */\nasync function foldAtomicCutFile(\n c: RouteContext,\n file: AtomicCutFileRequest,\n absPath: string,\n before: string,\n writer: \"recast\" | \"acorn\",\n): Promise<FoldedAtomicCutFile | Response> {\n let after = before;\n let splitCount = 0;\n const skippedSelectors = new Set<string>();\n const rightHalfIds: string[] = [];\n const respond = (data: unknown, status?: number) =>\n status ? c.json(data, status) : c.json(data);\n\n const orderedTargets = file.targets\n .map((cut, index) => ({ cut, index }))\n .sort((left, right) => {\n const locatorKey = (entry: AtomicCutTarget): string | null =>\n !entry.target.id && !entry.target.hfId && entry.target.selector\n ? entry.target.selector\n : null;\n const leftKey = locatorKey(left.cut);\n const rightKey = locatorKey(right.cut);\n if (leftKey && rightKey) {\n return (\n leftKey.localeCompare(rightKey) ||\n (right.cut.target.selectorIndex ?? 0) - (left.cut.target.selectorIndex ?? 0)\n );\n }\n if (leftKey) return -1;\n if (rightKey) return 1;\n return left.index - right.index;\n })\n .map(({ cut }) => cut);\n for (const cut of orderedTargets) {\n const baseId = cut.originalId || cut.target.id || \"clip\";\n const split = splitElementInHtml(after, cut.target, cut.splitTime, `${baseId}-split`, {\n start: cut.elementStart,\n duration: cut.elementDuration,\n playbackStart: cut.playbackStart,\n playbackRate: cut.playbackRate,\n stampPlaybackStart: cut.isComposition,\n track: cut.track,\n });\n if (!split.matched || !split.newId) {\n return c.json(\n { error: `Cut target was not found or was outside its authored bounds in ${file.path}` },\n 400,\n );\n }\n after = split.html;\n splitCount++;\n rightHalfIds.push(split.newId);\n\n if (!cut.originalId) continue;\n const block = extractGsapScriptBlock(after);\n if (!block) continue;\n const result = await executeGsapMutation(\n {\n type: \"split-animations\",\n originalId: cut.originalId,\n newId: split.newId,\n splitTime: cut.splitTime,\n elementStart: cut.elementStart,\n elementDuration: cut.elementDuration,\n },\n block,\n respond,\n writer,\n );\n if (result instanceof Response) return result;\n let script = typeof result === \"string\" ? result : result.script;\n if (typeof result !== \"string\") {\n for (const selector of result.skippedSelectors) skippedSelectors.add(selector);\n }\n if (script !== block.scriptText) {\n script =\n writer === \"acorn\"\n ? syncPositionHoldsBeforeKeyframes(script, block.scriptText)\n : (await loadGsapParser()).syncPositionHoldsBeforeKeyframes(script, block.scriptText);\n after = block.replaceScript(script);\n }\n }\n\n after = relinkSplitHalvesInHtml(after, rightHalfIds);\n return {\n path: file.path,\n absPath,\n before,\n after,\n splitCount,\n skippedSelectors: [...skippedSelectors],\n };\n}\n\n// ── Upload file processing ──────────────────────────────────────────────────\n\nexport const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;\n\nasync function processUploadedFiles(\n formData: FormData,\n targetDir: string,\n projectDir: string,\n): Promise<{\n uploaded: string[];\n skipped: string[];\n invalid: Array<{ name: string; reason: string }>;\n unchecked: Array<{ name: string; reason: string }>;\n}> {\n const uploaded: string[] = [];\n const skipped: string[] = [];\n const invalid: Array<{ name: string; reason: string }> = [];\n const unchecked: Array<{ name: string; reason: string }> = [];\n\n // @types/node v25 narrows the ambient `FormData.entries()` to\n // `[string, string]` in workspaces where another dep declares an\n // `onmessage` global (it trips the worker branch of v25's conditional\n // File type). At runtime the value is still `File | string` — cast the\n // iterator so the rest of this block keeps type-checking on every\n // bun-install layout (hoisted on Windows surfaces this; isolated on\n // Linux happens to keep v24 in scope).\n type FileLike = {\n readonly name: string;\n readonly size: number;\n arrayBuffer(): Promise<ArrayBuffer>;\n };\n const entries = formData.entries() as unknown as Iterable<[string, FileLike | string]>;\n\n // Derive the subdirectory prefix from targetDir relative to projectDir\n const subDir = targetDir === projectDir ? \"\" : targetDir.slice(projectDir.length + 1);\n\n for (const [, value] of entries) {\n if (typeof value === \"string\") continue;\n\n // Strip path separators — browsers may include directory components\n const name = value.name.split(\"/\").pop()?.split(\"\\\\\").pop() ?? \"\";\n if (!name || name.includes(\"\\0\") || name.includes(\"..\")) continue;\n\n // Reject individual files that exceed the size limit\n if (value.size > MAX_UPLOAD_BYTES) {\n skipped.push(name);\n continue;\n }\n\n const destPath = resolve(targetDir, name);\n if (!isSafePath(projectDir, destPath)) continue;\n\n // Don't overwrite — append (2), (3), etc.\n let finalPath = destPath;\n let finalName = name;\n // Handle dotfiles correctly: .gitignore → ext=\"\", base=\".gitignore\"\n const dotIdx = name.indexOf(\".\", name.startsWith(\".\") ? 1 : 0);\n const ext = dotIdx > 0 ? name.slice(dotIdx) : \"\";\n const base = dotIdx > 0 ? name.slice(0, dotIdx) : name;\n const MAX_COPY_INDEX = 10000;\n let n = 1;\n if (existsSync(finalPath)) {\n n = 2;\n while (n < MAX_COPY_INDEX && existsSync(resolve(targetDir, `${base} (${n})${ext}`))) n++;\n if (n >= MAX_COPY_INDEX) {\n skipped.push(name);\n continue;\n }\n finalName = `${base} (${n})${ext}`;\n finalPath = resolve(targetDir, finalName);\n }\n\n // The collision suffix chooses a different path; validate that destination\n // too, including dangling symlinks that existsSync treats as absent.\n if (!isSafePath(projectDir, finalPath) || isPrivateProjectFile(projectDir, finalPath)) continue;\n\n const buffer = Buffer.from(await value.arrayBuffer());\n const validation = validateUploadedMediaBuffer(finalName, buffer);\n if (!validation.ok) {\n invalid.push({ name: finalName, reason: validation.reason });\n continue;\n }\n\n // Reading the upload yields: another request can claim the selected name.\n // Only exclusive creation authorizes a write; retry collisions without\n // following a newly planted link or overwriting another upload.\n let written = false;\n while (n < MAX_COPY_INDEX && isSafePath(projectDir, finalPath)) {\n try {\n createFileAtomically(finalPath, buffer);\n written = true;\n break;\n } catch (error) {\n if (!(error instanceof Error) || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n n++;\n finalName = `${base} (${n})${ext}`;\n finalPath = resolve(targetDir, finalName);\n }\n }\n if (!written) {\n if (n >= MAX_COPY_INDEX) skipped.push(name);\n continue;\n }\n const relativePath = subDir ? join(subDir, finalName) : finalName;\n uploaded.push(relativePath);\n if (validation.unchecked) unchecked.push({ name: finalName, reason: validation.unchecked });\n if (isAudioFile(finalName)) {\n generateWaveformCache(projectDir, relativePath).catch(() => {});\n }\n }\n\n return { uploaded, skipped, invalid, unchecked };\n}\n\n// ── Route registration ──────────────────────────────────────────────────────\n\nconst MAX_TEXT_READ_BYTES = 32 * 1024 * 1024;\nconst GIT_BINARY_SNIFF_BYTES = 8000;\n\nexport function registerFileRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // ── Read ──\n\n api.get(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter);\n if (\"error\" in res) return res.error;\n\n // Opened once and checked/read through the same descriptor, not the path,\n // so a directory-for-file swap (or anything else) between the check below\n // and the read can't land a stale answer — both act on the identical inode.\n let fd: number;\n try {\n fd = openSync(res.absPath, \"r\");\n } catch {\n if (c.req.query(\"optional\") === \"1\") {\n // `missing: true` separates the absent-file shim from a genuinely\n // 0-byte file — both answer `content: \"\"`, and the caller could not\n // tell them apart. That ambiguity hid the largest remaining class of\n // SDK-session failures: a composition the file tree lists but this\n // read answers empty for is either a placeholder nobody has written\n // yet, or a path that does not resolve here at all, and those need\n // different fixes. Additive, so an older client ignores it.\n return c.json({ filename: res.filePath, content: \"\", missing: true });\n }\n return c.json({ error: \"not found\" }, 404);\n }\n try {\n // A listing built from `walkDir` can show a path that has since been\n // replaced by a directory (a rename, or an agent overwriting a file\n // with a folder of the same name) — opening it succeeds (POSIX allows\n // O_RDONLY on a directory), and reading it would throw `EISDIR`, which\n // Hono answers as a plain-text 500. The caller already handles a 404\n // with `why`; this reports the same shape instead of an opaque server\n // error for something that is not one.\n const stat = fstatSync(fd);\n if (!stat.isFile()) {\n return c.json({ error: \"not found\", why: \"not_a_file\" }, 404);\n }\n if (stat.size > MAX_TEXT_READ_BYTES) {\n return c.json({ error: \"too large to read as text\", why: \"too_large\" }, 413);\n }\n\n const content = readFileSync(fd);\n const version = fileContentVersion(content);\n c.header(\"ETag\", version);\n if (content.subarray(0, GIT_BINARY_SNIFF_BYTES).includes(0)) {\n return c.json({ error: \"not a text file\", why: \"binary\", version }, 415);\n }\n // `missing: false` on the read path too, so its PRESENCE is what tells a\n // caller this server distinguishes the two empty answers at all. Without\n // it here, a real 0-byte file from a new server looks exactly like either\n // case from an old one, and the split above buys nothing.\n return c.json({\n filename: res.filePath,\n content: content.toString(\"utf-8\"),\n version,\n missing: false,\n });\n } finally {\n closeSync(fd);\n }\n });\n\n // ── Write (overwrite) ──\n\n api.put(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter, { pin: true });\n if (\"error\" in res) return res.error;\n\n const body = Buffer.from(await c.req.arrayBuffer());\n const expectedVersion = c.req.header(\"If-Match\")?.trim() ?? null;\n const createOnly = c.req.header(\"If-None-Match\")?.trim() === \"*\";\n if (expectedVersion === null && !createOnly) {\n let currentContent: Buffer | null = null;\n try {\n currentContent = readFileSync(res.absPath);\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"ENOENT\") {\n throw error;\n }\n }\n return c.json(\n {\n error: \"precondition required\",\n path: res.filePath,\n currentVersion: currentContent === null ? null : fileContentVersion(currentContent),\n currentContent: currentContent?.toString(\"utf-8\") ?? null,\n },\n 428,\n );\n }\n\n let backup: ReturnType<typeof snapshotBeforeWrite> = { backupPath: null };\n let overwrote: Buffer | undefined;\n if (createOnly) {\n ensureDir(res.project.dir, res.absPath);\n try {\n createFileAtomically(res.absPath, body);\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n const currentContent = readFileSync(res.absPath);\n return c.json(\n {\n error: \"file conflict\",\n path: res.filePath,\n currentVersion: fileContentVersion(currentContent),\n currentContent: currentContent.toString(\"utf-8\"),\n },\n 409,\n );\n }\n } else {\n let fd: number | null;\n try {\n fd = openSync(res.absPath, \"r+\");\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"ENOENT\") {\n throw error;\n }\n return c.json(\n {\n error: \"file conflict\",\n path: res.filePath,\n currentVersion: null,\n currentContent: null,\n },\n 409,\n );\n }\n try {\n const currentContent = readFileSync(fd);\n overwrote = currentContent;\n const currentVersion = fileContentVersion(currentContent);\n if (expectedVersion !== currentVersion) {\n return c.json(\n {\n error: \"file conflict\",\n path: res.filePath,\n currentVersion,\n currentContent: currentContent.toString(\"utf-8\"),\n },\n 409,\n );\n }\n backup = snapshotBeforeWrite(res.project.dir, res.absPath);\n if (backup.error) return c.json({ error: `backup failed: ${backup.error}` }, 500);\n const mode = fstatSync(fd).mode;\n closeSync(fd);\n fd = null;\n replaceFileAtomically(res.absPath, body, mode);\n } finally {\n if (fd !== null) closeSync(fd);\n }\n }\n const version = fileContentVersion(body);\n const writeToken = createWriteToken(c.req.header(\"X-Hyperframes-Write-Token\"));\n recordFileWriteReceipt(res.absPath, { path: res.filePath, version, writeToken, overwrote });\n c.header(\"ETag\", version);\n\n return c.json({\n ok: true,\n path: res.filePath,\n version,\n writeToken,\n backupPath: backupPathForResponse(res.project.dir, backup.backupPath),\n });\n });\n\n // ── Create (fail if exists) ──\n\n api.post(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter);\n if (\"error\" in res) return res.error;\n\n ensureDir(res.project.dir, res.absPath);\n const body = Buffer.from(await c.req.arrayBuffer());\n try {\n createFileAtomically(res.absPath, body);\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n return c.json({ error: \"already exists\" }, 409);\n }\n\n return c.json({ ok: true, path: res.filePath }, 201);\n });\n\n // ── Delete ──\n\n api.delete(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter, { mustExist: true });\n if (\"error\" in res) return res.error;\n\n const stat = statSync(res.absPath);\n const backup = snapshotBeforeWrite(res.project.dir, res.absPath);\n if (backup.error) return c.json({ error: `backup failed: ${backup.error}` }, 500);\n if (stat.isDirectory()) {\n rmSync(res.absPath, { recursive: true });\n } else {\n unlinkSync(res.absPath);\n }\n\n return c.json({\n ok: true,\n backupPath: backupPathForResponse(res.project.dir, backup.backupPath),\n });\n });\n\n api.post(\"/projects/:id/file-mutations/insert-composition/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"insert-composition\");\n if (\"error\" in ctx) return ctx.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n sourcePath?: unknown;\n start?: unknown;\n track?: unknown;\n expectedVersion?: unknown;\n } | null;\n if (\n !body ||\n typeof body.sourcePath !== \"string\" ||\n typeof body.start !== \"number\" ||\n !Number.isFinite(body.start) ||\n body.start < 0 ||\n typeof body.track !== \"number\" ||\n !Number.isFinite(body.track) ||\n typeof body.expectedVersion !== \"string\"\n ) {\n return c.json({ error: \"sourcePath, finite placement, and expectedVersion required\" }, 400);\n }\n\n let before: string;\n try {\n before = readFileSync(ctx.absPath, \"utf-8\");\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"ENOENT\") {\n throw error;\n }\n return c.json({ error: \"not found\" }, 404);\n }\n const currentVersion = fileContentVersion(before);\n if (body.expectedVersion !== currentVersion) {\n return c.json({ error: \"file conflict\", currentVersion, currentContent: before }, 409);\n }\n\n let insertion: ReturnType<typeof insertCompositionIntoSource>;\n try {\n insertion = insertCompositionIntoSource({\n projectDir: ctx.project.dir,\n targetPath: ctx.filePath,\n sourcePath: body.sourcePath,\n parentSource: before,\n start: body.start,\n desiredTrack: body.track,\n });\n } catch (error) {\n if (error instanceof CompositionInsertionError) {\n return c.json({ error: error.message }, error.status);\n }\n throw error;\n }\n\n const backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);\n if (backup.error) return c.json({ error: `backup failed: ${backup.error}` }, 500);\n const current = readFileSync(ctx.absPath, \"utf-8\");\n if (current !== before) {\n const currentVersion = fileContentVersion(current);\n return c.json({ error: \"file conflict\", currentVersion, currentContent: current }, 409);\n }\n const { version, writeToken } = writeFileWithReceipt(\n c,\n ctx.filePath,\n ctx.absPath,\n insertion.html,\n );\n c.header(\"ETag\", version);\n return c.json({\n ok: true,\n path: ctx.filePath,\n hostId: insertion.hostId,\n track: insertion.track,\n duration: insertion.duration,\n before,\n after: insertion.html,\n version,\n writeToken,\n backupPath: backupPathForResponse(ctx.project.dir, backup.backupPath),\n });\n });\n\n api.post(\"/projects/:id/file-mutations/remove-element/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"remove-element\");\n if (\"error\" in ctx) return ctx.error;\n\n if (!existsSync(ctx.absPath)) {\n return c.json({ error: \"not found\" }, 404);\n }\n\n const parsed = await parseMutationBody<{ target?: MutationTarget }>(c);\n if (\"error\" in parsed) return parsed.error;\n\n const originalContent = readFileSync(ctx.absPath, \"utf-8\");\n return writeIfChanged(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n originalContent,\n removeElementFromHtml(originalContent, parsed.target),\n );\n });\n\n // Removing a marquee selection one element at a time meant one request and\n // one rewrite of the whole file per element. A canvas selection runs to\n // hundreds of members, so a single Delete press became hundreds of serial\n // round trips: the file ended up correct, but only after long enough that the\n // key looked like it had done nothing at all.\n api.post(\"/projects/:id/file-mutations/remove-elements/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"remove-elements\");\n if (\"error\" in ctx) return ctx.error;\n\n if (!existsSync(ctx.absPath)) {\n return c.json({ error: \"not found\" }, 404);\n }\n\n const body = (await c.req.json().catch(() => null)) as { targets?: MutationTarget[] } | null;\n const targets = body?.targets;\n if (!Array.isArray(targets) || targets.length === 0) {\n return c.json({ error: \"targets required\" }, 400);\n }\n\n const originalContent = readFileSync(ctx.absPath, \"utf-8\");\n // The response says whether the file changed, not how many of the targets landed, so a\n // caller can tell a no-op from a write, but not a partial pass from a complete one.\n return writeIfChanged(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n originalContent,\n removeElementsFromHtml(originalContent, targets),\n );\n });\n\n api.post(\"/projects/:id/file-mutations/split-batch\", async (c) => {\n const body = (await c.req.json().catch(() => null)) as {\n files?: unknown;\n transactionToken?: unknown;\n } | null;\n if (\n !Array.isArray(body?.files) ||\n body.files.length === 0 ||\n !body.files.every(isAtomicCutFileRequest)\n ) {\n return c.json({ error: \"files with path, expectedVersion, and cut targets required\" }, 400);\n }\n const files = body.files as AtomicCutFileRequest[];\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n let writer: \"recast\" | \"acorn\";\n try {\n writer = resolveGsapWriter({\n HYPERFRAMES_GSAP_WRITER: process.env[\"HYPERFRAMES_GSAP_WRITER\"],\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);\n }\n\n return serializeAtomicCut(async () => {\n const seen = new Set<string>();\n const prepared: FoldedAtomicCutFile[] = [];\n for (const file of files) {\n const absPath = pinWithinProject(project.dir, file.path);\n if (!absPath) return c.json({ error: `forbidden path: ${file.path}` }, 403);\n if (seen.has(absPath)) return c.json({ error: `duplicate path: ${file.path}` }, 400);\n seen.add(absPath);\n\n let before: string;\n try {\n before = readFileSync(absPath, \"utf-8\");\n } catch {\n return c.json({ error: `not found: ${file.path}` }, 404);\n }\n const currentVersion = fileContentVersion(before);\n if (currentVersion !== file.expectedVersion) {\n return c.json(\n {\n error: `file conflict: ${file.path}`,\n path: file.path,\n currentVersion,\n currentContent: before,\n },\n 409,\n );\n }\n let folded: FoldedAtomicCutFile | Response;\n try {\n folded = await foldAtomicCutFile(c, file, absPath, before, writer);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Cut transform failed\";\n return c.json({ error: message }, 400);\n }\n if (folded instanceof Response) return folded;\n prepared.push(folded);\n }\n\n // Lazy GSAP parsing above can yield; revalidate every base before the first write.\n for (const file of prepared) {\n const current = readFileSync(file.absPath, \"utf-8\");\n if (current !== file.before) {\n return c.json(\n {\n error: `file conflict: ${file.path}`,\n path: file.path,\n currentVersion: fileContentVersion(current),\n currentContent: current,\n },\n 409,\n );\n }\n }\n\n const backups = new Map<string, string | null>();\n for (const file of prepared) {\n const backup = snapshotBeforeWrite(project.dir, file.absPath);\n if (backup.error) {\n return c.json(\n { error: `Failed to create backup for ${file.path}: ${backup.error}` },\n 500,\n );\n }\n backups.set(file.path, backupPathForResponse(project.dir, backup.backupPath));\n }\n\n const writeToken = createWriteToken(\n typeof body.transactionToken === \"string\"\n ? body.transactionToken\n : c.req.header(\"X-Hyperframes-Write-Token\"),\n );\n const written: FoldedAtomicCutFile[] = [];\n try {\n for (const file of prepared) {\n replaceFileAtomically(file.absPath, file.after, statSync(file.absPath).mode);\n written.push(file);\n recordFileWriteReceipt(file.absPath, {\n path: file.path,\n version: fileContentVersion(file.after),\n writeToken,\n overwrote: file.before,\n });\n }\n } catch (error) {\n const conflicts: string[] = [];\n for (const file of written.reverse()) {\n try {\n const current = readFileSync(file.absPath, \"utf-8\");\n if (current !== file.after) {\n conflicts.push(file.path);\n continue;\n }\n replaceFileAtomically(file.absPath, file.before, statSync(file.absPath).mode);\n recordFileWriteReceipt(file.absPath, {\n path: file.path,\n version: fileContentVersion(file.before),\n writeToken,\n });\n } catch {\n conflicts.push(file.path);\n }\n }\n return c.json(\n {\n error: error instanceof Error ? error.message : \"Cut write failed\",\n outcome: conflicts.length ? \"aborted-with-conflicts\" : \"aborted-restored\",\n conflicts,\n },\n conflicts.length ? 409 : 500,\n );\n }\n\n const result = prepared.map((file) => ({\n path: file.path,\n before: file.before,\n after: file.after,\n version: fileContentVersion(file.after),\n writeToken,\n backupPath: backups.get(file.path) ?? null,\n splitCount: file.splitCount,\n skippedSelectors: file.skippedSelectors,\n }));\n return c.json({ ok: true, outcome: \"committed\", files: result });\n });\n });\n\n api.post(\"/projects/:id/file-mutations/split-element/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"split-element\");\n if (\"error\" in ctx) return ctx.error;\n\n const parsed = await parseMutationBody<{\n target?: { id?: string; selector?: string; selectorIndex?: number };\n splitTime?: number;\n newId?: string;\n elementStart?: number;\n elementDuration?: number;\n }>(c);\n if (\"error\" in parsed) return parsed.error;\n if (typeof parsed.body.splitTime !== \"number\" || !parsed.body.newId) {\n return c.json({ error: \"target, splitTime, and newId required\" }, 400);\n }\n const fallbackTiming =\n typeof parsed.body.elementStart === \"number\" &&\n typeof parsed.body.elementDuration === \"number\"\n ? { start: parsed.body.elementStart, duration: parsed.body.elementDuration }\n : undefined;\n\n let originalContent: string;\n try {\n originalContent = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ error: \"not found\" }, 404);\n }\n const result = splitElementInHtml(\n originalContent,\n parsed.target,\n parsed.body.splitTime,\n parsed.body.newId,\n fallbackTiming,\n );\n if (!result.matched) {\n const version = fileContentVersion(originalContent);\n c.header(\"ETag\", version);\n return c.json({\n ok: false,\n changed: false,\n content: originalContent,\n path: ctx.filePath,\n version,\n });\n }\n const mutationResult = writeMutationResult(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n result.html,\n originalContent,\n );\n if (mutationResult instanceof Response) return mutationResult;\n const { version, backupPath } = mutationResult;\n c.header(\"ETag\", version);\n return c.json({\n ok: true,\n changed: true,\n content: result.html,\n newId: result.newId,\n path: ctx.filePath,\n version,\n backupPath,\n });\n });\n\n api.post(\"/projects/:id/file-mutations/patch-element/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"patch-element\");\n if (\"error\" in ctx) return ctx.error;\n\n const parsed = await parseMutationBody<{\n target?: MutationTarget;\n operations?: PatchOperation[];\n fontFaceCss?: unknown;\n }>(c);\n if (\"error\" in parsed) return parsed.error;\n if (!Array.isArray(parsed.body.operations) || parsed.body.operations.length === 0) {\n return c.json({ error: \"target and operations required\" }, 400);\n }\n const { fontFaceCss } = parsed.body;\n if (fontFaceCss !== undefined && !isStudioFontFaceCss(fontFaceCss)) {\n return c.json({ error: \"fontFaceCss must be one @font-face rule\" }, 400);\n }\n const unsafeFields = findUnsafeDomPatchValues(parsed.body);\n if (unsafeFields.length > 0) {\n return rejectUnsafeMutationValues(c, unsafeFields);\n }\n\n for (let attempt = 1; ; attempt += 1) {\n let originalContent: string;\n try {\n originalContent = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ error: \"not found\" }, 404);\n }\n const takenIds = parsed.body.operations.some((op) => op.type === \"ensure-id\")\n ? projectHtmlIds(ctx.project.dir)\n : undefined;\n const element = patchElementInHtml(\n originalContent,\n parsed.target,\n parsed.body.operations,\n takenIds,\n );\n const { matched } = element;\n const patched =\n matched && isStudioFontFaceCss(fontFaceCss)\n ? ensureStudioFontFaceCss(element.html, fontFaceCss)\n : element.html;\n if (patched === originalContent) {\n const version = fileContentVersion(originalContent);\n c.header(\"ETag\", version);\n return c.json({\n ok: true,\n changed: false,\n matched,\n elementId: element.elementId,\n content: originalContent,\n path: ctx.filePath,\n version,\n });\n }\n const mutationResult = writeMutationResult(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n patched,\n originalContent,\n );\n if (mutationResult instanceof Response) {\n if (mutationResult.status === 409 && attempt < PATCH_CONFLICT_ATTEMPTS) continue;\n return mutationResult;\n }\n const { backupPath, version } = mutationResult;\n c.header(\"ETag\", version);\n return c.json({\n ok: true,\n changed: true,\n matched,\n elementId: element.elementId,\n content: patched,\n path: ctx.filePath,\n version,\n backupPath,\n });\n }\n });\n\n api.post(\"/projects/:id/file-mutations/patch-element-batches\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const body: unknown = await c.req.json().catch(() => null);\n if (\n typeof body !== \"object\" ||\n body === null ||\n !(\"batches\" in body) ||\n !Array.isArray(body.batches) ||\n body.batches.length === 0 ||\n !body.batches.every(isElementPatchBatchRequest)\n ) {\n return c.json({ error: \"batches with sourceFile and patches required\" }, 400);\n }\n const unsafeFields = findUnsafeElementPatchBatchValues(body.batches);\n if (unsafeFields.length > 0) return rejectUnsafeMutationValues(c, unsafeFields);\n\n const result = commitElementPatchBatchesWithReceipts(c, project.dir, body.batches);\n if (\"error\" in result) {\n return elementPatchBatchCommitErrorResponse(c, result.error, result.sourceFile);\n }\n return c.json(result);\n });\n\n api.post(\"/projects/:id/file-mutations/patch-elements-batch/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"patch-elements-batch\");\n if (\"error\" in ctx) return ctx.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n patches?: ElementPatchRequest[];\n } | null;\n if (\n !body ||\n !Array.isArray(body.patches) ||\n body.patches.length === 0 ||\n !body.patches.every(isElementPatchRequest)\n ) {\n return c.json({ error: \"patches with target and operations required\" }, 400);\n }\n const batch = { sourceFile: ctx.filePath, patches: body.patches };\n const unsafeFields = findUnsafeElementPatchBatchValues([batch]);\n if (unsafeFields.length > 0) {\n return rejectUnsafeMutationValues(c, unsafeFields);\n }\n\n const result = commitElementPatchBatchesWithReceipts(c, ctx.project.dir, [batch]);\n if (\"error\" in result) {\n return elementPatchBatchCommitErrorResponse(c, result.error, result.sourceFile);\n }\n const file = result.files[0];\n if (!file) return c.json({ error: \"empty element patch result\" }, 500);\n return c.json({\n ok: true,\n changed: file.changed,\n matched: file.matched,\n content: file.after,\n path: file.sourceFile,\n backupPath: file.backupPath,\n });\n });\n\n api.post(\"/projects/:id/file-mutations/wrap-elements/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"wrap-elements\");\n if (\"error\" in ctx) return ctx.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n targets?: MutationTarget[];\n groupId?: string;\n bbox?: { left?: number; top?: number; width?: number; height?: number };\n rebases?: ElementRebase[];\n } | null;\n if (!Array.isArray(body?.targets) || body.targets.length === 0 || !body.groupId) {\n return c.json({ error: \"targets and groupId required\" }, 400);\n }\n // left/top/width/height are interpolated into inline style strings; reject\n // anything non-numeric so a crafted value can't inject extra declarations.\n const bbox = body.bbox ?? {};\n const bboxNums = [bbox.left, bbox.top, bbox.width, bbox.height];\n const rebases = body.rebases ?? [];\n const allNumeric =\n bboxNums.every((n) => typeof n === \"number\" && Number.isFinite(n)) &&\n rebases.every(\n (r) =>\n typeof r?.left === \"number\" &&\n Number.isFinite(r.left) &&\n typeof r?.top === \"number\" &&\n Number.isFinite(r.top) &&\n isOptionalInteger(r?.track),\n );\n if (!allNumeric) {\n return c.json({ error: \"bbox and rebase coordinates must be finite numbers\" }, 400);\n }\n\n let originalContent: string;\n try {\n originalContent = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ error: \"not found\" }, 404);\n }\n const result = wrapElementsInHtml(\n originalContent,\n body.targets,\n body.groupId,\n { left: bbox.left!, top: bbox.top!, width: bbox.width!, height: bbox.height! },\n rebases,\n );\n if (!result.matched) {\n return c.json(\n {\n ok: false,\n changed: false,\n content: originalContent,\n path: ctx.filePath,\n error: result.error,\n },\n result.error === \"grouped elements must share a single parent\" ? 422 : 400,\n );\n }\n const mutationResult = writeMutationResult(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n result.html,\n originalContent,\n );\n if (mutationResult instanceof Response) return mutationResult;\n const { backupPath } = mutationResult;\n return c.json({\n ok: true,\n changed: true,\n groupId: result.groupId,\n content: result.html,\n path: ctx.filePath,\n backupPath,\n });\n });\n\n api.post(\"/projects/:id/file-mutations/unwrap-elements/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"unwrap-elements\");\n if (\"error\" in ctx) return ctx.error;\n\n const parsed = await parseMutationBody<{\n target?: MutationTarget;\n childTracks?: Array<{ target?: MutationTarget; track?: number }>;\n }>(c);\n if (\"error\" in parsed) return parsed.error;\n\n const rawChildTracks = parsed.body.childTracks ?? [];\n if (!rawChildTracks.every((entry) => isOptionalInteger(entry?.track))) {\n return c.json({ error: \"childTracks track must be a finite integer\" }, 400);\n }\n const childTracks = rawChildTracks\n .filter((entry): entry is { target: MutationTarget; track?: number } =>\n Boolean(entry?.target),\n )\n .map((entry) => ({ target: entry.target, track: entry.track }));\n\n let originalContent: string;\n try {\n originalContent = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ error: \"not found\" }, 404);\n }\n const result = unwrapElementsFromHtml(originalContent, parsed.target, childTracks);\n if (!result.unwrapped) {\n return c.json({ ok: false, changed: false, content: originalContent, path: ctx.filePath });\n }\n // BAKE the group's static transform into the members FIRST, so the group's\n // accumulated moves are preserved (otherwise members snap back to their\n // creation-time positions), THEN strip the group's GSAP — a leftover\n // `gsap.set(\"#group-1\")` throws \"target not found\" every preview run.\n let cleaned = result.html;\n if (result.unwrappedGroupId && result.members && result.groupCenter) {\n cleaned = bakeGroupTransformIntoMembers(\n cleaned,\n result.unwrappedGroupId,\n result.members,\n result.groupCenter,\n );\n }\n if (result.unwrappedGroupId) {\n cleaned = stripGsapAnimationsForSelector(cleaned, `#${result.unwrappedGroupId}`);\n }\n return writeIfChanged(c, ctx.project.dir, ctx.filePath, ctx.absPath, originalContent, cleaned);\n });\n\n api.post(\"/projects/:id/file-mutations/probe-element/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"probe-element\");\n if (\"error\" in ctx) return ctx.error;\n\n const parsed = await parseMutationBody<{ target?: MutationTarget }>(c);\n if (\"error\" in parsed) return parsed.error;\n\n let content: string;\n try {\n content = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ exists: false });\n }\n\n const exists = probeElementInSource(content, parsed.target);\n return c.json({ exists });\n });\n\n api.post(\"/projects/:id/file-mutations/probe-elements/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"probe-elements\");\n if (\"error\" in ctx) return ctx.error;\n\n const body = (await c.req.json().catch(() => null)) as { targets?: MutationTarget[] } | null;\n if (!Array.isArray(body?.targets)) return c.json({ error: \"targets required\" }, 400);\n\n let content: string;\n try {\n content = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ exists: body.targets.map(() => false) });\n }\n return c.json({ exists: probeElementsInSource(content, body.targets) });\n });\n\n // ── Rename / Move ──\n\n api.patch(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter, { mustExist: true });\n if (\"error\" in res) return res.error;\n\n const body = (await c.req.json()) as { newPath?: string };\n if (!body.newPath || body.newPath.includes(\"\\0\")) {\n return c.json({ error: \"newPath required\" }, 400);\n }\n\n const newAbs = resolveWithinProject(res.project.dir, body.newPath);\n if (!newAbs) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n if (existsSync(newAbs)) {\n return c.json({ error: \"already exists\" }, 409);\n }\n\n const isDirectory = statSync(res.absPath, { throwIfNoEntry: false })?.isDirectory() ?? false;\n ensureDir(res.project.dir, newAbs);\n renameSync(res.absPath, newAbs);\n\n // Update references to the old path across all project files\n const updatedFiles = updateReferences(res.project.dir, res.filePath, body.newPath, isDirectory);\n\n return c.json({ ok: true, path: body.newPath, updatedReferences: updatedFiles });\n });\n\n // ── Duplicate ──\n\n api.post(\"/projects/:id/duplicate-file\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const body = (await c.req.json()) as { path: string };\n if (!body.path || body.path.includes(\"\\0\")) {\n return c.json({ error: \"path required\" }, 400);\n }\n\n const srcAbs = resolveWithinProject(project.dir, body.path);\n if (!srcAbs || !existsSync(srcAbs)) {\n return c.json({ error: \"not found\" }, 404);\n }\n\n const copyPath = generateCopyPath(project.dir, body.path);\n const destAbs = resolveWithinProject(project.dir, copyPath);\n if (!destAbs) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n\n ensureDir(project.dir, destAbs);\n try {\n createFileAtomically(destAbs, readFileSync(srcAbs));\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n return c.json({ error: \"already exists\" }, 409);\n }\n\n return c.json({ ok: true, path: copyPath }, 201);\n });\n\n // ── Upload (binary assets via multipart form) ──\n\n api.post(\n \"/projects/:id/upload\",\n bodyLimit({\n maxSize: MAX_UPLOAD_BYTES,\n onError: (c) => c.json({ error: \"payload too large\" }, 413),\n }),\n async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n if (folderGone(project.dir)) return projectDirMissing(c);\n\n // Optional subdirectory within the project (e.g. \"assets/audio\")\n const subDir = c.req.query(\"dir\") ?? \"\";\n const targetDir = subDir ? resolveWithinProject(project.dir, subDir) : project.dir;\n if (!targetDir) return c.json({ error: \"forbidden\" }, 403);\n\n const formData = await c.req.formData();\n mkdirWithinProject(project.dir, targetDir);\n const result = await processUploadedFiles(formData, targetDir, project.dir);\n if (folderGone(project.dir)) return projectDirMissing(c);\n\n return c.json(\n {\n ok: true,\n files: result.uploaded,\n skipped: result.skipped,\n invalid: result.invalid,\n unchecked: result.unchecked,\n },\n 201,\n );\n },\n );\n\n // ── GSAP Animations (parse) ──\n\n api.get(\"/projects/:id/gsap-animations/*\", async (c) => {\n const res = await resolveProjectPath(c, adapter, \"gsap-animations\", {\n mustExist: true,\n });\n if (\"error\" in res) return res.error;\n\n // The parse is a pure function of the file and the parser, so a client that revalidates on\n // every read gets a 304 for every unchanged file; bump the `v1` salt when the parser changes.\n const html = readFileSync(res.absPath, \"utf-8\");\n const etag = `${fileContentVersion(html).slice(0, -1)}:gsap-animations:v1\"`;\n const headers = { ETag: etag, \"Cache-Control\": \"no-cache\" };\n if (c.req.header(\"If-None-Match\") === etag) return new Response(null, { status: 304, headers });\n\n const block = extractGsapScriptBlock(html);\n if (!block) {\n return c.json(\n { animations: [], timelineVar: \"tl\", preamble: \"\", postamble: \"\" },\n 200,\n headers,\n );\n }\n\n return c.json(parseGsapScriptAcorn(block.scriptText), 200, headers);\n });\n\n // ── GSAP Mutations ──\n\n api.get(\"/projects/:id/gsap-mutation-capabilities\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n return c.json({ atomicOwnershipPairs: true });\n });\n\n api.post(\"/projects/:id/gsap-mutations/*\", async (c) => {\n const res = await resolveProjectPath(c, adapter, \"gsap-mutations\", {\n mustExist: true,\n pin: true,\n });\n if (\"error\" in res) return res.error;\n\n const body = (await c.req.json().catch(() => null)) as GsapMutationRequest | null;\n if (!body) return c.json({ error: \"mutation type required\" }, 400);\n const error = validateGsapMutationRequest(c, body);\n if (error) return error;\n return applyGsapMutations(c, res, [body]);\n });\n\n api.post(\"/projects/:id/gsap-mutations-batch/*\", async (c) => {\n const res = await resolveProjectPath(c, adapter, \"gsap-mutations-batch\", {\n mustExist: true,\n pin: true,\n });\n if (\"error\" in res) return res.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n mutations?: GsapMutationRequest[];\n } | null;\n if (!body || !Array.isArray(body.mutations) || body.mutations.length === 0) {\n return c.json({ error: \"mutations array required\" }, 400);\n }\n for (const mutation of body.mutations) {\n const error = validateGsapMutationRequest(c, mutation);\n if (error) return error;\n }\n return applyGsapMutations(c, res, body.mutations);\n });\n\n // A failed multi-step GSAP transaction may restore only the exact bytes its\n // mutation wrote. Keep compare + write in this synchronous server section so\n // another request cannot land between a client-side check and the restore.\n api.post(\"/projects/:id/gsap-mutation-rollback/*\", async (c) => {\n const res = await resolveProjectPath(c, adapter, \"gsap-mutation-rollback\", {\n mustExist: true,\n pin: true,\n });\n if (\"error\" in res) return res.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n expected?: unknown;\n restore?: unknown;\n } | null;\n if (!body || typeof body.expected !== \"string\" || typeof body.restore !== \"string\") {\n return c.json({ error: \"expected and restore contents required\" }, 400);\n }\n\n const current = readFileSync(res.absPath, \"utf-8\");\n if (current !== body.expected) {\n return c.json({ ok: true, restored: false, conflict: true });\n }\n replaceFileAtomically(res.absPath, body.restore, statSync(res.absPath).mode);\n return c.json({ ok: true, restored: true, conflict: false });\n });\n}\n","export const MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html\",\n \".css\": \"text/css\",\n \".js\": \"text/javascript\",\n \".mjs\": \"text/javascript\",\n \".json\": \"application/json\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".ico\": \"image/x-icon\",\n \".mp4\": \"video/mp4\",\n \".m4v\": \"video/mp4\",\n \".mov\": \"video/quicktime\",\n \".mkv\": \"video/x-matroska\",\n \".mxf\": \"video/mxf\",\n \".mts\": \"video/mp2t\",\n \".m2ts\": \"video/mp2t\",\n \".ts\": \"video/mp2t\",\n \".webm\": \"video/webm\",\n \".mp3\": \"audio/mpeg\",\n \".wav\": \"audio/wav\",\n \".ogg\": \"audio/ogg\",\n \".m4a\": \"audio/mp4\",\n \".aac\": \"audio/aac\",\n \".flac\": \"audio/flac\",\n \".opus\": \"audio/ogg\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".otf\": \"font/otf\",\n \".txt\": \"text/plain\",\n \".md\": \"text/markdown\",\n \".cube\": \"text/plain; charset=utf-8\",\n};\n\nexport function getMimeType(path: string): string {\n const ext = path.slice(path.lastIndexOf(\".\")).toLowerCase();\n return MIME_TYPES[ext] || \"application/octet-stream\";\n}\n\nexport function isAudioFile(name: string): boolean {\n return (getMimeType(name) ?? \"\").startsWith(\"audio/\");\n}\n","import { readFileSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { parseHTML } from \"linkedom\";\nimport { createProjectSignature } from \"./projectSignature.js\";\nimport { rootHeadContent } from \"./subComposition.js\";\nimport { resolveWithinProject } from \"./safePath.js\";\nimport { descendants } from \"./compositionInsertion.js\";\n\nconst ROOT_COMPOSITION = \"index.html\";\n// A regex, not a parser: a stray match (say, inside a script string) only widens what a\n// change invalidates, never narrows it.\nconst COMPOSITION_SRC = /\\bdata-composition-src\\s*=\\s*([\"'])(.*?)\\1/g;\n\ntype SourceReader = (compPath: string) => string | null;\n\nfunction projectReader(projectDir: string): SourceReader {\n const sources = new Map<string, string | null>();\n return (compPath) => {\n if (!sources.has(compPath)) {\n const file = resolveWithinProject(projectDir, compPath);\n let source: string | null = null;\n try {\n source = file ? readFileSync(file, \"utf-8\") : null;\n } catch {\n // Missing or unreadable: it mounts nothing, and still counts as mounted by its host.\n }\n sources.set(compPath, source);\n }\n return sources.get(compPath) ?? null;\n };\n}\n\nfunction normalizeSource(src: string): string | null {\n if (/^[a-z][a-z0-9+.-]*:/i.test(src) || src.startsWith(\"//\")) return null;\n const path = src.split(/[?#]/)[0]?.replace(/^\\.?\\//, \"\") ?? \"\";\n return path || null;\n}\n\n/** `compPath` plus every composition it mounts, transitively, resolved from the project root as the bundler does. */\nfunction closureOf(read: SourceReader, compPath: string): Set<string> {\n const closure = new Set<string>();\n const visit = (path: string) => {\n if (closure.has(path)) return;\n closure.add(path);\n for (const match of (read(path) ?? \"\").matchAll(COMPOSITION_SRC)) {\n const mounted = normalizeSource(match[2] ?? \"\");\n if (mounted) visit(mounted);\n }\n };\n visit(compPath);\n return closure;\n}\n\n/** Whether `compPath` lasts as long as its own timeline (so a trim there could end the film early). */\nexport function lengthIsTimeline(projectDir: string, compPath: string): boolean {\n const read = projectReader(projectDir);\n const documents = new Map<string, Document>();\n const elements = (path: string, selector: string) => {\n let document = documents.get(path);\n if (!document) documents.set(path, (document = parseHTML(read(path) ?? \"\").document));\n return descendants(document, selector);\n };\n const comp = normalizeSource(compPath) ?? compPath;\n const unsized = (path: string) => {\n const [root] = elements(path, \"[data-composition-id]\");\n return Boolean(root && !root.hasAttribute(\"data-duration\"));\n };\n // An unsized root lasts as long as every timeline it plays, its compositions' included.\n if (unsized(ROOT_COMPOSITION)) return true;\n const hosts = [...closureOf(read, ROOT_COMPOSITION)].flatMap((path) =>\n elements(path, \"[data-composition-src]\").filter(\n (host) => normalizeSource(host.getAttribute(\"data-composition-src\") ?? \"\") === comp,\n ),\n );\n if (comp === ROOT_COMPOSITION || hosts.length === 0) return unsized(comp);\n return hosts.some(\n (host) => !host.hasAttribute(\"data-duration\") && !host.hasAttribute(\"data-end\"),\n );\n}\n\n// ponytail: this and projectSignature's per-exclusion cache keep one small entry per (project,\n// composition) ever thumbnailed, never evicted; LRU them if a server ever holds thousands.\nconst inputSignatures = new Map<string, { projectSignature: string; inputSignature: string }>();\n\ninterface RootMemo {\n root: string;\n head: string;\n affected: string[] | null;\n}\n\nconst rootMemos = new Map<string, RootMemo>();\n\nconst sha1 = (text: string) => createHash(\"sha1\").update(text).digest(\"hex\");\n\nfunction rootHashes(read: SourceReader) {\n const source = read(ROOT_COMPOSITION) ?? \"\";\n return { root: sha1(source), head: sha1(rootHeadContent(source)) };\n}\n\n// What a thumbnail of `compPath` renders from: the project minus the compositions the root\n// mounts that `compPath` does not; for a scene the root counts as its head alone.\nexport function compositionInputSignature(\n projectDir: string,\n compPath: string,\n projectSignature: string,\n): string {\n const key = `${projectDir}\\0${compPath}`;\n const known = inputSignatures.get(key);\n if (known?.projectSignature === projectSignature) return known.inputSignature;\n const read = projectReader(projectDir);\n const comp = normalizeSource(compPath) ?? compPath;\n const inputs = closureOf(read, comp).add(ROOT_COMPOSITION);\n const excluded = new Set(\n [...closureOf(read, ROOT_COMPOSITION)].filter((path) => !inputs.has(path)),\n );\n let inputSignature: string;\n if (comp === ROOT_COMPOSITION) {\n inputSignature = createProjectSignature(projectDir, excluded);\n } else {\n const hashes = rootHashes(read);\n if (!rootMemos.has(projectDir)) rootMemos.set(projectDir, { ...hashes, affected: null });\n inputSignature = `${createProjectSignature(projectDir, excluded.add(ROOT_COMPOSITION))}:${hashes.head}`;\n }\n inputSignatures.set(key, { projectSignature, inputSignature });\n return inputSignature;\n}\n\n/**\n * Compositions whose rendered frames a write at `changedPath` can change, or `null` for all\n * of them: assets, a root head edit, and any file the root does not mount reach every\n * composition. A head-preserving root write changes only the root's own frames.\n */\nexport function compositionsAffectedBy(projectDir: string, changedPath: string): string[] | null {\n const changed = changedPath.replace(/\\\\/g, \"/\");\n const read = projectReader(projectDir);\n if (changed === ROOT_COMPOSITION) {\n const now = rootHashes(read);\n const memo = rootMemos.get(projectDir);\n if (memo?.root === now.root) return memo.affected;\n const affected = memo?.head === now.head ? [ROOT_COMPOSITION] : null;\n rootMemos.set(projectDir, { ...now, affected });\n return affected;\n }\n const mounted = closureOf(read, ROOT_COMPOSITION);\n if (!mounted.has(changed)) return null;\n return [...mounted].filter((path) => closureOf(read, path).has(changed));\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseHTML } from \"linkedom\";\nimport {\n rewriteAssetPaths,\n rewriteCssAssetUrls,\n rewriteInlineStyleAssetUrls,\n} from \"@hyperframes/core\";\nimport {\n deferScriptsUntilFonts,\n RUNTIME_BOOTSTRAP_ATTR,\n stripEmbeddedRuntimeScripts,\n} from \"@hyperframes/core/compiler\";\nimport { isFullHtmlDocument } from \"@hyperframes/core/compiler/html-document\";\nimport { gsapCdnDist } from \"@hyperframes/core/gsap-cdn\";\n\n/**\n * Rewrite relative asset paths in a parsed DOM tree. Shared across all\n * three dispatch branches (template, full-doc, fragment) to avoid drift.\n *\n * The preview page borrows the project-root `<base>`, so a composition at\n * `design/styleframes/frame-01.html` referencing its sibling `_shared.css` was\n * requested as `/preview/_shared.css` (404). The frame then rendered unstyled,\n * which the thumbnailer's transparent-body fallback painted dark navy — the\n * \"illegible styleframe thumbnail\" bug. The `assetExists` probe re-points such\n * refs at the composition's own directory; see `rewriteAssetPath`.\n */\nfunction rewriteRelativePaths(root: ParentNode, compPath: string, projectDir: string): void {\n const assetExists = (path: string) => existsSync(join(projectDir, path));\n rewriteAssetPaths(\n root.querySelectorAll(\"[src], [href]\"),\n compPath,\n (el: Element, attr: string) => el.getAttribute(attr),\n (el: Element, attr: string, value: string) => el.setAttribute(attr, value),\n assetExists,\n );\n rewriteInlineStyleAssetUrls(\n root.querySelectorAll(\"[style]\"),\n compPath,\n (el: Element) => el.getAttribute(\"style\"),\n (el: Element, value: string) => el.setAttribute(\"style\", value),\n assetExists,\n );\n for (const styleEl of root.querySelectorAll(\"style\")) {\n styleEl.textContent = rewriteCssAssetUrls(styleEl.textContent || \"\", compPath, assetExists);\n }\n}\n\n/**\n * Escape a CSS identifier whose first character is a digit so it is a valid\n * selector. A CSS ident cannot start with a digit, so it must be written as an\n * escaped code point: `01-foo` → `\\30 1-foo` (leading `0` → `\\30 `, rest kept).\n *\n * Only the leading digit needs escaping (per CSS Syntax Level 3 §4.3.11): once\n * the parser consumes the `\\<hex> ` escape, the rest of the ident continues\n * normally, so `123-scene` → `\\31 23-scene` is valid (the `23-scene` tail is\n * consumed as identifier continuation). The trailing space terminates the hex\n * escape so a following hex digit isn't folded into the code point.\n */\nfunction escapeLeadingDigitIdent(id: string): string {\n return `\\\\${id.charCodeAt(0).toString(16)} ${id.slice(1)}`;\n}\n\nconst REGEXP_SPECIALS = /[.*+?^${}()|[\\]\\\\]/g;\n\n/**\n * Fix `#<digit-leading-id>` selectors in the tree's `<style>` blocks.\n *\n * CSS identifiers cannot start with a digit, so an authored rule like\n * `#01-wall-pushes-back { width: 1920px; height: 1080px; background: #F0EBDE }`\n * is an invalid selector and the browser silently drops the WHOLE rule — taking\n * the root's size and background with it. In a full composition the frame is\n * stretched/painted by its `data-composition-src` host so the collapse is\n * masked, but a standalone preview has no host: the root falls back to\n * `height: 0` + transparent and the frame renders blank (black).\n *\n * Rewrite each such selector to its escaped, valid form (`#\\30 1-wall-pushes-back`,\n * which still matches `id=\"01-wall-pushes-back\"`) so the rule applies and the\n * whole declaration block — size, background, position, container-type — comes\n * back. Scoped to ids that are actually present on elements in the content and\n * matched only as `#id` not followed by another ident char, so hex colors\n * (`#1F2BE0`) and other values are never touched (they are not element ids).\n */\nfunction fixDigitLeadingIdSelectors(root: ParentNode): void {\n const digitIds = new Set<string>();\n for (const el of root.querySelectorAll(\"[id]\")) {\n const id = el.getAttribute(\"id\");\n if (id && /^\\d/.test(id)) digitIds.add(id);\n }\n if (digitIds.size === 0) return;\n\n for (const styleEl of root.querySelectorAll(\"style\")) {\n let css = styleEl.textContent || \"\";\n for (const id of digitIds) {\n const pattern = new RegExp(`#${id.replace(REGEXP_SPECIALS, \"\\\\$&\")}(?![\\\\w-])`, \"g\");\n css = css.replace(pattern, `#${escapeLeadingDigitIdent(id)}`);\n }\n styleEl.textContent = css;\n }\n}\n\n/**\n * Parse a full HTML document and extract its head elements and body\n * content separately, so they can be reassembled into a clean standalone\n * page without nesting `<html>` inside `<body>`.\n *\n * Extracts the full innerHTML of `<head>` — this preserves `<style>`,\n * `<script>`, `<link>`, `<meta>`, and any other head-level tags the\n * composition declares. Dropping `<link rel=\"stylesheet\">` or `<meta>`\n * would cause silent rendering failures for compositions that ship with\n * external CSS or viewport-dependent meta.\n *\n * `<html>` and `<body>` attributes (lang, class, data-*) are extracted\n * so callers can forward them to the assembled page.\n */\nfunction extractFullDocumentParts(\n rawHtml: string,\n compPath: string,\n projectDir: string,\n): {\n headContent: string;\n bodyContent: string;\n htmlAttrs: string;\n bodyAttrs: string;\n} {\n const { document: doc } = parseHTML(rawHtml);\n\n const rewriteTargets = [doc.head, doc.body].filter(Boolean);\n for (const target of rewriteTargets) {\n rewriteRelativePaths(target, compPath, projectDir);\n }\n // Run on the whole document: ids live in <body> but their rules may live in\n // a <head> <style>, so the scope must span both.\n fixDigitLeadingIdSelectors(doc);\n\n const headContent = doc.head?.innerHTML ?? \"\";\n const bodyContent = doc.body?.innerHTML ?? \"\";\n\n const htmlEl = doc.documentElement;\n const htmlAttrs = extractElementAttrs(htmlEl);\n const bodyAttrs = doc.body ? extractElementAttrs(doc.body) : \"\";\n\n return { headContent, bodyContent, htmlAttrs, bodyAttrs };\n}\n\n/**\n * Extract the inner HTML of the composition's wrapping `<template>` element, or\n * `null` if the source has no `<template>`.\n *\n * Located via the DOM rather than a regex. A greedy\n * `/<template[^>]*>([\\s\\S]*)<\\/template>/` can latch onto a literal\n * `\"<template>\"` that appears inside an HTML comment — e.g. a head note such as\n * \"the HF runtime clones ONLY <template> contents\" — and mis-slice the capture,\n * leaving the real composition content re-wrapped in an inert `<template>` in\n * the output. That template is never rendered by the browser, so the standalone\n * preview has no `[data-composition-id]` element and no registered timeline, and\n * renders blank. `querySelector(\"template\")` only ever matches a real element\n * node, so comment text can't fool it.\n */\nfunction extractTemplateInnerHtml(rawComp: string): string | null {\n const { document: doc } = parseHTML(rawComp);\n const template = doc.querySelector(\"template\");\n return template ? template.innerHTML : null;\n}\n\n/** Attribute values read from the DOM are decoded — re-escape on rebuild or\n * quote-bearing values (data-composition-variables is a JSON array) shred\n * the wrapper's markup into bogus attributes. */\nfunction escapeAttrValue(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\nfunction extractElementAttrs(el: Element): string {\n const parts: string[] = [];\n for (let i = 0; i < el.attributes.length; i++) {\n const attr = el.attributes[i]!;\n if (attr.value === \"\") {\n parts.push(attr.name);\n } else {\n parts.push(`${attr.name}=\"${escapeAttrValue(attr.value)}\"`);\n }\n }\n return parts.join(\" \");\n}\n\nconst NON_RENDERED_TAGS = new Set([\"SCRIPT\", \"STYLE\", \"LINK\", \"META\", \"TEMPLATE\", \"NOSCRIPT\"]);\n\n/**\n * Carry the `<template>`'s `data-composition-id` onto the content's root\n * rendered element when the author declared it only on the `<template>` tag.\n *\n * In a full composition, each sub-composition is mounted under a wrapper\n * element (the `data-composition-src` host) that carries the composition id,\n * which is how the runtime binds `window.__timelines[id]` into the player's\n * master timeline. A standalone preview has no such wrapper, so it relies on\n * the frame's own root element carrying `data-composition-id`. If the id lives\n * only on the inert `<template>` tag (a common authoring pattern), the rendered\n * body has no `[data-composition-id]` element — the runtime then never selects\n * a root composition, the registered GSAP timeline stays unbound, and seeking\n * does nothing. The frame renders at its pre-animation state (GSAP `fromTo`\n * pins `opacity:0`), producing a blank preview/thumbnail.\n *\n * This is a no-op when the content already exposes a `[data-composition-id]`\n * element (e.g. the id is authored on the root div), so compositions that\n * already render correctly are untouched.\n */\nfunction promoteTemplateCompositionId(rawComp: string, body: Element): void {\n // Two-step match instead of one `[^>]*\\s…` regex: the single-pattern form\n // backtracks polynomially on crafted input (CodeQL js/polynomial-redos).\n // Step 1 grabs each <template …> open tag (linear); step 2 finds the attr\n // within that short tag text.\n let templateCompositionId: string | undefined;\n for (const tag of rawComp.matchAll(/<template\\b[^>]*/gi)) {\n const id = /\\bdata-composition-id\\s*=\\s*[\"']([^\"']+)[\"']/i.exec(tag[0] ?? \"\")?.[1];\n if (id) {\n templateCompositionId = id;\n break;\n }\n }\n if (!templateCompositionId) return;\n if (body.querySelector(\"[data-composition-id]\")) return;\n\n const root = Array.from(body.children).find((el) => !NON_RENDERED_TAGS.has(el.tagName));\n root?.setAttribute(\"data-composition-id\", templateCompositionId);\n}\n\n/**\n * Add `data-composition-file=\"<compPath>\"` to the comp's root composition\n * element (the first `[data-composition-id]` that lacks the attribute), so the\n * studio resolves its top-level elements to the right source file. Idempotent;\n * a no-op when no composition element is present.\n */\nfunction tagRootCompositionFile(bodyHtml: string, compPath: string): string {\n const match = bodyHtml.match(/<[a-zA-Z][^>]*\\bdata-composition-id=/);\n if (match?.index == null) return bodyHtml;\n const tagEnd = bodyHtml.indexOf(\">\", match.index);\n if (tagEnd === -1) return bodyHtml;\n if (bodyHtml.slice(match.index, tagEnd).includes(\"data-composition-file\")) return bodyHtml;\n return (\n bodyHtml.slice(0, tagEnd) + ` data-composition-file=\"${compPath}\"` + bodyHtml.slice(tagEnd)\n );\n}\n\nexport function rootHeadContent(rootHtml: string): string {\n return rootHtml.match(/<head[^>]*>([\\s\\S]*?)<\\/head>/i)?.[1] ?? \"\";\n}\n\n/**\n * Build a standalone HTML page for a sub-composition.\n *\n * Uses the project's own index.html `<head>` so all dependencies (GSAP, fonts,\n * Lottie, reset styles, runtime) are preserved — instead of building a minimal\n * page from scratch that would miss important scripts/styles.\n *\n * Three dispatch modes, tried in order:\n * 1. `<template>` wrapper → extract template content (existing compositions)\n * 2. Full HTML document → parse and extract head/body separately (registry blocks)\n * 3. Raw fragment → wrap in a minimal document\n *\n * For full-doc mode, the composition's own `<head>` content (styles, scripts,\n * links, meta) is appended AFTER the project's index.html head. When both\n * declare the same dependency (e.g. GSAP CDN), the composition's copy wins\n * by last-write-wins script execution order — this is intentional so the\n * composition can pin a specific version.\n */\nexport function buildSubCompositionHtml(\n projectDir: string,\n compPath: string,\n runtimeUrl: string,\n baseHref?: string,\n rawOverride?: string,\n): string | null {\n const compFile = join(projectDir, compPath);\n if (!existsSync(compFile)) return null;\n\n // rawOverride lets the preview route thread the hf-id-stamped content in\n // directly, so the build uses ids minted from the raw file, which is never\n // written by serving.\n const rawComp = rawOverride ?? readFileSync(compFile, \"utf-8\");\n\n let compHeadContent = \"\";\n let rewrittenContent: string;\n let htmlAttrs = \"\";\n let bodyAttrs = \"\";\n\n const templateInner = extractTemplateInnerHtml(rawComp);\n\n if (templateInner != null) {\n const { document: contentDoc } = parseHTML(\n `<!DOCTYPE html><html><head></head><body>${templateInner}</body></html>`,\n );\n rewriteRelativePaths(contentDoc, compPath, projectDir);\n fixDigitLeadingIdSelectors(contentDoc);\n promoteTemplateCompositionId(rawComp, contentDoc.body);\n rewrittenContent = contentDoc.body.innerHTML || templateInner;\n } else if (isFullHtmlDocument(rawComp)) {\n const parts = extractFullDocumentParts(rawComp, compPath, projectDir);\n compHeadContent = parts.headContent;\n rewrittenContent = parts.bodyContent;\n htmlAttrs = parts.htmlAttrs;\n bodyAttrs = parts.bodyAttrs;\n } else {\n const { document: contentDoc } = parseHTML(\n `<!DOCTYPE html><html><head></head><body>${rawComp}</body></html>`,\n );\n rewriteRelativePaths(contentDoc, compPath, projectDir);\n fixDigitLeadingIdSelectors(contentDoc);\n rewrittenContent = contentDoc.body.innerHTML || rawComp;\n }\n\n // A composition file may ship a baked inline runtime (from a prior export:\n // data-hyperframes-runtime / __hyperframeRuntime…). The studio injects its own\n // preview runtime below, so strip the baked one from the body — otherwise it's\n // double-loaded AND the baked inline copy can fail to parse inline (the\n // \"Unexpected token '<'\" SyntaxError seen on comps with a baked runtime).\n rewrittenContent = stripEmbeddedRuntimeScripts(rewrittenContent);\n const { document: scriptsDoc } = parseHTML(\n `<!DOCTYPE html><html><head></head><body>${rewrittenContent}</body></html>`,\n );\n deferScriptsUntilFonts(scriptsDoc as unknown as Document);\n rewrittenContent = scriptsDoc.body.innerHTML;\n\n // The comp's root carries data-composition-id but (unlike inlined sub-comps,\n // which inlineSubCompositions tags) no data-composition-file. Without it the\n // studio can't resolve which file this comp's top-level elements live in and\n // falls back to \"index.html\" — so the GSAP panel parses the project root (which\n // may be a multi-timeline master) and wrongly reports \"multiple timelines\",\n // disabling editing for a single-timeline comp. Tag the root with its own path.\n rewrittenContent = tagRootCompositionFile(rewrittenContent, compPath);\n\n // Use the project's index.html <head> to preserve all dependencies\n const indexPath = join(projectDir, \"index.html\");\n let headContent = \"\";\n\n if (existsSync(indexPath)) headContent = rootHeadContent(readFileSync(indexPath, \"utf-8\"));\n\n // Inject <base> for relative asset resolution (before other tags)\n if (baseHref && !hasBaseElement(headContent)) {\n headContent = `<base href=\"${baseHref}\">\\n${headContent}`;\n }\n\n // Append the sub-composition's own <head> content so its CSS, scripts,\n // links, and meta tags are preserved. Placed after the project head so\n // the composition's deps take precedence (last-write-wins for scripts).\n if (compHeadContent) headContent += `\\n${compHeadContent}`;\n\n // Strip any baked runtime the borrowed index/comp <head> carried, for the same\n // reason as the body above — done before injecting the preview runtime so the\n // injected tag (added next) is never removed.\n headContent = stripEmbeddedRuntimeScripts(headContent);\n\n headContent += `\\n<script ${RUNTIME_BOOTSTRAP_ATTR}=\"1\" src=\"${runtimeUrl}\"></script>`;\n\n // Fallback: if no index.html head was found, add minimal deps\n if (!headContent.includes(\"gsap\")) {\n headContent += `\\n<script src=\"${gsapCdnDist()}gsap.min.js\"></script>`;\n }\n\n const htmlOpen = htmlAttrs ? `<html ${htmlAttrs}>` : \"<html>\";\n const bodyOpen = bodyAttrs ? `<body ${bodyAttrs}>` : \"<body>\";\n\n return `<!DOCTYPE html>\n${htmlOpen}\n<head>\n${headContent}\n</head>\n${bodyOpen}\n<script>window.__timelines=window.__timelines||{};</script>\n${rewrittenContent}\n</body>\n</html>`;\n}\n\n/** True for a real `<base>` element; the text \"<base\" inside a script or comment does not count. */\nexport function hasBaseElement(html: string): boolean {\n return parseHTML(html).document.querySelector(\"base\") !== null;\n}\n","import { existsSync } from \"node:fs\";\nimport { readProjectFile } from \"@hyperframes/parsers/asset-resolution\";\nimport { randomUUID } from \"node:crypto\";\nimport { dirname, relative, resolve, sep } from \"node:path\";\nimport { parseHTML } from \"linkedom\";\nimport { ProjectRootMissingError } from \"@hyperframes/core\";\nimport { folderGone, isSafePath, realpath, resolveWithinProject } from \"./safePath.js\";\n\nexport class CompositionInsertionError extends Error {\n constructor(\n message: string,\n readonly status: 400 | 404,\n ) {\n super(message);\n }\n}\n\nexport function descendants(root: Document | Element, selector: string): Element[] {\n const found = Array.from(root.querySelectorAll(selector));\n for (const template of root.querySelectorAll(\"template\")) {\n found.push(...descendants(template, selector));\n }\n return [...new Set(found)];\n}\n\nfunction compositionRoot(source: string): { document: Document; root: Element } {\n const document = parseHTML(source).document;\n const root = descendants(document, \"[data-composition-id]\")[0];\n if (!root) throw new CompositionInsertionError(\"Composition source has no root\", 400);\n return { document, root };\n}\n\nfunction positiveAttribute(root: Element, ...names: string[]): number {\n for (const name of names) {\n const value = Number.parseFloat(root.getAttribute(name) ?? \"\");\n if (Number.isFinite(value) && value > 0) return value;\n }\n throw new CompositionInsertionError(`Composition source has no valid ${names[0]}`, 400);\n}\n\nfunction canonicalProjectPath(projectDir: string, candidate: string | null): string {\n if (!candidate) {\n if (folderGone(projectDir)) throw new ProjectRootMissingError(projectDir);\n throw new CompositionInsertionError(\"Composition source escapes the project\", 400);\n }\n if (!existsSync(candidate)) {\n throw new CompositionInsertionError(\"Composition source was not found\", 404);\n }\n const canonical = realpath(candidate);\n if (!isSafePath(realpath(projectDir), canonical)) {\n throw new CompositionInsertionError(\"Composition source escapes the project\", 400);\n }\n return canonical;\n}\n\nfunction readCompositionSource(file: string): string {\n const read = readProjectFile(file);\n if (read.kind === \"folder\") {\n throw new CompositionInsertionError(\"Composition source is a folder, not an HTML file\", 400);\n }\n if (read.kind === \"missing\") {\n throw new CompositionInsertionError(\"Composition source was not found\", 404);\n }\n return read.text;\n}\n\nfunction validateSourcePath(sourcePath: string): void {\n if (!sourcePath.trim() || sourcePath.includes(\"\\0\") || /^[a-z]+:/i.test(sourcePath)) {\n throw new CompositionInsertionError(\"Invalid composition source path\", 400);\n }\n}\n\nfunction canonicalProjectFile(projectDir: string, sourcePath: string): string {\n validateSourcePath(sourcePath);\n return canonicalProjectPath(projectDir, resolveWithinProject(projectDir, sourcePath));\n}\n\nfunction canonicalDependency(projectDir: string, ownerAbs: string, sourcePath: string): string {\n validateSourcePath(sourcePath);\n return canonicalProjectPath(\n projectDir,\n resolveWithinProject(projectDir, relative(projectDir, resolve(dirname(ownerAbs), sourcePath))),\n );\n}\n\nfunction validateDependencyGraph(projectDir: string, targetAbs: string, sourceAbs: string): void {\n const visited = new Set<string>();\n const visiting = new Set<string>();\n const visit = (file: string) => {\n if (file === targetAbs) {\n throw new CompositionInsertionError(\"Composition insertion would create a cycle\", 400);\n }\n if (visiting.has(file)) {\n throw new CompositionInsertionError(\"Composition dependency cycle detected\", 400);\n }\n if (visited.has(file)) return;\n visiting.add(file);\n const source = readCompositionSource(file);\n const { document } = compositionRoot(source);\n for (const host of descendants(document, \"[data-composition-src]\")) {\n const dependency = host.getAttribute(\"data-composition-src\");\n if (dependency) {\n visit(canonicalDependency(projectDir, file, dependency));\n }\n }\n visiting.delete(file);\n visited.add(file);\n };\n visit(sourceAbs);\n}\n\nfunction numberAttribute(element: Element, name: string, fallback = 0): number {\n const value = Number.parseFloat(element.getAttribute(name) ?? \"\");\n return Number.isFinite(value) ? value : fallback;\n}\n\nfunction rangesOverlap(start: number, duration: number, other: Element): boolean {\n const otherStart = numberAttribute(other, \"data-start\");\n const otherDuration = numberAttribute(other, \"data-duration\");\n return start < otherStart + otherDuration && otherStart < start + duration;\n}\n\nfunction resolveTrack(\n root: Element,\n desiredTrack: number,\n start: number,\n duration: number,\n): number {\n const clips = descendants(root, \"[data-start][data-duration]\").filter(\n (element) =>\n element !== root && element.parentElement?.closest(\"[data-composition-id]\") === root,\n );\n const tracks = [...new Set(clips.map((clip) => numberAttribute(clip, \"data-track-index\")))].sort(\n (a, b) => a - b,\n );\n const isFree = (track: number) =>\n !clips.some(\n (clip) =>\n numberAttribute(clip, \"data-track-index\") === track && rangesOverlap(start, duration, clip),\n );\n if (isFree(desiredTrack)) return desiredTrack;\n const row = tracks.indexOf(desiredTrack);\n for (let index = row - 1; index >= 0; index--) {\n const track = tracks[index];\n if (track !== undefined && isFree(track)) return track;\n }\n for (let index = Math.max(0, row + 1); index < tracks.length; index++) {\n const track = tracks[index];\n if (track !== undefined && isFree(track)) return track;\n }\n return Math.max(desiredTrack, ...tracks, -1) + 1;\n}\n\nfunction uniqueHostId(root: Element, base: string): string {\n const ids = new Set([\n ...descendants(root, \"[id]\").map((element) => element.id),\n ...descendants(root, \"[data-composition-id]\").flatMap((element) => {\n const id = element.getAttribute(\"data-composition-id\");\n return id ? [id] : [];\n }),\n ]);\n if (!ids.has(base)) return base;\n let suffix = 2;\n while (ids.has(`${base}_${suffix}`)) suffix += 1;\n return `${base}_${suffix}`;\n}\n\nfunction relativeSourcePath(targetAbs: string, sourceAbs: string): string {\n return relative(dirname(targetAbs), sourceAbs).split(sep).join(\"/\");\n}\n\nexport function insertCompositionIntoSource(input: {\n projectDir: string;\n targetPath: string;\n sourcePath: string;\n parentSource: string;\n start: number;\n desiredTrack: number;\n}): { html: string; hostId: string; track: number; duration: number } {\n const targetAbs = canonicalProjectFile(input.projectDir, input.targetPath);\n const sourceAbs = canonicalProjectFile(input.projectDir, input.sourcePath);\n validateDependencyGraph(input.projectDir, targetAbs, sourceAbs);\n\n const source = readCompositionSource(sourceAbs);\n const sourceComposition = compositionRoot(source).root;\n const duration = positiveAttribute(\n sourceComposition,\n \"data-composition-duration\",\n \"data-duration\",\n );\n const width = positiveAttribute(sourceComposition, \"data-width\");\n const height = positiveAttribute(sourceComposition, \"data-height\");\n const { document, root } = compositionRoot(input.parentSource);\n const parentDuration = positiveAttribute(root, \"data-duration\", \"data-composition-duration\");\n const base =\n (sourceComposition.getAttribute(\"data-composition-id\") ?? \"composition\")\n .replace(/[^a-zA-Z0-9_-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"composition\";\n const hostId = uniqueHostId(root, base);\n const track = resolveTrack(\n root,\n Math.max(0, Math.round(input.desiredTrack)),\n input.start,\n duration,\n );\n const zIndex =\n Math.max(\n 0,\n ...descendants(root, \"[style]\").map((element) => {\n const match = /(?:^|;)\\s*z-index\\s*:\\s*(-?\\d+)/i.exec(element.getAttribute(\"style\") ?? \"\");\n return match?.[1] ? Number.parseInt(match[1], 10) : 0;\n }),\n ) + 1;\n\n const host = document.createElement(\"div\");\n host.id = hostId;\n host.className = \"clip\";\n host.setAttribute(\"data-hf-id\", `hf-${randomUUID()}`);\n host.setAttribute(\"data-composition-id\", hostId);\n host.setAttribute(\"data-composition-src\", relativeSourcePath(targetAbs, sourceAbs));\n host.setAttribute(\"data-start\", String(Math.round(input.start * 100) / 100));\n host.setAttribute(\"data-duration\", String(duration));\n host.setAttribute(\"data-playback-start\", \"0\");\n host.setAttribute(\"data-track-index\", String(track));\n host.setAttribute(\"data-width\", String(width));\n host.setAttribute(\"data-height\", String(height));\n host.setAttribute(\n \"style\",\n `position: absolute; left: 0px; top: 0px; width: ${width}px; height: ${height}px; z-index: ${zIndex}`,\n );\n root.appendChild(host);\n if (input.start + duration > parentDuration) {\n const name = root.hasAttribute(\"data-duration\") ? \"data-duration\" : \"data-composition-duration\";\n root.setAttribute(name, String(Math.round((input.start + duration) * 100) / 100));\n }\n return { html: document.toString(), hostId, track, duration };\n}\n","import { spawn } from \"node:child_process\";\nimport {\n existsSync,\n writeFileSync,\n mkdirSync,\n lstatSync,\n mkdtempSync,\n renameSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\n\nconst SAMPLE_RATE = 4000;\nconst PEAK_COUNT = 4000;\nconst WAVEFORM_CACHE_VERSION = \"v2\";\n\n/**\n * Cache filename for one asset's peaks, keyed on its content as well as its name.\n *\n * The path alone is not an identity. An asset rebuilt in place — a bed\n * re-encoded without its ducking, a plate swapped for the right one — keeps its\n * name and gets new samples, and a path-keyed entry then served the old peaks\n * for the rest of the project's life: the timeline drew a duck that was no\n * longer in the file, which reads as the render having done it. Size and mtime\n * are what a rebuild always changes, and both are already on the stat the route\n * takes to check the file exists.\n *\n * Without a fingerprint it falls back to the old path-only key, so a caller that\n * cannot stat still gets caching rather than an error.\n */\nexport function buildWaveformCacheKey(\n assetPath: string,\n fingerprint?: { size: number; mtimeMs: number },\n): string {\n const name = assetPath.replace(/[/\\\\]/g, \"_\");\n if (!fingerprint) return `${WAVEFORM_CACHE_VERSION}_${name}.json`;\n const stamp = `${fingerprint.size}-${Math.round(fingerprint.mtimeMs)}`;\n return `${WAVEFORM_CACHE_VERSION}_${name}_${stamp}.json`;\n}\n\nfunction computePeaks(floats: Float32Array, count: number): number[] {\n const step = floats.length / count;\n const peaks: number[] = [];\n for (let i = 0; i < count; i++) {\n const start = Math.floor(i * step);\n const end = Math.min(Math.floor((i + 1) * step), floats.length);\n let max = 0;\n for (let j = start; j < end; j++) {\n // fallow-ignore-next-line code-duplication\n const abs = Math.abs(floats[j] ?? 0);\n if (abs > max) max = abs;\n }\n peaks.push(max);\n }\n const maxPeak = Math.max(...peaks, 0.001);\n return peaks.map((p) => p / maxPeak);\n}\n\nexport function decodeAudioPeaks(audioPath: string): Promise<number[]> {\n return new Promise((resolvePromise, reject) => {\n const proc = spawn(\n findFfBinary(\"ffmpeg\") ?? \"ffmpeg\",\n [\n \"-i\",\n audioPath,\n \"-af\",\n \"atrim=start_sample=1152\",\n \"-f\",\n \"f32le\",\n \"-ac\",\n \"1\",\n \"-ar\",\n String(SAMPLE_RATE),\n \"-vn\",\n \"pipe:1\",\n ],\n { stdio: [\"ignore\", \"pipe\", \"ignore\"], windowsHide: true },\n );\n\n const chunks: Buffer[] = [];\n proc.stdout?.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n proc.on(\"close\", (code) => {\n if (code !== 0 && chunks.length === 0) {\n reject(new Error(`ffmpeg exited with code ${code}`));\n return;\n }\n const buf = Buffer.concat(chunks);\n const numSamples = Math.floor(buf.length / 4);\n if (numSamples === 0) {\n reject(new Error(\"ffmpeg produced no audio samples\"));\n return;\n }\n const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + numSamples * 4);\n resolvePromise(computePeaks(new Float32Array(ab), PEAK_COUNT));\n });\n proc.on(\"error\", reject);\n });\n}\n\nexport async function generateWaveformCache(projectDir: string, assetPath: string): Promise<void> {\n const audioPath = join(projectDir, assetPath);\n if (!existsSync(audioPath)) return;\n\n const stats = statSync(audioPath);\n const cacheDir = join(projectDir, \".waveform-cache\");\n const cachePath = join(cacheDir, buildWaveformCacheKey(assetPath, stats));\n if (isWaveformCacheDirectory(cacheDir) && existsSync(cachePath)) return;\n\n const peaks = await decodeAudioPeaks(audioPath);\n writeWaveformCache(cachePath, peaks);\n}\n\nexport function isWaveformCacheDirectory(cacheDir: string): boolean {\n return lstatSync(cacheDir, { throwIfNoEntry: false })?.isDirectory() ?? false;\n}\n\n/** Publish complete peaks without following a replaced cache-file symlink. */\nexport function writeWaveformCache(cachePath: string, peaks: number[]): void {\n const cacheDir = dirname(cachePath);\n try {\n mkdirSync(cacheDir, { mode: 0o700 });\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"EEXIST\")) throw error;\n }\n if (!isWaveformCacheDirectory(cacheDir)) {\n throw new Error(\"Waveform cache must be a directory, not a symlink\");\n }\n const stagingDir = mkdtempSync(join(cacheDir, \".waveform-\"));\n try {\n const stagingPath = join(stagingDir, \"peaks.json\");\n writeFileSync(stagingPath, JSON.stringify(peaks), { flag: \"wx\" });\n renameSync(stagingPath, cachePath);\n } finally {\n try {\n rmSync(stagingDir, { recursive: true, force: true });\n } catch {\n // Cleanup must not mask a write error or fail an already published cache.\n }\n }\n}\n","import { spawnSync } from \"node:child_process\";\nimport { mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { FFPROBE_PATH_ENV, findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\n\nconst VIDEO_EXT = /\\.(mp4|webm|mov|mkv|avi|m4v|mxf|mts|m2ts|ts)$/i;\nconst AUDIO_EXT = /\\.(mp3|wav|ogg|m4a|aac|flac)$/i;\n\ntype FfprobeRunner = (\n command: string,\n args: string[],\n options: { windowsHide: boolean },\n) => {\n status: number | null;\n stdout: string | Buffer;\n stderr: string | Buffer;\n error?: NodeJS.ErrnoException;\n};\n\ntype MediaCheck = { ok: true; unchecked?: string } | { ok: false; reason: string };\n\nconst defaultRunner = spawnSync as unknown as FfprobeRunner;\nconst FFPROBE_MISSING =\n \"not checked: ffprobe was not found. Install FFmpeg or set HYPERFRAMES_FFPROBE_PATH.\";\n\nexport function validateUploadedMedia(\n filePath: string,\n runner: FfprobeRunner = defaultRunner,\n): MediaCheck {\n const isVideo = VIDEO_EXT.test(filePath);\n const isAudio = AUDIO_EXT.test(filePath);\n if (!isVideo && !isAudio) {\n return { ok: true };\n }\n\n const ffprobe = findFfBinary(\"ffprobe\") ?? (runner === defaultRunner ? undefined : \"ffprobe\");\n if (!ffprobe) return { ok: true, unchecked: FFPROBE_MISSING };\n const result = runner(\n ffprobe,\n [\"-v\", \"error\", \"-show_entries\", \"stream=codec_type\", \"-of\", \"json\", \"--\", filePath],\n { windowsHide: true },\n );\n\n if (result.error && process.env[FFPROBE_PATH_ENV]?.trim()) {\n return {\n ok: false,\n reason: `${FFPROBE_PATH_ENV} names \"${ffprobe}\", which cannot run: fix it or unset it`,\n };\n }\n if (result.error?.code === \"ENOENT\") {\n return { ok: true, unchecked: FFPROBE_MISSING };\n }\n if (result.status !== 0) {\n return { ok: false, reason: \"ffprobe failed to read the media file\" };\n }\n\n return checkStreams(String(result.stdout || \"{}\"), isVideo, isAudio);\n}\n\nfunction checkStreams(stdout: string, isVideo: boolean, isAudio: boolean): MediaCheck {\n try {\n const parsed = JSON.parse(stdout) as { streams?: Array<{ codec_type?: string }> };\n const streams = parsed.streams ?? [];\n const hasVideo = streams.some((stream) => stream.codec_type === \"video\");\n const hasAudio = streams.some((stream) => stream.codec_type === \"audio\");\n\n if (isVideo && !hasVideo) {\n return { ok: false, reason: \"no supported video stream found\" };\n }\n if (isAudio && !hasAudio) {\n return { ok: false, reason: \"no supported audio stream found\" };\n }\n return { ok: true };\n } catch {\n return { ok: false, reason: \"ffprobe returned unreadable media metadata\" };\n }\n}\n\nexport function validateUploadedMediaBuffer(\n fileName: string,\n buffer: Uint8Array,\n runner: FfprobeRunner = defaultRunner,\n): MediaCheck {\n const tempDir = mkdtempSync(join(tmpdir(), \"hyperframes-upload-\"));\n const tempPath = join(tempDir, basename(fileName));\n\n try {\n writeFileSync(tempPath, buffer);\n return validateUploadedMedia(tempPath, runner);\n } finally {\n rmSync(tempDir, { recursive: true, force: true });\n }\n}\n","import { readdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { Buffer } from \"node:buffer\";\nimport { join, relative } from \"node:path\";\nimport { isProjectRootMissing, isSafePath, mkdirWithinProject } from \"./safePath.js\";\n\nconst DEFAULT_KEEP_PER_FILE = 10;\n\nexport interface BackupJournalResult {\n backupPath: string | null;\n error?: string;\n}\n\nfunction backupKeyForPath(path: string): string {\n return Buffer.from(path, \"utf-8\").toString(\"base64url\");\n}\n\nfunction timestampPrefix(): string {\n return new Date().toISOString().replace(/[:.]/g, \"-\");\n}\n\nexport function backupPathForResponse(\n projectDir: string,\n backupPath: string | null,\n): string | null {\n if (!backupPath) return null;\n const rel = relative(projectDir, backupPath);\n if (!rel || rel.startsWith(\"..\")) return null;\n return rel.split(\"\\\\\").join(\"/\");\n}\n\nexport function snapshotBeforeWrite(\n projectDir: string,\n absPath: string,\n options: { keepPerFile?: number } = {},\n): BackupJournalResult {\n if (!isSafePath(projectDir, absPath)) return { backupPath: null };\n\n try {\n const content = readFileSync(absPath);\n\n const relativePath = relative(projectDir, absPath);\n const backupDir = join(projectDir, \".hyperframes\", \"backup\");\n mkdirWithinProject(projectDir, backupDir);\n\n const backupKey = backupKeyForPath(relativePath);\n const backupPath = nextBackupPath(backupDir, backupKey);\n writeFileSync(backupPath, content);\n pruneBackups(backupDir, backupKey, options.keepPerFile ?? DEFAULT_KEEP_PER_FILE);\n return { backupPath };\n } catch (error) {\n if (isProjectRootMissing(error)) throw error;\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n (error.code === \"ENOENT\" || error.code === \"EISDIR\")\n ) {\n return { backupPath: null };\n }\n return { backupPath: null, error: error instanceof Error ? error.message : String(error) };\n }\n}\n\nfunction nextBackupPath(backupDir: string, backupKey: string): string {\n const base = `${timestampPrefix()}-${backupKey}`;\n let candidate = join(backupDir, base);\n let counter = 2;\n while (true) {\n try {\n readFileSync(candidate);\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n return candidate;\n }\n throw error;\n }\n candidate = join(backupDir, `${base}-${counter}`);\n counter += 1;\n }\n}\n\nfunction pruneBackups(backupDir: string, backupKey: string, keepPerFile: number): void {\n const keep = Math.max(1, Math.floor(keepPerFile));\n const suffix = `-${backupKey}`;\n const numberedSuffix = new RegExp(`-${backupKey}-\\\\d+$`);\n const matches = readdirSync(backupDir)\n .filter((name) => name.endsWith(suffix) || numberedSuffix.test(name))\n .map((name) => join(backupDir, name))\n .sort((a, b) => {\n return b.localeCompare(a);\n });\n\n for (const file of matches.slice(keep)) {\n try {\n unlinkSync(file);\n } catch {\n // Backup pruning is best-effort and must not block the user's write.\n }\n }\n}\n","import type { Context } from \"hono\";\n\nconst PROJECT_DIR_MISSING = { error: \"not found\", why: \"project_dir_missing\" };\n\nexport const projectDirMissing = (c: {\n json: (data: { error: string; why: string }, status: 404) => Response;\n}) => c.json(PROJECT_DIR_MISSING, 404);\n\nexport function replaceWithProjectDirMissing(c: Context, hostHeaders: Headers): void {\n hostHeaders.delete(\"content-type\");\n c.res = undefined;\n c.res = Response.json(PROJECT_DIR_MISSING, { status: 404, headers: hostHeaders });\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport { replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\nimport { backupPathForResponse, snapshotBeforeWrite } from \"./backupJournal.js\";\nimport {\n clearFileWriteReceipt,\n createWriteToken,\n fileContentVersion,\n recordFileWriteReceipt,\n} from \"./fileVersion.js\";\n\nexport interface FileMutationInput {\n sourceFile: string;\n absPath: string;\n before?: string;\n after: string;\n expectedVersion?: string;\n}\n\nexport interface AppliedFileMutation {\n sourceFile: string;\n changed: boolean;\n before: string;\n after: string;\n backupPath: string | null;\n version: string;\n writeToken: string | null;\n}\n\n/** Applies prepared HTML mutations with the same journal and receipt semantics as Studio. */\nexport function applyFileMutations(\n projectDir: string,\n mutations: readonly FileMutationInput[],\n requestToken?: string,\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void = (path, content) =>\n replaceFileAtomically(path, content, statSync(path).mode),\n): AppliedFileMutation[] {\n const prepared = mutations.map((mutation) => ({\n ...mutation,\n before: mutation.before ?? readFileSync(mutation.absPath, \"utf-8\"),\n }));\n const results: AppliedFileMutation[] = [];\n const attempted: Array<\n PreparedMutation & { version: string; writeToken: string; written: boolean }\n > = [];\n for (const mutation of prepared)\n assertExpectedVersion(mutation, readFileSync(mutation.absPath, \"utf-8\"));\n try {\n for (const mutation of prepared) {\n results.push(applyOneMutation(projectDir, mutation, requestToken, writeFile, attempted));\n }\n return results;\n } catch (error) {\n const rollbackErrors: unknown[] = [];\n for (const mutation of attempted.reverse()) {\n try {\n if (!mutation.written || readFileSync(mutation.absPath, \"utf-8\") === mutation.after)\n writeFile(mutation.absPath, mutation.before, \"utf-8\");\n clearFileWriteReceipt(mutation.absPath, mutation.version, mutation.writeToken);\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n }\n if (rollbackErrors.length > 0) {\n throw new AggregateError(\n [error, ...rollbackErrors],\n \"File mutation failed and rollback did not complete\",\n );\n }\n throw error;\n }\n}\n\ntype PreparedMutation = FileMutationInput & { before: string };\n\nfunction applyOneMutation(\n projectDir: string,\n mutation: PreparedMutation,\n requestToken: string | undefined,\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void,\n attempted: Array<PreparedMutation & { version: string; writeToken: string; written: boolean }>,\n): AppliedFileMutation {\n const current = readFileSync(mutation.absPath, \"utf-8\");\n assertExpectedVersion(mutation, current);\n if (mutation.after === mutation.before) {\n return {\n ...mutation,\n before: current,\n changed: false,\n backupPath: null,\n version: fileContentVersion(mutation.before),\n writeToken: null,\n };\n }\n const backup = snapshotBeforeWrite(projectDir, mutation.absPath);\n if (backup.error) throw new Error(`backup failed: ${backup.error}`);\n assertExpectedVersion(mutation, readFileSync(mutation.absPath, \"utf-8\"));\n const before = current;\n const version = fileContentVersion(mutation.after);\n const writeToken = createWriteToken(requestToken);\n const attempt = { ...mutation, before, version, writeToken, written: false };\n attempted.push(attempt);\n writeFile(mutation.absPath, mutation.after, \"utf-8\");\n attempt.written = true;\n recordFileWriteReceipt(mutation.absPath, {\n path: mutation.sourceFile,\n version,\n writeToken,\n overwrote: before,\n });\n return {\n ...mutation,\n before,\n changed: true,\n backupPath: backupPathForResponse(projectDir, backup.backupPath),\n version,\n writeToken,\n };\n}\n\nexport class FileChangedError extends Error {\n constructor(readonly sourceFile: string) {\n super(\"file changed since the timeline was read\");\n }\n}\n\nfunction assertExpectedVersion(mutation: PreparedMutation, current: string): void {\n const stale =\n mutation.expectedVersion === undefined\n ? current !== mutation.before\n : fileContentVersion(current) !== mutation.expectedVersion;\n if (stale) throw new FileChangedError(mutation.sourceFile);\n}\n","const FONT_STYLE_RE = /<style\\b[^>]*data-hf-studio-fonts=([\"'])true\\1[^>]*>([\\s\\S]*?)<\\/style>/i;\n\n// Braces only inside quoted strings; `<` nowhere: `</style` ends the block whatever the quoting.\nconst ONE_FONT_FACE_RULE =\n /^@font-face \\{(?:[^{}<\"'\\\\]|\"(?:[^\"\\\\<\\n\\r\\f]|\\\\[^<\\n\\r\\f])*\"|'(?:[^'\\\\<\\n\\r\\f]|\\\\[^<\\n\\r\\f])*')*\\}$/;\n\nexport function isStudioFontFaceCss(css: unknown): css is string {\n return typeof css === \"string\" && ONE_FONT_FACE_RULE.test(css);\n}\n\nexport function ensureStudioFontFaceCss(html: string, css: string): string {\n if (html.includes(css)) return html;\n const block = FONT_STYLE_RE.exec(html);\n if (block) {\n const next = `${(block[2] ?? \"\").trim()}\\n${css}`.trim();\n return html.replace(block[0], () => `<style data-hf-studio-fonts=\"true\">\\n${next}\\n</style>`);\n }\n const styleTag = `<style data-hf-studio-fonts=\"true\">\\n${css}\\n</style>`;\n if (/<\\/head>/i.test(html)) return html.replace(/<\\/head>/i, () => ` ${styleTag}\\n </head>`);\n return `${styleTag}\\n${html}`;\n}\n","import type { GsapMutationRequest } from \"./files.js\";\n\nexport type GsapMutationType = GsapMutationRequest[\"type\"];\ntype GsapMutationFamily = \"animation\" | \"keyframe\" | \"motion_path\" | \"structure\" | \"timing\";\ntype GsapParityEvidence = \"differential\" | \"behavioral\";\n\ninterface GsapMutationCapability {\n family: GsapMutationFamily;\n acorn: \"supported\";\n recast: \"supported\";\n parity: GsapParityEvidence;\n}\n\nconst differential = (family: GsapMutationFamily): GsapMutationCapability => ({\n family,\n acorn: \"supported\",\n recast: \"supported\",\n parity: \"differential\",\n});\nconst behavioral = (family: GsapMutationFamily): GsapMutationCapability => ({\n family,\n acorn: \"supported\",\n recast: \"supported\",\n parity: \"behavioral\",\n});\n\n/** Compile-time exhaustive over the request union; runtime tests match both dispatchers. */\nexport const GSAP_MUTATION_CAPABILITIES = {\n \"update-property\": differential(\"animation\"),\n \"update-properties\": differential(\"animation\"),\n \"update-from-property\": differential(\"animation\"),\n \"update-meta\": differential(\"animation\"),\n add: differential(\"animation\"),\n delete: differential(\"animation\"),\n \"add-property\": differential(\"animation\"),\n \"add-from-property\": differential(\"animation\"),\n \"remove-property\": differential(\"animation\"),\n \"remove-from-property\": differential(\"animation\"),\n \"add-keyframe\": differential(\"keyframe\"),\n \"remove-keyframe\": differential(\"keyframe\"),\n \"move-keyframe\": behavioral(\"keyframe\"),\n \"resize-keyframed-tween\": behavioral(\"keyframe\"),\n \"update-keyframe\": differential(\"keyframe\"),\n \"convert-to-keyframes\": behavioral(\"keyframe\"),\n \"remove-all-keyframes\": behavioral(\"keyframe\"),\n \"materialize-keyframes\": behavioral(\"keyframe\"),\n \"set-arc-path\": behavioral(\"motion_path\"),\n \"update-arc-segment\": behavioral(\"motion_path\"),\n \"update-motion-path-point\": differential(\"motion_path\"),\n \"add-motion-path-point\": differential(\"motion_path\"),\n \"remove-motion-path-point\": differential(\"motion_path\"),\n \"add-motion-path\": differential(\"motion_path\"),\n \"remove-arc-path\": behavioral(\"motion_path\"),\n \"add-with-keyframes\": behavioral(\"keyframe\"),\n \"replace-with-keyframes\": behavioral(\"keyframe\"),\n \"split-animations\": behavioral(\"structure\"),\n \"split-into-property-groups\": behavioral(\"structure\"),\n \"delete-all-for-selector\": behavioral(\"structure\"),\n \"consolidate-position-writes\": behavioral(\"structure\"),\n \"unroll-timeline\": behavioral(\"structure\"),\n \"shift-positions\": behavioral(\"timing\"),\n \"shift-positions-batch\": behavioral(\"timing\"),\n \"scale-positions\": behavioral(\"timing\"),\n} as const satisfies Record<GsapMutationType, GsapMutationCapability>;\n\nconst GSAP_WRITER_MIGRATION = Object.freeze({\n flag: \"HYPERFRAMES_GSAP_WRITER\",\n owner: \"studio-foundations\",\n deadline: \"2026-09-30\",\n graduationCriteria:\n \"Acorn is the default writer. Recast is retained one watch window as HYPERFRAMES_GSAP_WRITER=recast, then deleted (spec 2026-09-17 §5).\",\n});\n\nexport function resolveGsapWriter(env: { HYPERFRAMES_GSAP_WRITER?: string }): \"recast\" | \"acorn\" {\n const configured = env.HYPERFRAMES_GSAP_WRITER ?? \"acorn\";\n if (configured === \"recast\" || configured === \"acorn\") return configured;\n throw new Error(`Invalid ${GSAP_WRITER_MIGRATION.flag}=${configured}; expected recast or acorn`);\n}\n\n/** Ops whose acorn/recast parity rests on behavioral tests, not a byte-diff oracle. */\nexport function behavioralParityOps(): GsapMutationType[] {\n return (\n Object.entries(GSAP_MUTATION_CAPABILITIES) as Array<[GsapMutationType, GsapMutationCapability]>\n )\n .filter(([, capability]) => capability.parity !== \"differential\")\n .map(([type]) => type);\n}\n\nexport function renderGsapMutationCapabilityReport(): string {\n const rows = (\n Object.entries(GSAP_MUTATION_CAPABILITIES) as Array<[GsapMutationType, GsapMutationCapability]>\n ).map(\n ([type, capability]) =>\n `| ${type} | ${capability.family} | ${capability.acorn} | ${capability.recast} | ${capability.parity} |`,\n );\n return [\n \"# GSAP writer capability report\",\n \"\",\n `Owner: ${GSAP_WRITER_MIGRATION.owner}`,\n `Deadline: ${GSAP_WRITER_MIGRATION.deadline}`,\n `Flag: \\`${GSAP_WRITER_MIGRATION.flag}=recast|acorn\\` (default: acorn)`,\n \"\",\n \"| Operation | Family | Acorn | Recast | Parity evidence |\",\n \"| --- | --- | --- | --- | --- |\",\n ...rows,\n \"\",\n `Behavioral-only parity (no byte-diff oracle): ${behavioralParityOps().join(\", \") || \"none\"}`,\n \"\",\n ].join(\"\\n\");\n}\n","// The decoded path after `route` (\"projects/:id/preview\", \"composition\"), cut by segment from the raw URL:\n// Hono's c.req.path leaves %40 %25 %23 %26 %3F encoded, so cutting a decoded prefix out of it misses.\nexport function requestSubPath(url: string, route: string): string {\n const routeSegments = route.split(\"/\");\n const segments = new URL(url).pathname.split(\"/\");\n const start = segments.indexOf(routeSegments[0] ?? \"\");\n return decodeURIComponent(segments.slice(start + routeSegments.length).join(\"/\"));\n}\n","import type { Hono } from \"hono\";\nimport { parseHTML } from \"linkedom\";\nimport { createReadStream, existsSync, readFileSync, statSync } from \"node:fs\";\nimport { Readable } from \"node:stream\";\nimport { join, resolve } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport {\n AFTER_FONTS_SCRIPT_TYPE,\n addScenePartsManifest,\n RUNTIME_BOOTSTRAP_ATTR,\n insertBeforeCloseTag,\n insertRuntimeTag,\n stripEmbeddedRuntimeScripts,\n type BundleOptions,\n} from \"@hyperframes/core/compiler\";\nimport {\n STUDIO_PREVIEW_MARK_META,\n STUDIO_PREVIEW_ERRORS,\n} from \"@hyperframes/core/studio-preview-mark\";\nimport { PREVIEW_PROXY_BOX_PARAM, parsePreviewProxyBox } from \"@hyperframes/core\";\nimport { gsapCdnDist, motionPathPluginUrl } from \"@hyperframes/core/gsap-cdn\";\nimport { findStartTags, injectTagsAtHeadStart } from \"@hyperframes/core/compiler/html-document\";\nimport { isWithinProjectRoot } from \"@hyperframes/parsers/asset-resolution\";\nimport type { ResolvedProject, StudioApiAdapter } from \"../types.js\";\nimport {\n isPrivateProjectFile,\n isProjectRootMissing,\n resolveWithinProject,\n} from \"../helpers/safePath.js\";\nimport { getMimeType } from \"../helpers/mime.js\";\nimport { buildSubCompositionHtml, hasBaseElement } from \"../helpers/subComposition.js\";\nimport {\n createProjectSignature,\n resolveProjectAndSignature,\n resolveProjectSignature,\n} from \"../helpers/projectSignature.js\";\nimport {\n createStudioMotionRenderBodyScript,\n STUDIO_MOTION_PATH,\n} from \"../helpers/studioMotionRenderScript.js\";\nimport { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport { settledFileTag } from \"../helpers/fileVersion.js\";\nimport {\n recordPreviewBuilt,\n recordPreviewRead,\n recordPreviewReferences,\n} from \"../helpers/previewReads.js\";\nimport { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from \"../helpers/variablesPayload.js\";\nimport { injectPreviewVariables } from \"../helpers/previewVariables.js\";\nimport {\n resolveProxy,\n waitForProxy,\n ProxyCapacityError,\n ProxyTranscodeError,\n ProxyWaitTimeoutError,\n PROXY_PENDING_RETRY_AFTER_SECONDS,\n} from \"../helpers/proxyTranscoder.js\";\nimport {\n decideMediaProxyEligibility,\n isProxyVariantRequest,\n probeAssetCodec,\n recordProxyRequest,\n resolveProxyVariantRequest,\n PROXY_VARIANT_CONFIG,\n type ProxyVariant,\n} from \"../helpers/mediaCodecMap.js\";\nimport {\n isAutoProxyEnabled,\n injectMediaCodecMap,\n proxyEtagSalt,\n resolvePreviewMediaCodecProbeCache,\n type PreviewApiAdapter,\n} from \"../helpers/mediaProxyPreview.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\nimport { lazyPreviewImages } from \"../helpers/lazyPreviewImages.js\";\n\nconst PROJECT_SIGNATURE_META = \"hyperframes-project-signature\";\nconst GSAP_CDN_SCRIPT = `<script src=\"${gsapCdnDist()}gsap.min.js\"></script>`;\nconst GSAP_CUSTOM_EASE_CDN_SCRIPT = `<script src=\"${gsapCdnDist()}CustomEase.min.js\"></script>`;\nconst GSAP_MOTION_PATH_CDN_SCRIPT = `<script src=\"${motionPathPluginUrl()}\"></script>`;\n\nfunction injectProjectSignature(html: string, signature: string): string {\n const tag = `<meta name=\"${PROJECT_SIGNATURE_META}\" content=\"${signature}\">`;\n if (html.includes(`name=\"${PROJECT_SIGNATURE_META}\"`)) {\n return html.replace(\n new RegExp(`<meta\\\\s+name=[\"']${PROJECT_SIGNATURE_META}[\"'][^>]*>`, \"i\"),\n tag,\n );\n }\n return insertBeforeCloseTag(html, \"head\", `${tag}\\n`) ?? `${tag}\\n${html}`;\n}\n\nfunction readStudioMotionManifestContent(projectDir: string): string {\n const manifestPath = join(projectDir, STUDIO_MOTION_PATH);\n if (!existsSync(manifestPath)) return \"\";\n try {\n return readFileSync(manifestPath, \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\nfunction parseStudioMotionManifestContent(content: string): {\n hasMotion: boolean;\n hasCustomEase: boolean;\n} {\n try {\n const parsed = JSON.parse(content) as {\n motions?: Array<{ customEase?: unknown }>;\n };\n const motions = Array.isArray(parsed.motions) ? parsed.motions : [];\n return {\n hasMotion: motions.length > 0,\n hasCustomEase: motions.some((motion) => Boolean(motion?.customEase)),\n };\n } catch {\n return { hasMotion: false, hasCustomEase: false };\n }\n}\n\n/** Swaps any runtime already in the page for the preview runtime, placed as the bundler places it. */\nfunction withPreviewRuntime(html: string, runtimeUrl: string): string {\n const tag = `<script ${RUNTIME_BOOTSTRAP_ATTR}=\"1\" src=\"${runtimeUrl}\"></script>`;\n return insertRuntimeTag(stripEmbeddedRuntimeScripts(html), tag);\n}\n\nfunction injectScriptTagIntoHead(html: string, scriptTag: string): string {\n return insertBeforeCloseTag(html, \"head\", `${scriptTag}\\n`) ?? `${scriptTag}\\n${html}`;\n}\n\nfunction htmlHasGsap(html: string): boolean {\n // Only match GSAP references outside <template> elements — scripts inside\n // templates are inert when cloned and don't make GSAP globally available.\n const outsideTemplates = html.replace(/<template\\b[^>]*>[\\s\\S]*?<\\/template>/gi, \"\");\n return (\n /<script\\b[^>]*src=[\"'][^\"']*gsap/i.test(outsideTemplates) ||\n /\\/\\*\\s*inlined:.*gsap/i.test(outsideTemplates) ||\n /\\b(GreenSock|_gsScope)\\b/.test(outsideTemplates) ||\n /\\bgsap\\.(config|defaults|registerPlugin|version)\\b/.test(outsideTemplates)\n );\n}\n\nfunction htmlHasCustomEase(html: string): boolean {\n return (\n /<script\\b[^>]*src=[\"'][^\"']*CustomEase/i.test(html) ||\n /\\bwindow\\.CustomEase\\b/.test(html) ||\n /\\bCustomEase\\s*=\\s*/.test(html)\n );\n}\n\n// A composition that drives motion via GSAP's `motionPath` (e.g. a studio-created\n// motion path written into the single-source timeline) needs MotionPathPlugin\n// registered before the timeline first renders — otherwise the initial seek\n// throws \"Invalid property motionPath ... Missing plugin?\". Detect it anywhere in\n// the bundle (the plugin registers globally, so sub-composition usage counts too).\nfunction htmlUsesMotionPath(html: string): boolean {\n return /motionPath\\s*[:{]/.test(html);\n}\n\nfunction htmlHasMotionPathPlugin(html: string): boolean {\n return (\n /<script\\b[^>]*src=[\"'][^\"']*MotionPathPlugin/i.test(html) ||\n /\\bwindow\\.MotionPathPlugin\\b/.test(html) ||\n /\\bMotionPathPlugin\\s*=\\s*/.test(html)\n );\n}\n\nfunction injectMotionPathPluginIfNeeded(html: string): string {\n if (!htmlUsesMotionPath(html) || htmlHasMotionPathPlugin(html)) return html;\n // The plugin registers onto an already-loaded gsap, so it must come AFTER the\n // core gsap script — which often lives at body-end, not <head>. Insert it\n // directly after the gsap script tag; only fall back to <head> if none is found\n // (e.g. gsap is inlined).\n const gsap = findGsapCoreScript(html);\n if (gsap) {\n const version = gsap.src.match(/gsap@([\\d.]+)/)?.[1];\n const ordering = `${gsap.type ? ` type=\"${gsap.type}\"` : \"\"}${gsap.defer ? \" defer\" : \"\"}`;\n const pluginTag = `<script${ordering} src=\"${motionPathPluginUrl(version)}\"></script>`;\n return html.slice(0, gsap.end) + \"\\n\" + pluginTag + html.slice(gsap.end);\n }\n return injectScriptTagIntoHead(html, GSAP_MOTION_PATH_CDN_SCRIPT);\n}\n\nfunction isGsapCoreUrl(src: string): boolean {\n const base = \"http://localhost/\";\n return URL.canParse(src, base) && /\\/gsap(\\.min)?\\.js$/i.test(new URL(src, base).pathname);\n}\n\ntype GsapCoreScript = { src: string; type: string | null; defer: boolean; end: number };\n\nfunction findGsapCoreScript(html: string): GsapCoreScript | null {\n const scripts = [...parseHTML(html).document.querySelectorAll(\"script\")];\n // The scanner skips comments, raw text and templates, so its `<script` offsets line up with the DOM's scripts.\n const starts = findStartTags(html, \"script\");\n if (starts.length !== scripts.length) return null;\n const at = scripts.findIndex((script) =>\n isGsapCoreUrl(lowerCaseAttributes(script).get(\"src\") ?? \"\"),\n );\n if (at === -1) return null;\n const attributes = lowerCaseAttributes(scripts[at]!);\n const end = scriptCloseEnd(html, starts[at]!);\n if (end === 0) return null;\n return {\n src: attributes.get(\"src\")!,\n type: attributes.get(\"type\") ?? null,\n defer: attributes.has(\"defer\"),\n end,\n };\n}\n\nfunction lowerCaseAttributes(el: Element): Map<string, string> {\n return new Map([...el.attributes].map((a) => [a.name.toLowerCase(), a.value]));\n}\n\n/** Index just past the `</script>` that closes the script starting at `start`; 0 when it never closes. */\nfunction scriptCloseEnd(html: string, start: number): number {\n const close = /<\\/script/gi;\n close.lastIndex = start;\n const closeAt = close.exec(html)?.index;\n return closeAt === undefined ? 0 : html.indexOf(\">\", closeAt) + 1;\n}\n\nfunction injectStudioMotionDependencies(html: string, manifestContent: string): string {\n const manifest = parseStudioMotionManifestContent(manifestContent);\n if (!manifest.hasMotion) return html;\n let next = html;\n if (!htmlHasGsap(next)) next = injectScriptTagIntoHead(next, GSAP_CDN_SCRIPT);\n if (manifest.hasCustomEase && !htmlHasCustomEase(next)) {\n next = injectScriptTagIntoHead(next, GSAP_CUSTOM_EASE_CDN_SCRIPT);\n }\n return next;\n}\n\nfunction injectStudioMotionScript(\n html: string,\n projectDir: string,\n activeCompositionPath: string,\n): string {\n const manifestContent = readStudioMotionManifestContent(projectDir);\n const script = createStudioMotionRenderBodyScript(manifestContent, {\n activeCompositionPath,\n });\n if (!script) return html;\n const withDependencies = injectStudioMotionDependencies(html, manifestContent);\n const tag = `<script type=\"${AFTER_FONTS_SCRIPT_TYPE}\">${script.replace(/<\\/script/gi, \"<\\\\/script\")}</script>`;\n return insertBeforeCloseTag(withDependencies, \"body\", tag) ?? `${withDependencies}${tag}`;\n}\n\nconst GSAP_FALLBACK_ATTR = \"data-hf-gsap-fallback\";\nconst GSAP_CDN_FALLBACK_SCRIPT = `<script ${GSAP_FALLBACK_ATTR}>\n(function(){\n var cdnBase=\"${gsapCdnDist()}\";\n var loaded={};\n function loadFallback(file){\n if(loaded[file])return loaded[file];\n return loaded[file]=new Promise(function(ok,fail){\n var s=document.createElement(\"script\");\n s.src=cdnBase+file;s.hfGsapFallback=true;s.onload=ok;s.onerror=fail;\n document.head.appendChild(s);\n });\n }\n document.addEventListener(\"error\",function(e){\n var t=e.target;\n if(!t||t.tagName!==\"SCRIPT\"||!t.src||t.hfGsapFallback)return;\n var m=t.src.match(/gsap[^/]*\\\\/dist\\\\/(.+\\\\.js)/);\n if(m)loadFallback(m[1]).catch(function(){\n reportError(new Error(\"GSAP could not load from \"+t.src+\" or \"+cdnBase+m[1]+\", so this preview's animations will not play.\"));\n });\n },true);\n})();\n</script>`;\n\nfunction injectGsapCdnFallback(html: string): string {\n if (html.includes(GSAP_FALLBACK_ATTR)) return html;\n if (html.includes(\"<head>\")) return html.replace(\"<head>\", \"<head>\" + GSAP_CDN_FALLBACK_SCRIPT);\n return GSAP_CDN_FALLBACK_SCRIPT + html;\n}\n\n/**\n * Parse the `?variables=` query param. Absent/empty → null (no injection).\n * Invalid JSON or a non-object payload is a caller error — surfaced as a 400\n * by the routes rather than silently previewing with defaults.\n */\nfunction parsePreviewVariablesParam(\n raw: string | undefined,\n): { ok: true; values: Record<string, unknown> | null } | { ok: false; error: string } {\n if (raw === undefined || raw === \"\") return { ok: true, values: null };\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return { ok: false, error: \"variables must be valid JSON\" };\n }\n if (!isVariablesPayload(parsed)) {\n return { ok: false, error: VARIABLES_PAYLOAD_ERROR };\n }\n return { ok: true, values: parsed };\n}\n\n/** ETag salt so cached previews revalidate when the variable values change. */\nfunction variablesEtagSalt(raw: string | undefined): string {\n if (!raw) return \"\";\n return `:vars:${createHash(\"sha1\").update(raw).digest(\"hex\").slice(0, 12)}`;\n}\n\n/**\n * Read + parse `?variables=` for a preview route. `error` present → the\n * route should 400; otherwise `values` is the override object (or null when\n * the param is absent) and `raw` feeds the ETag salt.\n */\nfunction previewVariablesFromRequest(rawVariables: string | undefined):\n | { error: string }\n | {\n error?: undefined;\n raw: string | undefined;\n values: Record<string, unknown> | null;\n } {\n const parse = parsePreviewVariablesParam(rawVariables);\n if (!parse.ok) return { error: parse.error };\n return { raw: rawVariables, values: parse.values };\n}\n\n/** Captures screenshot right after a seek, so they get every image eager and no preview mark. */\nexport const PREVIEW_CAPTURE_PARAM = \"hf-capture\";\n\n// Studio's console capture attaches at the iframe's load; this keeps what was raised before it.\nconst EARLY_ERRORS_SCRIPT = `<script>(function(){var seen=window.${STUDIO_PREVIEW_ERRORS}=[];\naddEventListener(\"error\",function(e){seen.push(e.message||String(e))});})();</script>`;\n\nfunction injectStudioPreviewAugmentations(\n html: string,\n adapter: StudioApiAdapter,\n projectDir: string,\n activeCompositionPath: string,\n capture: boolean,\n): string {\n const marked = capture\n ? html\n : injectTagsAtHeadStart(\n lazyPreviewImages(html),\n `<meta name=\"${STUDIO_PREVIEW_MARK_META}\">${EARLY_ERRORS_SCRIPT}`,\n );\n return injectStudioMotionScript(\n injectMotionPathPluginIfNeeded(\n injectGsapCdnFallback(\n injectProjectSignature(marked, resolveProjectSignature(adapter, projectDir)),\n ),\n ),\n projectDir,\n activeCompositionPath,\n );\n}\n\nasync function transformPreviewHtml(\n html: string,\n adapter: StudioApiAdapter,\n project: { id: string; dir: string; title?: string; sessionId?: string },\n activeCompositionPath: string,\n): Promise<string> {\n if (!adapter.transformPreviewHtml) return html;\n try {\n return await adapter.transformPreviewHtml({\n html,\n project,\n activeCompositionPath,\n });\n } catch (err) {\n console.warn(\"[Studio] preview transform failed, using original HTML:\", err);\n return html;\n }\n}\n\nfunction resolveProjectMainHtml(\n projectDir: string,\n projectId: string,\n): { html: string; compositionPath: string } | null {\n const indexPath = join(projectDir, \"index.html\");\n const blockHtmlPath = join(projectDir, `${projectId}.html`);\n recordPreviewRead(projectDir, indexPath);\n recordPreviewRead(projectDir, blockHtmlPath);\n if (existsSync(indexPath)) {\n return {\n html: readFileSync(indexPath, \"utf-8\"),\n compositionPath: \"index.html\",\n };\n }\n if (existsSync(blockHtmlPath)) {\n return {\n html: readFileSync(blockHtmlPath, \"utf-8\"),\n compositionPath: `${projectId}.html`,\n };\n }\n return null;\n}\n\n/** The bundler options every adapter's `bundle()` uses. This route serves project files under a\n * `<base href>`, so assets keep their URLs: inlined base64 multiplies the document per reference.\n * The lint route owns linting, so the bundle skips its own contract lint. */\nexport const PREVIEW_BUNDLE_OPTIONS = {\n runtime: \"placeholder\",\n inlineAssets: false,\n staticGuard: false,\n sceneParts: true,\n} as const satisfies BundleOptions;\n\nconst previewBaseHref = (projectId: string) =>\n `/api/projects/${encodeURIComponent(projectId)}/preview/`;\n\nconst withPreviewBase = (html: string, projectId: string) =>\n hasBaseElement(html)\n ? html\n : injectTagsAtHeadStart(html, `<base href=\"${previewBaseHref(projectId)}\">`);\n\nexport function registerPreviewRoutes(api: Hono, adapter: PreviewApiAdapter): void {\n const previewCacheHeaders = (etag: string) => ({\n \"Cache-Control\": \"private, no-cache\",\n ETag: etag,\n });\n\n // One probe cache per server instance (this function runs once per\n // registered API), reused across every preview request so the mtime-cache\n // benefit in scanProjectMediaCodecMap actually applies.\n const mediaCodecProbeCache = resolvePreviewMediaCodecProbeCache(adapter);\n\n // A build is a function of the project content its ETag names, so it is served again until the\n // content changes, to a cold browser as well as a revalidating one.\n const builtPreviews = new Map<string, string>();\n const rememberPreview = (key: string, html: string) => {\n builtPreviews.delete(key);\n builtPreviews.set(key, html);\n if (builtPreviews.size > 4) builtPreviews.delete(builtPreviews.keys().next().value!);\n };\n\n // Concurrent requests for one document (an early prefetch and the player's own load) share a build.\n const previewBuilds = new Map<string, Promise<string | null>>();\n\n // fallow-ignore-next-line complexity\n async function buildPreview(\n project: ResolvedProject,\n previewVariables: Record<string, unknown> | null,\n builtKey: string,\n capture: boolean,\n signature: string,\n ): Promise<string | null> {\n const diskMain = resolveProjectMainHtml(project.dir, project.id);\n\n try {\n let bundled = await adapter.bundle(project.dir, {\n stampHfIds: true,\n onRead: (filePath) => recordPreviewRead(project.dir, filePath),\n });\n let mainCompositionPath = \"index.html\";\n if (!bundled) {\n if (!diskMain) return null;\n bundled = ensureHfIds(diskMain.html);\n mainCompositionPath = diskMain.compositionPath;\n }\n bundled = withPreviewRuntime(bundled, adapter.runtimeUrl);\n recordPreviewReferences(project.dir, bundled);\n recordPreviewBuilt(project.dir);\n\n // Inject <base> for relative asset resolution\n bundled = withPreviewBase(bundled, project.id);\n\n // Also covers elements the adapter injected; ids already present are kept.\n bundled = injectStudioPreviewAugmentations(\n ensureHfIds(await transformPreviewHtml(bundled, adapter, project, mainCompositionPath)),\n adapter,\n project.dir,\n mainCompositionPath,\n capture,\n );\n if (previewVariables) bundled = injectPreviewVariables(bundled, previewVariables);\n bundled = await injectMediaCodecMap(\n bundled,\n adapter,\n project.dir,\n mainCompositionPath,\n mediaCodecProbeCache,\n );\n bundled = addScenePartsManifest(bundled, [`meta[name=\"${PROJECT_SIGNATURE_META}\"]`]);\n if (createProjectSignature(project.dir) === signature) {\n rememberPreview(builtKey, bundled);\n if (!capture) adapter.previewDocuments?.write(builtKey, bundled);\n }\n return bundled;\n } catch {\n // Re-read disk on bundle failure so we serve the latest file content,\n // not the pre-request snapshot that may have been saved over.\n const fallback = resolveProjectMainHtml(project.dir, project.id);\n if (fallback) {\n const fallbackHtml = withPreviewBase(\n withPreviewRuntime(ensureHfIds(fallback.html), adapter.runtimeUrl),\n project.id,\n );\n let fallbackAugmented = injectStudioPreviewAugmentations(\n await transformPreviewHtml(fallbackHtml, adapter, project, fallback.compositionPath),\n adapter,\n project.dir,\n fallback.compositionPath,\n capture,\n );\n if (previewVariables) {\n fallbackAugmented = injectPreviewVariables(fallbackAugmented, previewVariables);\n }\n fallbackAugmented = await injectMediaCodecMap(\n fallbackAugmented,\n adapter,\n project.dir,\n fallback.compositionPath,\n mediaCodecProbeCache,\n );\n return fallbackAugmented;\n }\n return null;\n }\n }\n\n // Bundled composition preview\n // fallow-ignore-next-line complexity\n api.get(\"/projects/:id/preview\", async (c) => {\n const resolved = await resolveProjectAndSignature(adapter, c.req.param(\"id\"));\n if (!resolved) return c.json({ error: \"not found\" }, 404);\n const { project, signature } = resolved;\n\n // fallow-ignore-next-line code-duplication\n const vars = previewVariablesFromRequest(c.req.query(\"variables\"));\n if (vars.error !== undefined) return c.json({ error: vars.error }, 400);\n const previewVariables = vars.values;\n const capture = c.req.query(PREVIEW_CAPTURE_PARAM) !== undefined;\n\n const etag = `\"preview:${signature}${variablesEtagSalt(vars.raw)}${capture ? \":capture\" : \"\"}\"`;\n const ifNoneMatch = c.req.header(\"If-None-Match\");\n if (ifNoneMatch === etag) {\n return new Response(null, {\n status: 304,\n headers: previewCacheHeaders(etag),\n });\n }\n const builtKey = `${project.id}\\n${etag}`;\n const cached = builtPreviews.get(builtKey) ?? adapter.previewDocuments?.read(builtKey);\n if (cached) {\n rememberPreview(builtKey, cached);\n return c.html(cached, 200, previewCacheHeaders(etag));\n }\n let pending = previewBuilds.get(builtKey);\n if (!pending) {\n pending = buildPreview(project, previewVariables, builtKey, capture, signature).finally(() =>\n previewBuilds.delete(builtKey),\n );\n previewBuilds.set(builtKey, pending);\n }\n const html = await pending;\n if (!html) return c.text(\"not found\", 404);\n return c.html(html, 200, previewCacheHeaders(etag));\n });\n\n /** Ids minted from the raw file before the build rewrites attributes, so they match the source's;\n * in memory only, since a write here reaches the watcher as an outside edit. null: the file vanished. */\n function pinSubCompHfIds(compFile: string, compPath: string): string | undefined | null {\n if (!/\\.html?$/i.test(compPath)) return undefined;\n try {\n return ensureHfIds(readFileSync(compFile, \"utf-8\"));\n } catch {\n return null;\n }\n }\n\n // Sub-composition preview\n // fallow-ignore-next-line complexity\n api.get(\"/projects/:id/preview/comp/*\", async (c) => {\n const resolved = await resolveProjectAndSignature(adapter, c.req.param(\"id\"));\n if (!resolved) return c.json({ error: \"not found\" }, 404);\n const { project, signature } = resolved;\n\n // fallow-ignore-next-line code-duplication\n const vars = previewVariablesFromRequest(c.req.query(\"variables\"));\n if (vars.error !== undefined) return c.json({ error: vars.error }, 400);\n const previewVariables = vars.values;\n const compPath = requestSubPath(c.req.url, \"projects/:id/preview/comp\");\n const compFile = resolveWithinProject(project.dir, compPath);\n if (compFile) recordPreviewRead(project.dir, compFile);\n // The sub-composition document takes its head from the root.\n recordPreviewRead(project.dir, \"index.html\");\n if (!compFile || !existsSync(compFile) || !statSync(compFile).isFile()) {\n return c.text(\"not found\", 404);\n }\n\n // \"v2\" salts the etag for the hf-id-pinning change below: a client holding\n // a pre-pin cached response (preview-only ids, unstamped disk file) must\n // not revalidate to a 304 that skips the pin.\n const compPathHash = createHash(\"sha1\").update(compPath).digest(\"hex\");\n const capture = c.req.query(PREVIEW_CAPTURE_PARAM) !== undefined;\n const etag = `\"comp:v2:${compPathHash}:${signature}${variablesEtagSalt(vars.raw)}${capture ? \":capture\" : \"\"}\"`;\n const ifNoneMatch = c.req.header(\"If-None-Match\");\n if (ifNoneMatch === etag) {\n return new Response(null, {\n status: 304,\n headers: previewCacheHeaders(etag),\n });\n }\n\n const stamped = pinSubCompHfIds(compFile, compPath);\n if (stamped === null) return c.text(\"not found\", 404); // file removed between stat and read\n\n const baseHref = previewBaseHref(project.id);\n let html = buildSubCompositionHtml(\n project.dir,\n compPath,\n adapter.runtimeUrl,\n baseHref,\n stamped,\n );\n if (!html) return c.text(\"not found\", 404);\n recordPreviewReferences(project.dir, html);\n html = ensureHfIds(await transformPreviewHtml(html, adapter, project, compPath));\n html = injectStudioPreviewAugmentations(html, adapter, project.dir, compPath, capture);\n if (previewVariables) html = injectPreviewVariables(html, previewVariables);\n html = await injectMediaCodecMap(html, adapter, project.dir, compPath, mediaCodecProbeCache);\n return c.html(html, 200, previewCacheHeaders(etag));\n });\n\n // Static asset serving (with range request support for audio/video seeking)\n // fallow-ignore-next-line complexity\n api.get(\"/projects/:id/preview/*\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const subPath = requestSubPath(c.req.url, \"projects/:id/preview\");\n // Assets are read-only and should mirror the renderer: permit a path that\n // is lexically inside the project even if an explicit project symlink\n // targets a shared directory outside it. Composition source files still\n // use resolveWithinProject because saves write their data-hf-id values.\n const candidate = resolve(project.dir, subPath);\n const file = isWithinProjectRoot(project.dir, candidate) ? candidate : null;\n if (!file || isPrivateProjectFile(project.dir, file)) {\n return c.text(\"not found\", 404);\n }\n recordPreviewRead(project.dir, file);\n const stat = existsSync(file) ? statSync(file) : null;\n if (!stat?.isFile()) {\n return c.text(\"not found\", 404);\n }\n const contentType = getMimeType(subPath);\n const isText = /\\.(html|css|js|json|svg|txt|md|cube)$/i.test(subPath);\n\n // `?hf-proxy=` follows the asset's alpha-aware proxy variant. The\n // param value must be recognized (matching play/staticProjectServer),\n // only a video asset can be proxied, and only when auto-proxy is enabled\n // for this adapter/project. Checked BEFORE any transcode or 304 shortcut\n // so a bogus/disabled request never spawns ffmpeg.\n const proxyParam = c.req.query(\"hf-proxy\");\n const boxParam = c.req.query(PREVIEW_PROXY_BOX_PARAM);\n const proxyBox = boxParam === undefined ? undefined : parsePreviewProxyBox(boxParam);\n if (proxyBox === null || (proxyBox && proxyParam === undefined)) {\n return c.text(\"not found\", 404);\n }\n let proxyVariant: ProxyVariant | undefined;\n if (proxyParam !== undefined) {\n if (\n !isProxyVariantRequest(proxyParam) ||\n !contentType.startsWith(\"video/\") ||\n !isAutoProxyEnabled(adapter)\n ) {\n return c.text(\"not found\", 404);\n }\n const facts = await probeAssetCodec(file, undefined, mediaCodecProbeCache);\n const eligibility = decideMediaProxyEligibility(facts);\n if (!eligibility.eligible) {\n return c.text(`media proxy unavailable: ${eligibility.reason}`, 422);\n }\n if (!facts) return c.text(\"media proxy unavailable: unknown_codec\", 422);\n proxyVariant = resolveProxyVariantRequest(proxyParam, facts) ?? undefined;\n if (!proxyVariant) {\n return c.text(\"media proxy variant does not match asset\", 422);\n }\n }\n\n const tag = settledFileTag(stat);\n const etag = tag && `\"${tag}${proxyEtagSalt(proxyVariant, proxyBox)}\"`;\n const cacheHeaders: Record<string, string> = isText\n ? { \"Cache-Control\": \"no-store\" }\n : { \"Cache-Control\": \"private, no-cache\", ...(etag && { ETag: etag }) };\n\n if (!isText && etag) {\n const ifNoneMatch = c.req.header(\"If-None-Match\");\n if (ifNoneMatch === etag) {\n return new Response(null, { status: 304, headers: cacheHeaders });\n }\n }\n\n // Resolve to the cached proxy (transcoding on miss) only after the 404/304\n // shortcuts above — the source's own mtime+size already salts the etag,\n // so a 304 never needs to await a transcode at all.\n let servedPath = file;\n let servedContentType = contentType;\n if (proxyVariant !== undefined) {\n try {\n // A cached copy settles before any timer; a transcode never holds one of\n // the browser's few connections to this host. 202 until the copy lands.\n servedPath = await waitForProxy(resolveProxy(project.dir, file, proxyVariant, proxyBox), 0);\n } catch (err) {\n if (err instanceof ProxyWaitTimeoutError) {\n return c.text(\"media proxy is being made\", 202, {\n \"Retry-After\": String(PROXY_PENDING_RETRY_AFTER_SECONDS),\n \"Cache-Control\": \"no-store\",\n });\n }\n if (err instanceof ProxyCapacityError) {\n return c.text(err.message, 503, { \"Retry-After\": \"5\" });\n }\n if (isProjectRootMissing(err)) throw err;\n const message = err instanceof ProxyTranscodeError ? err.message : \"proxy transcode failed\";\n return c.text(message, 502);\n }\n // After the wait, not at the eligibility gate: one count per served proxy shares\n // a unit with `prewarmsRequested`; a 304, a 202 or a failure serves none.\n recordProxyRequest();\n servedContentType = PROXY_VARIANT_CONFIG[proxyVariant].contentType;\n }\n\n // Text is small and keeps its utf-8 round trip in memory. Binary media\n // streams only the requested window: Chrome refills a playing <video> or\n // <audio> with a fresh Range request every few hundred milliseconds, and a\n // 1KB slice of a multi-hundred-MB source must not readFileSync the whole\n // file on each one. The full read also blocked the event loop, so every\n // other Studio request (SSE, saves, the voice track) waited behind it.\n const textBuffer = isText ? Buffer.from(readFileSync(file, \"utf-8\"), \"utf-8\") : null;\n const totalSize = textBuffer ? textBuffer.length : statSync(servedPath).size;\n const bodyFor = (start: number, end: number): BodyInit =>\n textBuffer\n ? new Uint8Array(textBuffer.subarray(start, end + 1))\n : // Node's web stream type and the DOM one do not overlap for tsc on\n // every platform's lib set; the double cast is the documented bridge.\n (Readable.toWeb(\n createReadStream(servedPath, { start, end }),\n ) as unknown as ReadableStream);\n\n // Support byte-range requests so browsers can seek audio/video elements.\n const rangeHeader = c.req.header(\"Range\");\n const match = rangeHeader ? /bytes=(\\d+)-(\\d*)/.exec(rangeHeader) : null;\n if (match) {\n const start = parseInt(match[1]!, 10);\n const end = match[2] ? parseInt(match[2], 10) : totalSize - 1;\n const safeEnd = Math.min(end, totalSize - 1);\n if (start > safeEnd) {\n return new Response(null, {\n status: 416,\n headers: { ...cacheHeaders, \"Content-Range\": `bytes */${totalSize}` },\n });\n }\n return new Response(bodyFor(start, safeEnd), {\n status: 206,\n headers: {\n ...cacheHeaders,\n \"Content-Type\": servedContentType,\n \"Content-Range\": `bytes ${start}-${safeEnd}/${totalSize}`,\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(safeEnd - start + 1),\n },\n });\n }\n\n return new Response(totalSize > 0 ? bodyFor(0, totalSize - 1) : null, {\n headers: {\n ...cacheHeaders,\n \"Content-Type\": servedContentType,\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(totalSize),\n },\n });\n });\n}\n","import { readlinkSync } from \"node:fs\";\nimport { dirname, join, parse, relative, resolve } from \"node:path\";\nimport { parseHTML } from \"linkedom\";\nimport { STUDIO_SIGNATURE_MANIFEST_PATHS } from \"./projectSignature.js\";\nimport { realFilePath } from \"./safePath.js\";\n\nconst ALWAYS_AFFECTS = [\"hyperframes.json\", ...STUDIO_SIGNATURE_MANIFEST_PATHS];\n// A malformed inline URL must not turn ancestor tracking into an image-sized path walk.\nconst MAX_PREVIEW_PATH_LENGTH = 4096;\nconst SHOW_ELEMENT = 1;\nconst REFERENCE =\n /\\b(?:src|href|poster|data-composition-src)\\s*=\\s*(?:\"([^\"\\n]*)\"|'([^'\\n]*)')|url\\(\\s*(?:\"([^\"\\n]*)\"|'([^'\\n]*)'|([^\"'\\s)]+))/gi;\nconst REFERENCE_ATTRIBUTE = /\\b(?:src|href|poster|data-composition-src)$/i;\nconst isElement = (node: Node): node is Element => node.nodeType === 1;\n// macOS and Windows volumes ignore letter case by default, so it is not part of a path's identity there.\nconst pathKey =\n process.platform === \"darwin\" || process.platform === \"win32\"\n ? (path: string) => resolve(path).toLowerCase()\n : (path: string) => resolve(path);\n// ponytail: grows until restart, so a file a film stopped using still reloads; reset per build if that matters.\nconst readsByProject = new Map<string, Set<string>>();\nconst builtProjects = new Set<string>();\nconst projectKey = (projectDir: string) => pathKey(realFilePath(resolve(projectDir)));\nconst inRealProject = (projectDir: string, path: string) =>\n join(realFilePath(resolve(projectDir)), relative(resolve(projectDir), resolve(projectDir, path)));\n\nconst readLink = (path: string): string | null => {\n try {\n return readlinkSync(path);\n } catch {\n return null;\n }\n};\n\n// Walks `path` as the OS does, returning every link it passes and where it ends up.\nfunction linksOnTheWay(path: string): string[] {\n const passed: string[] = [];\n let at = parse(path).root;\n let rest = path.slice(at.length).split(/[\\\\/]+/);\n for (let hops = 0; rest.length > 0; ) {\n const part = rest.shift()!;\n if (!part || part === \".\") continue;\n if (part === \"..\") {\n at = dirname(at);\n continue;\n }\n const next = join(at, part);\n if (next.length > MAX_PREVIEW_PATH_LENGTH) return passed;\n const target = hops < 40 ? readLink(next) : null;\n if (target === null) {\n at = next;\n continue;\n }\n hops++;\n passed.push(next);\n const root = parse(target).root;\n if (root) at = root;\n rest = [...target.slice(root.length).split(/[\\\\/]+/), ...rest];\n }\n passed.push(at);\n return passed;\n}\n\n// A link's target can be created or retargeted later, so every read resolves it again.\nexport function recordPreviewRead(projectDir: string, filePath: string): void {\n if (filePath.length > MAX_PREVIEW_PATH_LENGTH) return;\n const key = projectKey(projectDir);\n let reads = readsByProject.get(key);\n if (!reads) readsByProject.set(key, (reads = new Set()));\n const read = inRealProject(projectDir, filePath);\n if (read.length > MAX_PREVIEW_PATH_LENGTH) return;\n for (const found of [read, ...linksOnTheWay(read)]) {\n for (let path = pathKey(found); !reads.has(path); path = dirname(path)) reads.add(path);\n }\n}\n\nexport function recordPreviewReferences(projectDir: string, html: string): void {\n const named = new Set<string>();\n const add = (reference: string) => {\n const url = reference.trim();\n if (!url || /^(?:[a-z][a-z0-9+.-]*:|[/#])/i.test(url)) return;\n const path = url.split(/[?#]/)[0] ?? \"\";\n let decoded = path;\n try {\n decoded = decodeURIComponent(path);\n } catch {\n // A malformed escape names the file literally.\n }\n if (decoded && decoded.length <= MAX_PREVIEW_PATH_LENGTH) named.add(decoded);\n };\n const scan = (text: string) => {\n for (const match of text.matchAll(REFERENCE)) {\n add(match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? \"\");\n }\n };\n const scanElement = (element: Element) => {\n for (const attribute of element.attributes) {\n if (REFERENCE_ATTRIBUTE.test(attribute.name)) add(attribute.value);\n }\n const style = element.getAttribute(\"style\");\n if (style) scan(style);\n if (element.localName === \"style\" || element.localName === \"script\") {\n scan(element.textContent ?? \"\");\n }\n };\n // The parser decodes attributes; walking also visits inert template descendants without cloning them.\n const { document } = parseHTML(html);\n for (const root of document.children) {\n scanElement(root);\n const elements = document.createTreeWalker(root, SHOW_ELEMENT);\n for (let node = elements.nextNode(); node; node = elements.nextNode()) {\n if (isElement(node)) scanElement(node);\n }\n }\n for (const path of named) recordPreviewRead(projectDir, path);\n}\n\nexport function recordPreviewBuilt(projectDir: string): void {\n for (const path of ALWAYS_AFFECTS) recordPreviewRead(projectDir, path);\n builtProjects.add(projectKey(projectDir));\n}\n\n// Every write counts until this process built the preview; a folder event counts when a loaded file is inside it.\nexport function affectsPreview(projectDir: string, changedPath: string): boolean {\n const key = projectKey(projectDir);\n if (!builtProjects.has(key)) return true;\n return readsByProject.get(key)?.has(pathKey(inRealProject(projectDir, changedPath))) ?? false;\n}\n","/**\n * Shared shape check for composition-variable payloads (`?variables=` on the\n * preview routes, `body.variables` on the render route) — one contract, one\n * error string, so the routes can't drift.\n */\n\nexport const VARIABLES_PAYLOAD_ERROR = \"variables must be a JSON object of {variableId: value}\";\n\nexport function isVariablesPayload(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/**\n * Inject preview variable overrides: `?variables=<json>` becomes\n * `window.__hfVariables` set before any composition script runs — the exact\n * global the engine sets via evaluateOnNewDocument at render time\n * (engine/src/services/frameCapture.ts), so preview-with-values cannot\n * diverge from render behavior. The runtime's getVariables() merges these\n * overrides over the declared defaults.\n */\nexport function injectPreviewVariables(html: string, values: Record<string, unknown>): string {\n // <-escape prevents a string value containing \"</script>\" from\n // breaking out of the injected tag.\n const json = JSON.stringify(values).replace(/</g, \"\\\\u003c\");\n const tag = `<script data-hf-preview-variables>window.__hfVariables=${json};</script>`;\n // Insert as early as possible without ever landing before the doctype —\n // content before <!doctype> flips the document into quirks mode, so the\n // fallback chain is <head…> → <html…> → after the doctype → prepend.\n for (const pattern of [/<head/i, /<html/i, /^\\s*<!doctype/i]) {\n const match = pattern.exec(html);\n if (match) {\n // If the first prefix has no closing >, no later prefix can close either.\n const end = html.indexOf(\">\", match.index + match[0].length);\n if (end < 0) continue;\n const at = end + 1;\n return html.slice(0, at) + tag + html.slice(at);\n }\n }\n return tag + html;\n}\n","import { findStartTags } from \"@hyperframes/core/compiler/html-document\";\nimport { parseHTML } from \"linkedom\";\nimport { STUDIO_PREVIEW_LAZY_ATTR } from \"@hyperframes/core/studio-preview-mark\";\n\n// A start that is not a plain number (a reference) counts as unknown and keeps the image eager.\nfunction startsAfterZero(el: Element): boolean {\n for (let node: Element | null = el; node; node = node.parentElement) {\n if (Number(node.getAttribute(\"data-start\")) > 0) return true;\n }\n return false;\n}\n\nconst hasLoading = (img: Element) =>\n Array.from(img.attributes).some((attr) => attr.name.toLowerCase() === \"loading\");\n\nexport function lazyPreviewImages(html: string): string {\n if (!/<!doctype|<html[\\s>]/i.test(html)) return html;\n const images = [...parseHTML(html).document.querySelectorAll(\"img\")];\n // The scanner skips comments and raw text, so its `<img` offsets line up with the DOM's images.\n const tags = findStartTags(html, \"img\");\n if (tags.length !== images.length) return html;\n const parts: string[] = [];\n let from = 0;\n images.forEach((img, i) => {\n if (hasLoading(img) || !startsAfterZero(img)) return;\n const at = (tags[i] ?? 0) + 4;\n parts.push(html.slice(from, at), ` loading=\"lazy\" ${STUDIO_PREVIEW_LAZY_ATTR}`);\n from = at;\n });\n parts.push(html.slice(from));\n return parts.join(\"\");\n}\n","import type { Hono } from \"hono\";\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { LintResult, StudioApiAdapter } from \"../types.js\";\nimport { isInHiddenOrVendorDir, walkDir } from \"../helpers/safePath.js\";\n\ntype LintFinding = LintResult[\"findings\"][number];\n\nasync function collectProjectFindings(\n adapter: StudioApiAdapter,\n projectDir: string,\n): Promise<{ findings: LintFinding[]; coveredFiles: Set<string> }> {\n const findings: LintFinding[] = [];\n const coveredFiles = new Set<string>();\n if (!adapter.lintProject) return { findings, coveredFiles };\n\n const result = await adapter.lintProject(projectDir);\n for (const entry of result.results) {\n coveredFiles.add(entry.file);\n for (const finding of entry.result.findings) {\n findings.push({ ...finding, file: entry.file });\n }\n }\n return { findings, coveredFiles };\n}\n\nasync function lintUncoveredHtml(\n adapter: StudioApiAdapter,\n projectDir: string,\n htmlFiles: string[],\n coveredFiles: Set<string>,\n): Promise<LintFinding[]> {\n const findings: LintFinding[] = [];\n for (const file of htmlFiles) {\n if (coveredFiles.has(file)) continue;\n const content = readFileSync(join(projectDir, file), \"utf-8\");\n const result = await adapter.lint(content, { filePath: file, isSubComposition: true });\n for (const finding of result?.findings ?? []) {\n findings.push({ ...finding, file });\n }\n }\n return findings;\n}\n\nexport function registerLintRoutes(api: Hono, adapter: StudioApiAdapter): void {\n api.get(\"/projects/:id/lint\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n try {\n const htmlFiles = walkDir(project.dir).filter(\n (f) => f.endsWith(\".html\") && !isInHiddenOrVendorDir(f),\n );\n const projectLint = await collectProjectFindings(adapter, project.dir);\n const extraFindings = await lintUncoveredHtml(\n adapter,\n project.dir,\n htmlFiles,\n projectLint.coveredFiles,\n );\n return c.json({ findings: [...projectLint.findings, ...extraFindings] });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return c.json({ error: `Lint failed: ${msg}` }, 500);\n }\n });\n}\n","import type { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport { existsSync, lstatSync, readFileSync, unlinkSync, readdirSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { StudioApiAdapter, RenderJobState } from \"../types.js\";\nimport { VALID_CANVAS_RESOLUTIONS, type CanvasResolution } from \"@hyperframes/parsers\";\nimport { formatRenderOutputTimestamp, parseFps } from \"@hyperframes/core\";\nimport {\n folderGone,\n isPrivateProjectFile,\n mkdirWithinProject,\n resolveWithinProject,\n} from \"../helpers/safePath.js\";\nimport { projectDirMissing } from \"../helpers/projectDirMissing.js\";\nimport { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from \"../helpers/variablesPayload.js\";\n\nconst VALID_RESOLUTIONS = new Set<string>(VALID_CANVAS_RESOLUTIONS);\n\nfunction contentDispositionHeader(disposition: \"inline\" | \"attachment\", filename: string): string {\n const fallback = filename.replace(/[^\\x20-\\x7e]|[\"\\\\]/g, \"_\");\n const encoded = encodeURIComponent(filename).replace(\n /[!'()*]/g,\n (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n return `${disposition}; filename=\"${fallback}\"; filename*=UTF-8''${encoded}`;\n}\n\nexport function registerRenderRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // Scoped job store — not shared across createStudioApi() calls\n const renderJobs = new Map<string, RenderJobState & { createdAt: number }>();\n\n // TTL cleanup for completed jobs (5 minutes)\n const TTL_MS = 300_000;\n const CLEANUP_INTERVAL_MS = 60_000;\n let cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n const cleanupEnabled = () =>\n typeof process !== \"undefined\" &&\n process.env.NODE_ENV !== \"production\" &&\n !process.argv.includes(\"build\");\n\n const cleanupFinishedJobs = () => {\n const now = Date.now();\n for (const [key, job] of renderJobs) {\n if (job.status !== \"rendering\" && now - job.createdAt > TTL_MS) {\n renderJobs.delete(key);\n }\n }\n if (renderJobs.size === 0 && cleanupTimer) {\n clearInterval(cleanupTimer);\n cleanupTimer = null;\n }\n };\n\n const ensureCleanupTimer = () => {\n if (cleanupTimer || !cleanupEnabled()) return;\n cleanupTimer = setInterval(cleanupFinishedJobs, CLEANUP_INTERVAL_MS);\n if (typeof cleanupTimer === \"object\" && \"unref\" in cleanupTimer) {\n cleanupTimer.unref();\n }\n };\n\n ensureCleanupTimer();\n\n // Start a render\n api.post(\"/projects/:id/render\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const body = (await c.req.json().catch(() => ({}))) as {\n // Polymorphic per design note in core.types.Fps:\n // number → integer fps (e.g. 30)\n // string → rational fps (e.g. \"30000/1001\" for NTSC 29.97)\n // Decimals are rejected on purpose so the exact denominator stays\n // unambiguous (29.97 ≠ 30000/1001 when ffmpeg consumes them).\n fps?: number | string;\n quality?: string;\n format?: string;\n resolution?: string;\n composition?: string;\n // Browser telemetry id, so the server-emitted render outcome is\n // attributed to the user who triggered the render (joinable funnel).\n telemetryDistinctId?: string;\n // Explicit \"this browser profile opted out\" flag. Distinct from simply\n // omitting the id: an OLD client omits it too, and that case falls back\n // to the install anonymousId. Only an explicit `true` suppresses.\n telemetryOptOut?: boolean;\n // Composition-variable overrides ({variableId: value}), injected as\n // window.__hfVariables — same channel as `hyperframes render --variables`.\n variables?: Record<string, unknown>;\n };\n const VALID_FORMATS = new Set([\"mp4\", \"webm\", \"mov\"]);\n const FORMAT_EXT: Record<string, string> = { mp4: \".mp4\", webm: \".webm\", mov: \".mov\" };\n const format = VALID_FORMATS.has(body.format ?? \"\") ? (body.format as string) : \"mp4\";\n\n // Default to 30 fps when unset or unparseable. The route stays lenient on\n // invalid fps values (matching the lenient handling of `resolution` and\n // `quality` already in this file) — the producer surfaces a clearer error\n // message if the caller really did mean to fail loudly.\n const fpsParse = body.fps === undefined ? null : parseFps(body.fps);\n const fps = fpsParse && fpsParse.ok ? fpsParse.value : { num: 30, den: 1 };\n const quality = [\"draft\", \"standard\", \"high\"].includes(body.quality ?? \"\")\n ? (body.quality as string)\n : \"standard\";\n const outputResolution = VALID_RESOLUTIONS.has(body.resolution ?? \"\")\n ? (body.resolution as CanvasResolution)\n : undefined;\n let composition: string | undefined;\n if (typeof body.composition === \"string\" && body.composition.length > 0) {\n // `body.composition` is attacker-controlled (from c.req.json()).\n // resolveWithinProject dereferences symlinks, so an in-project symlink\n // pointing outside the root can't smuggle the render target out.\n if (!resolveWithinProject(project.dir, body.composition)) {\n if (folderGone(project.dir)) return projectDirMissing(c);\n return c.json({ error: \"composition path must be within the project directory\" }, 400);\n }\n composition = body.composition;\n }\n\n // Unlike fps/quality (lenient with safe fallbacks), a malformed variables\n // payload means the user's values would be silently dropped — fail loudly.\n let variables: Record<string, unknown> | undefined;\n if (body.variables !== undefined) {\n if (!isVariablesPayload(body.variables)) {\n return c.json({ error: VARIABLES_PAYLOAD_ERROR }, 400);\n }\n variables = body.variables;\n }\n\n const now = new Date();\n const jobId = `${project.id}_${formatRenderOutputTimestamp(now)}`;\n const rendersDir = adapter.rendersDir(project);\n mkdirWithinProject(project.dir, rendersDir);\n const ext = FORMAT_EXT[format] ?? \".mp4\";\n const outputPath = join(rendersDir, `${jobId}${ext}`);\n\n const jobState = adapter.startRender({\n project,\n outputPath,\n format: format as \"mp4\" | \"webm\" | \"mov\",\n fps,\n quality,\n jobId,\n outputResolution,\n composition,\n variables,\n distinctId:\n typeof body.telemetryDistinctId === \"string\" ? body.telemetryDistinctId : undefined,\n telemetryOptOut: body.telemetryOptOut === true,\n });\n (jobState as RenderJobState & { createdAt: number }).createdAt = Date.now();\n renderJobs.set(jobId, jobState as RenderJobState & { createdAt: number });\n\n ensureCleanupTimer();\n\n return c.json({ jobId, status: \"rendering\" });\n });\n\n // SSE progress stream\n api.get(\"/render/:jobId/progress\", (c) => {\n const { jobId } = c.req.param();\n const job = renderJobs.get(jobId);\n if (!job) return c.json({ error: \"not found\" }, 404);\n\n return streamSSE(c, async (stream) => {\n while (true) {\n const current = renderJobs.get(jobId);\n if (!current) break;\n await stream.writeSSE({\n event: \"progress\",\n data: JSON.stringify({\n progress: current.progress,\n status: current.status,\n stage: current.stage,\n error: current.error,\n ...(current.status === \"complete\" && current.audioLoweredDb !== undefined\n ? { audioLoweredDb: current.audioLoweredDb }\n : {}),\n }),\n });\n if (current.status !== \"rendering\") break;\n await stream.sleep(500);\n }\n });\n });\n\n // Cancel an in-flight render. Marks the job cancelled immediately (so the\n // SSE stream terminates) and invokes the adapter's abort hook when present.\n api.post(\"/render/:jobId/cancel\", (c) => {\n const { jobId } = c.req.param();\n const job = renderJobs.get(jobId);\n if (!job) return c.json({ error: \"not found\" }, 404);\n if (job.status === \"rendering\") {\n job.status = \"cancelled\";\n job.cancel?.();\n }\n return c.json({ status: job.status });\n });\n\n const RENDER_MIME: Record<string, string> = {\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".mov\": \"video/quicktime\",\n };\n const RENDER_EXTENSIONS = Object.keys(RENDER_MIME);\n\n const isPlainFile = (path: string): boolean => {\n try {\n return lstatSync(path).isFile();\n } catch {\n return false;\n }\n };\n\n function renderContentType(filePath: string): string {\n const ext = RENDER_EXTENSIONS.find((e) => filePath.endsWith(e));\n return (ext && RENDER_MIME[ext]) ?? \"video/mp4\";\n }\n\n // Serve render inline (for in-browser playback — opens in a new tab)\n // fallow-ignore-next-line code-duplication\n api.get(\"/render/:jobId/view\", (c) => {\n const { jobId } = c.req.param();\n const job = renderJobs.get(jobId);\n if (!job?.outputPath || !isPlainFile(job.outputPath)) {\n return c.json({ error: \"not found\" }, 404);\n }\n const contentType = renderContentType(job.outputPath);\n const filename = job.outputPath.split(\"/\").pop() ?? `render.mp4`;\n const content = readFileSync(job.outputPath);\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Content-Disposition\": contentDispositionHeader(\"inline\", filename),\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(content.length),\n },\n });\n });\n\n // Download render\n // fallow-ignore-next-line code-duplication\n api.get(\"/render/:jobId/download\", (c) => {\n const { jobId } = c.req.param();\n const job = renderJobs.get(jobId);\n if (!job?.outputPath || !isPlainFile(job.outputPath)) {\n return c.json({ error: \"not found\" }, 404);\n }\n const contentType = renderContentType(job.outputPath);\n const filename = job.outputPath.split(\"/\").pop() ?? `render.mp4`;\n const content = readFileSync(job.outputPath);\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Content-Disposition\": contentDispositionHeader(\"attachment\", filename),\n },\n });\n });\n\n // Delete render\n api.delete(\"/render/:jobId\", (c) => {\n const { jobId } = c.req.param();\n for (const [, state] of renderJobs) {\n if (state.id === jobId && state.outputPath) {\n const dir = state.outputPath.replace(/\\/[^/]+$/, \"\");\n for (const ext of [\".mp4\", \".webm\", \".mov\", \".meta.json\"]) {\n const fp = join(dir, `${jobId}${ext}`);\n if (existsSync(fp)) unlinkSync(fp);\n }\n break;\n }\n }\n renderJobs.delete(jobId);\n return c.json({ deleted: true });\n });\n\n // Serve render file directly from disk (no in-memory map dependency)\n api.get(\"/projects/:id/renders/file/*\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const filename = c.req.path.split(\"/renders/file/\")[1];\n if (!filename) return c.json({ error: \"missing filename\" }, 400);\n const rendersDir = adapter.rendersDir(project);\n // Containment guard: the filename is attacker-controlled wildcard input, so\n // route it through the same chokepoint every other project-scoped path uses.\n // Literal `..` is collapsed upstream by the URL parser, but a bare join() +\n // readFileSync still followed an in-rendersDir symlink pointing outside the\n // dir; resolveWithinProject canonicalizes with realpath before serving.\n const fp = resolveWithinProject(rendersDir, filename);\n if (!fp || isPrivateProjectFile(project.dir, fp)) return c.json({ error: \"forbidden\" }, 403);\n if (!existsSync(fp)) return c.json({ error: \"not found\" }, 404);\n const contentType = renderContentType(fp);\n const content = readFileSync(fp);\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Content-Disposition\": contentDispositionHeader(\"inline\", filename),\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(content.length),\n },\n });\n });\n\n // List renders\n api.get(\"/projects/:id/renders\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const rendersDir = adapter.rendersDir(project);\n if (!existsSync(rendersDir)) return c.json({ renders: [] });\n const files = readdirSync(rendersDir)\n .filter((f) => f.endsWith(\".mp4\") || f.endsWith(\".webm\") || f.endsWith(\".mov\"))\n .flatMap((f) => {\n const fp = resolveWithinProject(rendersDir, f);\n return fp && !isPrivateProjectFile(project.dir, fp) ? [{ f, fp }] : [];\n })\n .map(({ f, fp }) => {\n const stat = statSync(fp);\n const rid = f.replace(/\\.(mp4|webm|mov)$/, \"\");\n const metaPath = join(rendersDir, `${rid}.meta.json`);\n let status: \"complete\" | \"failed\" = \"complete\";\n let durationMs: number | undefined;\n let audioLoweredDb: number | undefined;\n if (existsSync(metaPath)) {\n try {\n const meta = JSON.parse(readFileSync(metaPath, \"utf-8\"));\n // A stale failed sidecar can remain after a retry succeeds. An\n // existing output artifact is authoritative for the list view;\n // don't present a downloadable render as failed solely because\n // an earlier attempt left behind failed metadata.\n if (meta.status === \"failed\" && !existsSync(fp)) status = \"failed\";\n if (meta.durationMs) durationMs = meta.durationMs;\n if (typeof meta.audioLoweredDb === \"number\") audioLoweredDb = meta.audioLoweredDb;\n } catch {\n /* ignore */\n }\n }\n return {\n id: rid,\n filename: f,\n path: fp,\n size: stat.size,\n createdAt: stat.mtimeMs,\n status,\n durationMs,\n ...(audioLoweredDb !== undefined ? { audioLoweredDb } : {}),\n };\n })\n .sort((a, b) => b.createdAt - a.createdAt);\n // Register on-disk renders that aren't in the current session's job map\n // so they remain downloadable after a server restart.\n for (const file of files) {\n if (!renderJobs.has(file.id)) {\n renderJobs.set(file.id, {\n id: file.id,\n status: file.status,\n progress: 100,\n outputPath: file.path,\n createdAt: file.createdAt,\n } as RenderJobState & { createdAt: number });\n }\n }\n return c.json({ renders: files.map(({ path: _path, ...render }) => render) });\n });\n}\n","import type { Hono } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { open, stat } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { pinWithinProject } from \"../helpers/safePath.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\nimport { ThumbnailGenerationCoordinator } from \"./thumbnailGenerationCoordinator.js\";\n\nconst MAX_SOURCE_BYTES = 64 * 1024 * 1024;\nconst MAX_CACHE_BYTES = 8 * 1024 * 1024;\n\nlet sharpLoad: Promise<typeof import(\"sharp\").default> | undefined;\nfunction loadSharp() {\n sharpLoad ??= import(\"sharp\").then(\n (module) => module.default,\n (error: unknown) => {\n console.warn(\"[Studio] JPEG thumbnails are off: sharp could not load:\", error);\n throw error;\n },\n );\n return sharpLoad;\n}\n\nasync function generateThumbnail(path: string, signal: AbortSignal): Promise<Buffer> {\n const sharp = await loadSharp();\n const file = await open(path, \"r\");\n try {\n const info = await file.stat();\n if (!info.isFile() || info.size > MAX_SOURCE_BYTES) throw new Error(\"Unsupported image\");\n const source = Buffer.alloc(info.size);\n let offset = 0;\n while (offset < source.length) {\n signal.throwIfAborted();\n const { bytesRead } = await file.read(source, offset, source.length - offset, offset);\n if (!bytesRead) break;\n offset += bytesRead;\n }\n if (source[0] !== 0xff || source[1] !== 0xd8) throw new Error(\"Unsupported image\");\n const image = sharp(source.subarray(0, offset), { limitInputPixels: 40_000_000 });\n if ((await image.metadata()).format !== \"jpeg\") throw new Error(\"Unsupported image\");\n signal.throwIfAborted();\n const result = await image\n .rotate()\n .resize(240, 135, { fit: \"inside\", withoutEnlargement: true })\n .jpeg({ quality: 80 })\n .toBuffer();\n signal.throwIfAborted();\n return result;\n } finally {\n await file.close();\n }\n}\n\nasync function resolveSource(adapter: StudioApiAdapter, id: string, url: string) {\n const project = await adapter.resolveProject(id);\n if (!project) throw new HTTPException(404);\n let relative: string;\n try {\n relative = requestSubPath(url, \"projects/:id/image-thumbnail\");\n } catch {\n throw new HTTPException(400);\n }\n if (!/\\.jpe?g$/i.test(relative)) throw new HTTPException(415);\n const path = pinWithinProject(project.dir, relative);\n if (!path) throw new HTTPException(404);\n const info = await stat(path).catch(() => {\n throw new HTTPException(404);\n });\n if (!info.isFile()) throw new HTTPException(404);\n if (info.size > MAX_SOURCE_BYTES) throw new HTTPException(413);\n return { path, info };\n}\n\nexport function registerImageThumbnailRoutes(api: Hono, adapter: StudioApiAdapter): void {\n const coordinator = new ThumbnailGenerationCoordinator(2);\n const cache = new Map<string, Buffer>();\n let cacheBytes = 0;\n const remember = (key: string, image: Buffer) => {\n cacheBytes -= cache.get(key)?.byteLength ?? 0;\n cache.delete(key);\n cache.set(key, image);\n cacheBytes += image.byteLength;\n while (cacheBytes > MAX_CACHE_BYTES || cache.size > 128) {\n const oldest = cache.keys().next().value;\n if (oldest === undefined) break;\n cacheBytes -= cache.get(oldest)?.byteLength ?? 0;\n cache.delete(oldest);\n }\n };\n api.get(\"/projects/:id/image-thumbnail/*\", async (c) => {\n try {\n const { path, info } = await resolveSource(adapter, c.req.param(\"id\"), c.req.url);\n const key = createHash(\"sha256\")\n .update(JSON.stringify([path, info.dev, info.ino, info.size, info.mtimeMs, info.ctimeMs]))\n .digest(\"hex\");\n const etag = `\"${key}\"`;\n c.header(\"ETag\", etag);\n c.header(\"Cache-Control\", \"private, no-cache\");\n c.header(\"X-Content-Type-Options\", \"nosniff\");\n if (c.req.header(\"If-None-Match\") === etag) return c.body(null, 304);\n let result = cache.get(key);\n if (result) remember(key, result);\n else {\n if (coordinator.protectedKeys().size >= 32) return c.text(\"thumbnail queue full\", 429);\n result =\n (await coordinator.acquire(key, c.req.raw.signal, async (signal) => {\n const image = await generateThumbnail(path, signal);\n remember(key, image);\n return image;\n })) ?? undefined;\n }\n if (!result) return c.text(\"image unavailable\", 422);\n c.header(\"Content-Type\", \"image/jpeg\");\n return c.body(new Uint8Array(result));\n } catch (error) {\n if (error instanceof HTTPException) return error.getResponse();\n return c.text(\"image unavailable\", 422);\n }\n });\n}\n","export type ThumbnailGenerationValue = Buffer | null;\nexport type ThumbnailGenerationWork = (signal: AbortSignal) => Promise<ThumbnailGenerationValue>;\n\ninterface GenerationEntry {\n key: string;\n controller: AbortController;\n leases: number;\n state: \"queued\" | \"active\";\n work: ThumbnailGenerationWork;\n promise: Promise<ThumbnailGenerationValue>;\n resolve: (value: ThumbnailGenerationValue) => void;\n reject: (reason: unknown) => void;\n}\n\n/** Sole server owner for same-key dedupe, concurrency, cancellation, and queue order. */\nexport class ThumbnailGenerationCoordinator {\n private readonly entries = new Map<string, GenerationEntry>();\n private readonly queue: GenerationEntry[] = [];\n private readonly activeEntries = new Set<GenerationEntry>();\n private active = 0;\n\n constructor(private readonly concurrency = 1) {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new RangeError(\"Thumbnail concurrency must be a positive integer\");\n }\n }\n\n acquire(\n key: string,\n signal: AbortSignal,\n work: ThumbnailGenerationWork,\n ): Promise<ThumbnailGenerationValue> {\n if (signal.aborted) return Promise.reject(new DOMException(\"Aborted\", \"AbortError\"));\n\n let entry = this.entries.get(key);\n if (!entry) {\n let resolve!: (value: ThumbnailGenerationValue) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<ThumbnailGenerationValue>((resolvePromise, rejectPromise) => {\n resolve = resolvePromise;\n reject = rejectPromise;\n });\n entry = {\n key,\n controller: new AbortController(),\n leases: 0,\n state: \"queued\",\n work,\n promise,\n resolve,\n reject,\n };\n this.entries.set(key, entry);\n this.queue.push(entry);\n }\n entry.leases++;\n this.pump();\n\n return this.lease(entry, signal);\n }\n\n protectedKeys(): ReadonlySet<string> {\n return new Set([...this.entries.keys(), ...[...this.activeEntries].map((entry) => entry.key)]);\n }\n\n private lease(entry: GenerationEntry, signal: AbortSignal): Promise<ThumbnailGenerationValue> {\n return new Promise((resolve, reject) => {\n let released = false;\n const release = () => {\n if (released) return;\n released = true;\n signal.removeEventListener(\"abort\", onAbort);\n entry.leases--;\n if (entry.leases > 0 || !this.entries.has(entry.key)) return;\n\n entry.controller.abort();\n if (this.entries.get(entry.key) === entry) this.entries.delete(entry.key);\n if (entry.state === \"queued\") {\n const index = this.queue.indexOf(entry);\n if (index >= 0) this.queue.splice(index, 1);\n entry.reject(new DOMException(\"Aborted\", \"AbortError\"));\n }\n };\n const onAbort = () => {\n release();\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n\n signal.addEventListener(\"abort\", onAbort, { once: true });\n entry.promise.then(\n (value) => {\n release();\n resolve(value);\n },\n (reason) => {\n release();\n reject(reason);\n },\n );\n });\n }\n\n private pump(): void {\n while (this.active < this.concurrency) {\n const entry = this.queue.shift();\n if (!entry) return;\n if (entry.leases === 0) continue;\n entry.state = \"active\";\n this.activeEntries.add(entry);\n this.active++;\n void this.run(entry);\n }\n }\n\n private async run(entry: GenerationEntry): Promise<void> {\n try {\n entry.resolve(await entry.work(entry.controller.signal));\n } catch (error) {\n entry.reject(error);\n } finally {\n this.active--;\n this.activeEntries.delete(entry);\n if (this.entries.get(entry.key) === entry) this.entries.delete(entry.key);\n this.pump();\n }\n }\n}\n\nexport const thumbnailGenerationCoordinator = new ThumbnailGenerationCoordinator(1);\n","import type { Hono } from \"hono\";\nimport {\n closeSync,\n type Dirent,\n fstatSync,\n openSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { STUDIO_MANUAL_EDITS_PATH } from \"../helpers/manualEditsRenderScript.js\";\nimport { compositionInputSignature } from \"../helpers/compositionInputs.js\";\nimport { createProjectSignature, resolveProjectAndSignature } from \"../helpers/projectSignature.js\";\nimport { STUDIO_MOTION_PATH } from \"../helpers/studioMotionRenderScript.js\";\nimport { thumbnailGenerationCoordinator } from \"./thumbnailGenerationCoordinator.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\nimport {\n isProjectRootMissing,\n mkdirWithinProject,\n resolveWithinProject,\n} from \"../helpers/safePath.js\";\nimport { proxyActivityMark } from \"../helpers/proxyTranscoder.js\";\nimport { PREVIEW_CAPTURE_PARAM } from \"./preview.js\";\n\nconst THUMBNAIL_CACHE_VERSION = \"v5\";\nconst THUMBNAIL_MAX_OUTPUT_WIDTH = 240;\nconst THUMBNAIL_MAX_OUTPUT_HEIGHT = 135;\nconst THUMBNAIL_CACHE_MAX_BYTES = 512 * 1024 * 1024;\nconst THUMBNAIL_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000;\nconst prunedCacheDirs = new Set<string>();\n\nexport function pruneThumbnailCache(\n cacheDir: string,\n protectedPaths: ReadonlySet<string>,\n now = Date.now(),\n): void {\n let entries: Dirent[];\n try {\n entries = readdirSync(cacheDir, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n throw err;\n }\n const files = entries.flatMap((entry) => {\n if (!entry.isFile()) return [];\n const path = join(cacheDir, entry.name);\n try {\n const stats = statSync(path);\n return [{ path, bytes: stats.size, mtimeMs: stats.mtimeMs }];\n } catch {\n return [];\n }\n });\n const retained = [];\n for (const file of files) {\n if (!protectedPaths.has(file.path) && now - file.mtimeMs > THUMBNAIL_CACHE_MAX_AGE_MS) {\n rmSync(file.path, { force: true });\n } else {\n retained.push(file);\n }\n }\n\n let bytes = retained.reduce((total, file) => total + file.bytes, 0);\n for (const file of retained.sort((left, right) => left.mtimeMs - right.mtimeMs)) {\n if (bytes <= THUMBNAIL_CACHE_MAX_BYTES) break;\n if (protectedPaths.has(file.path)) continue;\n try {\n unlinkSync(file.path);\n bytes -= file.bytes;\n } catch {\n // Another request may have pruned the same file.\n }\n }\n}\n\nfunction writeThumbnailAtomically(path: string, buffer: Buffer): void {\n const temporaryPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeFileSync(temporaryPath, buffer, { flag: \"wx\" });\n renameSync(temporaryPath, path);\n } finally {\n rmSync(temporaryPath, { force: true });\n }\n}\n\ntype FileRead = { data: Buffer; mtimeMs: number } | \"missing\" | \"not-a-file\";\n\n// One open for the stat and the read, so the file cannot change between the check and the use.\nfunction readFileOnce(file: string): FileRead {\n let fd: number;\n try {\n fd = openSync(file, \"r\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return \"missing\";\n if (code === \"ENOTDIR\") return \"not-a-file\";\n throw err;\n }\n try {\n const stat = fstatSync(fd);\n if (!stat.isFile()) return \"not-a-file\";\n return { data: readFileSync(fd), mtimeMs: stat.mtimeMs };\n } finally {\n closeSync(fd);\n }\n}\n\nfunction manifestKey(file: string): { key: string; mtimeMs: number } {\n const manifest = readFileOnce(file);\n if (typeof manifest === \"string\") return { key: \"\", mtimeMs: -Infinity };\n const hash = createHash(\"sha1\").update(manifest.data).digest(\"hex\").slice(0, 16);\n return { key: `_${hash}`, mtimeMs: Math.round(manifest.mtimeMs) };\n}\n\nexport function registerThumbnailRoutes(api: Hono, adapter: StudioApiAdapter): void {\n api.get(\"/projects/:id/thumbnail/*\", async (c) => {\n if (!adapter.generateThumbnail) {\n return c.json({ error: \"Thumbnails not available\" }, 501);\n }\n const resolved = await resolveProjectAndSignature(adapter, c.req.param(\"id\"));\n if (!resolved) return c.json({ error: \"not found\" }, 404);\n const { project, signature: projectSignature } = resolved;\n\n let compPath = requestSubPath(c.req.url, \"projects/:id/thumbnail\");\n if (compPath && !compPath.includes(\".\")) compPath += \".html\";\n const htmlFile = resolveWithinProject(project.dir, compPath);\n const source = htmlFile ? readFileOnce(htmlFile) : \"not-a-file\";\n if (source === \"not-a-file\") return c.json({ error: \"not found\" }, 404);\n // Keyed on what this composition renders from, so editing one scene leaves the others cached.\n const inputSignature = compositionInputSignature(project.dir, compPath, projectSignature);\n\n const url = new URL(c.req.url, `http://${c.req.header(\"host\") || \"localhost\"}`);\n const rawSeekTime = url.searchParams.get(\"t\");\n const parsedSeekTime = rawSeekTime == null ? Number.NaN : parseFloat(rawSeekTime);\n const seekTime = Number.isFinite(parsedSeekTime) ? parsedSeekTime : 0.5;\n const vpWidth = parseInt(url.searchParams.get(\"w\") || \"0\") || 0;\n const vpHeight = parseInt(url.searchParams.get(\"h\") || \"0\") || 0;\n const selector = url.searchParams.get(\"selector\") || undefined;\n const format = url.searchParams.get(\"format\") === \"png\" ? \"png\" : \"jpeg\";\n const contentType = format === \"png\" ? \"image/png\" : \"image/jpeg\";\n const requestedOutput = url.searchParams.get(\"output\");\n // PNG is the legacy source-density capture contract. Callers can opt either\n // format into the bounded preview contract explicitly.\n const outputMode =\n requestedOutput === \"source\" || (requestedOutput !== \"preview\" && format === \"png\")\n ? \"source\"\n : \"preview\";\n const rawSelectorIndex = Number.parseInt(url.searchParams.get(\"selectorIndex\") || \"0\", 10);\n const selectorIndex =\n Number.isFinite(rawSelectorIndex) && rawSelectorIndex > 0 ? rawSelectorIndex : undefined;\n const urlVersion = url.searchParams.get(\"v\") || \"\";\n\n // Determine composition dimensions from HTML\n let compW = vpWidth || 1920;\n let compH = vpHeight || 1080;\n let sourceMtime = 0;\n // Content-hash the composition HTML into the cache key — ALWAYS, even when\n // explicit w/h are supplied. The old code only read the file when `!vpWidth`,\n // so Studio thumbnail requests (which pass dimensions) kept the source out of\n // the key entirely (sourceMtime=0) and served a stale thumbnail after every\n // edit, even on a hard reload. Keyed on content (like manualEdits/motion), not\n // just mtime, so a restore/copy with a preserved mtime can't serve stale.\n let sourceKey = \"\";\n if (source !== \"missing\") {\n const html = source.data.toString(\"utf-8\");\n sourceKey = `_${createHash(\"sha1\").update(html).digest(\"hex\").slice(0, 16)}`;\n sourceMtime = Math.round(source.mtimeMs);\n if (!vpWidth) {\n const wMatch = html.match(/data-width=[\"'](\\d+)[\"']/);\n const hMatch = html.match(/data-height=[\"'](\\d+)[\"']/);\n if (wMatch?.[1]) compW = parseInt(wMatch[1]);\n if (hMatch?.[1]) compH = parseInt(hMatch[1]);\n }\n }\n const manualEdits = manifestKey(join(project.dir, STUDIO_MANUAL_EDITS_PATH));\n const motion = manifestKey(join(project.dir, STUDIO_MOTION_PATH));\n sourceMtime = Math.max(sourceMtime, manualEdits.mtimeMs, motion.mtimeMs);\n\n const projectUrl = `http://${c.req.header(\"host\")}/api/projects/${encodeURIComponent(project.id)}`;\n const previewPath =\n compPath === \"index.html\"\n ? `${projectUrl}/preview`\n : `${projectUrl}/preview/comp/${compPath.split(\"/\").map(encodeURIComponent).join(\"/\")}`;\n const previewUrl = `${previewPath}?${PREVIEW_CAPTURE_PARAM}=1`;\n\n // Cache\n const cacheDir = join(project.dir, \".thumbnails\");\n const selectorKey = selector\n ? `_${createHash(\"sha1\").update(selector).digest(\"hex\").slice(0, 16)}_${selectorIndex ?? 0}`\n : \"\";\n const urlVersionKey = urlVersion\n ? `_${urlVersion.replace(/[^a-zA-Z0-9_-]+/g, \"_\").slice(0, 32)}`\n : \"\";\n const inputSignatureKey = `_${createHash(\"sha1\").update(inputSignature).digest(\"hex\").slice(0, 16)}`;\n const outputScale =\n outputMode === \"source\"\n ? 1\n : Math.min(1, THUMBNAIL_MAX_OUTPUT_WIDTH / compW, THUMBNAIL_MAX_OUTPUT_HEIGHT / compH);\n const outputWidth = Math.max(1, Math.round(compW * outputScale));\n const outputHeight = Math.max(1, Math.round(compH * outputScale));\n const cacheKey = `${THUMBNAIL_CACHE_VERSION}${urlVersionKey}${inputSignatureKey}${manualEdits.key}${motion.key}${sourceKey}_${format}_${outputMode}_${compPath.replace(/\\//g, \"_\")}_${compW}x${compH}_${outputWidth}x${outputHeight}_${sourceMtime}_${seekTime.toFixed(2)}${selectorKey}.${format === \"png\" ? \"png\" : \"jpg\"}`;\n const cachePath = join(cacheDir, cacheKey);\n if (!prunedCacheDirs.has(cacheDir)) {\n prunedCacheDirs.add(cacheDir);\n pruneThumbnailCache(\n cacheDir,\n new Set([...thumbnailGenerationCoordinator.protectedKeys(), cachePath]),\n );\n }\n const cached = readFileOnce(cachePath);\n if (typeof cached === \"object\") {\n return new Response(new Uint8Array(cached.data), {\n headers: { \"Content-Type\": contentType, \"Cache-Control\": \"no-cache\" },\n });\n }\n if (url.searchParams.get(\"cached\") === \"1\")\n return c.body(null, 204, { \"Cache-Control\": \"no-cache\" });\n\n try {\n const buffer = await thumbnailGenerationCoordinator.acquire(\n cachePath,\n c.req.raw.signal,\n async (signal) => {\n const previewCopiesAtStart = proxyActivityMark(project.dir);\n const generated = await adapter.generateThumbnail!({\n project,\n compPath,\n seekTime,\n width: compW,\n height: compH,\n outputWidth,\n outputHeight,\n previewUrl,\n selector,\n format,\n selectorIndex,\n signal,\n });\n if (!generated) return null;\n const previewCopiesAtEnd = proxyActivityMark(project.dir);\n const afterGeneration = await resolveProjectAndSignature(adapter, project.id);\n const inputsUnchanged = (signature: string) =>\n compositionInputSignature(project.dir, compPath, signature) === inputSignature;\n // Both the adapter's signature and a fresh one: the adapter's can lag the watcher.\n if (\n previewCopiesAtStart === null ||\n previewCopiesAtEnd !== previewCopiesAtStart ||\n afterGeneration?.project.dir !== project.dir ||\n !inputsUnchanged(afterGeneration.signature) ||\n !inputsUnchanged(createProjectSignature(project.dir))\n ) {\n // The browser may have rendered content written after this request\n // captured its cache identity. Return the pixels to this caller,\n // but never file them under a signature they do not prove.\n return generated;\n }\n mkdirWithinProject(project.dir, cacheDir);\n writeThumbnailAtomically(cachePath, generated);\n return generated;\n },\n );\n if (!buffer) {\n return c.json(\n { error: \"Thumbnail generation failed — Chrome browser may not be available\" },\n 500,\n );\n }\n pruneThumbnailCache(cacheDir, thumbnailGenerationCoordinator.protectedKeys());\n return new Response(new Uint8Array(buffer), {\n headers: { \"Content-Type\": contentType, \"Cache-Control\": \"no-cache\" },\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return new Response(null, { status: 499 });\n }\n if (isProjectRootMissing(err)) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n return c.json({ error: `Thumbnail generation failed: ${msg}` }, 500);\n }\n });\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { isWithinProjectRoot } from \"@hyperframes/parsers/asset-resolution\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport {\n decodeAudioPeaks,\n buildWaveformCacheKey,\n writeWaveformCache,\n isWaveformCacheDirectory,\n} from \"../helpers/waveform.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\n\nexport function registerWaveformRoutes(api: Hono, adapter: StudioApiAdapter): void {\n api.get(\"/projects/:id/waveform/*\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const assetPath = requestSubPath(c.req.url, \"projects/:id/waveform\");\n const audioPath = resolve(project.dir, assetPath);\n if (!isWithinProjectRoot(project.dir, audioPath)) {\n return c.json({ error: \"file not found\" }, 404);\n }\n const stats = statSync(audioPath, { throwIfNoEntry: false });\n if (!stats) return c.json({ error: \"file not found\" }, 404);\n\n const cacheDir = join(project.dir, \".waveform-cache\");\n // Keyed on the file's size and mtime as well as its name, so re-encoding an\n // asset in place invalidates its peaks instead of drawing the old ones.\n const cachePath = join(cacheDir, buildWaveformCacheKey(assetPath, stats));\n\n try {\n if (isWaveformCacheDirectory(cacheDir) && existsSync(cachePath)) {\n const peaks = JSON.parse(readFileSync(cachePath, \"utf-8\")) as number[];\n return c.json({ peaks });\n }\n } catch {\n // corrupt or inaccessible cache — regenerate\n }\n\n let peaks: number[];\n try {\n peaks = await decodeAudioPeaks(audioPath);\n } catch {\n return c.json({ error: \"failed to decode audio\" }, 500);\n }\n\n try {\n writeWaveformCache(cachePath, peaks);\n } catch {\n // cache write failure is non-fatal\n }\n\n return c.json({ peaks });\n });\n}\n","import { execFile } from \"node:child_process\";\nimport { readFileSync, rmSync, statSync } from \"node:fs\";\nimport { basename, dirname, join, relative, sep } from \"node:path\";\nimport type { Hono } from \"hono\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { mkdirWithinProject, pinWithinProject } from \"../helpers/safePath.js\";\nimport {\n atomicTempPath,\n createFileAtomically,\n replaceFileAtomically,\n} from \"@hyperframes/core/atomic-file\";\nimport { backupPathForResponse, snapshotBeforeWrite } from \"../helpers/backupJournal.js\";\nimport {\n createWriteToken,\n fileContentVersion,\n recordFileWriteReceipt,\n} from \"../helpers/fileVersion.js\";\nimport {\n applyFreezeFrameToHtml,\n freezeExtractArgs,\n freezeStillFileName,\n randomStillToken,\n readFreezeSource,\n type FreezeSource,\n} from \"../helpers/freezeFrame.js\";\nimport type { SourceMutationTarget } from \"../helpers/sourceMutation.js\";\n\nexport type FrameExtractor = (args: string[]) => Promise<{ ok: boolean; error?: string }>;\n\nconst EXTRACT_TIMEOUT_MS = 30_000;\n\nconst ffmpegExtractor: FrameExtractor = (args) => {\n const ffmpeg = findFfBinary(\"ffmpeg\", { configuredMustExist: true });\n if (!ffmpeg) return Promise.resolve({ ok: false, error: \"ffmpeg not found\" });\n return new Promise((resolvePromise) => {\n execFile(\n ffmpeg,\n args,\n { timeout: EXTRACT_TIMEOUT_MS, windowsHide: true },\n (error, _o, stderr) =>\n resolvePromise(\n error ? { ok: false, error: String(stderr || error.message) } : { ok: true },\n ),\n );\n });\n};\n\ninterface FreezeFrameRequest {\n path: string;\n expectedVersion: string;\n target: SourceMutationTarget;\n playhead: number;\n transactionToken?: string;\n}\n\nfunction isFreezeFrameRequest(value: unknown): value is FreezeFrameRequest {\n if (typeof value !== \"object\" || value === null) return false;\n const body: Partial<Record<keyof FreezeFrameRequest, unknown>> = value;\n return (\n typeof body.path === \"string\" &&\n body.path.length > 0 &&\n typeof body.expectedVersion === \"string\" &&\n typeof body.target === \"object\" &&\n body.target !== null &&\n typeof body.playhead === \"number\" &&\n Number.isFinite(body.playhead)\n );\n}\n\nconst FREEZE_DIR = [\"assets\", \"freeze\"];\n\ntype Failure = { error: string; status: 403 | 404 | 409 | 500 };\n\nfunction readExpected(absPath: string, expectedVersion: string): { content: string } | Failure {\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n return { error: \"not found\", status: 404 };\n }\n return fileContentVersion(content) === expectedVersion\n ? { content }\n : { error: \"file conflict\", status: 409 };\n}\n\nfunction readFrame(path: string): Buffer | null {\n try {\n return readFileSync(path);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n}\n\nfunction publishStill(path: string, frame: Buffer): boolean {\n try {\n createFileAtomically(path, frame);\n return true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") return false;\n throw error;\n }\n}\n\nasync function extractThenPublishWhole(\n extract: FrameExtractor,\n mediaPath: string,\n mediaTime: number,\n imagePath: string,\n): Promise<Failure | null> {\n const unseenByHistory = atomicTempPath(imagePath);\n try {\n const extracted = await extract(freezeExtractArgs(mediaPath, mediaTime, unseenByHistory));\n const frame = extracted.ok ? readFrame(unseenByHistory) : null;\n if (!frame?.length) {\n const reason = extracted.ok ? \"no frame at this time\" : (extracted.error ?? \"ffmpeg failed\");\n return { error: `Could not extract the frame: ${reason}`, status: 500 };\n }\n if (publishStill(imagePath, frame)) return null;\n return { error: `freeze still already exists: ${basename(imagePath)}`, status: 409 };\n } finally {\n rmSync(unseenByHistory, { force: true });\n }\n}\n\nasync function extractStill(\n projectDir: string,\n absPath: string,\n source: FreezeSource,\n playhead: number,\n tools: { extract: FrameExtractor; stillToken: () => string },\n): Promise<{ imageSrc: string; stillPath: string; imagePath: string } | Failure> {\n const fileDir = dirname(absPath);\n const mediaPath = pinWithinProject(projectDir, relative(projectDir, join(fileDir, source.src)));\n if (!mediaPath) return { error: `forbidden media path: ${source.src}`, status: 403 };\n const freezeDir = join(projectDir, ...FREEZE_DIR);\n const fileName = freezeStillFileName(source.id, playhead, tools.stillToken());\n mkdirWithinProject(projectDir, freezeDir);\n const imagePath = pinWithinProject(projectDir, join(...FREEZE_DIR, fileName));\n if (!imagePath || dirname(imagePath) !== freezeDir) {\n return { error: `forbidden freeze path: ${fileName}`, status: 403 };\n }\n const failed = await extractThenPublishWhole(\n tools.extract,\n mediaPath,\n source.mediaTime,\n imagePath,\n );\n if (failed) return failed;\n const depth = relative(projectDir, fileDir).split(sep).filter(Boolean).length;\n const stillPath = `${FREEZE_DIR.join(\"/\")}/${fileName}`;\n return { imageSrc: `${\"../\".repeat(depth)}${stillPath}`, stillPath, imagePath };\n}\n\nfunction writeFolded(\n projectDir: string,\n absPath: string,\n path: string,\n before: string,\n after: string,\n options: { token?: string },\n): { version: string; writeToken: string; backupPath: string | null } | Failure {\n if (readFileSync(absPath, \"utf-8\") !== before) {\n return { error: `file conflict: ${path}`, status: 409 };\n }\n const backup = snapshotBeforeWrite(projectDir, absPath);\n if (backup.error) return { error: `Failed to create backup: ${backup.error}`, status: 500 };\n const writeToken = createWriteToken(options.token);\n replaceFileAtomically(absPath, after, statSync(absPath).mode);\n const version = fileContentVersion(after);\n recordFileWriteReceipt(absPath, { path, version, writeToken, overwrote: before });\n return { version, writeToken, backupPath: backupPathForResponse(projectDir, backup.backupPath) };\n}\n\n/** POST: extract the frame under the playhead and fold split + still + shift into one file write. */\nexport function registerFreezeFrameRoutes(\n api: Hono,\n adapter: StudioApiAdapter,\n extract: FrameExtractor = ffmpegExtractor,\n stillToken: () => string = randomStillToken,\n): void {\n // A straight line of request guards, each its own early return.\n // fallow-ignore-next-line complexity\n api.post(\"/projects/:id/file-mutations/freeze-frame\", async (c) => {\n const body: unknown = await c.req.json().catch(() => null);\n if (!isFreezeFrameRequest(body)) {\n return c.json({ error: \"path, expectedVersion, target and playhead required\" }, 400);\n }\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const absPath = pinWithinProject(project.dir, body.path);\n if (!absPath) return c.json({ error: `forbidden path: ${body.path}` }, 403);\n\n const read = readExpected(absPath, body.expectedVersion);\n if (\"error\" in read) return c.json({ error: `${read.error}: ${body.path}` }, read.status);\n const before = read.content;\n\n const source = readFreezeSource(before, body.target, body.playhead);\n if (!source) return c.json({ error: \"Move the playhead inside a video clip to freeze\" }, 400);\n const still = await extractStill(project.dir, absPath, source, body.playhead, {\n extract,\n stillToken,\n });\n if (\"error\" in still) return c.json({ error: still.error }, still.status);\n const { imageSrc, stillPath, imagePath } = still;\n const folded = applyFreezeFrameToHtml(before, {\n target: body.target,\n playhead: body.playhead,\n imageSrc,\n });\n const failAndRemoveStill = (error: string, status: 400 | Failure[\"status\"]) => {\n rmSync(imagePath, { force: true });\n return c.json({ error }, status);\n };\n if (!folded) return failAndRemoveStill(\"Freeze target was not found in the file\", 400);\n const written = writeFolded(project.dir, absPath, body.path, before, folded.html, {\n token: body.transactionToken ?? c.req.header(\"X-Hyperframes-Write-Token\"),\n });\n if (\"error\" in written) return failAndRemoveStill(written.error, written.status);\n const { version, writeToken, backupPath } = written;\n return c.json({\n ok: true,\n path: body.path,\n before,\n after: folded.html,\n version,\n writeToken,\n backupPath,\n freezeId: folded.freezeId,\n imageSrc,\n stillPath,\n });\n });\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport { readMediaOffsetSeconds } from \"@hyperframes/parsers/media-duration\";\nimport { resolveRateSpec, sourceTimeAt } from \"@hyperframes/core/speed-ramp\";\nimport { MEDIA_LINK_ATTR as LINK_ATTR, relinkSplitHalves } from \"@hyperframes/core/media-link\";\nimport {\n findTargetElement,\n isHTMLElement,\n nextUniqueId,\n parseSourceDocument,\n splitElementInHtml,\n type SourceMutationTarget,\n} from \"./sourceMutation.js\";\n\nconst FREEZE_HOLD_SECONDS = 2;\nconst EPSILON = 1e-3;\n\nconst round3 = (value: number) => Math.round(value * 1000) / 1000;\n\nfunction numberAttr(el: Element, name: string): number | null {\n const raw = el.getAttribute(name);\n if (raw === null || raw.trim() === \"\") return null;\n const value = Number(raw);\n return Number.isFinite(value) ? value : null;\n}\n\nfunction trackOf(el: Element): number {\n return numberAttr(el, \"data-track-index\") ?? numberAttr(el, \"data-layer\") ?? 0;\n}\n\n/** Media seconds shown at `playhead`: the clip's in-point plus the source its rate (or rate lane) has consumed. */\nexport function freezeFrameMediaTime(input: {\n clipStart: number;\n playhead: number;\n mediaStart: number;\n playbackRate: number;\n automation: string | null;\n}): number {\n const rate = resolveRateSpec(input.automation, input.playbackRate);\n return input.mediaStart + sourceTimeAt(rate, Math.max(0, input.playhead - input.clipStart));\n}\n\nexport function freezeExtractArgs(src: string, mediaTime: number, output: string): string[] {\n return [\n \"-y\",\n \"-ss\",\n String(round3(mediaTime)),\n \"-i\",\n src,\n \"-frames:v\",\n \"1\",\n \"-c:v\",\n \"png\",\n \"-f\",\n \"image2\",\n \"-update\",\n \"1\",\n output,\n ];\n}\n\nexport const randomStillToken = (): string => randomBytes(4).toString(\"hex\");\n\nexport function freezeStillFileName(\n clipId: string,\n playhead: number,\n token: string = randomStillToken(),\n): string {\n const stem = clipId.replace(/[^A-Za-z0-9_-]/g, \"_\").slice(0, 48) || \"clip\";\n const idHash = createHash(\"sha256\").update(clipId).digest(\"hex\").slice(0, 10);\n return `${stem}-${idHash}-${Math.round(playhead * 1000)}-${token}.png`;\n}\n\nexport interface FreezeSource {\n id: string;\n src: string;\n mediaTime: number;\n}\n\n/** The video to freeze and the media time under the playhead, read from the source file. */\nexport function readFreezeSource(\n html: string,\n target: SourceMutationTarget,\n playhead: number,\n): FreezeSource | null {\n const { document } = parseSourceDocument(html);\n const el = findTargetElement(document, target);\n if (!el || el.tagName.toLowerCase() !== \"video\") return null;\n const src = el.getAttribute(\"src\");\n const start = numberAttr(el, \"data-start\");\n const duration = numberAttr(el, \"data-duration\");\n if (!src || start === null || duration === null) return null;\n if (playhead <= start + EPSILON || playhead >= start + duration - EPSILON) return null;\n return {\n id: el.getAttribute(\"id\") || \"clip\",\n src,\n mediaTime: freezeFrameMediaTime({\n clipStart: start,\n playhead,\n mediaStart: readMediaOffsetSeconds((name) => el.getAttribute(name)),\n playbackRate: numberAttr(el, \"data-playback-rate\") ?? 1,\n automation: el.getAttribute(\"data-automation\"),\n }),\n };\n}\n\nfunction targetOf(el: Element): SourceMutationTarget {\n const hfId = el.getAttribute(\"data-hf-id\");\n return { ...(hfId ? { hfId } : {}), id: el.getAttribute(\"id\") };\n}\n\nfunction spans(el: Element, time: number): boolean {\n const start = numberAttr(el, \"data-start\");\n const duration = numberAttr(el, \"data-duration\");\n if (start === null || duration === null) return false;\n return time > start + EPSILON && time < start + duration - EPSILON;\n}\n\nfunction shiftTracks(document: Document, tracks: Set<number>, from: number, by: number): void {\n for (const el of document.querySelectorAll(\"[data-start]\")) {\n if (el.hasAttribute(\"data-composition-id\") || !tracks.has(trackOf(el))) continue;\n const start = numberAttr(el, \"data-start\");\n if (start === null || start < from - EPSILON) continue;\n el.setAttribute(\"data-start\", String(round3(start + by)));\n }\n}\n\nfunction growRootToFit(document: Document): void {\n const root = document.querySelector(\"[data-composition-id]\");\n const rootDuration = root ? numberAttr(root, \"data-duration\") : null;\n if (!root || rootDuration === null) return;\n let end = rootDuration;\n for (const el of root.querySelectorAll(\"[data-start][data-duration]\")) {\n const start = numberAttr(el, \"data-start\");\n const duration = numberAttr(el, \"data-duration\");\n if (start !== null && duration !== null) end = Math.max(end, start + duration);\n }\n if (end > rootDuration + EPSILON) root.setAttribute(\"data-duration\", String(round3(end)));\n}\n\nconst COPIED_PICTURE_ATTRS = [\"class\", \"style\", \"data-color-grading\"];\n\nfunction buildStill(\n document: Document,\n video: Element,\n input: { id: string; imageSrc: string; playhead: number; holdSeconds: number },\n): Element {\n const img = document.createElement(\"img\");\n img.setAttribute(\"id\", input.id);\n for (const name of COPIED_PICTURE_ATTRS) {\n const value = video.getAttribute(name);\n if (value !== null) img.setAttribute(name, value);\n }\n if (!img.classList.contains(\"clip\")) img.classList.add(\"clip\");\n img.setAttribute(\"src\", input.imageSrc);\n img.setAttribute(\"alt\", \"\");\n img.setAttribute(\"data-start\", String(round3(input.playhead)));\n img.setAttribute(\"data-duration\", String(input.holdSeconds));\n img.setAttribute(\"data-track-index\", String(trackOf(video)));\n img.setAttribute(\"data-timeline-label\", \"Freeze\");\n return img;\n}\n\nexport interface FreezeFrameResult {\n html: string;\n freezeId: string;\n}\n\n/**\n * Split the video at the playhead, put a still of that frame in the gap and push the rest of its\n * track (and a linked partner's, which is split too and left silent for the hold) right by the hold.\n */\nfunction linkedPartners(document: Document, video: Element): Element[] {\n const link = video.getAttribute(LINK_ATTR);\n if (!link) return [];\n return Array.from(document.querySelectorAll(`[${LINK_ATTR}]`)).filter(\n (el) => el !== video && el.getAttribute(LINK_ATTR) === link,\n );\n}\n\n/** Split every element at `time`, in order; the new right halves' ids, or null if one missed. */\nfunction splitAll(\n html: string,\n elements: readonly Element[],\n time: number,\n): { html: string; rightHalfIds: string[] } | null {\n const rightHalfIds: string[] = [];\n let next = html;\n for (const el of elements) {\n const split = splitElementInHtml(\n next,\n targetOf(el),\n time,\n `${el.getAttribute(\"id\") || \"clip\"}-split`,\n {\n start: numberAttr(el, \"data-start\") ?? 0,\n duration: numberAttr(el, \"data-duration\") ?? 0,\n track: trackOf(el),\n },\n );\n if (!split.matched || !split.newId) return null;\n next = split.html;\n rightHalfIds.push(split.newId);\n }\n return { html: next, rightHalfIds };\n}\n\n/**\n * Split the video at the playhead, put a still of that frame in the gap and push the rest of its\n * track (and a linked partner's, which is split too and left silent for the hold) right by the hold.\n */\nexport function applyFreezeFrameToHtml(\n html: string,\n input: {\n target: SourceMutationTarget;\n playhead: number;\n imageSrc: string;\n holdSeconds?: number;\n },\n): FreezeFrameResult | null {\n const hold = input.holdSeconds ?? FREEZE_HOLD_SECONDS;\n const { document: before } = parseSourceDocument(html);\n const video = findTargetElement(before, input.target);\n if (!video || !isHTMLElement(video) || !spans(video, input.playhead)) return null;\n const partners = linkedPartners(before, video);\n const tracks = new Set([trackOf(video), ...partners.map(trackOf)]);\n const cut = splitAll(\n html,\n [video, ...partners.filter((el) => spans(el, input.playhead))],\n input.playhead,\n );\n if (!cut) return null;\n\n const { document, wrappedFragment } = parseSourceDocument(cut.html);\n relinkSplitHalves(document, cut.rightHalfIds);\n shiftTracks(document, tracks, input.playhead, hold);\n const leftHalf = findTargetElement(document, input.target);\n if (!leftHalf?.parentElement) return null;\n const freezeId = nextUniqueId(document, `${video.getAttribute(\"id\") || \"clip\"}-freeze`);\n const still = buildStill(document, leftHalf, {\n id: freezeId,\n imageSrc: input.imageSrc,\n playhead: input.playhead,\n holdSeconds: hold,\n });\n leftHalf.parentElement.insertBefore(still, leftHalf.nextSibling);\n growRootToFit(document);\n return {\n html: ensureHfIds(wrappedFragment ? document.body.innerHTML || \"\" : document.toString()),\n freezeId,\n };\n}\n","import { existsSync } from \"node:fs\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport {\n absoluteLoudnessPlan,\n DEFAULT_TARGET_LUFS,\n measureAudio,\n requiredFfmpeg,\n resolveLocalAudioPath,\n type LoudnessMeasurement,\n type MeasuredWindow,\n} from \"../helpers/loudness.js\";\n\nexport type MeasureLoudness = (\n file: string,\n window: MeasuredWindow,\n) => Promise<LoudnessMeasurement>;\n\ninterface NormalizeRequest {\n id: string;\n src: string;\n window: MeasuredWindow;\n volume: number;\n targetLufs: number;\n}\n\nconst defaultMeasure: MeasureLoudness = (file, window) =>\n measureAudio(requiredFfmpeg(), file, window);\n\nclass InvalidField extends Error {}\n\nfunction numberField(\n body: Record<string, unknown>,\n name: string,\n fallback: number,\n valid: (value: number) => boolean,\n): number {\n const raw = body[name];\n if (raw === undefined || raw === null) return fallback;\n if (typeof raw === \"number\" && Number.isFinite(raw) && valid(raw)) return raw;\n throw new InvalidField(`${name} is out of range`);\n}\n\nfunction readNormalizeRequest(body: Record<string, unknown>): NormalizeRequest {\n const src = typeof body.src === \"string\" ? body.src.trim() : \"\";\n if (!src) throw new InvalidField(\"src is required\");\n const duration = numberField(body, \"duration\", 0, (v) => v > 0);\n return {\n id: typeof body.id === \"string\" && body.id ? body.id : src,\n src,\n window: {\n mediaStart: numberField(body, \"mediaStart\", 0, (v) => v >= 0),\n duration: duration > 0 ? duration : null,\n playbackRate: numberField(body, \"playbackRate\", 1, (v) => v > 0),\n },\n volume: numberField(body, \"volume\", 1, (v) => v >= 0),\n targetLufs: numberField(body, \"targetLufs\", DEFAULT_TARGET_LUFS, (v) => v < 0),\n };\n}\n\nfunction parseNormalizeRequest(body: Record<string, unknown>): NormalizeRequest | string {\n try {\n return readNormalizeRequest(body);\n } catch (error) {\n if (error instanceof InvalidField) return error.message;\n throw error;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Measure one clip's played window and answer the `data-volume` that brings it\n * to the target. Measure-only: Studio writes the attribute through its own\n * edit path so the change is one undo step like any other.\n */\nexport function registerLoudnessRoutes(\n api: Hono,\n adapter: StudioApiAdapter,\n measure: MeasureLoudness = defaultMeasure,\n): void {\n api.post(\"/projects/:id/loudness/normalize\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const body: unknown = await c.req.json().catch(() => null);\n if (!isRecord(body)) return c.json({ error: \"invalid body\" }, 400);\n const request = parseNormalizeRequest(body);\n if (typeof request === \"string\") return c.json({ error: request }, 400);\n\n let file: string;\n try {\n file = resolveLocalAudioPath(project.dir, request.src);\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);\n }\n if (!existsSync(file)) return c.json({ error: \"file not found\" }, 404);\n\n try {\n const measurement = await measure(file, request.window);\n const plan = absoluteLoudnessPlan(\n { id: request.id, volume: request.volume, ...measurement },\n request.targetLufs,\n );\n return c.json({ plan });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 422);\n }\n });\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { isWithinProjectRoot } from \"@hyperframes/parsers/asset-resolution\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isWaveformCacheDirectory, writeWaveformCache } from \"../helpers/waveform.js\";\nimport { buildPeakMapCacheKey, decodePeakMap, PEAK_BIN_SECONDS } from \"../helpers/peakMap.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\n\ntype DecodePeaks = (mediaPath: string) => Promise<number[]>;\n\nconst decodesInFlight = new Map<string, Promise<number[]>>();\n\nfunction decodeOnce(cachePath: string, mediaPath: string, decode: DecodePeaks): Promise<number[]> {\n const pending = decodesInFlight.get(cachePath);\n if (pending) return pending;\n const started = decode(mediaPath).finally(() => decodesInFlight.delete(cachePath));\n decodesInFlight.set(cachePath, started);\n return started;\n}\n\nfunction readCachedBins(cacheDir: string, cachePath: string): number[] | null {\n try {\n if (!isWaveformCacheDirectory(cacheDir) || !existsSync(cachePath)) return null;\n const parsed: unknown = JSON.parse(readFileSync(cachePath, \"utf-8\"));\n return Array.isArray(parsed) && parsed.every((n) => typeof n === \"number\") ? parsed : null;\n } catch {\n return null;\n }\n}\n\n/** Absolute per-bin sample peaks for one media file, so the timeline can mark where a clip redlines. */\nexport function registerPeakRoutes(\n api: Hono,\n adapter: StudioApiAdapter,\n decode: DecodePeaks = decodePeakMap,\n): void {\n api.get(\"/projects/:id/peaks/*\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const assetPath = requestSubPath(c.req.url, \"projects/:id/peaks\");\n const mediaPath = resolve(project.dir, assetPath);\n if (!isWithinProjectRoot(project.dir, mediaPath))\n return c.json({ error: \"file not found\" }, 404);\n const stats = statSync(mediaPath, { throwIfNoEntry: false });\n if (!stats?.isFile()) return c.json({ error: \"file not found\" }, 404);\n\n const cacheDir = join(project.dir, \".waveform-cache\");\n const cachePath = join(cacheDir, buildPeakMapCacheKey(assetPath, stats));\n const cached = readCachedBins(cacheDir, cachePath);\n if (cached) return c.json({ binSeconds: PEAK_BIN_SECONDS, bins: cached });\n\n let bins: number[];\n try {\n bins = await decodeOnce(cachePath, mediaPath, decode);\n } catch {\n return c.json({ error: \"failed to decode audio\" }, 500);\n }\n try {\n writeWaveformCache(cachePath, bins);\n } catch {\n // A cache that cannot be written only costs the next request a decode.\n }\n return c.json({ binSeconds: PEAK_BIN_SECONDS, bins });\n });\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\n\nexport const PEAK_BIN_SECONDS = 0.05;\nconst PEAK_SAMPLE_RATE = 48_000;\nconst execFileAsync = promisify(execFile);\nconst PEAK_MAP_CACHE_VERSION = \"peaks-v2\";\n\n/**\n * Running max-abs per bin over interleaved f32le at the source's own channel\n * count. Native channels, not `-ac 2`: ffmpeg's mono upmix pans at -3 dB,\n * which would hide a clip that really does reach 0 dBFS.\n */\nexport interface PeakAccumulator {\n bins: number[];\n frame: number;\n carry: Buffer;\n framesPerBin: number;\n channels: number;\n}\n\nexport function createPeakAccumulator(\n sampleRate = PEAK_SAMPLE_RATE,\n binSeconds = PEAK_BIN_SECONDS,\n channels = 2,\n): PeakAccumulator {\n return {\n bins: [],\n frame: 0,\n carry: Buffer.alloc(0),\n framesPerBin: Math.max(1, Math.round(sampleRate * binSeconds)),\n channels: Math.max(1, channels),\n };\n}\n\nfunction framePeak(data: Buffer, offset: number, channels: number): number {\n let peak = 0;\n for (let ch = 0; ch < channels; ch++) {\n peak = Math.max(peak, Math.abs(data.readFloatLE(offset + ch * 4)));\n }\n return peak;\n}\n\nexport function accumulatePeaks(acc: PeakAccumulator, chunk: Buffer): void {\n const data = acc.carry.length > 0 ? Buffer.concat([acc.carry, chunk]) : chunk;\n const frameBytes = 4 * acc.channels;\n const whole = data.length - (data.length % frameBytes);\n for (let offset = 0; offset < whole; offset += frameBytes) {\n const peak = framePeak(data, offset, acc.channels);\n const bin = Math.floor(acc.frame / acc.framesPerBin);\n if (acc.bins.length <= bin) acc.bins.push(0);\n if (peak > (acc.bins[bin] ?? 0)) acc.bins[bin] = peak;\n acc.frame += 1;\n }\n acc.carry = Buffer.from(data.subarray(whole));\n}\n\n/** Linear sample peak per bin, NOT normalized — the level is the point. */\nexport function finishPeaks(acc: PeakAccumulator): number[] {\n return acc.bins.map((peak) => Number(peak.toFixed(4)));\n}\n\nasync function probeChannels(mediaPath: string): Promise<number> {\n const { stdout } = await execFileAsync(\n findFfBinary(\"ffprobe\") ?? \"ffprobe\",\n [\n \"-v\",\n \"error\",\n \"-select_streams\",\n \"a:0\",\n \"-show_entries\",\n \"stream=channels\",\n \"-of\",\n \"csv=p=0\",\n \"--\",\n mediaPath,\n ],\n { encoding: \"utf8\", timeout: 30_000, windowsHide: true },\n );\n const channels = Number.parseInt(stdout.trim(), 10);\n if (!Number.isFinite(channels) || channels < 1) throw new Error(\"no audio stream\");\n return channels;\n}\n\nexport async function decodePeakMap(mediaPath: string): Promise<number[]> {\n const channels = await probeChannels(mediaPath);\n return new Promise((resolvePromise, reject) => {\n const proc = spawn(\n findFfBinary(\"ffmpeg\") ?? \"ffmpeg\",\n [\n \"-v\",\n \"error\",\n \"-i\",\n mediaPath,\n \"-map\",\n \"0:a:0\",\n \"-vn\",\n \"-ar\",\n String(PEAK_SAMPLE_RATE),\n \"-f\",\n \"f32le\",\n \"pipe:1\",\n ],\n { stdio: [\"ignore\", \"pipe\", \"ignore\"], windowsHide: true },\n );\n const acc = createPeakAccumulator(PEAK_SAMPLE_RATE, PEAK_BIN_SECONDS, channels);\n proc.stdout?.on(\"data\", (chunk: Buffer) => accumulatePeaks(acc, chunk));\n proc.on(\"close\", (code) => {\n if (code !== 0) {\n reject(new Error(`ffmpeg failed decoding audio (exit ${code})`));\n return;\n }\n if (acc.frame === 0) {\n reject(new Error(\"ffmpeg produced no audio samples\"));\n return;\n }\n resolvePromise(finishPeaks(acc));\n });\n proc.on(\"error\", reject);\n });\n}\n\n/** Keyed on content (size + mtime) like the waveform cache, under its own version prefix. */\nexport function buildPeakMapCacheKey(\n assetPath: string,\n fingerprint: { size: number; mtimeMs: number },\n): string {\n const name = assetPath.replace(/[/\\\\]/g, \"_\");\n return `${PEAK_MAP_CACHE_VERSION}_${name}_${fingerprint.size}-${Math.round(fingerprint.mtimeMs)}.json`;\n}\n","import { closeSync, constants, fstatSync, openSync, readSync } from \"node:fs\";\nimport type { Hono } from \"hono\";\nimport {\n collectFontFileEntries,\n fontDirectories,\n getSystemProfilerFamilies,\n locateSystemFont,\n SYSTEM_FONT_SIZE_LIMIT,\n} from \"@hyperframes/core/fonts/system-locator\";\n\nconst MAX_FONT_RESULTS = 2000;\nconst GOOGLE_FONTS_METADATA_URL = \"https://fonts.google.com/metadata/fonts\";\nconst GOOGLE_FONTS_FETCH_TIMEOUT_MS = 3000;\nlet cachedFonts: string[] | null = null;\nlet cachedGoogleFonts: string[] | null = null;\n\nconst GOOGLE_FONT_FALLBACKS = [\n \"Inter\",\n \"Roboto\",\n \"Open Sans\",\n \"Montserrat\",\n \"Poppins\",\n \"Lato\",\n \"Oswald\",\n \"Raleway\",\n \"Nunito\",\n \"Playfair Display\",\n \"Merriweather\",\n \"Source Sans 3\",\n \"Source Serif 4\",\n \"Source Code Pro\",\n \"DM Sans\",\n \"Space Grotesk\",\n \"Space Mono\",\n \"Bebas Neue\",\n \"Outfit\",\n \"JetBrains Mono\",\n];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction collectFontsFromDir(dir: string): string[] {\n return collectFontFileEntries(dir).map((e) => e.family);\n}\n\nfunction listInstalledFontFamilies(): string[] {\n if (cachedFonts) return cachedFonts;\n const families = new Set<string>();\n\n for (const family of getSystemProfilerFamilies()) {\n families.add(family);\n if (families.size >= MAX_FONT_RESULTS) break;\n }\n\n for (const dir of fontDirectories()) {\n for (const family of collectFontsFromDir(dir)) {\n families.add(family);\n if (families.size >= MAX_FONT_RESULTS) break;\n }\n if (families.size >= MAX_FONT_RESULTS) break;\n }\n\n cachedFonts = Array.from(families).sort((a, b) => a.localeCompare(b));\n return cachedFonts;\n}\n\nfunction parseGoogleFontMetadata(value: unknown): string[] {\n if (!isRecord(value) || !Array.isArray(value.familyMetadataList)) return [];\n const families: string[] = [];\n for (const entry of value.familyMetadataList) {\n if (!isRecord(entry) || typeof entry.family !== \"string\") continue;\n families.push(entry.family);\n }\n return families;\n}\n\nfunction stripGoogleJsonGuard(raw: string): string {\n const prefix = \")]}'\";\n if (!raw.startsWith(prefix)) return raw;\n\n let index = prefix.length;\n while (\n index < raw.length &&\n (raw[index] === \" \" ||\n raw[index] === \"\\n\" ||\n raw[index] === \"\\r\" ||\n raw[index] === \"\\t\" ||\n raw[index] === \"\\f\")\n ) {\n index += 1;\n }\n\n return raw.slice(index);\n}\n\nasync function listGoogleFontFamilies(): Promise<string[]> {\n if (cachedGoogleFonts) return cachedGoogleFonts;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), GOOGLE_FONTS_FETCH_TIMEOUT_MS);\n\n try {\n const response = await fetch(GOOGLE_FONTS_METADATA_URL, { signal: controller.signal });\n if (!response.ok) {\n cachedGoogleFonts = GOOGLE_FONT_FALLBACKS;\n return cachedGoogleFonts;\n }\n const raw = await response.text();\n const jsonText = stripGoogleJsonGuard(raw);\n const families = parseGoogleFontMetadata(JSON.parse(jsonText));\n cachedGoogleFonts = families.length > 0 ? families : GOOGLE_FONT_FALLBACKS;\n } catch {\n cachedGoogleFonts = GOOGLE_FONT_FALLBACKS;\n } finally {\n clearTimeout(timer);\n }\n\n return cachedGoogleFonts;\n}\n\nexport function registerFontRoutes(api: Hono): void {\n api.get(\"/fonts\", (c) => c.json({ fonts: listInstalledFontFamilies() }));\n api.get(\"/fonts/google\", async (c) => c.json({ fonts: await listGoogleFontFamilies() }));\n\n // fallow-ignore-next-line complexity\n api.get(\"/fonts/file\", (c) => {\n const family = c.req.query(\"family\");\n if (!family) return c.json({ error: \"family parameter required\" }, 400);\n\n const located = locateSystemFont(family);\n if (!located) return c.json({ error: \"font not found\" }, 404);\n\n let fd: number;\n try {\n fd = openSync(located.path, constants.O_RDONLY | constants.O_NOFOLLOW);\n } catch {\n return c.json({ error: \"font file not accessible\" }, 404);\n }\n try {\n const stat = fstatSync(fd);\n if (stat.size > SYSTEM_FONT_SIZE_LIMIT) {\n return c.json({ error: \"font file too large\" }, 413);\n }\n const buffer = Buffer.alloc(stat.size);\n readSync(fd, buffer, 0, stat.size, 0);\n const mimeType =\n located.format === \"otf\"\n ? \"font/otf\"\n : located.format === \"woff2\"\n ? \"font/woff2\"\n : located.format === \"woff\"\n ? \"font/woff\"\n : located.format === \"ttc\"\n ? \"font/collection\"\n : \"font/ttf\";\n\n const fileName = `${family.replace(/[^a-zA-Z0-9 -]/g, \"\")}.${located.format}`;\n return new Response(buffer, {\n headers: {\n \"Content-Type\": mimeType,\n \"Content-Disposition\": `attachment; filename=\"${fileName}\"`,\n },\n });\n } catch {\n return c.json({ error: \"failed to read font file\" }, 500);\n } finally {\n closeSync(fd);\n }\n });\n}\n","import type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { projectDirMissing } from \"../helpers/projectDirMissing.js\";\nimport { folderGone, isProjectRootMissing } from \"../helpers/safePath.js\";\n\nexport function registerRegistryRoutes(api: Hono, adapter: StudioApiAdapter): void {\n api.get(\"/registry/blocks\", async (c) => {\n if (!adapter.listRegistryCatalog) {\n return c.json({ error: \"Registry not available\" }, 501);\n }\n const items = await adapter.listRegistryCatalog();\n return c.json(items);\n });\n\n // fallow-ignore-next-line complexity\n api.post(\"/projects/:id/registry/install\", async (c) => {\n if (!adapter.installRegistryBlock) {\n return c.json({ error: \"Installing catalog items needs hyperframes preview\" }, 501);\n }\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"Project not found\" }, 404);\n if (folderGone(project.dir)) return projectDirMissing(c);\n\n const body = await c.req.json<{ blockName?: string }>().catch(() => null);\n if (!body?.blockName) {\n return c.json({ error: \"blockName is required\" }, 400);\n }\n\n try {\n const result = await adapter.installRegistryBlock({ project, blockName: body.blockName });\n return c.json(result);\n } catch (err) {\n if (isProjectRootMissing(err)) return projectDirMissing(c);\n const message = err instanceof Error ? err.message : \"Install failed\";\n return c.json({ error: message }, 500);\n }\n });\n}\n","import type { Hono } from \"hono\";\nimport type {\n StudioApiAdapter,\n StudioSelectionResponse,\n StudioSelectionSnapshot,\n} from \"../types.js\";\n\ninterface StoredSelection {\n selection: StudioSelectionSnapshot;\n updatedAt: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return isRecord(value) && Object.values(value).every((v) => typeof v === \"string\");\n}\n\nfunction hasString(value: Record<string, unknown>, key: string): boolean {\n return typeof value[key] === \"string\";\n}\n\nfunction hasRequiredStrings(value: Record<string, unknown>, keys: string[]): boolean {\n return keys.every((key) => hasString(value, key));\n}\n\nfunction hasOptionalString(value: Record<string, unknown>, key: string): boolean {\n return value[key] === undefined || typeof value[key] === \"string\";\n}\n\nfunction hasOptionalNullableString(value: Record<string, unknown>, key: string): boolean {\n return value[key] == null || typeof value[key] === \"string\";\n}\n\nfunction hasOptionalNumber(value: Record<string, unknown>, key: string): boolean {\n return value[key] === undefined || isFiniteNumber(value[key]);\n}\n\nfunction isBoundingBox(value: unknown): value is StudioSelectionSnapshot[\"boundingBox\"] {\n return (\n isRecord(value) && [\"x\", \"y\", \"width\", \"height\"].every((key) => isFiniteNumber(value[key]))\n );\n}\n\nfunction isTarget(value: unknown): value is StudioSelectionSnapshot[\"target\"] {\n if (!isRecord(value)) return false;\n return (\n hasOptionalNullableString(value, \"id\") &&\n hasOptionalString(value, \"hfId\") &&\n hasOptionalString(value, \"selector\") &&\n hasOptionalNumber(value, \"selectorIndex\")\n );\n}\n\nfunction isTextField(value: unknown): value is StudioSelectionSnapshot[\"textFields\"][number] {\n return (\n isRecord(value) &&\n hasRequiredStrings(value, [\"key\", \"label\", \"value\", \"tagName\"]) &&\n [\"self\", \"child\", \"text-node\"].includes(value.source as string)\n );\n}\n\nfunction isTextFields(value: unknown): value is StudioSelectionSnapshot[\"textFields\"] {\n return Array.isArray(value) && value.every(isTextField);\n}\n\nfunction isSelectionSnapshot(value: unknown): value is StudioSelectionSnapshot {\n if (!isRecord(value)) return false;\n\n const checks = [\n value.schemaVersion === 1 &&\n hasRequiredStrings(value, [\n \"projectId\",\n \"compositionPath\",\n \"sourceFile\",\n \"label\",\n \"tagName\",\n \"thumbnailUrl\",\n ]),\n isFiniteNumber(value.currentTime),\n isTarget(value.target),\n isBoundingBox(value.boundingBox),\n value.textContent === null || typeof value.textContent === \"string\",\n isStringRecord(value.dataAttributes),\n isStringRecord(value.inlineStyles),\n isStringRecord(value.computedStyles),\n isTextFields(value.textFields),\n isRecord(value.capabilities),\n ];\n\n return checks.every(Boolean);\n}\n\nexport function registerSelectionRoutes(api: Hono, adapter: StudioApiAdapter): void {\n const selections = new Map<string, StoredSelection>();\n\n api.get(\"/projects/:id/selection\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const stored = selections.get(project.id);\n return c.json({\n selection: stored?.selection ?? null,\n updatedAt: stored?.updatedAt ?? null,\n } satisfies StudioSelectionResponse);\n });\n\n api.put(\"/projects/:id/selection\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"invalid json\" }, 400);\n }\n if (!isRecord(body) || !(\"selection\" in body)) {\n return c.json({ error: \"missing selection\" }, 400);\n }\n\n if (body.selection === null) {\n selections.delete(project.id);\n return c.json({ ok: true, selection: null, updatedAt: null });\n }\n\n if (!isSelectionSnapshot(body.selection)) {\n return c.json({ error: \"invalid selection\" }, 400);\n }\n\n const selection = { ...body.selection, projectId: project.id };\n const updatedAt = new Date().toISOString();\n selections.set(project.id, { selection, updatedAt });\n return c.json({ ok: true, selection, updatedAt });\n });\n}\n","import type { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport { existsSync } from \"node:fs\";\nimport { basename, dirname, extname, join, posix } from \"node:path\";\nimport type { MediaProcessingJobState, StudioApiAdapter } from \"../types.js\";\nimport { mkdirWithinProject, pinWithinProject, resolveWithinProject } from \"../helpers/safePath.js\";\nimport { probeMediaMetadata } from \"../helpers/mediaMetadata.js\";\n\nconst VIDEO_EXTENSIONS = new Set([\n \".mp4\",\n \".mov\",\n \".webm\",\n \".mkv\",\n \".avi\",\n \".m4v\",\n \".mxf\",\n \".mts\",\n \".m2ts\",\n \".ts\",\n]);\nconst IMAGE_EXTENSIONS = new Set([\".jpg\", \".jpeg\", \".png\", \".webp\"]);\nconst VIDEO_OUTPUT_EXTENSIONS = new Set([\".webm\", \".mov\"]);\nconst QUALITIES = new Set([\"fast\", \"balanced\", \"best\"]);\nconst DEVICES = new Set([\"auto\", \"cpu\", \"coreml\", \"cuda\"]);\n\ntype BackgroundRemovalQuality = \"fast\" | \"balanced\" | \"best\";\ntype BackgroundRemovalDevice = \"auto\" | \"cpu\" | \"coreml\" | \"cuda\";\n\ninterface BackgroundRemovalBody {\n inputPath?: string;\n outputPath?: string;\n createBackgroundPlate?: boolean;\n quality?: string;\n device?: string;\n}\n\ntype JobWithCreatedAt = MediaProcessingJobState & { createdAt: number };\ntype ProbeMediaMetadata = typeof probeMediaMetadata;\n\nfunction isVideoPath(path: string): boolean {\n return VIDEO_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\nfunction isImagePath(path: string): boolean {\n return IMAGE_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\nfunction normalizeProjectAssetPath(path: string): string {\n return path\n .trim()\n .replace(/^[.]\\//, \"\")\n .replace(/[?#].*$/, \"\");\n}\n\nfunction containsNullByte(path: string): boolean {\n return path.includes(\"\\0\");\n}\n\nfunction slugFileBase(path: string): string {\n const name = basename(path, extname(path))\n .replace(/[^a-zA-Z0-9._-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return name || \"media\";\n}\n\nfunction uniqueAssetPath(\n projectDir: string,\n assetPath: string,\n taken: ReadonlySet<string>,\n): string {\n const ext = extname(assetPath);\n const withoutExt = assetPath.slice(0, -ext.length);\n let candidate = assetPath;\n for (let index = 2; taken.has(candidate) || existsSync(join(projectDir, candidate)); index++) {\n candidate = `${withoutExt}-${index}${ext}`;\n }\n return candidate;\n}\n\nfunction defaultOutputPath(\n projectDir: string,\n inputPath: string,\n taken: ReadonlySet<string>,\n): string {\n const ext = isImagePath(inputPath) ? \".png\" : \".webm\";\n return uniqueAssetPath(\n projectDir,\n `assets/cutouts/${slugFileBase(inputPath)}-cutout${ext}`,\n taken,\n );\n}\n\nfunction defaultPlatePath(\n projectDir: string,\n inputPath: string,\n taken: ReadonlySet<string>,\n): string {\n return uniqueAssetPath(projectDir, `assets/cutouts/${slugFileBase(inputPath)}-plate.webm`, taken);\n}\n\nfunction outputsInFlight(mediaJobs: Map<string, JobWithCreatedAt>): Set<string> {\n const running = [...mediaJobs.values()].filter((job) => job.status === \"processing\");\n return new Set(\n running.flatMap((job) => [job.outputAssetPath, job.backgroundOutputAssetPath ?? \"\"]),\n );\n}\n\nfunction makeJobId(projectId: string, mediaJobs: Map<string, JobWithCreatedAt>): string {\n const stamp = new Date()\n .toISOString()\n .replace(/[-:.TZ]/g, \"\")\n .slice(0, 14);\n const safeProject = projectId.replace(/[^a-zA-Z0-9_-]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n const base = `${safeProject || \"project\"}_remove-bg_${stamp}`;\n if (!mediaJobs.has(base)) return base;\n for (let index = 2; ; index++) {\n const candidate = `${base}-${index}`;\n if (!mediaJobs.has(candidate)) return candidate;\n }\n}\n\nfunction normalizeQuality(value: string | undefined): BackgroundRemovalQuality {\n return QUALITIES.has(value ?? \"\") ? (value as BackgroundRemovalQuality) : \"balanced\";\n}\n\nfunction normalizeDevice(value: string | undefined): BackgroundRemovalDevice {\n return DEVICES.has(value ?? \"\") ? (value as BackgroundRemovalDevice) : \"auto\";\n}\n\nexport function registerMediaRoutes(\n api: Hono,\n adapter: StudioApiAdapter,\n options: { probeMediaMetadata?: ProbeMediaMetadata } = {},\n): void {\n const mediaJobs = new Map<string, JobWithCreatedAt>();\n const TTL_MS = 300_000;\n const readMediaMetadata = options.probeMediaMetadata ?? probeMediaMetadata;\n\n function cleanupFinishedJobs(): void {\n const now = Date.now();\n for (const [id, job] of mediaJobs) {\n if ((job.status === \"complete\" || job.status === \"failed\") && now - job.createdAt > TTL_MS) {\n mediaJobs.delete(id);\n }\n }\n }\n\n api.get(\"/projects/:id/media/metadata\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const assetPath = normalizeProjectAssetPath(c.req.query(\"path\") ?? \"\");\n if (!assetPath) return c.json({ error: \"path required\" }, 400);\n if (containsNullByte(assetPath)) return c.json({ error: \"forbidden\" }, 403);\n if (/^(?:https?:|data:|blob:)/i.test(assetPath)) {\n return c.json({ error: \"media metadata requires a project-local asset\" }, 400);\n }\n\n const filePath = resolveWithinProject(project.dir, assetPath);\n if (!filePath) return c.json({ error: \"forbidden\" }, 403);\n if (!existsSync(filePath)) return c.json({ error: \"media not found\" }, 404);\n\n return c.json({ path: assetPath, metadata: await readMediaMetadata(filePath) });\n });\n\n api.post(\n \"/projects/:id/media/remove-background\",\n // fallow-ignore-next-line complexity\n async (c) => {\n cleanupFinishedJobs();\n if (!adapter.startBackgroundRemoval) {\n return c.json({ error: \"background removal is not available in this Studio server\" }, 501);\n }\n\n // fallow-ignore-next-line code-duplication\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const body = (await c.req.json().catch(() => ({}))) as BackgroundRemovalBody;\n const inputAssetPath = body.inputPath ? normalizeProjectAssetPath(body.inputPath) : \"\";\n if (!inputAssetPath) return c.json({ error: \"inputPath required\" }, 400);\n if (containsNullByte(inputAssetPath)) return c.json({ error: \"forbidden\" }, 403);\n if (/^(?:https?:|data:|blob:)/i.test(inputAssetPath)) {\n return c.json({ error: \"background removal requires a project-local media asset\" }, 400);\n }\n\n const inputPath = resolveWithinProject(project.dir, inputAssetPath);\n if (!inputPath) return c.json({ error: \"forbidden\" }, 403);\n if (!existsSync(inputPath)) return c.json({ error: \"input media not found\" }, 404);\n\n const inputIsVideo = isVideoPath(inputAssetPath);\n const inputIsImage = isImagePath(inputAssetPath);\n if (!inputIsVideo && !inputIsImage) {\n return c.json({ error: \"background removal supports video or image assets only\" }, 400);\n }\n\n const requestedOutput = body.outputPath\n ? posix.normalize(normalizeProjectAssetPath(body.outputPath))\n : \"\";\n if (requestedOutput && containsNullByte(requestedOutput)) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n if (requestedOutput && !resolveWithinProject(project.dir, requestedOutput)) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n const taken = outputsInFlight(mediaJobs);\n const outputAssetPath = requestedOutput\n ? uniqueAssetPath(project.dir, requestedOutput, taken)\n : defaultOutputPath(project.dir, inputAssetPath, taken);\n const outputPath = pinWithinProject(project.dir, outputAssetPath);\n if (!outputPath) return c.json({ error: \"forbidden\" }, 403);\n if (inputIsVideo && !VIDEO_OUTPUT_EXTENSIONS.has(extname(outputAssetPath).toLowerCase())) {\n return c.json({ error: \"video background removal output must be .webm or .mov\" }, 400);\n }\n if (inputIsImage && extname(outputAssetPath).toLowerCase() !== \".png\") {\n return c.json({ error: \"image background removal output must be .png\" }, 400);\n }\n\n let backgroundOutputAssetPath: string | undefined;\n let backgroundOutputPath: string | undefined;\n if (body.createBackgroundPlate) {\n if (!inputIsVideo) {\n return c.json({ error: \"background plates are only supported for video inputs\" }, 400);\n }\n taken.add(outputAssetPath);\n backgroundOutputAssetPath = defaultPlatePath(project.dir, inputAssetPath, taken);\n backgroundOutputPath =\n pinWithinProject(project.dir, backgroundOutputAssetPath) ?? undefined;\n if (!backgroundOutputPath) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n }\n\n mkdirWithinProject(project.dir, dirname(outputPath));\n if (backgroundOutputPath) mkdirWithinProject(project.dir, dirname(backgroundOutputPath));\n\n const jobId = makeJobId(project.id, mediaJobs);\n const state = adapter.startBackgroundRemoval({\n project,\n inputPath,\n inputAssetPath,\n outputPath,\n outputAssetPath,\n backgroundOutputPath,\n backgroundOutputAssetPath,\n quality: normalizeQuality(body.quality),\n device: normalizeDevice(body.device),\n jobId,\n }) as JobWithCreatedAt;\n state.createdAt = Date.now();\n mediaJobs.set(jobId, state);\n\n return c.json({\n jobId,\n status: state.status,\n outputPath: outputAssetPath,\n backgroundOutputPath: backgroundOutputAssetPath,\n });\n },\n );\n\n api.get(\"/media-jobs/:jobId/progress\", (c) => {\n cleanupFinishedJobs();\n const { jobId } = c.req.param();\n const job = mediaJobs.get(jobId);\n if (!job) return c.json({ error: \"not found\" }, 404);\n\n return streamSSE(c, async (stream) => {\n while (true) {\n const current = mediaJobs.get(jobId);\n if (!current) break;\n await stream.writeSSE({\n event: \"progress\",\n data: JSON.stringify({\n id: current.id,\n status: current.status,\n progress: current.progress,\n stage: current.stage,\n outputPath: current.outputAssetPath,\n backgroundOutputPath: current.backgroundOutputAssetPath,\n error: current.error,\n provider: current.provider,\n framesProcessed: current.framesProcessed,\n durationSeconds: current.durationSeconds,\n avgMsPerFrame: current.avgMsPerFrame,\n }),\n });\n if (current.status === \"complete\" || current.status === \"failed\") break;\n await stream.sleep(500);\n }\n });\n });\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Hono } from \"hono\";\n\n// Non-project-scoped route: the media-use global asset cache (~/.media). Lets the\n// Studio Asset tab show assets resolved in OTHER projects (cross-project reuse).\n// Reads ONLY the global manifest — no path params, no arbitrary fs access.\n\nexport interface GlobalAssetRecord {\n id?: string;\n type?: string;\n description?: string;\n sha?: string;\n cached_path?: string;\n entity?: string;\n}\n\n/** Parse the global manifest (~/.media/manifest.jsonl) into reusable records. */\nexport function readGlobalAssets(home = homedir()): GlobalAssetRecord[] {\n const manifestPath = join(home, \".media\", \"manifest.jsonl\");\n if (!existsSync(manifestPath)) return [];\n const out: GlobalAssetRecord[] = [];\n for (const line of readFileSync(manifestPath, \"utf8\").split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const rec = JSON.parse(line);\n if (rec && rec.reusable) out.push(rec);\n } catch {\n // skip malformed lines — a torn write shouldn't 500 the panel\n }\n }\n return out;\n}\n\n// Fields the Studio panel actually renders. Deliberately omits cached_path —\n// an absolute ~/.media filesystem path has no business reaching the browser (m13).\nexport function toPublicAsset(r: GlobalAssetRecord): GlobalAssetRecord {\n return { id: r.id, type: r.type, description: r.description, sha: r.sha, entity: r.entity };\n}\n\nexport function registerGlobalAssetRoutes(api: Hono): void {\n api.get(\"/assets/global\", (c) => c.json({ assets: readGlobalAssets().map(toPublicAsset) }));\n}\n","import type { Context, Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { createWriteToken } from \"../helpers/fileVersion.js\";\nimport {\n MAX_WINDOW_IDLE_MS,\n UNDO_MODES,\n type HistoryWindow,\n type ProjectHistory,\n} from \"../history/projectHistory.js\";\nimport type { HistoryWho } from \"../history/historyLog.js\";\n\nconst YOU: HistoryWho = { kind: \"person\", name: \"You\" };\n\nasync function historyOf(adapter: StudioApiAdapter, c: Context): Promise<ProjectHistory | null> {\n const project = await adapter.resolveProject(c.req.param(\"id\") ?? \"\");\n return project ? ((await adapter.history?.(project)) ?? null) : null;\n}\n\nasync function bodyOf(c: Context): Promise<Record<string, unknown>> {\n const body = await c.req.json().catch(() => null);\n return body && typeof body === \"object\" ? (body as Record<string, unknown>) : {};\n}\n\nconst text = (value: unknown) => (typeof value === \"string\" && value ? value : null);\n\n/** Studio's write token, so the watcher's echo of an undo reads as Studio's own write. */\nfunction writing(c: Context): { writeToken?: string } {\n const header = c.req.header(\"X-Hyperframes-Write-Token\");\n return header ? { writeToken: createWriteToken(header) } : {};\n}\n\n/** An agent names itself (`who: {kind: \"agent\", name}`); anyone else is the person at Studio. */\nfunction whoOf(body: Record<string, unknown>): HistoryWho {\n const who = body.who as { kind?: unknown; name?: unknown } | undefined;\n const name = text(who?.name);\n return who?.kind === \"agent\" && name ? { kind: \"agent\", name } : YOU;\n}\n\n/** How long a window or a coalescing claim may wait for its next write; past the cap a timer overflows. */\nfunction idleOf(body: Record<string, unknown>): number | undefined {\n const idleMs = body.idleMs;\n return typeof idleMs === \"number\" && idleMs > 0\n ? Math.min(idleMs, MAX_WINDOW_IDLE_MS)\n : undefined;\n}\n\n/** `{ [path]: version }` from a request body, keeping only string pairs. */\nfunction versionsOf(value: unknown): Record<string, string> | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const pairs = Object.entries(value).filter(\n (pair): pair is [string, string] => typeof pair[1] === \"string\",\n );\n return pairs.length ? Object.fromEntries(pairs) : undefined;\n}\n\n/** What Cmd+Z or Cmd+Shift+Z would revert next, so Studio can name it on its buttons. */\nfunction nextStep(history: ProjectHistory, direction: \"back\" | \"forward\") {\n const target = history.next(direction, YOU);\n if (!target) return null;\n const paths = target.files.map((file) => file.path);\n return { id: target.id, label: target.label, endedAt: target.endedAt, paths };\n}\n\n/** Runs `task` on the project's history; no history is a 404, an engine refusal (\"no longer kept\") a 409. */\nasync function withHistory(\n adapter: StudioApiAdapter,\n c: Context,\n task: (history: ProjectHistory, body: Record<string, unknown>) => Promise<unknown> | unknown,\n) {\n const history = await historyOf(adapter, c);\n if (!history) return c.json({ error: \"This project has no history here.\" }, 404);\n try {\n return c.json((await task(history, await bodyOf(c))) ?? null);\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n}\n\n/** Studio's history: list, Cmd+Z and Shift+Z, undo with the conflict choice, restore, peek, pin, edit windows. */\nexport function registerHistoryRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // ponytail: a window whose close never arrives ends itself when idle; its entry here stays until the server stops.\n const windows = new Map<string, { history: ProjectHistory; window: HistoryWindow }>();\n const base = \"/projects/:id/history\";\n\n api.get(base, (c) =>\n withHistory(adapter, c, (history) => {\n const entries = history.list();\n return { entries, back: nextStep(history, \"back\"), forward: nextStep(history, \"forward\") };\n }),\n );\n api.post(`${base}/step`, (c) =>\n withHistory(adapter, c, (history, body) =>\n history.step(body.direction === \"forward\" ? \"forward\" : \"back\", YOU, writing(c)),\n ),\n );\n api.post(`${base}/undo`, (c) =>\n withHistory(adapter, c, (history, body) => {\n const mode = UNDO_MODES.find((known) => known === body.mode);\n return history.undo(text(body.entryId) ?? \"\", { who: whoOf(body), mode, ...writing(c) });\n }),\n );\n api.post(`${base}/restore`, (c) =>\n withHistory(adapter, c, (history, body) =>\n history.restore(text(body.point) ?? \"\", whoOf(body), writing(c)),\n ),\n );\n api.get(`${base}/peek/:point`, (c) =>\n withHistory(adapter, c, (history) => ({ files: history.peek(c.req.param(\"point\")) })),\n );\n api.post(`${base}/pin`, (c) =>\n withHistory(adapter, c, (history, body) => {\n history.pin(text(body.entryId) ?? \"\", body.pinned === true);\n return { ok: true };\n }),\n );\n api.get(`${base}/blob/:hash`, async (c) => {\n const history = await historyOf(adapter, c);\n const hash = c.req.param(\"hash\") ?? \"\";\n const missing = () =>\n c.json({ error: \"That file is not kept in this project's history.\" }, 404);\n if (!history || !/^[0-9a-f]{64}$/.test(hash)) return missing();\n const bytes = await history.readBlob(hash).catch(() => null);\n return bytes ? c.body(new Uint8Array(bytes)) : missing();\n });\n // Studio records after it writes, under the edit's label; a gesture with no idleMs holds until another key.\n api.post(`${base}/claim`, (c) =>\n withHistory(adapter, c, async (history, body) => {\n const paths = Array.isArray(body.paths) ? body.paths.filter((path) => text(path)) : [];\n const coalesceKey = text(body.coalesceKey) ?? undefined;\n const overwrote = versionsOf(body.overwrote);\n const claimed = await history.claim(YOU, text(body.label) ?? \"Edited in Studio\", paths, {\n ...(coalesceKey && { coalesceKey, idleMs: idleOf(body) ?? Infinity }),\n ...(overwrote && { overwrote }),\n });\n return { claimed };\n }),\n );\n api.post(`${base}/window`, (c) =>\n withHistory(adapter, c, async (history, body) => {\n const idleMs = idleOf(body);\n const window = await history.beginWindow(\n whoOf(body),\n text(body.label) ?? \"Edited in Studio\",\n idleMs ? { idleMs } : undefined,\n );\n windows.set(window.id, { history, window });\n // The window's id is its last entry's id, unless nothing was left after its last part.\n return { windowId: window.id, startedAt: window.startedAt };\n }),\n );\n api.post(`${base}/window/:windowId/close`, (c) =>\n withHistory(adapter, c, async (history) => {\n const id = c.req.param(\"windowId\") ?? \"\";\n const held = windows.get(id);\n if (held?.history !== history) throw new Error(\"That window is not open in this project.\");\n windows.delete(id);\n return { entry: await held.window.close() };\n }),\n );\n}\n","import { sameInstant } from \"@hyperframes/core/clip-facts\";\nimport { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport {\n findTargetElement,\n dedupeClonedCompositionId,\n isHTMLElement,\n nextUniqueId,\n parseSourceDocument,\n type SourceMutationTarget,\n} from \"./sourceMutation.js\";\n\nexport interface DuplicateElementResult {\n html: string;\n matched: boolean;\n newId: string | null;\n}\n\nexport function duplicateElementInHtml(\n source: string,\n target: SourceMutationTarget,\n newId: string,\n at: number,\n): DuplicateElementResult {\n const { document, wrappedFragment } = parseSourceDocument(source);\n const element = findTargetElement(document, target);\n if (!element || !element.parentElement) return { html: source, matched: false, newId: null };\n const duration = numericAttribute(element, \"data-duration\");\n const track = numericAttribute(element, \"data-track-index\") ?? 0;\n if (duration === null || numericAttribute(element, \"data-start\") === null) {\n return { html: source, matched: false, newId: null };\n }\n const uniqueId = nextUniqueId(document, newId);\n rippleElements(document, element, at, duration, track);\n const clone = element.cloneNode(true);\n if (!isHTMLElement(clone)) return { html: source, matched: false, newId: null };\n clone.setAttribute(\"id\", uniqueId);\n dedupeClonedCompositionId(document, clone);\n stripStableIds(clone);\n clone.setAttribute(\"data-start\", String(at));\n element.parentElement.insertBefore(clone, element.nextSibling);\n const html = wrappedFragment ? document.body.innerHTML || \"\" : document.toString();\n return { html: ensureHfIds(html), matched: true, newId: uniqueId };\n}\n\nfunction rippleElements(\n document: Document,\n element: Element,\n at: number,\n duration: number,\n track: number,\n): void {\n for (const candidate of Array.from(document.querySelectorAll(\"[data-start][data-duration]\"))) {\n if (candidate === element || candidate.getAttribute(\"data-track-index\") !== String(track)) {\n continue;\n }\n const start = numericAttribute(candidate, \"data-start\");\n if (start === null) continue;\n const metInsertionPoint = sameInstant(start, at);\n if (start < at && !metInsertionPoint) continue;\n candidate.setAttribute(\"data-start\", String((metInsertionPoint ? at : start) + duration));\n }\n}\n\nfunction stripStableIds(element: Element): void {\n element.removeAttribute(\"data-hf-id\");\n for (const child of Array.from(element.querySelectorAll(\"[data-hf-id]\"))) {\n child.removeAttribute(\"data-hf-id\");\n }\n}\n\nfunction numericAttribute(element: Element, name: string): number | null {\n const value = Number(element.getAttribute(name));\n return Number.isFinite(value) ? value : null;\n}\n","import { createHash } from \"node:crypto\";\nimport { readFileSync, readdirSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\nimport { mkdirWithinProject } from \"./safePath.js\";\nimport type { PreviewDocumentStore } from \"./mediaProxyPreview.js\";\n\n/** One built preview document under the project's `.hyperframes/preview`. `salt` names the server build, so new\n * code never reads a document an older build wrote. A failed read or write only costs a rebuild. */\nexport function createPreviewDocumentStore(projectDir: string, salt: string): PreviewDocumentStore {\n const dir = join(projectDir, \".hyperframes\", \"preview\");\n const fileFor = (key: string) =>\n join(dir, `${createHash(\"sha256\").update(`${salt}\\n${key}`).digest(\"hex\").slice(0, 32)}.html`);\n return {\n read(key) {\n try {\n return readFileSync(fileFor(key), \"utf-8\");\n } catch {\n return null;\n }\n },\n write(key, html) {\n try {\n mkdirWithinProject(projectDir, dir);\n const file = fileFor(key);\n replaceFileAtomically(file, html, 0o644);\n for (const name of readdirSync(dir)) {\n if (join(dir, name) !== file) rmSync(join(dir, name), { force: true });\n }\n } catch {\n // A document that fails to persist is rebuilt on the next open.\n }\n },\n };\n}\n","export interface ThumbnailOutputDimensions {\n width: number;\n height: number;\n outputWidth: number;\n outputHeight: number;\n}\n\n/** Sole adapter rule for capturing authored layout at bounded physical dimensions. */\nexport function thumbnailDeviceScaleFactor({\n width,\n height,\n outputWidth,\n outputHeight,\n}: ThumbnailOutputDimensions): number {\n const dimensions = [width, height, outputWidth, outputHeight];\n if (dimensions.some((value) => !Number.isFinite(value) || value <= 0)) {\n throw new RangeError(\"Thumbnail dimensions must be positive finite numbers\");\n }\n return Math.min(1, outputWidth / width, outputHeight / height);\n}\n","import type { MediaProcessingJobState, StudioApiAdapter } from \"../types.js\";\n\nexport type BackgroundRemovalJobOptions = Parameters<\n NonNullable<StudioApiAdapter[\"startBackgroundRemoval\"]>\n>[0];\n\nexport type BackgroundRemovalProgressEvent =\n | { kind: \"info\"; message: string }\n | { kind: \"metadata\"; width: number; height: number; fps: number; frameCount: number }\n | { kind: \"frame\"; index: number; total: number; avgMsPerFrame: number };\n\nexport type BackgroundRemovalRender = (options: {\n inputPath: string;\n outputPath: string;\n backgroundOutputPath?: string;\n device?: BackgroundRemovalJobOptions[\"device\"];\n quality?: BackgroundRemovalJobOptions[\"quality\"];\n onProgress?: (event: BackgroundRemovalProgressEvent) => void;\n}) => Promise<{\n provider: string;\n framesProcessed: number;\n durationSeconds: number;\n avgMsPerFrame: number;\n}>;\n\nexport function createBackgroundRemovalJob(\n opts: BackgroundRemovalJobOptions,\n render: BackgroundRemovalRender,\n): MediaProcessingJobState {\n const state: MediaProcessingJobState = {\n id: opts.jobId,\n status: \"processing\",\n progress: 0,\n stage: \"Preparing background removal\",\n inputAssetPath: opts.inputAssetPath,\n outputAssetPath: opts.outputAssetPath,\n outputPath: opts.outputPath,\n ...(opts.backgroundOutputPath ? { backgroundOutputPath: opts.backgroundOutputPath } : {}),\n ...(opts.backgroundOutputAssetPath\n ? { backgroundOutputAssetPath: opts.backgroundOutputAssetPath }\n : {}),\n };\n\n void (async () => {\n try {\n const result = await render({\n inputPath: opts.inputPath,\n outputPath: opts.outputPath,\n backgroundOutputPath: opts.backgroundOutputPath,\n device: opts.device,\n quality: opts.quality,\n onProgress: (event) => updateBackgroundRemovalProgress(state, event),\n });\n state.status = \"complete\";\n state.progress = 100;\n state.stage = \"Complete\";\n state.provider = result.provider;\n state.framesProcessed = result.framesProcessed;\n state.durationSeconds = result.durationSeconds;\n state.avgMsPerFrame = result.avgMsPerFrame;\n } catch (err) {\n state.status = \"failed\";\n state.error = err instanceof Error ? err.message : String(err);\n state.stage = \"Failed\";\n }\n })();\n\n return state;\n}\n\nfunction updateBackgroundRemovalProgress(\n state: MediaProcessingJobState,\n event: BackgroundRemovalProgressEvent,\n): void {\n if (event.kind === \"info\") {\n state.stage = event.message;\n return;\n }\n if (event.kind === \"metadata\") {\n state.stage = `Source ${event.width}×${event.height}`;\n state.progress = 2;\n return;\n }\n state.progress = event.total ? Math.min(99, Math.floor((event.index / event.total) * 100)) : 0;\n state.stage = event.total\n ? `Removing background ${event.index}/${event.total}`\n : `Removing background frame ${event.index}`;\n state.framesProcessed = event.index;\n state.avgMsPerFrame = event.avgMsPerFrame;\n}\n"],"mappings":"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","names":["existsSync","lstatSync","readFileSync","unlinkSync","rmSync","statSync","renameSync","readdirSync","resolve","dirname","join","readFileSync","parseHTML","join","existsSync","parseHTML","parseHTML","existsSync","readFileSync","parseHTML","text","replaceFileAtomically","existsSync","dirname","join","mkdtempSync","rmSync","writeFileSync","join","findFfBinary","readFileSync","writeFileSync","Buffer","join","relative","Buffer","relative","readFileSync","join","writeFileSync","readFileSync","statSync","statSync","readFileSync","parseHTML","dirname","lstatSync","resolve","statSync","existsSync","readFileSync","join","replaceFileAtomically","readdirSync","text","parseHTML","round3","targetSelector","updateAnimationInScript","addAnimationToScript","removeAnimationFromScript","addKeyframeToScript","removeKeyframeFromScript","moveKeyframeInScript","resizeKeyframedTweenInScript","updateKeyframeInScript","removeAllKeyframesFromScript","unrollDynamicAnimations","setArcPathInScript","updateArcSegmentInScript","updateMotionPathPointInScript","addMotionPathPointInScript","removeMotionPathPointInScript","addMotionPathToScript","removeArcPathFromScript","addAnimationWithKeyframesToScript","splitAnimationsInScript","dedupePositionWritesInScript","stat","rmSync","unlinkSync","currentVersion","version","renameSync","parseHTML","existsSync","readFileSync","statSync","join","resolve","createHash","RUNTIME_BOOTSTRAP_ATTR","insertBeforeCloseTag","stripEmbeddedRuntimeScripts","gsapCdnDist","findStartTags","ensureHfIds","readlinkSync","dirname","join","relative","resolve","parseHTML","resolve","join","relative","readlinkSync","dirname","text","parseHTML","parseHTML","gsapCdnDist","insertBeforeCloseTag","join","existsSync","readFileSync","RUNTIME_BOOTSTRAP_ATTR","stripEmbeddedRuntimeScripts","parseHTML","findStartTags","createHash","parse","ensureHfIds","statSync","resolve","stat","readFileSync","join","readFileSync","join","existsSync","lstatSync","readFileSync","unlinkSync","readdirSync","statSync","join","join","lstatSync","readFileSync","existsSync","unlinkSync","readdirSync","stat","statSync","createHash","resolve","relative","createHash","closeSync","fstatSync","openSync","readFileSync","readdirSync","renameSync","rmSync","statSync","unlinkSync","writeFileSync","join","createHash","randomUUID","readdirSync","join","statSync","rmSync","unlinkSync","randomUUID","writeFileSync","renameSync","openSync","stat","fstatSync","readFileSync","closeSync","createHash","existsSync","readFileSync","statSync","join","resolve","isWithinProjectRoot","resolve","isWithinProjectRoot","statSync","join","existsSync","peaks","readFileSync","readFileSync","rmSync","statSync","basename","dirname","join","relative","sep","findFfBinary","createFileAtomically","replaceFileAtomically","createHash","ensureHfIds","createHash","ensureHfIds","findFfBinary","readFileSync","createFileAtomically","basename","rmSync","dirname","relative","join","sep","replaceFileAtomically","statSync","existsSync","existsSync","existsSync","readFileSync","statSync","join","resolve","isWithinProjectRoot","execFile","spawn","findFfBinary","existsSync","readFileSync","resolve","isWithinProjectRoot","statSync","join","closeSync","fstatSync","openSync","isRecord","stat","isRecord","streamSSE","existsSync","basename","dirname","join","basename","existsSync","join","dirname","streamSSE","existsSync","readFileSync","join","ensureHfIds","ensureHfIds","createHash","readFileSync","readdirSync","rmSync","join","replaceFileAtomically","join","createHash","readFileSync","replaceFileAtomically","readdirSync","rmSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/createStudioApi.ts","../src/routes/projects.ts","../src/routes/files.ts","../src/helpers/mime.ts","../src/helpers/compositionInputs.ts","../src/helpers/subComposition.ts","../src/helpers/compositionInsertion.ts","../src/helpers/waveform.ts","../src/helpers/mediaValidation.ts","../src/helpers/backupJournal.ts","../src/helpers/projectDirMissing.ts","../src/helpers/applyFileMutations.ts","../src/helpers/studioFontFace.ts","../src/routes/gsapMutationCapabilities.ts","../src/routes/preview.ts","../src/helpers/previewReads.ts","../src/helpers/variablesPayload.ts","../src/helpers/previewVariables.ts","../src/helpers/lazyPreviewImages.ts","../src/routes/lint.ts","../src/routes/render.ts","../src/routes/imageThumbnail.ts","../src/routes/thumbnailGenerationCoordinator.ts","../src/routes/thumbnail.ts","../src/routes/waveform.ts","../src/routes/freezeFrame.ts","../src/helpers/freezeFrame.ts","../src/routes/loudness.ts","../src/routes/peaks.ts","../src/helpers/peakMap.ts","../src/routes/fonts.ts","../src/routes/registry.ts","../src/routes/selection.ts","../src/routes/media.ts","../src/routes/globalAssets.ts","../src/routes/history.ts","../src/helpers/duplicateElement.ts","../src/helpers/previewDocumentStore.ts","../src/helpers/thumbnailOutput.ts","../src/helpers/backgroundRemovalJob.ts"],"sourcesContent":["import { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"./types.js\";\nimport { registerProjectRoutes } from \"./routes/projects.js\";\nimport { registerFileRoutes } from \"./routes/files.js\";\nimport { registerPreviewRoutes } from \"./routes/preview.js\";\nimport { registerLintRoutes } from \"./routes/lint.js\";\nimport { registerRenderRoutes } from \"./routes/render.js\";\nimport { registerImageThumbnailRoutes } from \"./routes/imageThumbnail.js\";\nimport { registerThumbnailRoutes } from \"./routes/thumbnail.js\";\nimport { registerWaveformRoutes } from \"./routes/waveform.js\";\nimport { registerFreezeFrameRoutes } from \"./routes/freezeFrame.js\";\nimport { registerLoudnessRoutes } from \"./routes/loudness.js\";\nimport { registerPeakRoutes } from \"./routes/peaks.js\";\nimport { registerFontRoutes } from \"./routes/fonts.js\";\nimport { registerRegistryRoutes } from \"./routes/registry.js\";\nimport { registerSelectionRoutes } from \"./routes/selection.js\";\nimport { registerMediaRoutes } from \"./routes/media.js\";\nimport { registerGlobalAssetRoutes } from \"./routes/globalAssets.js\";\nimport { registerHistoryRoutes } from \"./routes/history.js\";\nimport { replaceWithProjectDirMissing } from \"./helpers/projectDirMissing.js\";\nimport { folderGone, isProjectRootMissing } from \"./helpers/safePath.js\";\n\n/**\n * Create a Hono sub-app with all studio API routes.\n *\n * Both the vite dev server and CLI embedded server mount this app\n * under /api, each providing their own adapter for host-specific behavior.\n */\nexport function createStudioApi(adapter: StudioApiAdapter): Hono {\n const api = new Hono();\n api.use(async function answerProjectDirMissingAfterErrorHandlers(c, next) {\n const hostHeaders = new Headers(c.res.headers);\n await next();\n if (isProjectRootMissing(c.error)) replaceWithProjectDirMissing(c, hostHeaders);\n });\n api.use(\"/projects/:id/*\", async function answerProjectDirMissingForVanishedFolder(c, next) {\n const hostHeaders = new Headers(c.res.headers);\n const dirBeforeRoute = await Promise.resolve()\n .then(() => adapter.resolveProject(c.req.param(\"id\")))\n .then(\n (project) => project?.dir,\n () => undefined,\n );\n await next();\n if (c.res.status >= 403 && dirBeforeRoute && folderGone(dirBeforeRoute))\n replaceWithProjectDirMissing(c, hostHeaders);\n });\n api.use(\"/projects/:id/*\", async function forgetSignatureAfterWrite(c, next) {\n await next();\n if (c.req.method === \"GET\" || c.req.method === \"HEAD\") return;\n const project = await Promise.resolve()\n .then(() => adapter.resolveProject(c.req.param(\"id\")))\n .catch(() => null);\n if (project) adapter.invalidateProjectSignature?.(project.dir);\n });\n api.use(\"/projects/:id/*\", async function openHistorySoNoWriteBecomesItsBaseline(c, next) {\n if (c.req.method !== \"GET\" && c.req.method !== \"HEAD\" && adapter.history) {\n await Promise.resolve()\n .then(() => adapter.resolveProject(c.req.param(\"id\")))\n .then((project) => project && adapter.history?.(project))\n .catch(() => null);\n }\n await next();\n });\n\n registerProjectRoutes(api, adapter);\n registerFileRoutes(api, adapter);\n registerPreviewRoutes(api, adapter);\n registerLintRoutes(api, adapter);\n registerRenderRoutes(api, adapter);\n registerThumbnailRoutes(api, adapter);\n registerImageThumbnailRoutes(api, adapter);\n registerSelectionRoutes(api, adapter);\n registerMediaRoutes(api, adapter);\n registerWaveformRoutes(api, adapter);\n registerFreezeFrameRoutes(api, adapter);\n registerLoudnessRoutes(api, adapter);\n registerPeakRoutes(api, adapter);\n registerFontRoutes(api);\n registerRegistryRoutes(api, adapter);\n registerGlobalAssetRoutes(api);\n registerHistoryRoutes(api, adapter);\n\n return api;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isInHiddenOrVendorDir, isPrivateProjectPath, walkDir } from \"../helpers/safePath.js\";\nimport { isCompositionSource } from \"../helpers/hfIdPersist.js\";\nimport { resolveProjectSignature } from \"../helpers/projectSignature.js\";\n\nasync function filterCompositionFiles(projectDir: string, files: string[]): Promise<string[]> {\n const htmlFiles = files.filter((f) => f.endsWith(\".html\") && !isInHiddenOrVendorDir(f));\n const checks = await Promise.all(\n htmlFiles.map(async (f) => {\n try {\n const content = await readFile(join(projectDir, f), \"utf-8\");\n return isCompositionSource(content);\n } catch {\n return false;\n }\n }),\n );\n return htmlFiles.filter((_, i) => checks[i]);\n}\n\nexport function registerProjectRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // List all projects\n api.get(\"/projects\", async (c) => {\n const projects = await adapter.listProjects();\n return c.json({ projects });\n });\n\n // Resolve session to project (multi-project mode)\n api.get(\"/resolve-session/:sessionId\", async (c) => {\n if (!adapter.resolveSession) {\n return c.json({ error: \"not available\" }, 404);\n }\n const { sessionId } = c.req.param();\n const result = await adapter.resolveSession(sessionId);\n if (!result) return c.json({ error: \"Session not found\" }, 404);\n return c.json(result);\n });\n\n // Current content signature for a project: a cheap poll target for clients that refresh when files change on disk.\n api.get(\"/projects/:id/signature\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n return c.json({ signature: resolveProjectSignature(adapter, project.dir) });\n });\n\n // Project file tree\n api.get(\"/projects/:id\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const files = walkDir(project.dir).filter((file) => !isPrivateProjectPath(file));\n const compositions = await filterCompositionFiles(project.dir, files);\n return c.json({ id: project.id, dir: project.dir, title: project.title, files, compositions });\n });\n}\n","// fallow-ignore-file code-duplication\n// executeGsapMutationRecast and executeGsapMutationAcorn are intentionally\n// parallel — two writers, same switch-case interface. Structural duplication\n// is load-bearing (both paths must remain testable in isolation).\nimport type { Hono } from \"hono\";\nimport { encodeUrlPath, decodedUrlPath, decodeCssEscapes } from \"@hyperframes/parsers/asset-paths\";\nimport {\n scanHtmlOpeningTags,\n decodeAuthoredAttribute,\n HTML_ATTRIBUTE_ENTITIES,\n} from \"@hyperframes/parsers\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport {\n closeSync,\n existsSync,\n lstatSync,\n openSync,\n readFileSync,\n readlinkSync,\n unlinkSync,\n rmSync,\n statSync,\n fstatSync,\n renameSync,\n readdirSync,\n realpathSync,\n type Dirent,\n} from \"node:fs\";\nimport { resolve, dirname, join, sep } from \"node:path\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isAudioFile } from \"../helpers/mime.js\";\nimport { lengthIsTimeline } from \"../helpers/compositionInputs.js\";\nimport { createFileAtomically, replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\nimport { generateWaveformCache } from \"../helpers/waveform.js\";\nimport { validateUploadedMediaBuffer } from \"../helpers/mediaValidation.js\";\nimport {\n folderGone,\n isInHiddenOrVendorDir,\n isPrivateProjectFile,\n isSafePath,\n mkdirWithinProject,\n pinWithinProject,\n resolveWithinProject,\n walkDir,\n} from \"../helpers/safePath.js\";\nimport { backupPathForResponse, snapshotBeforeWrite } from \"../helpers/backupJournal.js\";\nimport { projectDirMissing } from \"../helpers/projectDirMissing.js\";\nimport {\n createWriteToken,\n fileContentVersion,\n recordFileWriteReceipt,\n} from \"../helpers/fileVersion.js\";\nimport { applyFileMutations, FileChangedError } from \"../helpers/applyFileMutations.js\";\nimport {\n findUnsafeDomPatchValues,\n findUnsafeMutationValues,\n type UnsafeMutationValue,\n} from \"../helpers/finiteMutation.js\";\nimport type { GsapAnimation } from \"@hyperframes/parsers\";\nimport { classifyPropertyGroup } from \"@hyperframes/parsers/gsap-constants\";\nimport { findTimelineScript, parseGsapScriptAcorn } from \"@hyperframes/parsers/gsap-parser-acorn\";\nimport { unrollComputedTimeline } from \"@hyperframes/parsers\";\nimport {\n updateAnimationInScript,\n addAnimationToScript,\n removeAnimationFromScript,\n addKeyframeToScript,\n removeKeyframeFromScript,\n moveKeyframeInScript,\n resizeKeyframedTweenInScript,\n updateKeyframeInScript,\n convertToKeyframesFromScript,\n removeAllKeyframesFromScript,\n materializeKeyframesFromScript,\n unrollDynamicAnimations,\n setArcPathInScript,\n updateArcSegmentInScript,\n updateMotionPathPointInScript,\n addMotionPathPointInScript,\n removeMotionPathPointInScript,\n addMotionPathToScript,\n removeArcPathFromScript,\n addAnimationWithKeyframesToScript,\n replaceTweenWithKeyframesInScript,\n splitAnimationsInScript,\n splitIntoPropertyGroupsFromScript,\n retimeClipTweensInScript,\n type ClipTweenRetime,\n dedupePositionWritesInScript,\n syncPositionHoldsBeforeKeyframes,\n trimTrailingKeyframeSpans,\n clipQueryRoot,\n} from \"@hyperframes/parsers/gsap-writer-acorn\";\nimport {\n removeElementFromHtml,\n removeElementsFromHtml,\n patchElementInHtml,\n probeElementInSource,\n probeElementsInSource,\n splitElementInHtml,\n relinkSplitHalvesInHtml,\n wrapElementsInHtml,\n unwrapElementsFromHtml,\n isHTMLElement,\n type PatchOperation,\n type ElementRebase,\n} from \"../helpers/sourceMutation.js\";\nimport { ensureStudioFontFaceCss, isStudioFontFaceCss } from \"../helpers/studioFontFace.js\";\nimport { parseHTML } from \"linkedom\";\nimport { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport {\n CompositionInsertionError,\n insertCompositionIntoSource,\n} from \"../helpers/compositionInsertion.js\";\nimport { resolveGsapWriter } from \"./gsapMutationCapabilities.js\";\nimport { decodeWellFormedEscapes, requestSubPath } from \"../helpers/requestSubPath.js\";\nimport {\n hasCompositionOutsideTemplates,\n insertBeforeCloseTag,\n} from \"@hyperframes/core/compiler/html-document\";\n\n// ── Server cutover flag ─────────────────────────────────────────────────────\n\n/**\n * Writer selection is deliberately independent from the Studio SDK cutover.\n * Recast remains the default until the capability report has no parity blockers.\n */\n/**\n * Lazy-load gsapParser for write ops (recast-backed) — the default server writer.\n * The read path uses the browser-safe acorn parser; this loader is only needed\n * for the recast write path (the default until the migration gate graduates).\n */\nasync function loadGsapParser() {\n return import(\"@hyperframes/parsers/gsap-parser-recast\");\n}\n\n// ── Shared helpers ──────────────────────────────────────────────────────────\n\n/**\n * Resolve the project and file path from the request, validating safety.\n * Returns null (and sends an error response) if anything is invalid.\n */\ninterface RouteContext {\n req: {\n param: (name: string) => string;\n url: string;\n query: (name: string) => string | undefined;\n header: (name: string) => string | undefined;\n };\n header: (name: string, value: string) => void;\n json: (data: unknown, status?: number) => Response;\n}\n\ninterface ResolvedGsapFile {\n project: { dir: string };\n filePath: string;\n absPath: string;\n}\n\n/**\n * True only for a symlink that itself lives inside the project, whose target\n * (once resolved against the link's own directory) also names a location\n * inside the project, and does not exist anywhere — not for one that exists\n * (that stays a real containment failure) and not for a plain missing path\n * (the ordinary case `resolveWithinProject` already covers).\n *\n * Both containment checks matter, not just the second: a request can name a\n * path lexically *outside* the project (reached via `..`) that happens to be\n * a dangling symlink out there, or a real in-project symlink that points\n * *outside* the project at a target that may or may not exist. Labeling\n * either of those \"not found\" would leak, to anyone who can hit the route,\n * whether an out-of-project path exists — the containment check exists\n * precisely so that answer never depends on what's outside the project.\n * `isSafePath` fails closed on a dangling in-project symlink by design (a\n * write through it could later resolve outside the project once something\n * creates the target) — this does not loosen that; it only tells the caller\n * *why* the containment check refused, so the response can say \"not found\"\n * instead of a path-traversal-shaped \"forbidden\" for a case that scans as\n * broken plumbing, not an attack.\n */\nfunction isDanglingSymlinkInProject(projectDir: string, lexicalPath: string): boolean {\n if (!isSafePath(projectDir, dirname(lexicalPath))) return false;\n let stats;\n try {\n stats = lstatSync(lexicalPath);\n } catch {\n return false;\n }\n if (!stats.isSymbolicLink()) return false;\n const target = resolve(dirname(lexicalPath), readlinkSync(lexicalPath));\n if (!isSafePath(projectDir, target)) return false;\n try {\n statSync(lexicalPath);\n return false;\n } catch {\n return true;\n }\n}\n\n/** Resolve project + safe absolute path for any project-scoped route. */\nasync function resolveProjectPath(\n c: RouteContext,\n adapter: StudioApiAdapter,\n route: string,\n opts?: { mustExist?: boolean; pin?: boolean },\n) {\n const id = c.req.param(\"id\");\n const project = await adapter.resolveProject(id);\n if (!project) {\n return { error: c.json({ error: \"not found\" }, 404) } as const;\n }\n\n // The CLI host's `resolveProject` is static (`id === projectId ? project : null`),\n // so it keeps answering with this project even after its folder is renamed\n // or deleted out from under a running `preview` — mount-time validation\n // (`/api/projects/:id`) still passes, so nothing upstream catches this.\n // Every subsequent read then failed closed inside `isSafePath` (its\n // `realpathSync(base)` throws when the base itself is gone) and reported as\n // `403 forbidden` — indistinguishable from a real path-traversal attempt.\n // Checked here, once, so every route built on this shares the fix.\n if (folderGone(project.dir)) {\n return { error: projectDirMissing(c) } as const;\n }\n\n const filePath = requestSubPath(c.req.url, `projects/:id/${route}`);\n if (filePath.includes(\"\\0\")) {\n return { error: c.json({ error: \"forbidden\", why: \"nul\" }, 403) } as const;\n }\n\n // An edit pins its target; create-only writes use `wx`, and a delete or rename acts on a link itself.\n const absPath = (opts?.pin ? pinWithinProject : resolveWithinProject)(project.dir, filePath);\n if (!absPath) {\n if (isDanglingSymlinkInProject(project.dir, resolve(project.dir, filePath))) {\n return { error: c.json({ error: \"not found\", why: \"dangling_symlink\" }, 404) } as const;\n }\n return { error: c.json({ error: \"forbidden\", why: \"outside_project\" }, 403) } as const;\n }\n\n if (opts?.mustExist && !existsSync(absPath)) {\n return { error: c.json({ error: \"not found\" }, 404) } as const;\n }\n\n return { project, filePath, absPath } as const;\n}\n\nfunction resolveProjectFile(\n c: RouteContext,\n adapter: StudioApiAdapter,\n opts?: { mustExist?: boolean; pin?: boolean },\n) {\n return resolveProjectPath(c, adapter, \"files\", opts);\n}\n\nfunction resolveFileMutationContext(c: RouteContext, adapter: StudioApiAdapter, operation: string) {\n return resolveProjectPath(c, adapter, `file-mutations/${operation}`, { pin: true });\n}\n\ntype MutationTarget = {\n id?: string | null;\n hfId?: string;\n selector?: string;\n selectorIndex?: number;\n};\n\ninterface ElementPatchRequest {\n target: MutationTarget;\n operations: PatchOperation[];\n}\n\ninterface ElementPatchBatchRequest {\n sourceFile: string;\n patches: ElementPatchRequest[];\n}\n\ninterface ElementPatchBatchFileResult {\n sourceFile: string;\n changed: boolean;\n matched: boolean[];\n before: string;\n after: string;\n backupPath?: string | null;\n}\n\ninterface AtomicCutTarget {\n target: MutationTarget;\n originalId?: string;\n splitTime: number;\n elementStart: number;\n elementDuration: number;\n playbackStart?: number;\n playbackRate?: number;\n isComposition?: boolean;\n track?: number;\n}\n\ninterface AtomicCutFileRequest {\n path: string;\n expectedVersion: string;\n targets: AtomicCutTarget[];\n}\n\nfunction isOptionalInteger(value: unknown): value is number | undefined {\n return value === undefined || Number.isInteger(value);\n}\n\nfunction isAtomicCutTarget(value: unknown): value is AtomicCutTarget {\n if (!value || typeof value !== \"object\") return false;\n const target = value as Partial<AtomicCutTarget>;\n return (\n !!target.target &&\n typeof target.target === \"object\" &&\n Number.isFinite(target.splitTime) &&\n Number.isFinite(target.elementStart) &&\n Number.isFinite(target.elementDuration) &&\n Number(target.elementDuration) > 0 &&\n isOptionalInteger(target.track)\n );\n}\n\nfunction isAtomicCutFileRequest(value: unknown): value is AtomicCutFileRequest {\n if (!value || typeof value !== \"object\") return false;\n const file = value as Partial<AtomicCutFileRequest>;\n return (\n typeof file.path === \"string\" &&\n file.path.length > 0 &&\n typeof file.expectedVersion === \"string\" &&\n Array.isArray(file.targets) &&\n file.targets.length > 0 &&\n file.targets.every(isAtomicCutTarget)\n );\n}\n\nlet atomicCutTail: Promise<unknown> = Promise.resolve();\n\n/** Serialize cut actions so a rapid second gesture observes the first one's bytes. */\nfunction serializeAtomicCut<T>(task: () => Promise<T>): Promise<T> {\n const next = atomicCutTail.then(task, task);\n atomicCutTail = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n}\n\nfunction isElementPatchRequest(value: unknown): value is ElementPatchRequest {\n if (typeof value !== \"object\" || value === null) return false;\n if (!(\"target\" in value) || typeof value.target !== \"object\" || value.target === null) {\n return false;\n }\n return \"operations\" in value && Array.isArray(value.operations) && value.operations.length > 0;\n}\n\nfunction isElementPatchBatchRequest(value: unknown): value is ElementPatchBatchRequest {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"sourceFile\" in value &&\n typeof value.sourceFile === \"string\" &&\n value.sourceFile.length > 0 &&\n \"patches\" in value &&\n Array.isArray(value.patches) &&\n value.patches.length > 0 &&\n value.patches.every(isElementPatchRequest)\n );\n}\n\nfunction findUnsafeElementPatchBatchValues(\n batches: readonly ElementPatchBatchRequest[],\n): UnsafeMutationValue[] {\n return batches.flatMap((batch) =>\n batch.patches.flatMap((patch) => findUnsafeDomPatchValues(patch)),\n );\n}\n\nfunction foldElementPatches(\n originalContent: string,\n patches: ElementPatchRequest[],\n): { content: string; matched: boolean[] } {\n let content = originalContent;\n const matched: boolean[] = [];\n for (const patch of patches) {\n const result = patchElementInHtml(content, patch.target, patch.operations);\n content = result.html;\n matched.push(result.matched);\n }\n return { content, matched };\n}\n\nconst PATCH_CONFLICT_ATTEMPTS = 3;\n\nconst ID_ATTRIBUTE = /[\\s\"'/]id\\s*=\\s*(?=(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))/gi;\n\n/** Every id in the project's HTML files: sub-compositions share one preview document. */\nfunction projectHtmlIds(projectDir: string): Set<string> {\n const ids = new Set<string>();\n for (const rel of walkDir(projectDir)) {\n if (!rel.endsWith(\".html\") || isInHiddenOrVendorDir(rel)) continue;\n let html: string;\n try {\n html = readFileSync(join(projectDir, rel), \"utf-8\");\n } catch {\n continue;\n }\n for (const m of html.matchAll(ID_ATTRIBUTE)) ids.add(m[1] ?? m[2] ?? m[3] ?? \"\");\n }\n return ids;\n}\n\ntype ElementPatchCommitResult =\n | { error: \"duplicate\" | \"forbidden\" | \"not-found\" | \"conflict\"; sourceFile: string }\n | { durable: boolean; files: ElementPatchBatchFileResult[] };\n\n/**\n * The single commit owner for element patch batches. All files are resolved,\n * read, and folded before the first write; any unmatched target refuses the\n * whole request, and a write from elsewhere mid-fold refolds before it answers 409.\n * Studio Server is single-process; within it the final snapshots/writes are\n * synchronous, so another route cannot interleave once the commit begins. A\n * multi-process deployment needs a shared per-project file lock instead.\n */\nexport function commitElementPatchBatches(\n projectDir: string,\n batches: ElementPatchBatchRequest[],\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void = (path, content) =>\n replaceFileAtomically(path, content, statSync(path).mode),\n requestToken?: string,\n): ElementPatchCommitResult {\n for (let attempt = 1; ; attempt += 1) {\n try {\n return foldAndCommitElementPatchBatches(projectDir, batches, writeFile, requestToken);\n } catch (error) {\n if (!(error instanceof FileChangedError)) throw error;\n if (attempt === PATCH_CONFLICT_ATTEMPTS)\n return { error: \"conflict\", sourceFile: error.sourceFile };\n }\n }\n}\n\nfunction foldAndCommitElementPatchBatches(\n projectDir: string,\n batches: ElementPatchBatchRequest[],\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void,\n requestToken: string | undefined,\n): ElementPatchCommitResult {\n const resolvedPaths = new Set<string>();\n const prepared: Array<{\n sourceFile: string;\n absPath: string;\n before: string;\n matched: boolean[];\n after: string;\n }> = [];\n\n for (const batch of batches) {\n const absPath = pinWithinProject(projectDir, batch.sourceFile);\n if (!absPath) return { error: \"forbidden\", sourceFile: batch.sourceFile };\n if (resolvedPaths.has(absPath)) return { error: \"duplicate\", sourceFile: batch.sourceFile };\n resolvedPaths.add(absPath);\n\n let before: string;\n try {\n before = readFileSync(absPath, \"utf-8\");\n } catch {\n return { error: \"not-found\", sourceFile: batch.sourceFile };\n }\n const folded = foldElementPatches(before, batch.patches);\n prepared.push({\n sourceFile: batch.sourceFile,\n absPath,\n before,\n matched: folded.matched,\n after: folded.content,\n });\n }\n\n const durable = prepared.every((file) => file.matched.every(Boolean));\n if (!durable) {\n return {\n durable: false,\n files: prepared.map((file) => ({\n sourceFile: file.sourceFile,\n changed: false,\n matched: file.matched,\n before: file.before,\n after: file.before,\n })),\n };\n }\n\n const applied = applyFileMutations(\n projectDir,\n prepared.map(({ sourceFile, absPath, before, after }) => ({\n sourceFile,\n absPath,\n before,\n after,\n })),\n requestToken,\n writeFile,\n );\n const files: ElementPatchBatchFileResult[] = applied.map((file, index) => ({\n sourceFile: file.sourceFile,\n changed: file.changed,\n matched: prepared[index]?.matched ?? [],\n before: file.before,\n after: file.after,\n backupPath: file.backupPath ?? undefined,\n }));\n return { durable: true, files };\n}\n\nfunction commitElementPatchBatchesWithReceipts(\n c: RouteContext,\n projectDir: string,\n batches: ElementPatchBatchRequest[],\n): ReturnType<typeof commitElementPatchBatches> {\n return commitElementPatchBatches(\n projectDir,\n batches,\n undefined,\n c.req.header(\"X-Hyperframes-Write-Token\"),\n );\n}\n\n/**\n * Record the receipt that claims a mutation result.\n *\n * The file watcher broadcasts every write, including the ones Studio itself just\n * asked for. The receipt is what lets the client tell its own echo from an agent\n * or an editor writing the file behind its back: without one, the client treats\n * its own edit as an external change and does a full preview reload, which blanks\n * the stage for a few hundred milliseconds right after the user typed. Every\n * mutation route records through here so no route can forget.\n */\nfunction writeFileWithReceipt(\n c: RouteContext,\n filePath: string,\n absPath: string,\n html: string,\n): { version: string; writeToken: string } {\n const overwrote = readFileSync(absPath);\n replaceFileAtomically(absPath, html, statSync(absPath).mode);\n // The synchronous write cannot yield before its receipt is recorded; keep this block await-free.\n const version = fileContentVersion(html);\n const writeToken = createWriteToken(c.req.header(\"X-Hyperframes-Write-Token\"));\n recordFileWriteReceipt(absPath, { path: filePath, version, writeToken, overwrote });\n return { version, writeToken };\n}\n\nfunction writeMutationResult(\n c: RouteContext,\n projectDir: string,\n filePath: string,\n absPath: string,\n html: string,\n original: string,\n): { backupPath: string | null; version: string } | Response {\n const backup = snapshotBeforeWrite(projectDir, absPath);\n if (backup.error) return c.json({ error: `backup failed: ${backup.error}` }, 500);\n if (readFileSync(absPath, \"utf-8\") !== original) {\n return c.json({ error: \"file changed\", conflict: true, path: filePath }, 409);\n }\n const { version } = writeFileWithReceipt(c, filePath, absPath, html);\n return { backupPath: backupPathForResponse(projectDir, backup.backupPath), version };\n}\n\n/** Write `next` to `absPath` only if it differs from `original`, returning a standardized change response. */\nfunction writeIfChanged(\n c: RouteContext,\n projectDir: string,\n filePath: string,\n absPath: string,\n original: string,\n next: string,\n): Response {\n if (next === original) {\n return c.json({ ok: true, changed: false, content: original, path: filePath });\n }\n const mutationResult = writeMutationResult(c, projectDir, filePath, absPath, next, original);\n if (mutationResult instanceof Response) return mutationResult;\n const { backupPath } = mutationResult;\n return c.json({\n ok: true,\n changed: true,\n content: next,\n path: filePath,\n backupPath,\n });\n}\n\nfunction rejectUnsafeMutationValues(\n c: RouteContext,\n unsafeFields: UnsafeMutationValue[],\n): Response {\n return c.json(\n {\n error: \"mutation contains unsafe values\",\n fields: unsafeFields.map((field) => field.path),\n unsafeValues: unsafeFields,\n },\n 400,\n );\n}\n\nfunction elementPatchBatchCommitErrorResponse(\n c: RouteContext,\n error: Extract<ElementPatchCommitResult, { error: unknown }>[\"error\"],\n sourceFile: string,\n): Response {\n if (error === \"conflict\")\n return c.json({ error: \"file changed\", conflict: true, sourceFile }, 409);\n if (error === \"not-found\") return c.json({ error, sourceFile }, 404);\n if (error === \"forbidden\") return c.json({ error, sourceFile }, 403);\n return c.json({ error: \"duplicate source file\", sourceFile }, 400);\n}\n\n/**\n * Parse the request body and validate that `target` is present.\n * Returns `{ error }` if missing, or `{ target, body }` for the full parsed body.\n */\nasync function parseMutationBody<T extends { target?: MutationTarget }>(\n c: RouteContext & { req: { json(): Promise<unknown> } },\n): Promise<{ error: Response } | { target: MutationTarget; body: T }> {\n const body = (await (c.req as { json(): Promise<unknown> }).json().catch(() => null)) as T | null;\n if (!body?.target) {\n return { error: c.json({ error: \"target required\" }, 400) };\n }\n return { target: body.target, body };\n}\n\n/** Ensure the parent directory of a path exists, never recreating a project folder that is gone. */\nfunction ensureDir(projectDir: string, filePath: string) {\n mkdirWithinProject(projectDir, dirname(filePath));\n}\n\n/**\n * Generate a copy name: foo.html → foo (copy).html → foo (copy 2).html\n */\nfunction generateCopyPath(projectDir: string, originalPath: string): string {\n const ext = originalPath.includes(\".\") ? \".\" + originalPath.split(\".\").pop() : \"\";\n const base = ext ? originalPath.slice(0, -ext.length) : originalPath;\n\n // If already a copy, increment the number\n const copyMatch = base.match(/ \\(copy(?: (\\d+))?\\)$/);\n const cleanBase = copyMatch ? base.slice(0, -copyMatch[0].length) : base;\n let num = copyMatch ? (copyMatch[1] ? parseInt(copyMatch[1]) + 1 : 2) : 1;\n\n let candidate = num === 1 ? `${cleanBase} (copy)${ext}` : `${cleanBase} (copy ${num})${ext}`;\n while (existsSync(resolve(projectDir, candidate))) {\n num++;\n candidate = `${cleanBase} (copy ${num})${ext}`;\n }\n\n return candidate;\n}\n\n/**\n * Walk a directory recursively and return all file paths matching a filter.\n */\nfunction walkFiles(dir: string, filter: (name: string) => boolean): string[] {\n const results: string[] = [];\n for (const entry of readableEntries(dir)) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (\n entry.name === \"node_modules\" ||\n entry.name === \".thumbnails\" ||\n entry.name === \"renders\" ||\n entry.name === \".transcode-cache\"\n )\n continue;\n results.push(...walkFiles(full, filter));\n } else if (filter(entry.name)) {\n results.push(full);\n }\n }\n return results;\n}\n\nconst SKIPPED_ENTRY = new Set([\"EACCES\", \"EPERM\", \"ENOENT\"]);\n\nfunction skippable(error: unknown): boolean {\n return error instanceof Error && SKIPPED_ENTRY.has((error as NodeJS.ErrnoException).code ?? \"\");\n}\n\nfunction readableEntries(dir: string): Dirent[] {\n try {\n return readdirSync(dir, { withFileTypes: true });\n } catch (error) {\n if (skippable(error)) return [];\n throw error;\n }\n}\n\nfunction readableText(file: string): string | null {\n try {\n return readFileSync(file, \"utf-8\");\n } catch (error) {\n if (skippable(error)) return null;\n throw error;\n }\n}\n\nconst escapeRegExp = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nconst SEPARATOR = String.raw`\\\\{0,2}[\\\\/]`;\nconst REFERENCE_START = String.raw`(?<![\\w./\\\\+-])`;\nconst FILE_END = String.raw`(?![\\w-]|\\.\\w)`;\n\nconst ENTITY_SPELLINGS = HTML_ATTRIBUTE_ENTITIES;\n\nfunction referenceSpellings(char: string): string {\n const spellings = [escapeRegExp(char)];\n const encoded = encodeUrlPath(char);\n if (encoded !== char)\n spellings.push(encoded.replace(/[A-F]/g, (hex) => `[${hex}${hex.toLowerCase()}]`));\n if (ENTITY_SPELLINGS[char]) spellings.push(...ENTITY_SPELLINGS[char]);\n if ([\"'\", '\"', \"`\", \"$\", \" \", \"(\", \")\"].includes(char)) {\n spellings.push(escapeRegExp(`\${char}`), escapeRegExp(`\${escapeHtmlReference(char)}`));\n }\n const scriptSpelling = escapeQuotedReference(char, '\"');\n if (scriptSpelling !== char) spellings.push(escapeRegExp(scriptSpelling));\n if ([\"'\", \"`\", \"$\", \" \", \"(\", \")\"].includes(char)) spellings.push(escapeRegExp(`\\\\${char}`));\n if (/[\\t\\n\\f\\r =<>`]/.test(char)) spellings.push(`&#${char.codePointAt(0)!};`);\n if (char.charCodeAt(0) < 0x20 || char.charCodeAt(0) === 0x7f) {\n spellings.push(escapeRegExp(`\\\\${char.charCodeAt(0).toString(16)} `));\n }\n return spellings.length === 1 ? spellings[0]! : `(?:${spellings.join(\"|\")})`;\n}\n\ntype ReferenceSyntax = \"html\" | \"script\" | \"css\" | \"plain\";\ninterface ReferenceContext {\n syntax: ReferenceSyntax;\n url: boolean;\n htmlAttribute: boolean;\n encodeAll: boolean;\n quote: string;\n}\n\nfunction escapeHtmlReference(path: string): string {\n return path.replace(/[&\"']/g, (char) => ENTITY_SPELLINGS[char]![0]!);\n}\n\nfunction escapeQuotedReference(path: string, quote: string): string {\n const escaped = JSON.stringify(path).slice(1, -1);\n return quote === '\"'\n ? escaped\n : escaped.replace(new RegExp(escapeRegExp(quote), \"g\"), `\\\\${quote}`);\n}\n\nfunction escapeRawUrlPath(path: string): string {\n const encodeSpaces = path.startsWith(\" \") || path.endsWith(\" \");\n return path.replace(/[\\s\\S]/g, (char) => {\n if (char.charCodeAt(0) < 0x20 || \":?%#\\\\\".includes(char) || (encodeSpaces && char === \" \")) {\n return encodeUrlPath(char);\n }\n return char;\n });\n}\n\nfunction spellLike(\n reference: string,\n path: string,\n oldPath: string,\n context: ReferenceContext,\n): string {\n const { syntax, quote, url, encodeAll } = context;\n if (url && (encodeAll || (reference !== oldPath && /%[0-9A-Fa-f]{2}/.test(reference))))\n return encodeUrlPath(path);\n switch (syntax) {\n case \"html\": {\n const escaped = escapeHtmlReference(url ? escapeRawUrlPath(path) : path);\n return [\"'\", '\"'].includes(quote)\n ? escaped\n : escaped.replace(/[\\t\\n\\f\\r =<>`]/g, (char) => `&#${char.codePointAt(0)!};`);\n }\n case \"script\": {\n if (![\"'\", '\"', \"`\"].includes(quote)) return path;\n const escaped = escapeQuotedReference(path, quote);\n return quote === \"`\" ? escaped.replace(/\\$\\{/g, \"\\\\${\") : escaped;\n }\n case \"css\":\n return url ? encodeUrlPath(path) : path;\n case \"plain\":\n return path;\n }\n}\n\nfunction referenceSyntax(file: string): ReferenceSyntax {\n if (/\\.html$/i.test(file)) return \"html\";\n if (/\\.css$/i.test(file)) return \"css\";\n if (/\\.(?:[cm]?js|jsx|tsx?|json)$/i.test(file)) return \"script\";\n return \"plain\";\n}\n\nfunction decodeQuotedReference(text: string, syntax: ReferenceSyntax): string {\n if (syntax === \"css\") return decodeCssEscapes(text);\n if (syntax === \"script\") {\n const controls: Record<string, string> = { b: \"\\b\", f: \"\\f\", n: \"\\n\", r: \"\\r\", t: \"\\t\" };\n return text.replace(\n /\\\\(?:u([0-9a-fA-F]{4})|([bfnrt\"'`$\\\\/]))/g,\n (_escaped, hex: string | undefined, char: string | undefined) => {\n if (hex !== undefined) return String.fromCharCode(Number.parseInt(hex, 16));\n return controls[char!] ?? char!;\n },\n );\n }\n return text;\n}\n\nfunction referencePattern(oldPath: string, isDirectory: boolean): RegExp {\n const name = oldPath\n .split(\"/\")\n .map((segment) => Array.from(segment, referenceSpellings).join(\"\"))\n .join(SEPARATOR);\n const end = isDirectory ? `(?=${SEPARATOR})` : FILE_END;\n return new RegExp(\n String.raw`${REFERENCE_START}(?<lead>(?:\\.{1,2}${SEPARATOR}|${SEPARATOR}){0,4})${name}${end}`,\n \"g\",\n );\n}\n\nfunction rewriteEntityAttributes(text: string, rewrite: (text: string) => string): string {\n const parts: string[] = [];\n let cursor = 0;\n for (const tag of scanHtmlOpeningTags(text)) {\n for (const attr of tag.attributes) {\n if (attr.kind !== \"value\") continue;\n const decoded = decodeAuthoredAttribute(attr.value);\n if (decoded === attr.value) continue;\n let value = escapeHtmlReference(decoded);\n if (!attr.quote)\n value = value.replace(/[\\t\\n\\f\\r =<>`]/g, (char) => `&#${char.codePointAt(0)!};`);\n const source = `<x ${attr.name}=${attr.quote}${value}${attr.quote}>`;\n const updated = rewrite(source);\n if (updated === source) continue;\n const replacement = scanHtmlOpeningTags(updated)[0]!.attributes[0]!;\n if (replacement.kind !== \"value\") throw new Error(\"Reference rewrite removed its attribute\");\n parts.push(text.slice(cursor, attr.valueStart), replacement.value);\n cursor = attr.valueEnd;\n }\n }\n parts.push(text.slice(cursor));\n return parts.join(\"\");\n}\n\n// A match inside the longer path of a file or folder that exists (`a.png&b.png`, `other assets/`) is that path's.\n// Existing paths are indexed by the text after the old path, then the text before it, so a match costs a few lookups.\nexport function referenceRewriter(\n oldPath: string,\n newPath: string,\n isDirectory: boolean,\n existing: readonly string[] = [],\n): (text: string, syntax?: ReferenceSyntax) => string {\n const oldIdentity = sep === \"\\\\\" ? oldPath.replace(/\\\\/g, \"/\") : oldPath;\n const pattern = referencePattern(oldPath, isDirectory);\n const around = new Map<string, Map<number, Set<string>>>();\n const afterLengths = new Set<number>();\n let window = 0;\n for (const path of existing) {\n if (path.length <= oldPath.length) continue;\n for (const start of occurrences(path, oldPath)) {\n const [before, after] = [path.slice(0, start), path.slice(start + oldPath.length)];\n const befores = around.get(after) ?? around.set(after, new Map()).get(after)!;\n (befores.get(before.length) ?? befores.set(before.length, new Set()).get(before.length)!).add(\n before,\n );\n afterLengths.add(after.length);\n window = Math.max(window, path.length * 9);\n }\n }\n const normalized = (text: string, context: ReferenceContext, full = false) => {\n let value = text;\n if (context.syntax === \"html\" || context.htmlAttribute) {\n value = decodeAuthoredAttribute(value);\n }\n value = decodeQuotedReference(value, context.syntax);\n if (context.url) {\n value = value.replace(/\\\\/g, \"/\");\n value = full ? decodedUrlPath(value) : decodeWellFormedEscapes(value);\n }\n return sep === \"\\\\\" ? value.replace(/\\\\/g, \"/\") : value;\n };\n return function rewriteText(text, syntax = \"html\", normalizeEntities = true) {\n if (syntax === \"html\" && normalizeEntities) {\n text = rewriteEntityAttributes(text, (source) => rewriteText(source, \"html\", false));\n }\n pattern.lastIndex = 0;\n if (!pattern.test(text)) return text;\n pattern.lastIndex = 0;\n const tags = syntax === \"html\" ? scanHtmlOpeningTags(text) : [];\n const inlineRegions = tags\n .filter(\n (tag) => tag.closed && [\"script\", \"style\"].includes(tag.name) && tag.rawTextEnd !== null,\n )\n .map((tag) => ({\n start: tag.end,\n end: tag.rawTextEnd!,\n syntax: tag.name === \"style\" ? (\"css\" as const) : (\"script\" as const),\n }));\n const attributes = tags.flatMap((tag) =>\n tag.attributes.flatMap((attr) => (attr.kind === \"value\" ? [attr] : [])),\n );\n const cssContexts =\n syntax === \"css\"\n ? [{ start: 0, end: text.length, htmlAttribute: false }]\n : [\n ...inlineRegions\n .filter((region) => region.syntax === \"css\")\n .map((region) => ({ ...region, htmlAttribute: false })),\n ...attributes\n .filter((attr) => attr.name === \"style\")\n .map((attr) => ({ ...attr, htmlAttribute: true })),\n ];\n const cssFields = (pattern: RegExp) =>\n cssContexts.flatMap((context) =>\n [...text.slice(context.start, context.end).matchAll(pattern)].map((match) => {\n const prefix = /^(?:url\\(\\s*|@import\\s+)/i.exec(match[0])![0];\n const rest = match[0].slice(prefix.length);\n const delimiter = context.htmlAttribute\n ? /^(?:[\"']|"|'|')/.exec(rest)?.[0]\n : /^[\"']/.exec(rest)?.[0];\n const start = context.start + match.index! + prefix.length + (delimiter?.length ?? 0);\n return {\n start,\n end: context.start + match.index! + match[0].length,\n syntax: \"css\" as const,\n htmlAttribute: context.htmlAttribute,\n encodeAll: true,\n };\n }),\n );\n const urlRegions = [\n ...attributes\n .filter((attr) => [\"src\", \"href\", \"poster\", \"xlink:href\"].includes(attr.name))\n .map((attr) => ({\n start: attr.valueStart + (/^[\\t\\n\\f\\r ]*/.exec(attr.value)?.[0].length ?? 0),\n end: attr.valueEnd,\n syntax: \"html\" as const,\n htmlAttribute: true,\n encodeAll: false,\n })),\n ...attributes\n .filter((attr) => attr.name === \"srcset\")\n .flatMap((attr) =>\n [...attr.value.matchAll(/(^|,)[\\t\\n\\f\\r ]*([^,\\t\\n\\f\\r ]+)/g)].map((match) => ({\n start: attr.valueStart + match.index! + match[0].length - match[2]!.length,\n end: attr.valueStart + match.index! + match[0].length,\n syntax: \"html\" as const,\n htmlAttribute: true,\n encodeAll: true,\n })),\n ),\n ...cssFields(\n /\\burl\\((?:\\s*\"(?:\\\\.|[^\"\\\\])*\"\\s*|\\s*'(?:\\\\.|[^'\\\\])*'\\s*|(?:\\\\.|[^)\\\\])*)\\)/gi,\n ),\n ...cssFields(/@import\\s+(?:\"[^\"]*\"|'[^']*')/gi),\n ].sort((a, b) => a.start - b.start);\n let urlIndex = 0;\n let regionIndex = 0;\n return text.replace(pattern, (...args) => {\n const [match, offset] = [args[0] as string, args.at(-3) as number];\n const { lead } = args.at(-1) as { lead: string };\n while (inlineRegions[regionIndex] && inlineRegions[regionIndex]!.end <= offset) regionIndex++;\n const region = inlineRegions[regionIndex];\n const matchSyntax = region && offset >= region.start ? region.syntax : syntax;\n while (urlRegions[urlIndex] && urlRegions[urlIndex]!.end <= offset) urlIndex++;\n const urlRegion = urlRegions[urlIndex];\n const url = matchSyntax !== \"script\" && !!urlRegion && offset >= urlRegion.start;\n const context: ReferenceContext = {\n syntax: url ? urlRegion!.syntax : matchSyntax,\n url,\n htmlAttribute: url && urlRegion!.htmlAttribute,\n encodeAll: url && urlRegion!.encodeAll,\n quote: text[offset - 1] ?? \"\",\n };\n if (url && offset !== urlRegion!.start) return match;\n const reference = match.slice(lead.length);\n if (normalized(reference, context, true) !== oldIdentity) return match;\n if (\n isDirectory &&\n !normalized(\n text.slice(offset + match.length, offset + match.length + 4),\n context,\n ).startsWith(\"/\")\n )\n return match;\n const at = offset + lead.length;\n const head = normalized(text.slice(Math.max(0, at - window), at), context);\n const tail = normalized(\n text.slice(offset + match.length, offset + match.length + window),\n context,\n context.url,\n );\n const inLonger = [...afterLengths].some((after) => {\n const befores = tail.length >= after && around.get(tail.slice(0, after));\n return (\n befores &&\n [...befores].some(\n ([length, set]) => head.length >= length && set.has(head.slice(head.length - length)),\n )\n );\n });\n if (inLonger) return match;\n return `${lead}${spellLike(reference, newPath, oldPath, context)}`;\n });\n };\n}\n\nfunction occurrences(text: string, part: string): number[] {\n const at: number[] = [];\n for (let i = text.indexOf(part); i >= 0; i = text.indexOf(part, i + 1)) at.push(i);\n return at;\n}\n\nfunction projectPaths(\n root: string,\n dir = root,\n prefix = \"\",\n ancestors: ReadonlySet<string> = new Set(),\n): string[] {\n return readableEntries(dir).flatMap((entry) => {\n const [path, full] = [`${prefix}${entry.name}`, join(dir, entry.name)];\n const real = entry.name === \"node_modules\" ? null : directoryReal(entry, full);\n if (real === null || ancestors.has(real) || !isSafePath(root, full)) return [path];\n return [path, ...projectPaths(root, full, `${path}/`, new Set([...ancestors, real]))];\n });\n}\n\n// A directory's real path, through a link, or null for anything else: aliases are paths too.\nfunction directoryReal(entry: Dirent, full: string): string | null {\n try {\n return entry.isDirectory() || (entry.isSymbolicLink() && statSync(full).isDirectory())\n ? realpathSync(full)\n : null;\n } catch {\n return null;\n }\n}\n\n/**\n * After a rename, update all references to the old path in project files.\n * Scans HTML, CSS, JS, and JSON files for the old path and replaces it where it names that path.\n */\nfunction updateReferences(\n projectDir: string,\n oldPath: string,\n newPath: string,\n isDirectory: boolean,\n): number {\n const textFiles = walkFiles(projectDir, (name) =>\n /\\.(html|css|js|jsx|ts|tsx|json|mjs|cjs|md|mdx)$/i.test(name),\n );\n\n const rewrite = referenceRewriter(oldPath, newPath, isDirectory, projectPaths(projectDir));\n let updatedCount = 0;\n for (const file of textFiles) {\n if (!isSafePath(projectDir, file) || isPrivateProjectFile(projectDir, file)) continue;\n const content = readableText(file);\n if (content === null) continue;\n\n const updated = rewrite(content, referenceSyntax(file));\n if (updated !== content) {\n replaceFileAtomically(file, updated, statSync(file).mode);\n updatedCount++;\n }\n }\n return updatedCount;\n}\n\n// ── GSAP script extraction ──────────────────────────────────────────────────\n\n/**\n * Mint the HTML's ids (so a tween saved on a served id writes that id too), parse it with\n * linkedom, locate the inline `<script>` holding GSAP timeline code, and return its text and\n * a function that replaces that script block and serialises back to HTML.\n */\nfunction extractGsapScriptBlock(html: string): {\n scriptText: string;\n document: Document;\n root: ParentNode;\n replaceScript: (newText: string) => string;\n} | null {\n const { document } = parseHTML(ensureHfIds(html));\n const scripts = [\n ...document.querySelectorAll(\"script:not([src])\"),\n ...Array.from(document.querySelectorAll(\"template\")).flatMap((tmpl) =>\n Array.from(tmpl.querySelectorAll(\"script:not([src])\")),\n ),\n ];\n const script = findTimelineScript(scripts);\n if (!script) return null;\n return {\n scriptText: script.textContent || \"\",\n document,\n root: clipQueryRoot(script),\n replaceScript(newText: string): string {\n script.textContent = newText;\n return document.toString();\n },\n };\n}\n\n/**\n * Remove every GSAP animation that targets `selector` from an HTML string's\n * inline script. Used after unwrapping a group so its leftover `gsap.set(\"#id\")`\n * (the wrapper is gone) doesn't throw \"target not found\" on every preview run.\n */\nfunction stripGsapAnimationsForSelector(html: string, selector: string): string {\n const block = extractGsapScriptBlock(html);\n if (!block) return html;\n const parsed = parseGsapScriptAcorn(block.scriptText);\n const matching = parsed.animations.filter((a) => a.targetSelector === selector);\n if (matching.length === 0) return html;\n let script = block.scriptText;\n // Reverse so earlier removals don't shift the spans of later ones.\n for (const anim of [...matching].reverse()) {\n script = removeAnimationFromScript(script, anim.id);\n }\n return block.replaceScript(script);\n}\n\n/**\n * Bake a group's STATIC GSAP transform into each member BEFORE the group is\n * stripped on ungroup. Moving a group is stored as `gsap.set(\"#group-1\",{x,y,…})`;\n * without distributing it to the members they snap back to their creation-time\n * positions. Translation (x/y/z) is an exact per-axis add; rotation/scale are\n * composed about the group's centre (the pivot) so off-centre members don't drift.\n * Animated group transforms (keyframes/tweens) are NOT baked — left to be stripped.\n */\nfunction bakeGroupTransformIntoMembers(\n html: string,\n groupId: string,\n members: Array<{ id: string; cx: number; cy: number }>,\n groupCenter: { cx: number; cy: number },\n): string {\n const block = extractGsapScriptBlock(html);\n if (!block) return html;\n const parsed = parseGsapScriptAcorn(block.scriptText);\n const groupSel = `#${groupId}`;\n const groupSets = parsed.animations.filter(\n (a) => a.targetSelector === groupSel && a.method === \"set\",\n );\n if (groupSets.length === 0) return html;\n // Merge the group's sets (later per-prop wins) → its effective static transform.\n const gt: Record<string, number> = {};\n for (const s of groupSets) {\n for (const [k, v] of Object.entries(s.properties)) if (typeof v === \"number\") gt[k] = v;\n }\n const gx = gt.x ?? 0;\n const gy = gt.y ?? 0;\n const gz = gt.z ?? 0;\n const grot = gt.rotation ?? 0;\n const gscale = gt.scale ?? 1;\n // Identity across ALL axes (incl. the extras baked below) — else a group whose\n // only transform is e.g. scaleX would skip the bake and silently drop it.\n const isScaleAxis = (k: string) => k === \"scale\" || k === \"scaleX\" || k === \"scaleY\";\n const groupIsIdentity = Object.entries(gt).every(([k, v]) =>\n isScaleAxis(k) ? v === 1 : v === 0,\n );\n if (groupIsIdentity) return html;\n\n const rad = (grot * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const round3 = (n: number) => Math.round(n * 1000) / 1000;\n\n let script = block.scriptText;\n for (const m of members) {\n const memberSel = `#${m.id}`;\n const sets = parsed.animations.filter(\n (a) => a.targetSelector === memberSel && a.method === \"set\",\n );\n // Effective member transform (merge its sets — last per-prop wins).\n const mProps: Record<string, number | string> = {};\n for (const s of sets) Object.assign(mProps, s.properties);\n const mx = typeof mProps.x === \"number\" ? mProps.x : 0;\n const my = typeof mProps.y === \"number\" ? mProps.y : 0;\n // Compose the group transform onto the member's centre, then back to an offset.\n const dx = m.cx + mx - groupCenter.cx;\n const dy = m.cy + my - groupCenter.cy;\n const visX = groupCenter.cx + gscale * (cos * dx - sin * dy) + gx;\n const visY = groupCenter.cy + gscale * (sin * dx + cos * dy) + gy;\n const newProps: Record<string, number | string> = {\n ...mProps,\n x: round3(visX - m.cx),\n y: round3(visY - m.cy),\n };\n if (gz !== 0) newProps.z = (typeof mProps.z === \"number\" ? mProps.z : 0) + gz;\n if (grot !== 0) {\n newProps.rotation = round3(\n (typeof mProps.rotation === \"number\" ? mProps.rotation : 0) + grot,\n );\n }\n if (gscale !== 1) {\n newProps.scale = round3((typeof mProps.scale === \"number\" ? mProps.scale : 1) * gscale);\n }\n // Bake any REMAINING group transform axis so nothing is silently dropped on\n // ungroup. The pivot-composed axes (x/y/z/rotation/scale) are handled above;\n // these extras (scaleX/Y, rotationX/Y/Z, skewX/Y, transformPerspective) compose\n // about the member's own origin — exact for a member at the group centre, a\n // close approximation otherwise (groups rarely carry these).\n const pivoted = new Set([\"x\", \"y\", \"z\", \"rotation\", \"scale\"]);\n for (const [k, v] of Object.entries(gt)) {\n if (pivoted.has(k) || typeof v !== \"number\") continue;\n if (k === \"scaleX\" || k === \"scaleY\") {\n if (v !== 1) newProps[k] = round3((typeof mProps[k] === \"number\" ? mProps[k] : 1) * v);\n } else if (k === \"transformPerspective\") {\n // Adopt the group's lens only if the member has none of its own — never\n // silently overwrite a member's existing perspective.\n if (typeof mProps[k] !== \"number\") newProps[k] = v;\n } else if (v !== 0) {\n newProps[k] = round3((typeof mProps[k] === \"number\" ? mProps[k] : 0) + v);\n }\n }\n\n // Strip ALL the member's existing sets and write ONE fresh gsap.set at position\n // 0. The baked transform is the member's static base — writing it to an arbitrary\n // \"last\" set could land it at a non-zero timeline position, or leave stale earlier\n // sets that override it. Reverse-remove so spans don't shift, then add fresh.\n for (const s of [...sets].reverse()) {\n script = removeAnimationFromScript(script, s.id);\n }\n script = addAnimationToScript(script, {\n targetSelector: memberSel,\n method: \"set\",\n position: 0,\n properties: newProps,\n global: true,\n }).script;\n }\n return block.replaceScript(script);\n}\n\nfunction stripStudioEditsFromTarget(document: Document, selector: string): number {\n if (!selector) return 0;\n let stripped = 0;\n try {\n for (const el of document.querySelectorAll(selector)) {\n if (!isHTMLElement(el)) continue;\n const htmlEl = el;\n let touched = false;\n // Manual path offset (--hf-studio-offset / translate) — a GSAP position tween\n // now owns position, so the stale offset channel must go.\n if (el.getAttribute(\"data-hf-studio-path-offset\")) {\n const originalTranslate = el.getAttribute(\"data-hf-studio-original-inline-translate\");\n htmlEl.style.removeProperty(\"--hf-studio-offset-x\");\n htmlEl.style.removeProperty(\"--hf-studio-offset-y\");\n if (originalTranslate) {\n htmlEl.style.setProperty(\"translate\", originalTranslate);\n } else {\n htmlEl.style.removeProperty(\"translate\");\n }\n el.removeAttribute(\"data-hf-studio-path-offset\");\n el.removeAttribute(\"data-hf-studio-original-translate\");\n el.removeAttribute(\"data-hf-studio-original-inline-translate\");\n touched = true;\n }\n // Manual rotation (--hf-studio-rotation / rotate) — likewise, a GSAP rotation\n // set/tween now owns rotation, so clear the legacy CSS-var channel.\n if (el.getAttribute(\"data-hf-studio-rotation\")) {\n const originalRotate = el.getAttribute(\"data-hf-studio-original-inline-rotate\");\n const originalOrigin = el.getAttribute(\"data-hf-studio-original-rotation-transform-origin\");\n htmlEl.style.removeProperty(\"--hf-studio-rotation\");\n if (originalRotate) {\n htmlEl.style.setProperty(\"rotate\", originalRotate);\n } else {\n htmlEl.style.removeProperty(\"rotate\");\n }\n if (originalOrigin) {\n htmlEl.style.setProperty(\"transform-origin\", originalOrigin);\n } else {\n htmlEl.style.removeProperty(\"transform-origin\");\n }\n el.removeAttribute(\"data-hf-studio-rotation\");\n el.removeAttribute(\"data-hf-studio-rotation-draft\");\n el.removeAttribute(\"data-hf-studio-original-rotate\");\n el.removeAttribute(\"data-hf-studio-original-inline-rotate\");\n el.removeAttribute(\"data-hf-studio-original-rotation-transform-origin\");\n touched = true;\n }\n if (touched) stripped++;\n }\n } catch {\n // Invalid selector — skip silently.\n }\n return stripped;\n}\n\n// A studio path-offset (--hf-studio-offset / data-hf-studio-path-offset) and a GSAP\n// position tween both drive translate — keeping both stacks the offsets (a gesture or\n// drag recorded over a stale offset plays shoved off-position). When a committed tween\n// writes a position property, the tween owns position, so the stale offset must go.\nfunction keyframesWritePosition(\n keyframes: Array<{ properties: Record<string, number | string> }>,\n): boolean {\n return keyframes.some((kf) =>\n Object.keys(kf.properties).some((k) => classifyPropertyGroup(k) === \"position\"),\n );\n}\n\n// A studio rotation edit (--hf-studio-rotation / data-hf-studio-rotation) and a GSAP\n// rotation tween both drive rotate — keeping both stacks them. When a committed keyframe\n// set writes a rotation property, the tween owns rotation, so the stale CSS-var channel\n// must go (the position twin of this is `keyframesWritePosition`).\nfunction keyframesWriteRotation(\n keyframes: Array<{ properties: Record<string, number | string> }>,\n): boolean {\n return keyframes.some((kf) =>\n Object.keys(kf.properties).some((k) => classifyPropertyGroup(k) === \"rotation\"),\n );\n}\n\nfunction lastKeyframeOpacity(kfs: GsapAnimation[\"keyframes\"]): number | string | undefined {\n if (!kfs) return undefined;\n for (let i = kfs.keyframes.length - 1; i >= 0; i--) {\n if (\"opacity\" in kfs.keyframes[i]!.properties) return kfs.keyframes[i]!.properties.opacity;\n }\n return undefined;\n}\n\nfunction resolveFinalOpacity(anim: GsapAnimation): number | null {\n if (anim.method === \"from\") return null;\n const raw = anim.keyframes ? lastKeyframeOpacity(anim.keyframes) : anim.properties.opacity;\n if (raw == null) return null;\n if (typeof raw === \"string\" && /^[+\\-*]=/.test(raw)) return null;\n const num = Number(raw);\n return Number.isFinite(num) && num !== 0 ? num : null;\n}\n\nfunction bakeVisibilityOnDelete(document: Document, anim: GsapAnimation): void {\n const opacity = resolveFinalOpacity(anim);\n if (opacity === null) return;\n try {\n for (const el of document.querySelectorAll(anim.targetSelector)) {\n if (isHTMLElement(el)) el.style.setProperty(\"opacity\", String(opacity));\n }\n } catch {\n // Invalid selector — skip silently.\n }\n}\n\n// ── GSAP mutation types ─────────────────────────────────────────────────────\n\nexport type GsapMutationRequest =\n | {\n type: \"update-property\";\n animationId: string;\n property: string;\n value: number | string;\n }\n | {\n // Merge MULTIPLE properties into an animation in ONE call. A per-property\n // loop on a `set` can shift its group-derived id mid-way (e.g. adding `scale`\n // to a rotation set), 404-ing the next update; this lands them all at once.\n type: \"update-properties\";\n animationId: string;\n properties: Record<string, number | string>;\n }\n | {\n type: \"update-from-property\";\n animationId: string;\n property: string;\n value: number | string;\n }\n | {\n type: \"update-meta\";\n animationId: string;\n updates: {\n duration?: number;\n ease?: string;\n easeEach?: string;\n position?: number;\n resetKeyframeEases?: boolean;\n };\n }\n | {\n type: \"add\";\n targetSelector: string;\n method: \"to\" | \"from\" | \"set\" | \"fromTo\";\n position: number;\n duration?: number;\n ease?: string;\n properties: Record<string, number | string>;\n fromProperties?: Record<string, number | string>;\n /** Emit a base `gsap.set` (off-timeline, no keyframe marker) instead of `tl.set`. */\n global?: boolean;\n }\n | { type: \"delete\"; animationId: string; stripStudioEdits?: boolean }\n | {\n type: \"add-property\";\n animationId: string;\n property: string;\n defaultValue: number | string;\n }\n | {\n type: \"add-from-property\";\n animationId: string;\n property: string;\n defaultValue: number | string;\n }\n | { type: \"remove-property\"; animationId: string; property: string }\n | { type: \"remove-from-property\"; animationId: string; property: string }\n | {\n type: \"add-keyframe\";\n animationId: string;\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n backfillDefaults?: Record<string, number | string>;\n }\n | { type: \"remove-keyframe\"; animationId: string; percentage: number }\n | {\n type: \"move-keyframe\";\n animationId: string;\n fromPercentage: number;\n toPercentage: number;\n }\n | {\n // Boundary drag-to-retime: grow/shift a keyframed tween's window and re-key\n // its existing keyframes in place (preserves _auto / per-keyframe ease /\n // easeEach / outer ease, unlike the array-rebuild replace-with-keyframes).\n type: \"resize-keyframed-tween\";\n animationId: string;\n position: number;\n duration: number;\n pctRemap: Array<{ from: number; to: number }>;\n }\n | {\n type: \"update-keyframe\";\n animationId: string;\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n }\n | {\n type: \"convert-to-keyframes\";\n animationId: string;\n resolvedFromValues?: Record<string, number | string>;\n /** Duration (s) to give a converted static `set`, which has none. */\n duration?: number;\n }\n | { type: \"remove-all-keyframes\"; animationId: string }\n | {\n type: \"materialize-keyframes\";\n animationId: string;\n keyframes: Array<{\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n }>;\n easeEach?: string;\n resolvedSelector?: string;\n allElements?: Array<{\n selector: string;\n keyframes: Array<{ percentage: number; properties: Record<string, number | string> }>;\n easeEach?: string;\n }>;\n }\n | {\n type: \"set-arc-path\";\n animationId: string;\n enabled: boolean;\n autoRotate?: boolean | number;\n segments?: Array<{\n curviness: number;\n cp1?: { x: number; y: number };\n cp2?: { x: number; y: number };\n }>;\n }\n | {\n type: \"update-arc-segment\";\n animationId: string;\n segmentIndex: number;\n curviness?: number;\n cp1?: { x: number; y: number };\n cp2?: { x: number; y: number };\n }\n | {\n type: \"update-motion-path-point\";\n animationId: string;\n pointIndex: number;\n x: number;\n y: number;\n }\n | { type: \"add-motion-path-point\"; animationId: string; index: number; x: number; y: number }\n | { type: \"remove-motion-path-point\"; animationId: string; index: number }\n | {\n type: \"add-motion-path\";\n targetSelector: string;\n position: number;\n duration: number;\n x: number;\n y: number;\n ease?: string;\n }\n | { type: \"remove-arc-path\"; animationId: string }\n | {\n type: \"add-with-keyframes\";\n targetSelector: string;\n position: number;\n duration: number;\n keyframes: Array<{\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n auto?: boolean;\n }>;\n ease?: string;\n easeEach?: string;\n }\n | {\n type: \"replace-with-keyframes\";\n animationId: string;\n targetSelector: string;\n position: number;\n duration: number;\n keyframes: Array<{\n percentage: number;\n properties: Record<string, number | string>;\n ease?: string;\n auto?: boolean;\n }>;\n ease?: string;\n easeEach?: string;\n }\n | {\n type: \"split-animations\";\n originalId: string;\n newId: string;\n splitTime: number;\n elementStart: number;\n elementDuration: number;\n }\n | {\n type: \"split-into-property-groups\";\n animationId: string;\n }\n | {\n type: \"delete-all-for-selector\";\n targetSelector: string;\n }\n | {\n // Enforce \"exactly one position write per element\": keep `keepAnimationId`\n // (the write the commit is editing) and strip every other pure-position\n // write for the selector. Self-heals files that already have duplicates.\n type: \"consolidate-position-writes\";\n targetSelector: string;\n keepAnimationId?: string;\n }\n | {\n // Rewrite all top-level helper/loop constructs into literal tweens so\n // computed keyframes become directly editable (visual no-op).\n type: \"unroll-timeline\";\n }\n | {\n type: \"shift-positions\";\n targetSelector: string;\n delta: number;\n }\n | {\n // Batched shift: fold shiftPositionsInScript over N selectors in one write.\n // Lets a multi-clip timeline move (ripple / insert) shift every affected\n // clip's tweens atomically instead of one racing server round-trip per clip.\n type: \"shift-positions-batch\";\n shifts: Array<{ targetSelector: string; delta: number }>;\n }\n | {\n type: \"scale-positions\";\n targetSelector: string;\n oldStart: number;\n oldDuration: number;\n newStart: number;\n newDuration: number;\n };\n\n// ── GSAP mutation executor ──────────────────────────────────────────────────\n\ntype GsapMutationResult = string | { script: string; skippedSelectors: string[] };\n\nfunction replaceInPlaceUnlessSetOrUnknown(\n scriptText: string,\n body: Extract<GsapMutationRequest, { type: \"replace-with-keyframes\" }>,\n): string {\n const edit = { ...body, easeEach: resolveReplacementEaseEach(scriptText, body) };\n const inPlace = replaceTweenWithKeyframesInScript(scriptText, body.animationId, edit);\n if (inPlace !== null) return inPlace;\n const script = removeAnimationFromScript(scriptText, body.animationId);\n return addAnimationWithKeyframesToScript(\n script,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n edit.easeEach,\n ).script;\n}\n\nfunction resolveReplacementEaseEach(\n scriptText: string,\n request: { animationId: string; easeEach?: string },\n): string | undefined {\n if (request.easeEach !== undefined) return request.easeEach;\n const original = parseGsapScriptAcorn(scriptText).animations.find(\n (animation) => animation.id === request.animationId,\n );\n if (!original?.arcPath?.enabled) return undefined;\n return original?.keyframes?.easeEach ?? original?.ease;\n}\n\n// Mutations that can change a position tween's first keyframe (value/existence/timing)\n// and therefore require the pre-keyframe hold-`set`s to be re-synced afterwards.\n// `syncPositionHoldsBeforeKeyframes` rebuilds all `hf-hold` sets from scratch: it acts\n// on every tween whose 0% keyframe carries a position prop and\n// whose start is > 0. So any mutation that creates such a tween, retargets it, or moves\n// its start across the t=0 boundary must trigger a re-sync.\nconst HOLD_SYNC_MUTATION_TYPES = new Set<string>([\n \"add-keyframe\",\n \"update-keyframe\",\n \"remove-keyframe\",\n \"move-keyframe\",\n \"resize-keyframed-tween\",\n \"remove-all-keyframes\",\n \"add-with-keyframes\",\n \"replace-with-keyframes\",\n \"convert-to-keyframes\",\n \"materialize-keyframes\",\n \"update-motion-path-point\",\n \"add-motion-path-point\",\n \"remove-motion-path-point\",\n // Authors a fresh motionPath tween whose parsed first keyframe is (0,0); if it lands\n // at position > 0 the element snaps home at t=0 without a pre-tween hold-`set`.\n \"add-motion-path\",\n // Can move a tween's `position` (start) across the t=0 boundary, which flips whether a\n // keyframed position tween needs a hold (started at 0 → moved later, or vice versa).\n \"update-meta\",\n // Time-shift / time-scale tweens, which can move a keyframed position tween's start\n // across t=0, flipping hold need; stale holds are not repositioned by these ops.\n \"shift-positions\",\n \"shift-positions-batch\",\n \"scale-positions\",\n // Retargets keyframed position tweens to a cloned element's selector; the old hold is\n // keyed to the prior selector, so holds must be rebuilt for the new target.\n \"split-animations\",\n \"delete\",\n \"delete-all-for-selector\",\n]);\n\nasync function executeGsapMutation(\n body: GsapMutationRequest,\n block: NonNullable<ReturnType<typeof extractGsapScriptBlock>>,\n respond: (data: unknown, status?: number) => Response,\n writer: \"recast\" | \"acorn\",\n): Promise<GsapMutationResult | Response> {\n // Keep writer selection explicit at the route boundary so a batch cannot\n // switch implementations between operations.\n if (writer === \"recast\") {\n return executeGsapMutationRecast(body, block, respond);\n }\n return executeGsapMutationAcorn(body, block, respond);\n}\n\nfunction validateGsapMutationRequest(\n c: RouteContext,\n body: GsapMutationRequest | null,\n): Response | null {\n if (!body || typeof body !== \"object\" || !(\"type\" in body) || !body.type) {\n return c.json({ error: \"mutation type required\" }, 400);\n }\n if (containsRawGsapExpression(body)) {\n return c.json({ error: \"raw JavaScript expressions are not accepted\" }, 400);\n }\n const unsafeFields = findUnsafeMutationValues(body);\n if (unsafeFields.length > 0) return rejectUnsafeMutationValues(c, unsafeFields);\n if (\n body.type === \"shift-positions-batch\" &&\n (!(\"shifts\" in body) || !Array.isArray(body.shifts))\n ) {\n return c.json({ error: \"shift-positions-batch requires a `shifts` array\" }, 400);\n }\n return null;\n}\n\nfunction containsRawGsapExpression(value: unknown): boolean {\n if (typeof value === \"string\") return value.startsWith(\"__raw:\");\n if (Array.isArray(value)) return value.some(containsRawGsapExpression);\n if (!value || typeof value !== \"object\") return false;\n return Object.values(value).some(containsRawGsapExpression);\n}\n\nasync function prepareGsapMutationScript(\n c: RouteContext,\n res: ResolvedGsapFile,\n firstMutation: GsapMutationRequest,\n): Promise<\n | Response\n | {\n html: string;\n beforeHtml: string;\n block: NonNullable<ReturnType<typeof extractGsapScriptBlock>>;\n }\n> {\n const beforeHtml = readFileSync(res.absPath, \"utf-8\");\n let html = beforeHtml;\n let block = extractGsapScriptBlock(html);\n if (!block && (firstMutation.type === \"add\" || firstMutation.type === \"add-with-keyframes\")) {\n const compId = html.match(/data-composition-id=\"([^\"]+)\"/)?.[1] ?? \"main\";\n const { GSAP_CDN } = await import(\"@hyperframes/core\");\n const bootstrap = [\n `<script src=\"${GSAP_CDN}\"></script>`,\n \"<script>\",\n \"window.__timelines = window.__timelines || {};\",\n \"const tl = gsap.timeline({ paused: true });\",\n `window.__timelines[\"${compId}\"] = tl;`,\n \"</script>\",\n ].join(\"\\n\");\n const [first, second] = hasCompositionOutsideTemplates(html)\n ? ([\"body\", \"template\"] as const)\n : ([\"template\", \"body\"] as const);\n html =\n insertBeforeCloseTag(html, first, `${bootstrap}\\n`) ??\n insertBeforeCloseTag(html, second, `${bootstrap}\\n`) ??\n `${html}\\n${bootstrap}`;\n block = extractGsapScriptBlock(html);\n }\n if (\n !block &&\n (firstMutation.type === \"shift-positions\" ||\n firstMutation.type === \"scale-positions\" ||\n firstMutation.type === \"shift-positions-batch\")\n ) {\n return c.json({\n ok: true,\n changed: false,\n mutated: false,\n parsed: { animations: [], timelineVar: \"tl\", preamble: \"\", postamble: \"\" },\n before: html,\n after: html,\n scriptText: \"\",\n path: res.filePath,\n backupPath: null,\n });\n }\n if (!block) return c.json({ error: \"no GSAP script found in file\" }, 400);\n return { html, beforeHtml, block };\n}\n\ntype RetimeSlot = ClipTweenRetime | \"no-op\";\n\nfunction retimeRuns(mutations: readonly GsapMutationRequest[]): Map<number, RetimeSlot[]> {\n const runs = new Map<number, RetimeSlot[]>();\n let start = -1;\n mutations.forEach((mutation, index) => {\n const retime = clipRetimeOf(mutation);\n if (!retime) return void (start = -1);\n if (start < 0) runs.set((start = index), []);\n runs.get(start)!.push(retime);\n });\n return runs;\n}\n\n// The one owner of the clip-retime no-op rules; a no-op keeps its slot so flags line up.\nfunction clipRetimeOf(mutation: GsapMutationRequest): RetimeSlot | null {\n if (mutation.type === \"shift-positions\") {\n const { targetSelector, delta } = mutation;\n return targetSelector && Number.isFinite(delta) && delta !== 0\n ? { kind: \"shift\", targetSelector, delta }\n : \"no-op\";\n }\n if (mutation.type !== \"scale-positions\") return null;\n const { targetSelector, oldStart, oldDuration, newStart, newDuration } = mutation;\n const finite = [oldStart, oldDuration, newStart, newDuration].every(Number.isFinite);\n if (!targetSelector || !finite || oldDuration <= 0 || newDuration <= 0) return \"no-op\";\n if (oldStart === newStart && oldDuration === newDuration) return \"no-op\";\n return { kind: \"scale\", targetSelector, oldStart, oldDuration, newStart, newDuration };\n}\n\nfunction retimeRun(script: string, run: readonly RetimeSlot[], root: ParentNode | undefined) {\n const live = run.filter((slot): slot is ClipTweenRetime => slot !== \"no-op\");\n const retimed = retimeClipTweensInScript(script, live, root);\n const synced = syncPositionHoldsBeforeKeyframes(retimed.script, script);\n let next = 0;\n const changed = run.map((slot) => slot !== \"no-op\" && retimed.changed[next++]!);\n if (synced !== retimed.script) changed[changed.length - 1] = true;\n return { script: synced, changed: synced === script ? changed.map(() => false) : changed };\n}\n\nasync function applyGsapMutations(\n c: RouteContext,\n res: ResolvedGsapFile,\n mutations: GsapMutationRequest[],\n): Promise<Response> {\n const firstMutation = mutations[0];\n if (!firstMutation) return c.json({ error: \"mutations array required\" }, 400);\n const prepared = await prepareGsapMutationScript(c, res, firstMutation);\n if (prepared instanceof Response) return prepared;\n const { html, beforeHtml, block } = prepared;\n let lengthIsAuthored: boolean | undefined;\n\n const initialScript = block.scriptText;\n const skippedSelectors = new Set<string>();\n const respond = (data: unknown, status?: number) =>\n status ? c.json(data, status) : c.json(data);\n let writer: \"recast\" | \"acorn\";\n try {\n writer = resolveGsapWriter({\n HYPERFRAMES_GSAP_WRITER: process.env[\"HYPERFRAMES_GSAP_WRITER\"],\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);\n }\n\n const mutationChanges: boolean[] = [];\n const retimes = writer === \"acorn\" ? retimeRuns(mutations) : new Map<number, RetimeSlot[]>();\n for (let index = 0; index < mutations.length; index++) {\n const run = retimes.get(index);\n if (run) {\n const retimed = retimeRun(block.scriptText, run, block.root);\n mutationChanges.push(...retimed.changed);\n block.scriptText = retimed.script;\n index += run.length - 1;\n continue;\n }\n const mutation = mutations[index]!;\n const previousScript = block.scriptText;\n const result = await executeGsapMutation(mutation, block, respond, writer);\n if (result instanceof Response) return result;\n let newScript = typeof result === \"string\" ? result : result.script;\n if (typeof result !== \"string\") {\n for (const selector of result.skippedSelectors) skippedSelectors.add(selector);\n }\n if (HOLD_SYNC_MUTATION_TYPES.has(mutation.type)) {\n lengthIsAuthored ??= !lengthIsTimeline(res.project.dir, res.filePath);\n if (lengthIsAuthored) newScript = trimTrailingKeyframeSpans(previousScript, newScript);\n newScript =\n writer === \"acorn\"\n ? syncPositionHoldsBeforeKeyframes(newScript, previousScript)\n : (await loadGsapParser()).syncPositionHoldsBeforeKeyframes(newScript, previousScript);\n }\n mutationChanges.push(newScript !== previousScript);\n block.scriptText = newScript;\n }\n\n const changed = block.scriptText !== initialScript;\n const newHtml = changed ? block.replaceScript(block.scriptText) : html;\n let backupPath: string | null = null;\n // Parsing can await lazy imports. Revalidate before EVERY successful response,\n // including semantic no-ops: a stale no-op response would otherwise claim\n // the old bytes and let the client keep a preview that missed a successor.\n if (readFileSync(res.absPath, \"utf-8\") !== beforeHtml) {\n return c.json({ error: \"file changed during GSAP mutation\", conflict: true }, 409);\n }\n if (changed) {\n const mutationResult = writeMutationResult(\n c,\n res.project.dir,\n res.filePath,\n res.absPath,\n newHtml,\n beforeHtml,\n );\n if (mutationResult instanceof Response) return mutationResult;\n backupPath = mutationResult.backupPath;\n }\n\n const responsePayload: Record<string, unknown> = {\n ok: true,\n changed,\n mutated: changed,\n mutationChanges,\n parsed: parseGsapScriptAcorn(block.scriptText),\n before: beforeHtml,\n after: newHtml,\n scriptText: block.scriptText,\n path: res.filePath,\n version: fileContentVersion(newHtml),\n backupPath,\n };\n if (skippedSelectors.size > 0) responsePayload.skippedSelectors = [...skippedSelectors];\n c.header(\"ETag\", responsePayload.version as string);\n return c.json(responsePayload);\n}\n\nfunction executeGsapMutationAcorn(\n body: GsapMutationRequest,\n block: NonNullable<ReturnType<typeof extractGsapScriptBlock>>,\n respond: (data: unknown, status?: number) => Response,\n): GsapMutationResult | Response {\n function requireAnimation(\n scriptText: string,\n animationId: string,\n ): { anim: GsapAnimation } | { err: Response } {\n const parsed = parseGsapScriptAcorn(scriptText);\n const anim = parsed.animations.find((a) => a.id === animationId);\n if (!anim) return { err: respond({ error: \"animation not found\" }, 404) };\n return { anim };\n }\n\n function requireFromToAnimation(\n scriptText: string,\n animationId: string,\n ): { anim: GsapAnimation } | { err: Response } {\n const result = requireAnimation(scriptText, animationId);\n if (\"err\" in result) return result;\n if (result.anim.method !== \"fromTo\")\n return { err: respond({ error: \"animation is not a fromTo\" }, 400) };\n return result;\n }\n\n switch (body.type) {\n case \"update-property\":\n case \"add-property\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const val = body.type === \"update-property\" ? body.value : body.defaultValue;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: { ...r.anim.properties, [body.property]: val },\n });\n }\n case \"update-properties\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: { ...r.anim.properties, ...body.properties },\n });\n }\n case \"update-from-property\":\n case \"add-from-property\": {\n const r = requireFromToAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const val = body.type === \"update-from-property\" ? body.value : body.defaultValue;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n fromProperties: { ...(r.anim.fromProperties ?? {}), [body.property]: val },\n });\n }\n case \"update-meta\": {\n return updateAnimationInScript(block.scriptText, body.animationId, body.updates);\n }\n case \"add\": {\n if (body.fromProperties && body.method !== \"fromTo\") {\n return respond({ error: \"fromProperties is only valid for method=fromTo\" }, 400);\n }\n if (\n Object.keys(body.properties).some((key) => {\n const group = classifyPropertyGroup(key);\n return group === \"position\" || group === \"rotation\";\n })\n ) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n const result = addAnimationToScript(block.scriptText, {\n targetSelector: body.targetSelector,\n method: body.method,\n position: body.position,\n duration: body.duration,\n ease: body.ease,\n properties: body.properties,\n fromProperties: body.fromProperties,\n ...(body.global ? { global: true } : {}),\n });\n return result.script;\n }\n case \"delete\": {\n const delTarget = requireAnimation(block.scriptText, body.animationId);\n if (!(\"err\" in delTarget) && body.stripStudioEdits) {\n stripStudioEditsFromTarget(block.document, delTarget.anim.targetSelector);\n bakeVisibilityOnDelete(block.document, delTarget.anim);\n }\n return removeAnimationFromScript(block.scriptText, body.animationId);\n }\n case \"delete-all-for-selector\": {\n const parsed = parseGsapScriptAcorn(block.scriptText);\n const matching = parsed.animations.filter((a) => a.targetSelector === body.targetSelector);\n if (matching.length === 0) return block.scriptText;\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n let script = block.scriptText;\n for (const anim of matching.reverse()) {\n script = removeAnimationFromScript(script, anim.id);\n }\n return script;\n }\n case \"consolidate-position-writes\": {\n if (!body.targetSelector) return block.scriptText;\n return dedupePositionWritesInScript(\n block.scriptText,\n body.targetSelector,\n body.keepAnimationId,\n );\n }\n case \"remove-property\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const filtered = { ...r.anim.properties };\n delete filtered[body.property];\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: filtered,\n });\n }\n case \"remove-from-property\": {\n const r = requireFromToAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const filtered = { ...(r.anim.fromProperties ?? {}) };\n delete filtered[body.property];\n return updateAnimationInScript(block.scriptText, body.animationId, {\n fromProperties: filtered,\n });\n }\n case \"add-keyframe\": {\n return addKeyframeToScript(\n block.scriptText,\n body.animationId,\n body.percentage,\n body.properties,\n body.ease,\n body.backfillDefaults,\n );\n }\n case \"remove-keyframe\": {\n return removeKeyframeFromScript(block.scriptText, body.animationId, body.percentage);\n }\n case \"move-keyframe\": {\n return moveKeyframeInScript(\n block.scriptText,\n body.animationId,\n body.fromPercentage,\n body.toPercentage,\n );\n }\n case \"resize-keyframed-tween\": {\n return resizeKeyframedTweenInScript(\n block.scriptText,\n body.animationId,\n body.position,\n body.duration,\n body.pctRemap,\n );\n }\n case \"update-keyframe\": {\n return updateKeyframeInScript(\n block.scriptText,\n body.animationId,\n body.percentage,\n body.properties,\n body.ease,\n );\n }\n case \"convert-to-keyframes\": {\n return convertToKeyframesFromScript(\n block.scriptText,\n body.animationId,\n body.resolvedFromValues,\n body.duration,\n );\n }\n case \"remove-all-keyframes\": {\n const preCollapse = requireAnimation(block.scriptText, body.animationId);\n if (!(\"err\" in preCollapse)) {\n bakeVisibilityOnDelete(block.document, preCollapse.anim);\n }\n return removeAllKeyframesFromScript(block.scriptText, body.animationId);\n }\n case \"materialize-keyframes\": {\n if (body.allElements && body.allElements.length > 0) {\n return unrollDynamicAnimations(block.scriptText, body.animationId, body.allElements);\n }\n return materializeKeyframesFromScript(\n block.scriptText,\n body.animationId,\n body.keyframes,\n body.easeEach,\n body.resolvedSelector,\n );\n }\n case \"set-arc-path\": {\n return setArcPathInScript(block.scriptText, body.animationId, {\n enabled: body.enabled,\n autoRotate: body.autoRotate ?? false,\n segments: body.segments ?? [],\n });\n }\n case \"update-arc-segment\": {\n return updateArcSegmentInScript(block.scriptText, body.animationId, body.segmentIndex, {\n ...(body.curviness !== undefined ? { curviness: body.curviness } : {}),\n ...(body.cp1 ? { cp1: body.cp1 } : {}),\n ...(body.cp2 ? { cp2: body.cp2 } : {}),\n });\n }\n case \"update-motion-path-point\": {\n return updateMotionPathPointInScript(block.scriptText, body.animationId, body.pointIndex, {\n x: body.x,\n y: body.y,\n });\n }\n case \"add-motion-path-point\": {\n return addMotionPathPointInScript(block.scriptText, body.animationId, body.index, {\n x: body.x,\n y: body.y,\n });\n }\n case \"remove-motion-path-point\": {\n return removeMotionPathPointInScript(block.scriptText, body.animationId, body.index);\n }\n case \"add-motion-path\": {\n return addMotionPathToScript(\n block.scriptText,\n body.targetSelector,\n body.position,\n body.duration,\n { x: body.x, y: body.y },\n body.ease,\n ).script;\n }\n case \"remove-arc-path\": {\n return removeArcPathFromScript(block.scriptText, body.animationId);\n }\n case \"add-with-keyframes\": {\n if (keyframesWritePosition(body.keyframes) || keyframesWriteRotation(body.keyframes)) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n const result = addAnimationWithKeyframesToScript(\n block.scriptText,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n body.easeEach,\n );\n return result.script;\n }\n case \"replace-with-keyframes\": {\n if (keyframesWritePosition(body.keyframes) || keyframesWriteRotation(body.keyframes)) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n return replaceInPlaceUnlessSetOrUnknown(block.scriptText, body);\n }\n case \"split-animations\": {\n if (\n typeof body.originalId !== \"string\" ||\n !body.originalId ||\n typeof body.newId !== \"string\" ||\n !body.newId ||\n typeof body.splitTime !== \"number\" ||\n !Number.isFinite(body.splitTime) ||\n typeof body.elementStart !== \"number\" ||\n !Number.isFinite(body.elementStart) ||\n typeof body.elementDuration !== \"number\" ||\n !Number.isFinite(body.elementDuration) ||\n body.elementDuration <= 0\n ) {\n return respond(\n {\n error:\n \"split-animations requires originalId, newId (non-empty strings), splitTime, elementStart (finite numbers), and elementDuration (positive number)\",\n },\n 400,\n );\n }\n return splitAnimationsInScript(block.scriptText, {\n originalId: body.originalId,\n newId: body.newId,\n splitTime: body.splitTime,\n elementStart: body.elementStart,\n elementDuration: body.elementDuration,\n });\n }\n case \"split-into-property-groups\": {\n const result = splitIntoPropertyGroupsFromScript(block.scriptText, body.animationId);\n return result.script;\n }\n case \"unroll-timeline\": {\n return unrollComputedTimeline(block.scriptText);\n }\n case \"shift-positions-batch\": {\n const shifts = body.shifts\n .filter((s) => s.targetSelector && Number.isFinite(s.delta) && s.delta !== 0)\n .map((s) => ({ kind: \"shift\" as const, targetSelector: s.targetSelector, delta: s.delta }));\n return retimeClipTweensInScript(block.scriptText, shifts, block.root).script;\n }\n case \"shift-positions\":\n case \"scale-positions\": {\n const retime = clipRetimeOf(body);\n return retime && retime !== \"no-op\"\n ? retimeClipTweensInScript(block.scriptText, [retime], block.root).script\n : block.scriptText;\n }\n default:\n return respond({ error: `unknown mutation type: ${(body as { type: string }).type}` }, 400);\n }\n}\n\nasync function executeGsapMutationRecast(\n body: GsapMutationRequest,\n block: NonNullable<ReturnType<typeof extractGsapScriptBlock>>,\n respond: (data: unknown, status?: number) => Response,\n): Promise<GsapMutationResult | Response> {\n const parser = await loadGsapParser();\n const {\n updateAnimationInScript,\n addAnimationToScript,\n removeAnimationFromScript,\n addKeyframeToScript,\n removeKeyframeFromScript,\n moveKeyframeInScript,\n resizeKeyframedTweenInScript,\n updateKeyframeInScript,\n convertToKeyframesInScript,\n removeAllKeyframesFromScript,\n materializeKeyframesInScript,\n unrollDynamicAnimations,\n setArcPathInScript,\n updateArcSegmentInScript,\n updateMotionPathPointInScript,\n addMotionPathPointInScript,\n removeMotionPathPointInScript,\n addMotionPathToScript,\n removeArcPathFromScript,\n addAnimationWithKeyframesToScript,\n splitAnimationsInScript,\n splitIntoPropertyGroups,\n dedupePositionWritesInScript,\n } = parser;\n\n function requireAnimation(\n scriptText: string,\n animationId: string,\n ): { anim: GsapAnimation } | { err: Response } {\n const parsed = parseGsapScriptAcorn(scriptText);\n const anim = parsed.animations.find((a) => a.id === animationId);\n if (!anim) return { err: respond({ error: \"animation not found\" }, 404) };\n return { anim };\n }\n\n function requireFromToAnimation(\n scriptText: string,\n animationId: string,\n ): { anim: GsapAnimation } | { err: Response } {\n const result = requireAnimation(scriptText, animationId);\n if (\"err\" in result) return result;\n if (result.anim.method !== \"fromTo\")\n return { err: respond({ error: \"animation is not a fromTo\" }, 400) };\n return result;\n }\n\n switch (body.type) {\n case \"update-property\":\n case \"add-property\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const val = body.type === \"update-property\" ? body.value : body.defaultValue;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: { ...r.anim.properties, [body.property]: val },\n });\n }\n case \"update-properties\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: { ...r.anim.properties, ...body.properties },\n });\n }\n case \"update-from-property\":\n case \"add-from-property\": {\n const r = requireFromToAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const val = body.type === \"update-from-property\" ? body.value : body.defaultValue;\n return updateAnimationInScript(block.scriptText, body.animationId, {\n fromProperties: { ...(r.anim.fromProperties ?? {}), [body.property]: val },\n });\n }\n case \"update-meta\": {\n return updateAnimationInScript(block.scriptText, body.animationId, body.updates);\n }\n case \"add\": {\n if (body.fromProperties && body.method !== \"fromTo\") {\n return respond({ error: \"fromProperties is only valid for method=fromTo\" }, 400);\n }\n // A new position/rotation animation owns that channel — strip the matching\n // legacy studio CSS var (--hf-studio-offset / --hf-studio-rotation) so it can't\n // double with the tween, matching add-with-keyframes/replace-with-keyframes.\n if (\n Object.keys(body.properties).some((k) => {\n const group = classifyPropertyGroup(k);\n return group === \"position\" || group === \"rotation\";\n })\n ) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n const result = addAnimationToScript(block.scriptText, {\n targetSelector: body.targetSelector,\n method: body.method,\n position: body.position,\n duration: body.duration,\n ease: body.ease,\n properties: body.properties,\n fromProperties: body.fromProperties,\n ...(body.global ? { global: true } : {}),\n });\n return result.script;\n }\n case \"delete\": {\n const delTarget = requireAnimation(block.scriptText, body.animationId);\n if (!(\"err\" in delTarget) && body.stripStudioEdits) {\n stripStudioEditsFromTarget(block.document, delTarget.anim.targetSelector);\n bakeVisibilityOnDelete(block.document, delTarget.anim);\n }\n return removeAnimationFromScript(block.scriptText, body.animationId);\n }\n case \"delete-all-for-selector\": {\n const parsed = parseGsapScriptAcorn(block.scriptText);\n const matching = parsed.animations.filter((a) => a.targetSelector === body.targetSelector);\n if (matching.length === 0) return block.scriptText;\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n let script = block.scriptText;\n for (const anim of matching.reverse()) {\n script = removeAnimationFromScript(script, anim.id);\n }\n return script;\n }\n case \"consolidate-position-writes\": {\n if (!body.targetSelector) return block.scriptText;\n return dedupePositionWritesInScript(\n block.scriptText,\n body.targetSelector,\n body.keepAnimationId,\n );\n }\n case \"remove-property\": {\n const r = requireAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const filtered = { ...r.anim.properties };\n delete filtered[body.property];\n return updateAnimationInScript(block.scriptText, body.animationId, {\n properties: filtered,\n });\n }\n case \"remove-from-property\": {\n const r = requireFromToAnimation(block.scriptText, body.animationId);\n if (\"err\" in r) return r.err;\n const filtered = { ...(r.anim.fromProperties ?? {}) };\n delete filtered[body.property];\n return updateAnimationInScript(block.scriptText, body.animationId, {\n fromProperties: filtered,\n });\n }\n case \"add-keyframe\": {\n return addKeyframeToScript(\n block.scriptText,\n body.animationId,\n body.percentage,\n body.properties,\n body.ease,\n body.backfillDefaults,\n );\n }\n case \"remove-keyframe\": {\n return removeKeyframeFromScript(block.scriptText, body.animationId, body.percentage);\n }\n case \"move-keyframe\": {\n return moveKeyframeInScript(\n block.scriptText,\n body.animationId,\n body.fromPercentage,\n body.toPercentage,\n );\n }\n case \"resize-keyframed-tween\": {\n return resizeKeyframedTweenInScript(\n block.scriptText,\n body.animationId,\n body.position,\n body.duration,\n body.pctRemap,\n );\n }\n case \"update-keyframe\": {\n return updateKeyframeInScript(\n block.scriptText,\n body.animationId,\n body.percentage,\n body.properties,\n body.ease,\n );\n }\n case \"convert-to-keyframes\": {\n return convertToKeyframesInScript(\n block.scriptText,\n body.animationId,\n body.resolvedFromValues,\n body.duration,\n );\n }\n case \"remove-all-keyframes\": {\n const preCollapse = requireAnimation(block.scriptText, body.animationId);\n if (!(\"err\" in preCollapse)) {\n bakeVisibilityOnDelete(block.document, preCollapse.anim);\n }\n return removeAllKeyframesFromScript(block.scriptText, body.animationId);\n }\n case \"materialize-keyframes\": {\n if (body.allElements && body.allElements.length > 0) {\n return unrollDynamicAnimations(block.scriptText, body.animationId, body.allElements);\n }\n return materializeKeyframesInScript(\n block.scriptText,\n body.animationId,\n body.keyframes,\n body.easeEach,\n body.resolvedSelector,\n );\n }\n case \"set-arc-path\": {\n return setArcPathInScript(block.scriptText, body.animationId, {\n enabled: body.enabled,\n autoRotate: body.autoRotate ?? false,\n segments: body.segments ?? [],\n });\n }\n case \"update-arc-segment\": {\n return updateArcSegmentInScript(block.scriptText, body.animationId, body.segmentIndex, {\n ...(body.curviness !== undefined ? { curviness: body.curviness } : {}),\n ...(body.cp1 ? { cp1: body.cp1 } : {}),\n ...(body.cp2 ? { cp2: body.cp2 } : {}),\n });\n }\n case \"update-motion-path-point\": {\n return updateMotionPathPointInScript(block.scriptText, body.animationId, body.pointIndex, {\n x: body.x,\n y: body.y,\n });\n }\n case \"add-motion-path-point\": {\n return addMotionPathPointInScript(block.scriptText, body.animationId, body.index, {\n x: body.x,\n y: body.y,\n });\n }\n case \"remove-motion-path-point\": {\n return removeMotionPathPointInScript(block.scriptText, body.animationId, body.index);\n }\n case \"add-motion-path\": {\n const result = addMotionPathToScript(\n block.scriptText,\n body.targetSelector,\n body.position,\n body.duration,\n { x: body.x, y: body.y },\n body.ease,\n );\n return result.script;\n }\n case \"remove-arc-path\": {\n return removeArcPathFromScript(block.scriptText, body.animationId);\n }\n case \"add-with-keyframes\": {\n if (keyframesWritePosition(body.keyframes) || keyframesWriteRotation(body.keyframes)) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n const result = addAnimationWithKeyframesToScript(\n block.scriptText,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n body.easeEach,\n );\n return result.script;\n }\n case \"replace-with-keyframes\": {\n if (keyframesWritePosition(body.keyframes) || keyframesWriteRotation(body.keyframes)) {\n stripStudioEditsFromTarget(block.document, body.targetSelector);\n }\n return replaceInPlaceUnlessSetOrUnknown(block.scriptText, body);\n }\n case \"split-animations\": {\n if (\n typeof body.originalId !== \"string\" ||\n !body.originalId ||\n typeof body.newId !== \"string\" ||\n !body.newId ||\n typeof body.splitTime !== \"number\" ||\n !Number.isFinite(body.splitTime) ||\n typeof body.elementStart !== \"number\" ||\n !Number.isFinite(body.elementStart) ||\n typeof body.elementDuration !== \"number\" ||\n !Number.isFinite(body.elementDuration) ||\n body.elementDuration <= 0\n ) {\n return respond(\n {\n error:\n \"split-animations requires originalId, newId (non-empty strings), splitTime, elementStart (finite numbers), and elementDuration (positive number)\",\n },\n 400,\n );\n }\n return splitAnimationsInScript(block.scriptText, {\n originalId: body.originalId,\n newId: body.newId,\n splitTime: body.splitTime,\n elementStart: body.elementStart,\n elementDuration: body.elementDuration,\n });\n }\n case \"split-into-property-groups\": {\n const result = splitIntoPropertyGroups(block.scriptText, body.animationId);\n return result.script;\n }\n case \"unroll-timeline\": {\n return unrollComputedTimeline(block.scriptText);\n }\n case \"shift-positions\": {\n const { targetSelector, delta } = body;\n if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;\n const { shiftPositionsInScript } = parser;\n return shiftPositionsInScript(block.scriptText, targetSelector, delta, block.root);\n }\n case \"shift-positions-batch\": {\n const { shiftPositionsInScript } = parser;\n let script = block.scriptText;\n for (const s of body.shifts) {\n if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;\n script = shiftPositionsInScript(script, s.targetSelector, s.delta, block.root);\n }\n return script;\n }\n case \"scale-positions\": {\n const { targetSelector, oldStart, oldDuration, newStart, newDuration } = body;\n if (\n !targetSelector ||\n !Number.isFinite(oldStart) ||\n !Number.isFinite(oldDuration) ||\n !Number.isFinite(newStart) ||\n !Number.isFinite(newDuration) ||\n oldDuration <= 0 ||\n newDuration <= 0\n )\n return block.scriptText;\n if (oldStart === newStart && oldDuration === newDuration) return block.scriptText;\n const { scalePositionsInScript } = parser;\n return scalePositionsInScript(\n block.scriptText,\n targetSelector,\n oldStart,\n oldDuration,\n newStart,\n newDuration,\n block.root,\n );\n }\n default:\n return respond({ error: `unknown mutation type: ${(body as { type: string }).type}` }, 400);\n }\n}\n\ninterface FoldedAtomicCutFile {\n path: string;\n absPath: string;\n before: string;\n after: string;\n splitCount: number;\n skippedSelectors: string[];\n}\n\n/** Fold every split and optional GSAP retarget for one file without touching disk. */\nasync function foldAtomicCutFile(\n c: RouteContext,\n file: AtomicCutFileRequest,\n absPath: string,\n before: string,\n writer: \"recast\" | \"acorn\",\n): Promise<FoldedAtomicCutFile | Response> {\n let after = before;\n let splitCount = 0;\n const skippedSelectors = new Set<string>();\n const rightHalfIds: string[] = [];\n const respond = (data: unknown, status?: number) =>\n status ? c.json(data, status) : c.json(data);\n\n const orderedTargets = file.targets\n .map((cut, index) => ({ cut, index }))\n .sort((left, right) => {\n const locatorKey = (entry: AtomicCutTarget): string | null =>\n !entry.target.id && !entry.target.hfId && entry.target.selector\n ? entry.target.selector\n : null;\n const leftKey = locatorKey(left.cut);\n const rightKey = locatorKey(right.cut);\n if (leftKey && rightKey) {\n return (\n leftKey.localeCompare(rightKey) ||\n (right.cut.target.selectorIndex ?? 0) - (left.cut.target.selectorIndex ?? 0)\n );\n }\n if (leftKey) return -1;\n if (rightKey) return 1;\n return left.index - right.index;\n })\n .map(({ cut }) => cut);\n for (const cut of orderedTargets) {\n const baseId = cut.originalId || cut.target.id || \"clip\";\n const split = splitElementInHtml(after, cut.target, cut.splitTime, `${baseId}-split`, {\n start: cut.elementStart,\n duration: cut.elementDuration,\n playbackStart: cut.playbackStart,\n playbackRate: cut.playbackRate,\n stampPlaybackStart: cut.isComposition,\n track: cut.track,\n });\n if (!split.matched || !split.newId) {\n return c.json(\n { error: `Cut target was not found or was outside its authored bounds in ${file.path}` },\n 400,\n );\n }\n after = split.html;\n splitCount++;\n rightHalfIds.push(split.newId);\n\n if (!cut.originalId) continue;\n const block = extractGsapScriptBlock(after);\n if (!block) continue;\n const result = await executeGsapMutation(\n {\n type: \"split-animations\",\n originalId: cut.originalId,\n newId: split.newId,\n splitTime: cut.splitTime,\n elementStart: cut.elementStart,\n elementDuration: cut.elementDuration,\n },\n block,\n respond,\n writer,\n );\n if (result instanceof Response) return result;\n let script = typeof result === \"string\" ? result : result.script;\n if (typeof result !== \"string\") {\n for (const selector of result.skippedSelectors) skippedSelectors.add(selector);\n }\n if (script !== block.scriptText) {\n script =\n writer === \"acorn\"\n ? syncPositionHoldsBeforeKeyframes(script, block.scriptText)\n : (await loadGsapParser()).syncPositionHoldsBeforeKeyframes(script, block.scriptText);\n after = block.replaceScript(script);\n }\n }\n\n after = relinkSplitHalvesInHtml(after, rightHalfIds);\n return {\n path: file.path,\n absPath,\n before,\n after,\n splitCount,\n skippedSelectors: [...skippedSelectors],\n };\n}\n\n// ── Upload file processing ──────────────────────────────────────────────────\n\nexport const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;\n\nasync function processUploadedFiles(\n formData: FormData,\n targetDir: string,\n projectDir: string,\n): Promise<{\n uploaded: string[];\n skipped: string[];\n invalid: Array<{ name: string; reason: string }>;\n unchecked: Array<{ name: string; reason: string }>;\n}> {\n const uploaded: string[] = [];\n const skipped: string[] = [];\n const invalid: Array<{ name: string; reason: string }> = [];\n const unchecked: Array<{ name: string; reason: string }> = [];\n\n // @types/node v25 narrows the ambient `FormData.entries()` to\n // `[string, string]` in workspaces where another dep declares an\n // `onmessage` global (it trips the worker branch of v25's conditional\n // File type). At runtime the value is still `File | string` — cast the\n // iterator so the rest of this block keeps type-checking on every\n // bun-install layout (hoisted on Windows surfaces this; isolated on\n // Linux happens to keep v24 in scope).\n type FileLike = {\n readonly name: string;\n readonly size: number;\n arrayBuffer(): Promise<ArrayBuffer>;\n };\n const entries = formData.entries() as unknown as Iterable<[string, FileLike | string]>;\n\n // Derive the subdirectory prefix from targetDir relative to projectDir\n const subDir = targetDir === projectDir ? \"\" : targetDir.slice(projectDir.length + 1);\n\n for (const [, value] of entries) {\n if (typeof value === \"string\") continue;\n\n // Strip path separators — browsers may include directory components\n const name = value.name.split(\"/\").pop()?.split(\"\\\\\").pop() ?? \"\";\n if (!name || name.includes(\"\\0\") || name.includes(\"..\")) continue;\n\n // Reject individual files that exceed the size limit\n if (value.size > MAX_UPLOAD_BYTES) {\n skipped.push(name);\n continue;\n }\n\n const destPath = resolve(targetDir, name);\n if (!isSafePath(projectDir, destPath)) continue;\n\n // Don't overwrite — append (2), (3), etc.\n let finalPath = destPath;\n let finalName = name;\n // Handle dotfiles correctly: .gitignore → ext=\"\", base=\".gitignore\"\n const dotIdx = name.indexOf(\".\", name.startsWith(\".\") ? 1 : 0);\n const ext = dotIdx > 0 ? name.slice(dotIdx) : \"\";\n const base = dotIdx > 0 ? name.slice(0, dotIdx) : name;\n const MAX_COPY_INDEX = 10000;\n let n = 1;\n if (existsSync(finalPath)) {\n n = 2;\n while (n < MAX_COPY_INDEX && existsSync(resolve(targetDir, `${base} (${n})${ext}`))) n++;\n if (n >= MAX_COPY_INDEX) {\n skipped.push(name);\n continue;\n }\n finalName = `${base} (${n})${ext}`;\n finalPath = resolve(targetDir, finalName);\n }\n\n // The collision suffix chooses a different path; validate that destination\n // too, including dangling symlinks that existsSync treats as absent.\n if (!isSafePath(projectDir, finalPath) || isPrivateProjectFile(projectDir, finalPath)) continue;\n\n const buffer = Buffer.from(await value.arrayBuffer());\n const validation = validateUploadedMediaBuffer(finalName, buffer);\n if (!validation.ok) {\n invalid.push({ name: finalName, reason: validation.reason });\n continue;\n }\n\n // Reading the upload yields: another request can claim the selected name.\n // Only exclusive creation authorizes a write; retry collisions without\n // following a newly planted link or overwriting another upload.\n let written = false;\n while (n < MAX_COPY_INDEX && isSafePath(projectDir, finalPath)) {\n try {\n createFileAtomically(finalPath, buffer);\n written = true;\n break;\n } catch (error) {\n if (!(error instanceof Error) || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n n++;\n finalName = `${base} (${n})${ext}`;\n finalPath = resolve(targetDir, finalName);\n }\n }\n if (!written) {\n if (n >= MAX_COPY_INDEX) skipped.push(name);\n continue;\n }\n const relativePath = subDir ? join(subDir, finalName) : finalName;\n uploaded.push(relativePath);\n if (validation.unchecked) unchecked.push({ name: finalName, reason: validation.unchecked });\n if (isAudioFile(finalName)) {\n generateWaveformCache(projectDir, relativePath).catch(() => {});\n }\n }\n\n return { uploaded, skipped, invalid, unchecked };\n}\n\n// ── Route registration ──────────────────────────────────────────────────────\n\nconst MAX_TEXT_READ_BYTES = 32 * 1024 * 1024;\nconst GIT_BINARY_SNIFF_BYTES = 8000;\n\nexport function registerFileRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // ── Read ──\n\n api.get(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter);\n if (\"error\" in res) return res.error;\n\n // Opened once and checked/read through the same descriptor, not the path,\n // so a directory-for-file swap (or anything else) between the check below\n // and the read can't land a stale answer — both act on the identical inode.\n let fd: number;\n try {\n fd = openSync(res.absPath, \"r\");\n } catch {\n if (c.req.query(\"optional\") === \"1\") {\n // `missing: true` separates the absent-file shim from a genuinely\n // 0-byte file — both answer `content: \"\"`, and the caller could not\n // tell them apart. That ambiguity hid the largest remaining class of\n // SDK-session failures: a composition the file tree lists but this\n // read answers empty for is either a placeholder nobody has written\n // yet, or a path that does not resolve here at all, and those need\n // different fixes. Additive, so an older client ignores it.\n return c.json({ filename: res.filePath, content: \"\", missing: true });\n }\n return c.json({ error: \"not found\" }, 404);\n }\n try {\n // A listing built from `walkDir` can show a path that has since been\n // replaced by a directory (a rename, or an agent overwriting a file\n // with a folder of the same name) — opening it succeeds (POSIX allows\n // O_RDONLY on a directory), and reading it would throw `EISDIR`, which\n // Hono answers as a plain-text 500. The caller already handles a 404\n // with `why`; this reports the same shape instead of an opaque server\n // error for something that is not one.\n const stat = fstatSync(fd);\n if (!stat.isFile()) {\n return c.json({ error: \"not found\", why: \"not_a_file\" }, 404);\n }\n if (stat.size > MAX_TEXT_READ_BYTES) {\n return c.json({ error: \"too large to read as text\", why: \"too_large\" }, 413);\n }\n\n const content = readFileSync(fd);\n const version = fileContentVersion(content);\n c.header(\"ETag\", version);\n if (content.subarray(0, GIT_BINARY_SNIFF_BYTES).includes(0)) {\n return c.json({ error: \"not a text file\", why: \"binary\", version }, 415);\n }\n // `missing: false` on the read path too, so its PRESENCE is what tells a\n // caller this server distinguishes the two empty answers at all. Without\n // it here, a real 0-byte file from a new server looks exactly like either\n // case from an old one, and the split above buys nothing.\n return c.json({\n filename: res.filePath,\n content: content.toString(\"utf-8\"),\n version,\n missing: false,\n });\n } finally {\n closeSync(fd);\n }\n });\n\n // ── Write (overwrite) ──\n\n api.put(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter, { pin: true });\n if (\"error\" in res) return res.error;\n\n const body = Buffer.from(await c.req.arrayBuffer());\n const expectedVersion = c.req.header(\"If-Match\")?.trim() ?? null;\n const createOnly = c.req.header(\"If-None-Match\")?.trim() === \"*\";\n if (expectedVersion === null && !createOnly) {\n let currentContent: Buffer | null = null;\n try {\n currentContent = readFileSync(res.absPath);\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"ENOENT\") {\n throw error;\n }\n }\n return c.json(\n {\n error: \"precondition required\",\n path: res.filePath,\n currentVersion: currentContent === null ? null : fileContentVersion(currentContent),\n currentContent: currentContent?.toString(\"utf-8\") ?? null,\n },\n 428,\n );\n }\n\n let backup: ReturnType<typeof snapshotBeforeWrite> = { backupPath: null };\n let overwrote: Buffer | undefined;\n if (createOnly) {\n ensureDir(res.project.dir, res.absPath);\n try {\n createFileAtomically(res.absPath, body);\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n const currentContent = readFileSync(res.absPath);\n return c.json(\n {\n error: \"file conflict\",\n path: res.filePath,\n currentVersion: fileContentVersion(currentContent),\n currentContent: currentContent.toString(\"utf-8\"),\n },\n 409,\n );\n }\n } else {\n let fd: number | null;\n try {\n fd = openSync(res.absPath, \"r+\");\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"ENOENT\") {\n throw error;\n }\n return c.json(\n {\n error: \"file conflict\",\n path: res.filePath,\n currentVersion: null,\n currentContent: null,\n },\n 409,\n );\n }\n try {\n const currentContent = readFileSync(fd);\n overwrote = currentContent;\n const currentVersion = fileContentVersion(currentContent);\n if (expectedVersion !== currentVersion) {\n return c.json(\n {\n error: \"file conflict\",\n path: res.filePath,\n currentVersion,\n currentContent: currentContent.toString(\"utf-8\"),\n },\n 409,\n );\n }\n backup = snapshotBeforeWrite(res.project.dir, res.absPath);\n if (backup.error) return c.json({ error: `backup failed: ${backup.error}` }, 500);\n const mode = fstatSync(fd).mode;\n closeSync(fd);\n fd = null;\n replaceFileAtomically(res.absPath, body, mode);\n } finally {\n if (fd !== null) closeSync(fd);\n }\n }\n const version = fileContentVersion(body);\n const writeToken = createWriteToken(c.req.header(\"X-Hyperframes-Write-Token\"));\n recordFileWriteReceipt(res.absPath, { path: res.filePath, version, writeToken, overwrote });\n c.header(\"ETag\", version);\n\n return c.json({\n ok: true,\n path: res.filePath,\n version,\n writeToken,\n backupPath: backupPathForResponse(res.project.dir, backup.backupPath),\n });\n });\n\n // ── Create (fail if exists) ──\n\n api.post(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter);\n if (\"error\" in res) return res.error;\n\n ensureDir(res.project.dir, res.absPath);\n const body = Buffer.from(await c.req.arrayBuffer());\n try {\n createFileAtomically(res.absPath, body);\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n return c.json({ error: \"already exists\" }, 409);\n }\n\n return c.json({ ok: true, path: res.filePath }, 201);\n });\n\n // ── Delete ──\n\n api.delete(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter, { mustExist: true });\n if (\"error\" in res) return res.error;\n\n const stat = statSync(res.absPath);\n const backup = snapshotBeforeWrite(res.project.dir, res.absPath);\n if (backup.error) return c.json({ error: `backup failed: ${backup.error}` }, 500);\n if (stat.isDirectory()) {\n rmSync(res.absPath, { recursive: true });\n } else {\n unlinkSync(res.absPath);\n }\n\n return c.json({\n ok: true,\n backupPath: backupPathForResponse(res.project.dir, backup.backupPath),\n });\n });\n\n api.post(\"/projects/:id/file-mutations/insert-composition/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"insert-composition\");\n if (\"error\" in ctx) return ctx.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n sourcePath?: unknown;\n start?: unknown;\n track?: unknown;\n expectedVersion?: unknown;\n } | null;\n if (\n !body ||\n typeof body.sourcePath !== \"string\" ||\n typeof body.start !== \"number\" ||\n !Number.isFinite(body.start) ||\n body.start < 0 ||\n typeof body.track !== \"number\" ||\n !Number.isFinite(body.track) ||\n typeof body.expectedVersion !== \"string\"\n ) {\n return c.json({ error: \"sourcePath, finite placement, and expectedVersion required\" }, 400);\n }\n\n let before: string;\n try {\n before = readFileSync(ctx.absPath, \"utf-8\");\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"ENOENT\") {\n throw error;\n }\n return c.json({ error: \"not found\" }, 404);\n }\n const currentVersion = fileContentVersion(before);\n if (body.expectedVersion !== currentVersion) {\n return c.json({ error: \"file conflict\", currentVersion, currentContent: before }, 409);\n }\n\n let insertion: ReturnType<typeof insertCompositionIntoSource>;\n try {\n insertion = insertCompositionIntoSource({\n projectDir: ctx.project.dir,\n targetPath: ctx.filePath,\n sourcePath: body.sourcePath,\n parentSource: before,\n start: body.start,\n desiredTrack: body.track,\n });\n } catch (error) {\n if (error instanceof CompositionInsertionError) {\n return c.json({ error: error.message }, error.status);\n }\n throw error;\n }\n\n const backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);\n if (backup.error) return c.json({ error: `backup failed: ${backup.error}` }, 500);\n const current = readFileSync(ctx.absPath, \"utf-8\");\n if (current !== before) {\n const currentVersion = fileContentVersion(current);\n return c.json({ error: \"file conflict\", currentVersion, currentContent: current }, 409);\n }\n const { version, writeToken } = writeFileWithReceipt(\n c,\n ctx.filePath,\n ctx.absPath,\n insertion.html,\n );\n c.header(\"ETag\", version);\n return c.json({\n ok: true,\n path: ctx.filePath,\n hostId: insertion.hostId,\n track: insertion.track,\n duration: insertion.duration,\n before,\n after: insertion.html,\n version,\n writeToken,\n backupPath: backupPathForResponse(ctx.project.dir, backup.backupPath),\n });\n });\n\n api.post(\"/projects/:id/file-mutations/remove-element/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"remove-element\");\n if (\"error\" in ctx) return ctx.error;\n\n if (!existsSync(ctx.absPath)) {\n return c.json({ error: \"not found\" }, 404);\n }\n\n const parsed = await parseMutationBody<{ target?: MutationTarget }>(c);\n if (\"error\" in parsed) return parsed.error;\n\n const originalContent = readFileSync(ctx.absPath, \"utf-8\");\n return writeIfChanged(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n originalContent,\n removeElementFromHtml(originalContent, parsed.target),\n );\n });\n\n // Removing a marquee selection one element at a time meant one request and\n // one rewrite of the whole file per element. A canvas selection runs to\n // hundreds of members, so a single Delete press became hundreds of serial\n // round trips: the file ended up correct, but only after long enough that the\n // key looked like it had done nothing at all.\n api.post(\"/projects/:id/file-mutations/remove-elements/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"remove-elements\");\n if (\"error\" in ctx) return ctx.error;\n\n if (!existsSync(ctx.absPath)) {\n return c.json({ error: \"not found\" }, 404);\n }\n\n const body = (await c.req.json().catch(() => null)) as { targets?: MutationTarget[] } | null;\n const targets = body?.targets;\n if (!Array.isArray(targets) || targets.length === 0) {\n return c.json({ error: \"targets required\" }, 400);\n }\n\n const originalContent = readFileSync(ctx.absPath, \"utf-8\");\n // The response says whether the file changed, not how many of the targets landed, so a\n // caller can tell a no-op from a write, but not a partial pass from a complete one.\n return writeIfChanged(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n originalContent,\n removeElementsFromHtml(originalContent, targets),\n );\n });\n\n api.post(\"/projects/:id/file-mutations/split-batch\", async (c) => {\n const body = (await c.req.json().catch(() => null)) as {\n files?: unknown;\n transactionToken?: unknown;\n } | null;\n if (\n !Array.isArray(body?.files) ||\n body.files.length === 0 ||\n !body.files.every(isAtomicCutFileRequest)\n ) {\n return c.json({ error: \"files with path, expectedVersion, and cut targets required\" }, 400);\n }\n const files = body.files as AtomicCutFileRequest[];\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n let writer: \"recast\" | \"acorn\";\n try {\n writer = resolveGsapWriter({\n HYPERFRAMES_GSAP_WRITER: process.env[\"HYPERFRAMES_GSAP_WRITER\"],\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);\n }\n\n return serializeAtomicCut(async () => {\n const seen = new Set<string>();\n const prepared: FoldedAtomicCutFile[] = [];\n for (const file of files) {\n const absPath = pinWithinProject(project.dir, file.path);\n if (!absPath) return c.json({ error: `forbidden path: ${file.path}` }, 403);\n if (seen.has(absPath)) return c.json({ error: `duplicate path: ${file.path}` }, 400);\n seen.add(absPath);\n\n let before: string;\n try {\n before = readFileSync(absPath, \"utf-8\");\n } catch {\n return c.json({ error: `not found: ${file.path}` }, 404);\n }\n const currentVersion = fileContentVersion(before);\n if (currentVersion !== file.expectedVersion) {\n return c.json(\n {\n error: `file conflict: ${file.path}`,\n path: file.path,\n currentVersion,\n currentContent: before,\n },\n 409,\n );\n }\n let folded: FoldedAtomicCutFile | Response;\n try {\n folded = await foldAtomicCutFile(c, file, absPath, before, writer);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Cut transform failed\";\n return c.json({ error: message }, 400);\n }\n if (folded instanceof Response) return folded;\n prepared.push(folded);\n }\n\n // Lazy GSAP parsing above can yield; revalidate every base before the first write.\n for (const file of prepared) {\n const current = readFileSync(file.absPath, \"utf-8\");\n if (current !== file.before) {\n return c.json(\n {\n error: `file conflict: ${file.path}`,\n path: file.path,\n currentVersion: fileContentVersion(current),\n currentContent: current,\n },\n 409,\n );\n }\n }\n\n const backups = new Map<string, string | null>();\n for (const file of prepared) {\n const backup = snapshotBeforeWrite(project.dir, file.absPath);\n if (backup.error) {\n return c.json(\n { error: `Failed to create backup for ${file.path}: ${backup.error}` },\n 500,\n );\n }\n backups.set(file.path, backupPathForResponse(project.dir, backup.backupPath));\n }\n\n const writeToken = createWriteToken(\n typeof body.transactionToken === \"string\"\n ? body.transactionToken\n : c.req.header(\"X-Hyperframes-Write-Token\"),\n );\n const written: FoldedAtomicCutFile[] = [];\n try {\n for (const file of prepared) {\n replaceFileAtomically(file.absPath, file.after, statSync(file.absPath).mode);\n written.push(file);\n recordFileWriteReceipt(file.absPath, {\n path: file.path,\n version: fileContentVersion(file.after),\n writeToken,\n overwrote: file.before,\n });\n }\n } catch (error) {\n const conflicts: string[] = [];\n for (const file of written.reverse()) {\n try {\n const current = readFileSync(file.absPath, \"utf-8\");\n if (current !== file.after) {\n conflicts.push(file.path);\n continue;\n }\n replaceFileAtomically(file.absPath, file.before, statSync(file.absPath).mode);\n recordFileWriteReceipt(file.absPath, {\n path: file.path,\n version: fileContentVersion(file.before),\n writeToken,\n });\n } catch {\n conflicts.push(file.path);\n }\n }\n return c.json(\n {\n error: error instanceof Error ? error.message : \"Cut write failed\",\n outcome: conflicts.length ? \"aborted-with-conflicts\" : \"aborted-restored\",\n conflicts,\n },\n conflicts.length ? 409 : 500,\n );\n }\n\n const result = prepared.map((file) => ({\n path: file.path,\n before: file.before,\n after: file.after,\n version: fileContentVersion(file.after),\n writeToken,\n backupPath: backups.get(file.path) ?? null,\n splitCount: file.splitCount,\n skippedSelectors: file.skippedSelectors,\n }));\n return c.json({ ok: true, outcome: \"committed\", files: result });\n });\n });\n\n api.post(\"/projects/:id/file-mutations/split-element/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"split-element\");\n if (\"error\" in ctx) return ctx.error;\n\n const parsed = await parseMutationBody<{\n target?: { id?: string; selector?: string; selectorIndex?: number };\n splitTime?: number;\n newId?: string;\n elementStart?: number;\n elementDuration?: number;\n }>(c);\n if (\"error\" in parsed) return parsed.error;\n if (typeof parsed.body.splitTime !== \"number\" || !parsed.body.newId) {\n return c.json({ error: \"target, splitTime, and newId required\" }, 400);\n }\n const fallbackTiming =\n typeof parsed.body.elementStart === \"number\" &&\n typeof parsed.body.elementDuration === \"number\"\n ? { start: parsed.body.elementStart, duration: parsed.body.elementDuration }\n : undefined;\n\n let originalContent: string;\n try {\n originalContent = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ error: \"not found\" }, 404);\n }\n const result = splitElementInHtml(\n originalContent,\n parsed.target,\n parsed.body.splitTime,\n parsed.body.newId,\n fallbackTiming,\n );\n if (!result.matched) {\n const version = fileContentVersion(originalContent);\n c.header(\"ETag\", version);\n return c.json({\n ok: false,\n changed: false,\n content: originalContent,\n path: ctx.filePath,\n version,\n });\n }\n const mutationResult = writeMutationResult(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n result.html,\n originalContent,\n );\n if (mutationResult instanceof Response) return mutationResult;\n const { version, backupPath } = mutationResult;\n c.header(\"ETag\", version);\n return c.json({\n ok: true,\n changed: true,\n content: result.html,\n newId: result.newId,\n path: ctx.filePath,\n version,\n backupPath,\n });\n });\n\n api.post(\"/projects/:id/file-mutations/patch-element/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"patch-element\");\n if (\"error\" in ctx) return ctx.error;\n\n const parsed = await parseMutationBody<{\n target?: MutationTarget;\n operations?: PatchOperation[];\n fontFaceCss?: unknown;\n }>(c);\n if (\"error\" in parsed) return parsed.error;\n if (!Array.isArray(parsed.body.operations) || parsed.body.operations.length === 0) {\n return c.json({ error: \"target and operations required\" }, 400);\n }\n const { fontFaceCss } = parsed.body;\n if (fontFaceCss !== undefined && !isStudioFontFaceCss(fontFaceCss)) {\n return c.json({ error: \"fontFaceCss must be one @font-face rule\" }, 400);\n }\n const unsafeFields = findUnsafeDomPatchValues(parsed.body);\n if (unsafeFields.length > 0) {\n return rejectUnsafeMutationValues(c, unsafeFields);\n }\n\n for (let attempt = 1; ; attempt += 1) {\n let originalContent: string;\n try {\n originalContent = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ error: \"not found\" }, 404);\n }\n const takenIds = parsed.body.operations.some((op) => op.type === \"ensure-id\")\n ? projectHtmlIds(ctx.project.dir)\n : undefined;\n const element = patchElementInHtml(\n originalContent,\n parsed.target,\n parsed.body.operations,\n takenIds,\n );\n const { matched } = element;\n const patched =\n matched && isStudioFontFaceCss(fontFaceCss)\n ? ensureStudioFontFaceCss(element.html, fontFaceCss)\n : element.html;\n if (patched === originalContent) {\n const version = fileContentVersion(originalContent);\n c.header(\"ETag\", version);\n return c.json({\n ok: true,\n changed: false,\n matched,\n elementId: element.elementId,\n content: originalContent,\n path: ctx.filePath,\n version,\n });\n }\n const mutationResult = writeMutationResult(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n patched,\n originalContent,\n );\n if (mutationResult instanceof Response) {\n if (mutationResult.status === 409 && attempt < PATCH_CONFLICT_ATTEMPTS) continue;\n return mutationResult;\n }\n const { backupPath, version } = mutationResult;\n c.header(\"ETag\", version);\n return c.json({\n ok: true,\n changed: true,\n matched,\n elementId: element.elementId,\n content: patched,\n path: ctx.filePath,\n version,\n backupPath,\n });\n }\n });\n\n api.post(\"/projects/:id/file-mutations/patch-element-batches\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const body: unknown = await c.req.json().catch(() => null);\n if (\n typeof body !== \"object\" ||\n body === null ||\n !(\"batches\" in body) ||\n !Array.isArray(body.batches) ||\n body.batches.length === 0 ||\n !body.batches.every(isElementPatchBatchRequest)\n ) {\n return c.json({ error: \"batches with sourceFile and patches required\" }, 400);\n }\n const unsafeFields = findUnsafeElementPatchBatchValues(body.batches);\n if (unsafeFields.length > 0) return rejectUnsafeMutationValues(c, unsafeFields);\n\n const result = commitElementPatchBatchesWithReceipts(c, project.dir, body.batches);\n if (\"error\" in result) {\n return elementPatchBatchCommitErrorResponse(c, result.error, result.sourceFile);\n }\n return c.json(result);\n });\n\n api.post(\"/projects/:id/file-mutations/patch-elements-batch/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"patch-elements-batch\");\n if (\"error\" in ctx) return ctx.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n patches?: ElementPatchRequest[];\n } | null;\n if (\n !body ||\n !Array.isArray(body.patches) ||\n body.patches.length === 0 ||\n !body.patches.every(isElementPatchRequest)\n ) {\n return c.json({ error: \"patches with target and operations required\" }, 400);\n }\n const batch = { sourceFile: ctx.filePath, patches: body.patches };\n const unsafeFields = findUnsafeElementPatchBatchValues([batch]);\n if (unsafeFields.length > 0) {\n return rejectUnsafeMutationValues(c, unsafeFields);\n }\n\n const result = commitElementPatchBatchesWithReceipts(c, ctx.project.dir, [batch]);\n if (\"error\" in result) {\n return elementPatchBatchCommitErrorResponse(c, result.error, result.sourceFile);\n }\n const file = result.files[0];\n if (!file) return c.json({ error: \"empty element patch result\" }, 500);\n return c.json({\n ok: true,\n changed: file.changed,\n matched: file.matched,\n content: file.after,\n path: file.sourceFile,\n backupPath: file.backupPath,\n });\n });\n\n api.post(\"/projects/:id/file-mutations/wrap-elements/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"wrap-elements\");\n if (\"error\" in ctx) return ctx.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n targets?: MutationTarget[];\n groupId?: string;\n bbox?: { left?: number; top?: number; width?: number; height?: number };\n rebases?: ElementRebase[];\n } | null;\n if (!Array.isArray(body?.targets) || body.targets.length === 0 || !body.groupId) {\n return c.json({ error: \"targets and groupId required\" }, 400);\n }\n // left/top/width/height are interpolated into inline style strings; reject\n // anything non-numeric so a crafted value can't inject extra declarations.\n const bbox = body.bbox ?? {};\n const bboxNums = [bbox.left, bbox.top, bbox.width, bbox.height];\n const rebases = body.rebases ?? [];\n const allNumeric =\n bboxNums.every((n) => typeof n === \"number\" && Number.isFinite(n)) &&\n rebases.every(\n (r) =>\n typeof r?.left === \"number\" &&\n Number.isFinite(r.left) &&\n typeof r?.top === \"number\" &&\n Number.isFinite(r.top) &&\n isOptionalInteger(r?.track),\n );\n if (!allNumeric) {\n return c.json({ error: \"bbox and rebase coordinates must be finite numbers\" }, 400);\n }\n\n let originalContent: string;\n try {\n originalContent = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ error: \"not found\" }, 404);\n }\n const result = wrapElementsInHtml(\n originalContent,\n body.targets,\n body.groupId,\n { left: bbox.left!, top: bbox.top!, width: bbox.width!, height: bbox.height! },\n rebases,\n );\n if (!result.matched) {\n return c.json(\n {\n ok: false,\n changed: false,\n content: originalContent,\n path: ctx.filePath,\n error: result.error,\n },\n result.error === \"grouped elements must share a single parent\" ? 422 : 400,\n );\n }\n const mutationResult = writeMutationResult(\n c,\n ctx.project.dir,\n ctx.filePath,\n ctx.absPath,\n result.html,\n originalContent,\n );\n if (mutationResult instanceof Response) return mutationResult;\n const { backupPath } = mutationResult;\n return c.json({\n ok: true,\n changed: true,\n groupId: result.groupId,\n content: result.html,\n path: ctx.filePath,\n backupPath,\n });\n });\n\n api.post(\"/projects/:id/file-mutations/unwrap-elements/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"unwrap-elements\");\n if (\"error\" in ctx) return ctx.error;\n\n const parsed = await parseMutationBody<{\n target?: MutationTarget;\n childTracks?: Array<{ target?: MutationTarget; track?: number }>;\n }>(c);\n if (\"error\" in parsed) return parsed.error;\n\n const rawChildTracks = parsed.body.childTracks ?? [];\n if (!rawChildTracks.every((entry) => isOptionalInteger(entry?.track))) {\n return c.json({ error: \"childTracks track must be a finite integer\" }, 400);\n }\n const childTracks = rawChildTracks\n .filter((entry): entry is { target: MutationTarget; track?: number } =>\n Boolean(entry?.target),\n )\n .map((entry) => ({ target: entry.target, track: entry.track }));\n\n let originalContent: string;\n try {\n originalContent = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ error: \"not found\" }, 404);\n }\n const result = unwrapElementsFromHtml(originalContent, parsed.target, childTracks);\n if (!result.unwrapped) {\n return c.json({ ok: false, changed: false, content: originalContent, path: ctx.filePath });\n }\n // BAKE the group's static transform into the members FIRST, so the group's\n // accumulated moves are preserved (otherwise members snap back to their\n // creation-time positions), THEN strip the group's GSAP — a leftover\n // `gsap.set(\"#group-1\")` throws \"target not found\" every preview run.\n let cleaned = result.html;\n if (result.unwrappedGroupId && result.members && result.groupCenter) {\n cleaned = bakeGroupTransformIntoMembers(\n cleaned,\n result.unwrappedGroupId,\n result.members,\n result.groupCenter,\n );\n }\n if (result.unwrappedGroupId) {\n cleaned = stripGsapAnimationsForSelector(cleaned, `#${result.unwrappedGroupId}`);\n }\n return writeIfChanged(c, ctx.project.dir, ctx.filePath, ctx.absPath, originalContent, cleaned);\n });\n\n api.post(\"/projects/:id/file-mutations/probe-element/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"probe-element\");\n if (\"error\" in ctx) return ctx.error;\n\n const parsed = await parseMutationBody<{ target?: MutationTarget }>(c);\n if (\"error\" in parsed) return parsed.error;\n\n let content: string;\n try {\n content = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ exists: false });\n }\n\n const exists = probeElementInSource(content, parsed.target);\n return c.json({ exists });\n });\n\n api.post(\"/projects/:id/file-mutations/probe-elements/*\", async (c) => {\n const ctx = await resolveFileMutationContext(c, adapter, \"probe-elements\");\n if (\"error\" in ctx) return ctx.error;\n\n const body = (await c.req.json().catch(() => null)) as { targets?: MutationTarget[] } | null;\n if (!Array.isArray(body?.targets)) return c.json({ error: \"targets required\" }, 400);\n\n let content: string;\n try {\n content = readFileSync(ctx.absPath, \"utf-8\");\n } catch {\n return c.json({ exists: body.targets.map(() => false) });\n }\n return c.json({ exists: probeElementsInSource(content, body.targets) });\n });\n\n // ── Rename / Move ──\n\n api.patch(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter, { mustExist: true });\n if (\"error\" in res) return res.error;\n\n const body: unknown = await c.req.json();\n const newPath =\n body !== null && typeof body === \"object\" && \"newPath\" in body ? body.newPath : undefined;\n if (\n typeof newPath !== \"string\" ||\n !newPath ||\n newPath.includes(\"\\0\") ||\n /[\\uD800-\\uDFFF]/u.test(newPath)\n ) {\n return c.json({ error: \"newPath required\" }, 400);\n }\n\n const newAbs = resolveWithinProject(res.project.dir, newPath);\n if (!newAbs) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n if (existsSync(newAbs)) {\n return c.json({ error: \"already exists\" }, 409);\n }\n\n const isDirectory = statSync(res.absPath, { throwIfNoEntry: false })?.isDirectory() ?? false;\n ensureDir(res.project.dir, newAbs);\n renameSync(res.absPath, newAbs);\n\n // Update references to the old path across all project files\n const updatedFiles = updateReferences(res.project.dir, res.filePath, newPath, isDirectory);\n\n return c.json({ ok: true, path: newPath, updatedReferences: updatedFiles });\n });\n\n // ── Duplicate ──\n\n api.post(\"/projects/:id/duplicate-file\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const body = (await c.req.json()) as { path: string };\n if (!body.path || body.path.includes(\"\\0\")) {\n return c.json({ error: \"path required\" }, 400);\n }\n\n const srcAbs = resolveWithinProject(project.dir, body.path);\n if (!srcAbs || !existsSync(srcAbs)) {\n return c.json({ error: \"not found\" }, 404);\n }\n\n const copyPath = generateCopyPath(project.dir, body.path);\n const destAbs = resolveWithinProject(project.dir, copyPath);\n if (!destAbs) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n\n ensureDir(project.dir, destAbs);\n try {\n createFileAtomically(destAbs, readFileSync(srcAbs));\n } catch (error) {\n if (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n return c.json({ error: \"already exists\" }, 409);\n }\n\n return c.json({ ok: true, path: copyPath }, 201);\n });\n\n // ── Upload (binary assets via multipart form) ──\n\n api.post(\n \"/projects/:id/upload\",\n bodyLimit({\n maxSize: MAX_UPLOAD_BYTES,\n onError: (c) => c.json({ error: \"payload too large\" }, 413),\n }),\n async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n if (folderGone(project.dir)) return projectDirMissing(c);\n\n // Optional subdirectory within the project (e.g. \"assets/audio\")\n const subDir = c.req.query(\"dir\") ?? \"\";\n const targetDir = subDir ? resolveWithinProject(project.dir, subDir) : project.dir;\n if (!targetDir) return c.json({ error: \"forbidden\" }, 403);\n\n const formData = await c.req.formData();\n mkdirWithinProject(project.dir, targetDir);\n const result = await processUploadedFiles(formData, targetDir, project.dir);\n if (folderGone(project.dir)) return projectDirMissing(c);\n\n return c.json(\n {\n ok: true,\n files: result.uploaded,\n skipped: result.skipped,\n invalid: result.invalid,\n unchecked: result.unchecked,\n },\n 201,\n );\n },\n );\n\n // ── GSAP Animations (parse) ──\n\n api.get(\"/projects/:id/gsap-animations/*\", async (c) => {\n const res = await resolveProjectPath(c, adapter, \"gsap-animations\", {\n mustExist: true,\n });\n if (\"error\" in res) return res.error;\n\n // The parse is a pure function of the file and the parser, so a client that revalidates on\n // every read gets a 304 for every unchanged file; bump the `v1` salt when the parser changes.\n const html = readFileSync(res.absPath, \"utf-8\");\n const etag = `${fileContentVersion(html).slice(0, -1)}:gsap-animations:v1\"`;\n const headers = { ETag: etag, \"Cache-Control\": \"no-cache\" };\n if (c.req.header(\"If-None-Match\") === etag) return new Response(null, { status: 304, headers });\n\n const block = extractGsapScriptBlock(html);\n if (!block) {\n return c.json(\n { animations: [], timelineVar: \"tl\", preamble: \"\", postamble: \"\" },\n 200,\n headers,\n );\n }\n\n return c.json(parseGsapScriptAcorn(block.scriptText), 200, headers);\n });\n\n // ── GSAP Mutations ──\n\n api.get(\"/projects/:id/gsap-mutation-capabilities\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n return c.json({ atomicOwnershipPairs: true });\n });\n\n api.post(\"/projects/:id/gsap-mutations/*\", async (c) => {\n const res = await resolveProjectPath(c, adapter, \"gsap-mutations\", {\n mustExist: true,\n pin: true,\n });\n if (\"error\" in res) return res.error;\n\n const body = (await c.req.json().catch(() => null)) as GsapMutationRequest | null;\n if (!body) return c.json({ error: \"mutation type required\" }, 400);\n const error = validateGsapMutationRequest(c, body);\n if (error) return error;\n return applyGsapMutations(c, res, [body]);\n });\n\n api.post(\"/projects/:id/gsap-mutations-batch/*\", async (c) => {\n const res = await resolveProjectPath(c, adapter, \"gsap-mutations-batch\", {\n mustExist: true,\n pin: true,\n });\n if (\"error\" in res) return res.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n mutations?: GsapMutationRequest[];\n } | null;\n if (!body || !Array.isArray(body.mutations) || body.mutations.length === 0) {\n return c.json({ error: \"mutations array required\" }, 400);\n }\n for (const mutation of body.mutations) {\n const error = validateGsapMutationRequest(c, mutation);\n if (error) return error;\n }\n return applyGsapMutations(c, res, body.mutations);\n });\n\n // A failed multi-step GSAP transaction may restore only the exact bytes its\n // mutation wrote. Keep compare + write in this synchronous server section so\n // another request cannot land between a client-side check and the restore.\n api.post(\"/projects/:id/gsap-mutation-rollback/*\", async (c) => {\n const res = await resolveProjectPath(c, adapter, \"gsap-mutation-rollback\", {\n mustExist: true,\n pin: true,\n });\n if (\"error\" in res) return res.error;\n\n const body = (await c.req.json().catch(() => null)) as {\n expected?: unknown;\n restore?: unknown;\n } | null;\n if (!body || typeof body.expected !== \"string\" || typeof body.restore !== \"string\") {\n return c.json({ error: \"expected and restore contents required\" }, 400);\n }\n\n const current = readFileSync(res.absPath, \"utf-8\");\n if (current !== body.expected) {\n return c.json({ ok: true, restored: false, conflict: true });\n }\n replaceFileAtomically(res.absPath, body.restore, statSync(res.absPath).mode);\n return c.json({ ok: true, restored: true, conflict: false });\n });\n}\n","export const MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html\",\n \".css\": \"text/css\",\n \".js\": \"text/javascript\",\n \".mjs\": \"text/javascript\",\n \".json\": \"application/json\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".ico\": \"image/x-icon\",\n \".mp4\": \"video/mp4\",\n \".m4v\": \"video/mp4\",\n \".mov\": \"video/quicktime\",\n \".mkv\": \"video/x-matroska\",\n \".mxf\": \"video/mxf\",\n \".mts\": \"video/mp2t\",\n \".m2ts\": \"video/mp2t\",\n \".ts\": \"video/mp2t\",\n \".webm\": \"video/webm\",\n \".mp3\": \"audio/mpeg\",\n \".wav\": \"audio/wav\",\n \".ogg\": \"audio/ogg\",\n \".m4a\": \"audio/mp4\",\n \".aac\": \"audio/aac\",\n \".flac\": \"audio/flac\",\n \".opus\": \"audio/ogg\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".otf\": \"font/otf\",\n \".txt\": \"text/plain\",\n \".md\": \"text/markdown\",\n \".cube\": \"text/plain; charset=utf-8\",\n};\n\nexport function getMimeType(path: string): string {\n const ext = path.slice(path.lastIndexOf(\".\")).toLowerCase();\n return MIME_TYPES[ext] || \"application/octet-stream\";\n}\n\nexport function isAudioFile(name: string): boolean {\n return (getMimeType(name) ?? \"\").startsWith(\"audio/\");\n}\n","import { readFileSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { parseHTML } from \"linkedom\";\nimport { createProjectSignature } from \"./projectSignature.js\";\nimport { rootHeadContent } from \"./subComposition.js\";\nimport { resolveWithinProject } from \"./safePath.js\";\nimport { descendants } from \"./compositionInsertion.js\";\n\nconst ROOT_COMPOSITION = \"index.html\";\n// A regex, not a parser: a stray match (say, inside a script string) only widens what a\n// change invalidates, never narrows it.\nconst COMPOSITION_SRC = /\\bdata-composition-src\\s*=\\s*([\"'])(.*?)\\1/g;\n\ntype SourceReader = (compPath: string) => string | null;\n\nfunction projectReader(projectDir: string): SourceReader {\n const sources = new Map<string, string | null>();\n return (compPath) => {\n if (!sources.has(compPath)) {\n const file = resolveWithinProject(projectDir, compPath);\n let source: string | null = null;\n try {\n source = file ? readFileSync(file, \"utf-8\") : null;\n } catch {\n // Missing or unreadable: it mounts nothing, and still counts as mounted by its host.\n }\n sources.set(compPath, source);\n }\n return sources.get(compPath) ?? null;\n };\n}\n\nfunction normalizeSource(src: string): string | null {\n if (/^[a-z][a-z0-9+.-]*:/i.test(src) || src.startsWith(\"//\")) return null;\n const path = src.split(/[?#]/)[0]?.replace(/^\\.?\\//, \"\") ?? \"\";\n return path || null;\n}\n\n/** `compPath` plus every composition it mounts, transitively, resolved from the project root as the bundler does. */\nfunction closureOf(read: SourceReader, compPath: string): Set<string> {\n const closure = new Set<string>();\n const visit = (path: string) => {\n if (closure.has(path)) return;\n closure.add(path);\n for (const match of (read(path) ?? \"\").matchAll(COMPOSITION_SRC)) {\n const mounted = normalizeSource(match[2] ?? \"\");\n if (mounted) visit(mounted);\n }\n };\n visit(compPath);\n return closure;\n}\n\n/** Whether `compPath` lasts as long as its own timeline (so a trim there could end the film early). */\nexport function lengthIsTimeline(projectDir: string, compPath: string): boolean {\n const read = projectReader(projectDir);\n const documents = new Map<string, Document>();\n const elements = (path: string, selector: string) => {\n let document = documents.get(path);\n if (!document) documents.set(path, (document = parseHTML(read(path) ?? \"\").document));\n return descendants(document, selector);\n };\n const comp = normalizeSource(compPath) ?? compPath;\n const unsized = (path: string) => {\n const [root] = elements(path, \"[data-composition-id]\");\n return Boolean(root && !root.hasAttribute(\"data-duration\"));\n };\n // An unsized root lasts as long as every timeline it plays, its compositions' included.\n if (unsized(ROOT_COMPOSITION)) return true;\n const hosts = [...closureOf(read, ROOT_COMPOSITION)].flatMap((path) =>\n elements(path, \"[data-composition-src]\").filter(\n (host) => normalizeSource(host.getAttribute(\"data-composition-src\") ?? \"\") === comp,\n ),\n );\n if (comp === ROOT_COMPOSITION || hosts.length === 0) return unsized(comp);\n return hosts.some(\n (host) => !host.hasAttribute(\"data-duration\") && !host.hasAttribute(\"data-end\"),\n );\n}\n\n// ponytail: this and projectSignature's per-exclusion cache keep one small entry per (project,\n// composition) ever thumbnailed, never evicted; LRU them if a server ever holds thousands.\nconst inputSignatures = new Map<string, { projectSignature: string; inputSignature: string }>();\n\ninterface RootMemo {\n root: string;\n head: string;\n affected: string[] | null;\n}\n\nconst rootMemos = new Map<string, RootMemo>();\n\nconst sha1 = (text: string) => createHash(\"sha1\").update(text).digest(\"hex\");\n\nfunction rootHashes(read: SourceReader) {\n const source = read(ROOT_COMPOSITION) ?? \"\";\n return { root: sha1(source), head: sha1(rootHeadContent(source)) };\n}\n\n// What a thumbnail of `compPath` renders from: the project minus the compositions the root\n// mounts that `compPath` does not; for a scene the root counts as its head alone.\nexport function compositionInputSignature(\n projectDir: string,\n compPath: string,\n projectSignature: string,\n): string {\n const key = `${projectDir}\\0${compPath}`;\n const known = inputSignatures.get(key);\n if (known?.projectSignature === projectSignature) return known.inputSignature;\n const read = projectReader(projectDir);\n const comp = normalizeSource(compPath) ?? compPath;\n const inputs = closureOf(read, comp).add(ROOT_COMPOSITION);\n const excluded = new Set(\n [...closureOf(read, ROOT_COMPOSITION)].filter((path) => !inputs.has(path)),\n );\n let inputSignature: string;\n if (comp === ROOT_COMPOSITION) {\n inputSignature = createProjectSignature(projectDir, excluded);\n } else {\n const hashes = rootHashes(read);\n if (!rootMemos.has(projectDir)) rootMemos.set(projectDir, { ...hashes, affected: null });\n inputSignature = `${createProjectSignature(projectDir, excluded.add(ROOT_COMPOSITION))}:${hashes.head}`;\n }\n inputSignatures.set(key, { projectSignature, inputSignature });\n return inputSignature;\n}\n\n/**\n * Compositions whose rendered frames a write at `changedPath` can change, or `null` for all\n * of them: assets, a root head edit, and any file the root does not mount reach every\n * composition. A head-preserving root write changes only the root's own frames.\n */\nexport function compositionsAffectedBy(projectDir: string, changedPath: string): string[] | null {\n const changed = changedPath.replace(/\\\\/g, \"/\");\n const read = projectReader(projectDir);\n if (changed === ROOT_COMPOSITION) {\n const now = rootHashes(read);\n const memo = rootMemos.get(projectDir);\n if (memo?.root === now.root) return memo.affected;\n const affected = memo?.head === now.head ? [ROOT_COMPOSITION] : null;\n rootMemos.set(projectDir, { ...now, affected });\n return affected;\n }\n const mounted = closureOf(read, ROOT_COMPOSITION);\n if (!mounted.has(changed)) return null;\n return [...mounted].filter((path) => closureOf(read, path).has(changed));\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseHTML } from \"linkedom\";\nimport {\n rewriteAssetPaths,\n rewriteCssAssetUrls,\n rewriteInlineStyleAssetUrls,\n} from \"@hyperframes/core\";\nimport {\n deferScriptsUntilFonts,\n RUNTIME_BOOTSTRAP_ATTR,\n stripEmbeddedRuntimeScripts,\n} from \"@hyperframes/core/compiler\";\nimport { isFullHtmlDocument } from \"@hyperframes/core/compiler/html-document\";\nimport { gsapCdnDist } from \"@hyperframes/core/gsap-cdn\";\n\n/**\n * Rewrite relative asset paths in a parsed DOM tree. Shared across all\n * three dispatch branches (template, full-doc, fragment) to avoid drift.\n *\n * The preview page borrows the project-root `<base>`, so a composition at\n * `design/styleframes/frame-01.html` referencing its sibling `_shared.css` was\n * requested as `/preview/_shared.css` (404). The frame then rendered unstyled,\n * which the thumbnailer's transparent-body fallback painted dark navy — the\n * \"illegible styleframe thumbnail\" bug. The `assetExists` probe re-points such\n * refs at the composition's own directory; see `rewriteAssetPath`.\n */\nfunction rewriteRelativePaths(root: ParentNode, compPath: string, projectDir: string): void {\n const assetExists = (path: string) => existsSync(join(projectDir, path));\n rewriteAssetPaths(\n root.querySelectorAll(\"[src], [href]\"),\n compPath,\n (el: Element, attr: string) => el.getAttribute(attr),\n (el: Element, attr: string, value: string) => el.setAttribute(attr, value),\n assetExists,\n );\n rewriteInlineStyleAssetUrls(\n root.querySelectorAll(\"[style]\"),\n compPath,\n (el: Element) => el.getAttribute(\"style\"),\n (el: Element, value: string) => el.setAttribute(\"style\", value),\n assetExists,\n );\n for (const styleEl of root.querySelectorAll(\"style\")) {\n styleEl.textContent = rewriteCssAssetUrls(styleEl.textContent || \"\", compPath, assetExists);\n }\n}\n\n/**\n * Escape a CSS identifier whose first character is a digit so it is a valid\n * selector. A CSS ident cannot start with a digit, so it must be written as an\n * escaped code point: `01-foo` → `\\30 1-foo` (leading `0` → `\\30 `, rest kept).\n *\n * Only the leading digit needs escaping (per CSS Syntax Level 3 §4.3.11): once\n * the parser consumes the `\\<hex> ` escape, the rest of the ident continues\n * normally, so `123-scene` → `\\31 23-scene` is valid (the `23-scene` tail is\n * consumed as identifier continuation). The trailing space terminates the hex\n * escape so a following hex digit isn't folded into the code point.\n */\nfunction escapeLeadingDigitIdent(id: string): string {\n return `\\\\${id.charCodeAt(0).toString(16)} ${id.slice(1)}`;\n}\n\nconst REGEXP_SPECIALS = /[.*+?^${}()|[\\]\\\\]/g;\n\n/**\n * Fix `#<digit-leading-id>` selectors in the tree's `<style>` blocks.\n *\n * CSS identifiers cannot start with a digit, so an authored rule like\n * `#01-wall-pushes-back { width: 1920px; height: 1080px; background: #F0EBDE }`\n * is an invalid selector and the browser silently drops the WHOLE rule — taking\n * the root's size and background with it. In a full composition the frame is\n * stretched/painted by its `data-composition-src` host so the collapse is\n * masked, but a standalone preview has no host: the root falls back to\n * `height: 0` + transparent and the frame renders blank (black).\n *\n * Rewrite each such selector to its escaped, valid form (`#\\30 1-wall-pushes-back`,\n * which still matches `id=\"01-wall-pushes-back\"`) so the rule applies and the\n * whole declaration block — size, background, position, container-type — comes\n * back. Scoped to ids that are actually present on elements in the content and\n * matched only as `#id` not followed by another ident char, so hex colors\n * (`#1F2BE0`) and other values are never touched (they are not element ids).\n */\nfunction fixDigitLeadingIdSelectors(root: ParentNode): void {\n const digitIds = new Set<string>();\n for (const el of root.querySelectorAll(\"[id]\")) {\n const id = el.getAttribute(\"id\");\n if (id && /^\\d/.test(id)) digitIds.add(id);\n }\n if (digitIds.size === 0) return;\n\n for (const styleEl of root.querySelectorAll(\"style\")) {\n let css = styleEl.textContent || \"\";\n for (const id of digitIds) {\n const pattern = new RegExp(`#${id.replace(REGEXP_SPECIALS, \"\\\\$&\")}(?![\\\\w-])`, \"g\");\n css = css.replace(pattern, `#${escapeLeadingDigitIdent(id)}`);\n }\n styleEl.textContent = css;\n }\n}\n\n/**\n * Parse a full HTML document and extract its head elements and body\n * content separately, so they can be reassembled into a clean standalone\n * page without nesting `<html>` inside `<body>`.\n *\n * Extracts the full innerHTML of `<head>` — this preserves `<style>`,\n * `<script>`, `<link>`, `<meta>`, and any other head-level tags the\n * composition declares. Dropping `<link rel=\"stylesheet\">` or `<meta>`\n * would cause silent rendering failures for compositions that ship with\n * external CSS or viewport-dependent meta.\n *\n * `<html>` and `<body>` attributes (lang, class, data-*) are extracted\n * so callers can forward them to the assembled page.\n */\nfunction extractFullDocumentParts(\n rawHtml: string,\n compPath: string,\n projectDir: string,\n): {\n headContent: string;\n bodyContent: string;\n htmlAttrs: string;\n bodyAttrs: string;\n} {\n const { document: doc } = parseHTML(rawHtml);\n\n const rewriteTargets = [doc.head, doc.body].filter(Boolean);\n for (const target of rewriteTargets) {\n rewriteRelativePaths(target, compPath, projectDir);\n }\n // Run on the whole document: ids live in <body> but their rules may live in\n // a <head> <style>, so the scope must span both.\n fixDigitLeadingIdSelectors(doc);\n\n const headContent = doc.head?.innerHTML ?? \"\";\n const bodyContent = doc.body?.innerHTML ?? \"\";\n\n const htmlEl = doc.documentElement;\n const htmlAttrs = extractElementAttrs(htmlEl);\n const bodyAttrs = doc.body ? extractElementAttrs(doc.body) : \"\";\n\n return { headContent, bodyContent, htmlAttrs, bodyAttrs };\n}\n\n/**\n * Extract the inner HTML of the composition's wrapping `<template>` element, or\n * `null` if the source has no `<template>`.\n *\n * Located via the DOM rather than a regex. A greedy\n * `/<template[^>]*>([\\s\\S]*)<\\/template>/` can latch onto a literal\n * `\"<template>\"` that appears inside an HTML comment — e.g. a head note such as\n * \"the HF runtime clones ONLY <template> contents\" — and mis-slice the capture,\n * leaving the real composition content re-wrapped in an inert `<template>` in\n * the output. That template is never rendered by the browser, so the standalone\n * preview has no `[data-composition-id]` element and no registered timeline, and\n * renders blank. `querySelector(\"template\")` only ever matches a real element\n * node, so comment text can't fool it.\n */\nfunction extractTemplateInnerHtml(rawComp: string): string | null {\n const { document: doc } = parseHTML(rawComp);\n const template = doc.querySelector(\"template\");\n return template ? template.innerHTML : null;\n}\n\n/** Attribute values read from the DOM are decoded — re-escape on rebuild or\n * quote-bearing values (data-composition-variables is a JSON array) shred\n * the wrapper's markup into bogus attributes. */\nfunction escapeAttrValue(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\nfunction extractElementAttrs(el: Element): string {\n const parts: string[] = [];\n for (let i = 0; i < el.attributes.length; i++) {\n const attr = el.attributes[i]!;\n if (attr.value === \"\") {\n parts.push(attr.name);\n } else {\n parts.push(`${attr.name}=\"${escapeAttrValue(attr.value)}\"`);\n }\n }\n return parts.join(\" \");\n}\n\nconst NON_RENDERED_TAGS = new Set([\"SCRIPT\", \"STYLE\", \"LINK\", \"META\", \"TEMPLATE\", \"NOSCRIPT\"]);\n\n/**\n * Carry the `<template>`'s `data-composition-id` onto the content's root\n * rendered element when the author declared it only on the `<template>` tag.\n *\n * In a full composition, each sub-composition is mounted under a wrapper\n * element (the `data-composition-src` host) that carries the composition id,\n * which is how the runtime binds `window.__timelines[id]` into the player's\n * master timeline. A standalone preview has no such wrapper, so it relies on\n * the frame's own root element carrying `data-composition-id`. If the id lives\n * only on the inert `<template>` tag (a common authoring pattern), the rendered\n * body has no `[data-composition-id]` element — the runtime then never selects\n * a root composition, the registered GSAP timeline stays unbound, and seeking\n * does nothing. The frame renders at its pre-animation state (GSAP `fromTo`\n * pins `opacity:0`), producing a blank preview/thumbnail.\n *\n * This is a no-op when the content already exposes a `[data-composition-id]`\n * element (e.g. the id is authored on the root div), so compositions that\n * already render correctly are untouched.\n */\nfunction promoteTemplateCompositionId(rawComp: string, body: Element): void {\n // Two-step match instead of one `[^>]*\\s…` regex: the single-pattern form\n // backtracks polynomially on crafted input (CodeQL js/polynomial-redos).\n // Step 1 grabs each <template …> open tag (linear); step 2 finds the attr\n // within that short tag text.\n let templateCompositionId: string | undefined;\n for (const tag of rawComp.matchAll(/<template\\b[^>]*/gi)) {\n const id = /\\bdata-composition-id\\s*=\\s*[\"']([^\"']+)[\"']/i.exec(tag[0] ?? \"\")?.[1];\n if (id) {\n templateCompositionId = id;\n break;\n }\n }\n if (!templateCompositionId) return;\n if (body.querySelector(\"[data-composition-id]\")) return;\n\n const root = Array.from(body.children).find((el) => !NON_RENDERED_TAGS.has(el.tagName));\n root?.setAttribute(\"data-composition-id\", templateCompositionId);\n}\n\n/**\n * Add `data-composition-file=\"<compPath>\"` to the comp's root composition\n * element (the first `[data-composition-id]` that lacks the attribute), so the\n * studio resolves its top-level elements to the right source file. Idempotent;\n * a no-op when no composition element is present.\n */\nfunction tagRootCompositionFile(bodyHtml: string, compPath: string): string {\n const match = bodyHtml.match(/<[a-zA-Z][^>]*\\bdata-composition-id=/);\n if (match?.index == null) return bodyHtml;\n const tagEnd = bodyHtml.indexOf(\">\", match.index);\n if (tagEnd === -1) return bodyHtml;\n if (bodyHtml.slice(match.index, tagEnd).includes(\"data-composition-file\")) return bodyHtml;\n return (\n bodyHtml.slice(0, tagEnd) + ` data-composition-file=\"${compPath}\"` + bodyHtml.slice(tagEnd)\n );\n}\n\nexport function rootHeadContent(rootHtml: string): string {\n return rootHtml.match(/<head[^>]*>([\\s\\S]*?)<\\/head>/i)?.[1] ?? \"\";\n}\n\n/**\n * Build a standalone HTML page for a sub-composition.\n *\n * Uses the project's own index.html `<head>` so all dependencies (GSAP, fonts,\n * Lottie, reset styles, runtime) are preserved — instead of building a minimal\n * page from scratch that would miss important scripts/styles.\n *\n * Three dispatch modes, tried in order:\n * 1. `<template>` wrapper → extract template content (existing compositions)\n * 2. Full HTML document → parse and extract head/body separately (registry blocks)\n * 3. Raw fragment → wrap in a minimal document\n *\n * For full-doc mode, the composition's own `<head>` content (styles, scripts,\n * links, meta) is appended AFTER the project's index.html head. When both\n * declare the same dependency (e.g. GSAP CDN), the composition's copy wins\n * by last-write-wins script execution order — this is intentional so the\n * composition can pin a specific version.\n */\nexport function buildSubCompositionHtml(\n projectDir: string,\n compPath: string,\n runtimeUrl: string,\n baseHref?: string,\n rawOverride?: string,\n): string | null {\n const compFile = join(projectDir, compPath);\n if (!existsSync(compFile)) return null;\n\n // rawOverride lets the preview route thread the hf-id-stamped content in\n // directly, so the build uses ids minted from the raw file, which is never\n // written by serving.\n const rawComp = rawOverride ?? readFileSync(compFile, \"utf-8\");\n\n let compHeadContent = \"\";\n let rewrittenContent: string;\n let htmlAttrs = \"\";\n let bodyAttrs = \"\";\n\n const templateInner = extractTemplateInnerHtml(rawComp);\n\n if (templateInner != null) {\n const { document: contentDoc } = parseHTML(\n `<!DOCTYPE html><html><head></head><body>${templateInner}</body></html>`,\n );\n rewriteRelativePaths(contentDoc, compPath, projectDir);\n fixDigitLeadingIdSelectors(contentDoc);\n promoteTemplateCompositionId(rawComp, contentDoc.body);\n rewrittenContent = contentDoc.body.innerHTML || templateInner;\n } else if (isFullHtmlDocument(rawComp)) {\n const parts = extractFullDocumentParts(rawComp, compPath, projectDir);\n compHeadContent = parts.headContent;\n rewrittenContent = parts.bodyContent;\n htmlAttrs = parts.htmlAttrs;\n bodyAttrs = parts.bodyAttrs;\n } else {\n const { document: contentDoc } = parseHTML(\n `<!DOCTYPE html><html><head></head><body>${rawComp}</body></html>`,\n );\n rewriteRelativePaths(contentDoc, compPath, projectDir);\n fixDigitLeadingIdSelectors(contentDoc);\n rewrittenContent = contentDoc.body.innerHTML || rawComp;\n }\n\n // A composition file may ship a baked inline runtime (from a prior export:\n // data-hyperframes-runtime / __hyperframeRuntime…). The studio injects its own\n // preview runtime below, so strip the baked one from the body — otherwise it's\n // double-loaded AND the baked inline copy can fail to parse inline (the\n // \"Unexpected token '<'\" SyntaxError seen on comps with a baked runtime).\n rewrittenContent = stripEmbeddedRuntimeScripts(rewrittenContent);\n const { document: scriptsDoc } = parseHTML(\n `<!DOCTYPE html><html><head></head><body>${rewrittenContent}</body></html>`,\n );\n deferScriptsUntilFonts(scriptsDoc as unknown as Document);\n rewrittenContent = scriptsDoc.body.innerHTML;\n\n // The comp's root carries data-composition-id but (unlike inlined sub-comps,\n // which inlineSubCompositions tags) no data-composition-file. Without it the\n // studio can't resolve which file this comp's top-level elements live in and\n // falls back to \"index.html\" — so the GSAP panel parses the project root (which\n // may be a multi-timeline master) and wrongly reports \"multiple timelines\",\n // disabling editing for a single-timeline comp. Tag the root with its own path.\n rewrittenContent = tagRootCompositionFile(rewrittenContent, compPath);\n\n // Use the project's index.html <head> to preserve all dependencies\n const indexPath = join(projectDir, \"index.html\");\n let headContent = \"\";\n\n if (existsSync(indexPath)) headContent = rootHeadContent(readFileSync(indexPath, \"utf-8\"));\n\n // Inject <base> for relative asset resolution (before other tags)\n if (baseHref && !hasBaseElement(headContent)) {\n headContent = `<base href=\"${baseHref}\">\\n${headContent}`;\n }\n\n // Append the sub-composition's own <head> content so its CSS, scripts,\n // links, and meta tags are preserved. Placed after the project head so\n // the composition's deps take precedence (last-write-wins for scripts).\n if (compHeadContent) headContent += `\\n${compHeadContent}`;\n\n // Strip any baked runtime the borrowed index/comp <head> carried, for the same\n // reason as the body above — done before injecting the preview runtime so the\n // injected tag (added next) is never removed.\n headContent = stripEmbeddedRuntimeScripts(headContent);\n\n headContent += `\\n<script ${RUNTIME_BOOTSTRAP_ATTR}=\"1\" src=\"${runtimeUrl}\"></script>`;\n\n // Fallback: if no index.html head was found, add minimal deps\n if (!headContent.includes(\"gsap\")) {\n headContent += `\\n<script src=\"${gsapCdnDist()}gsap.min.js\"></script>`;\n }\n\n const htmlOpen = htmlAttrs ? `<html ${htmlAttrs}>` : \"<html>\";\n const bodyOpen = bodyAttrs ? `<body ${bodyAttrs}>` : \"<body>\";\n\n return `<!DOCTYPE html>\n${htmlOpen}\n<head>\n${headContent}\n</head>\n${bodyOpen}\n<script>window.__timelines=window.__timelines||{};</script>\n${rewrittenContent}\n</body>\n</html>`;\n}\n\n/** True for a real `<base>` element; the text \"<base\" inside a script or comment does not count. */\nexport function hasBaseElement(html: string): boolean {\n return parseHTML(html).document.querySelector(\"base\") !== null;\n}\n","import { existsSync } from \"node:fs\";\nimport { readProjectFile } from \"@hyperframes/parsers/asset-resolution\";\nimport { randomUUID } from \"node:crypto\";\nimport { dirname, relative, resolve, sep } from \"node:path\";\nimport { parseHTML } from \"linkedom\";\nimport { ProjectRootMissingError } from \"@hyperframes/core\";\nimport { folderGone, isSafePath, realpath, resolveWithinProject } from \"./safePath.js\";\n\nexport class CompositionInsertionError extends Error {\n constructor(\n message: string,\n readonly status: 400 | 404,\n ) {\n super(message);\n }\n}\n\nexport function descendants(root: Document | Element, selector: string): Element[] {\n const found = Array.from(root.querySelectorAll(selector));\n for (const template of root.querySelectorAll(\"template\")) {\n found.push(...descendants(template, selector));\n }\n return [...new Set(found)];\n}\n\nfunction compositionRoot(source: string): { document: Document; root: Element } {\n const document = parseHTML(source).document;\n const root = descendants(document, \"[data-composition-id]\")[0];\n if (!root) throw new CompositionInsertionError(\"Composition source has no root\", 400);\n return { document, root };\n}\n\nfunction positiveAttribute(root: Element, ...names: string[]): number {\n for (const name of names) {\n const value = Number.parseFloat(root.getAttribute(name) ?? \"\");\n if (Number.isFinite(value) && value > 0) return value;\n }\n throw new CompositionInsertionError(`Composition source has no valid ${names[0]}`, 400);\n}\n\nfunction canonicalProjectPath(projectDir: string, candidate: string | null): string {\n if (!candidate) {\n if (folderGone(projectDir)) throw new ProjectRootMissingError(projectDir);\n throw new CompositionInsertionError(\"Composition source escapes the project\", 400);\n }\n if (!existsSync(candidate)) {\n throw new CompositionInsertionError(\"Composition source was not found\", 404);\n }\n const canonical = realpath(candidate);\n if (!isSafePath(realpath(projectDir), canonical)) {\n throw new CompositionInsertionError(\"Composition source escapes the project\", 400);\n }\n return canonical;\n}\n\nfunction readCompositionSource(file: string): string {\n const read = readProjectFile(file);\n if (read.kind === \"folder\") {\n throw new CompositionInsertionError(\"Composition source is a folder, not an HTML file\", 400);\n }\n if (read.kind === \"missing\") {\n throw new CompositionInsertionError(\"Composition source was not found\", 404);\n }\n return read.text;\n}\n\nfunction validateSourcePath(sourcePath: string): void {\n if (!sourcePath.trim() || sourcePath.includes(\"\\0\") || /^[a-z]+:/i.test(sourcePath)) {\n throw new CompositionInsertionError(\"Invalid composition source path\", 400);\n }\n}\n\nfunction canonicalProjectFile(projectDir: string, sourcePath: string): string {\n validateSourcePath(sourcePath);\n return canonicalProjectPath(projectDir, resolveWithinProject(projectDir, sourcePath));\n}\n\nfunction canonicalDependency(projectDir: string, ownerAbs: string, sourcePath: string): string {\n validateSourcePath(sourcePath);\n return canonicalProjectPath(\n projectDir,\n resolveWithinProject(projectDir, relative(projectDir, resolve(dirname(ownerAbs), sourcePath))),\n );\n}\n\nfunction validateDependencyGraph(projectDir: string, targetAbs: string, sourceAbs: string): void {\n const visited = new Set<string>();\n const visiting = new Set<string>();\n const visit = (file: string) => {\n if (file === targetAbs) {\n throw new CompositionInsertionError(\"Composition insertion would create a cycle\", 400);\n }\n if (visiting.has(file)) {\n throw new CompositionInsertionError(\"Composition dependency cycle detected\", 400);\n }\n if (visited.has(file)) return;\n visiting.add(file);\n const source = readCompositionSource(file);\n const { document } = compositionRoot(source);\n for (const host of descendants(document, \"[data-composition-src]\")) {\n const dependency = host.getAttribute(\"data-composition-src\");\n if (dependency) {\n visit(canonicalDependency(projectDir, file, dependency));\n }\n }\n visiting.delete(file);\n visited.add(file);\n };\n visit(sourceAbs);\n}\n\nfunction numberAttribute(element: Element, name: string, fallback = 0): number {\n const value = Number.parseFloat(element.getAttribute(name) ?? \"\");\n return Number.isFinite(value) ? value : fallback;\n}\n\nfunction rangesOverlap(start: number, duration: number, other: Element): boolean {\n const otherStart = numberAttribute(other, \"data-start\");\n const otherDuration = numberAttribute(other, \"data-duration\");\n return start < otherStart + otherDuration && otherStart < start + duration;\n}\n\nfunction resolveTrack(\n root: Element,\n desiredTrack: number,\n start: number,\n duration: number,\n): number {\n const clips = descendants(root, \"[data-start][data-duration]\").filter(\n (element) =>\n element !== root && element.parentElement?.closest(\"[data-composition-id]\") === root,\n );\n const tracks = [...new Set(clips.map((clip) => numberAttribute(clip, \"data-track-index\")))].sort(\n (a, b) => a - b,\n );\n const isFree = (track: number) =>\n !clips.some(\n (clip) =>\n numberAttribute(clip, \"data-track-index\") === track && rangesOverlap(start, duration, clip),\n );\n if (isFree(desiredTrack)) return desiredTrack;\n const row = tracks.indexOf(desiredTrack);\n for (let index = row - 1; index >= 0; index--) {\n const track = tracks[index];\n if (track !== undefined && isFree(track)) return track;\n }\n for (let index = Math.max(0, row + 1); index < tracks.length; index++) {\n const track = tracks[index];\n if (track !== undefined && isFree(track)) return track;\n }\n return Math.max(desiredTrack, ...tracks, -1) + 1;\n}\n\nfunction uniqueHostId(root: Element, base: string): string {\n const ids = new Set([\n ...descendants(root, \"[id]\").map((element) => element.id),\n ...descendants(root, \"[data-composition-id]\").flatMap((element) => {\n const id = element.getAttribute(\"data-composition-id\");\n return id ? [id] : [];\n }),\n ]);\n if (!ids.has(base)) return base;\n let suffix = 2;\n while (ids.has(`${base}_${suffix}`)) suffix += 1;\n return `${base}_${suffix}`;\n}\n\nfunction relativeSourcePath(targetAbs: string, sourceAbs: string): string {\n return relative(dirname(targetAbs), sourceAbs).split(sep).join(\"/\");\n}\n\nexport function insertCompositionIntoSource(input: {\n projectDir: string;\n targetPath: string;\n sourcePath: string;\n parentSource: string;\n start: number;\n desiredTrack: number;\n}): { html: string; hostId: string; track: number; duration: number } {\n const targetAbs = canonicalProjectFile(input.projectDir, input.targetPath);\n const sourceAbs = canonicalProjectFile(input.projectDir, input.sourcePath);\n validateDependencyGraph(input.projectDir, targetAbs, sourceAbs);\n\n const source = readCompositionSource(sourceAbs);\n const sourceComposition = compositionRoot(source).root;\n const duration = positiveAttribute(\n sourceComposition,\n \"data-composition-duration\",\n \"data-duration\",\n );\n const width = positiveAttribute(sourceComposition, \"data-width\");\n const height = positiveAttribute(sourceComposition, \"data-height\");\n const { document, root } = compositionRoot(input.parentSource);\n const parentDuration = positiveAttribute(root, \"data-duration\", \"data-composition-duration\");\n const base =\n (sourceComposition.getAttribute(\"data-composition-id\") ?? \"composition\")\n .replace(/[^a-zA-Z0-9_-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"composition\";\n const hostId = uniqueHostId(root, base);\n const track = resolveTrack(\n root,\n Math.max(0, Math.round(input.desiredTrack)),\n input.start,\n duration,\n );\n const zIndex =\n Math.max(\n 0,\n ...descendants(root, \"[style]\").map((element) => {\n const match = /(?:^|;)\\s*z-index\\s*:\\s*(-?\\d+)/i.exec(element.getAttribute(\"style\") ?? \"\");\n return match?.[1] ? Number.parseInt(match[1], 10) : 0;\n }),\n ) + 1;\n\n const host = document.createElement(\"div\");\n host.id = hostId;\n host.className = \"clip\";\n host.setAttribute(\"data-hf-id\", `hf-${randomUUID()}`);\n host.setAttribute(\"data-composition-id\", hostId);\n host.setAttribute(\"data-composition-src\", relativeSourcePath(targetAbs, sourceAbs));\n host.setAttribute(\"data-start\", String(Math.round(input.start * 100) / 100));\n host.setAttribute(\"data-duration\", String(duration));\n host.setAttribute(\"data-playback-start\", \"0\");\n host.setAttribute(\"data-track-index\", String(track));\n host.setAttribute(\"data-width\", String(width));\n host.setAttribute(\"data-height\", String(height));\n host.setAttribute(\n \"style\",\n `position: absolute; left: 0px; top: 0px; width: ${width}px; height: ${height}px; z-index: ${zIndex}`,\n );\n root.appendChild(host);\n if (input.start + duration > parentDuration) {\n const name = root.hasAttribute(\"data-duration\") ? \"data-duration\" : \"data-composition-duration\";\n root.setAttribute(name, String(Math.round((input.start + duration) * 100) / 100));\n }\n return { html: document.toString(), hostId, track, duration };\n}\n","import { spawn } from \"node:child_process\";\nimport {\n existsSync,\n writeFileSync,\n mkdirSync,\n lstatSync,\n mkdtempSync,\n renameSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\n\nconst SAMPLE_RATE = 4000;\nconst PEAK_COUNT = 4000;\nconst WAVEFORM_CACHE_VERSION = \"v2\";\n\n/**\n * Cache filename for one asset's peaks, keyed on its content as well as its name.\n *\n * The path alone is not an identity. An asset rebuilt in place — a bed\n * re-encoded without its ducking, a plate swapped for the right one — keeps its\n * name and gets new samples, and a path-keyed entry then served the old peaks\n * for the rest of the project's life: the timeline drew a duck that was no\n * longer in the file, which reads as the render having done it. Size and mtime\n * are what a rebuild always changes, and both are already on the stat the route\n * takes to check the file exists.\n *\n * Without a fingerprint it falls back to the old path-only key, so a caller that\n * cannot stat still gets caching rather than an error.\n */\nexport function buildWaveformCacheKey(\n assetPath: string,\n fingerprint?: { size: number; mtimeMs: number },\n): string {\n const name = assetPath.replace(/[/\\\\]/g, \"_\");\n if (!fingerprint) return `${WAVEFORM_CACHE_VERSION}_${name}.json`;\n const stamp = `${fingerprint.size}-${Math.round(fingerprint.mtimeMs)}`;\n return `${WAVEFORM_CACHE_VERSION}_${name}_${stamp}.json`;\n}\n\nfunction computePeaks(floats: Float32Array, count: number): number[] {\n const step = floats.length / count;\n const peaks: number[] = [];\n for (let i = 0; i < count; i++) {\n const start = Math.floor(i * step);\n const end = Math.min(Math.floor((i + 1) * step), floats.length);\n let max = 0;\n for (let j = start; j < end; j++) {\n // fallow-ignore-next-line code-duplication\n const abs = Math.abs(floats[j] ?? 0);\n if (abs > max) max = abs;\n }\n peaks.push(max);\n }\n const maxPeak = Math.max(...peaks, 0.001);\n return peaks.map((p) => p / maxPeak);\n}\n\nexport function decodeAudioPeaks(audioPath: string): Promise<number[]> {\n return new Promise((resolvePromise, reject) => {\n const proc = spawn(\n findFfBinary(\"ffmpeg\") ?? \"ffmpeg\",\n [\n \"-i\",\n audioPath,\n \"-af\",\n \"atrim=start_sample=1152\",\n \"-f\",\n \"f32le\",\n \"-ac\",\n \"1\",\n \"-ar\",\n String(SAMPLE_RATE),\n \"-vn\",\n \"pipe:1\",\n ],\n { stdio: [\"ignore\", \"pipe\", \"ignore\"], windowsHide: true },\n );\n\n const chunks: Buffer[] = [];\n proc.stdout?.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n proc.on(\"close\", (code) => {\n if (code !== 0 && chunks.length === 0) {\n reject(new Error(`ffmpeg exited with code ${code}`));\n return;\n }\n const buf = Buffer.concat(chunks);\n const numSamples = Math.floor(buf.length / 4);\n if (numSamples === 0) {\n reject(new Error(\"ffmpeg produced no audio samples\"));\n return;\n }\n const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + numSamples * 4);\n resolvePromise(computePeaks(new Float32Array(ab), PEAK_COUNT));\n });\n proc.on(\"error\", reject);\n });\n}\n\nexport async function generateWaveformCache(projectDir: string, assetPath: string): Promise<void> {\n const audioPath = join(projectDir, assetPath);\n if (!existsSync(audioPath)) return;\n\n const stats = statSync(audioPath);\n const cacheDir = join(projectDir, \".waveform-cache\");\n const cachePath = join(cacheDir, buildWaveformCacheKey(assetPath, stats));\n if (isWaveformCacheDirectory(cacheDir) && existsSync(cachePath)) return;\n\n const peaks = await decodeAudioPeaks(audioPath);\n writeWaveformCache(cachePath, peaks);\n}\n\nexport function isWaveformCacheDirectory(cacheDir: string): boolean {\n return lstatSync(cacheDir, { throwIfNoEntry: false })?.isDirectory() ?? false;\n}\n\n/** Publish complete peaks without following a replaced cache-file symlink. */\nexport function writeWaveformCache(cachePath: string, peaks: number[]): void {\n const cacheDir = dirname(cachePath);\n try {\n mkdirSync(cacheDir, { mode: 0o700 });\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"EEXIST\")) throw error;\n }\n if (!isWaveformCacheDirectory(cacheDir)) {\n throw new Error(\"Waveform cache must be a directory, not a symlink\");\n }\n const stagingDir = mkdtempSync(join(cacheDir, \".waveform-\"));\n try {\n const stagingPath = join(stagingDir, \"peaks.json\");\n writeFileSync(stagingPath, JSON.stringify(peaks), { flag: \"wx\" });\n renameSync(stagingPath, cachePath);\n } finally {\n try {\n rmSync(stagingDir, { recursive: true, force: true });\n } catch {\n // Cleanup must not mask a write error or fail an already published cache.\n }\n }\n}\n","import { spawnSync } from \"node:child_process\";\nimport { mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { FFPROBE_PATH_ENV, findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\n\nconst VIDEO_EXT = /\\.(mp4|webm|mov|mkv|avi|m4v|mxf|mts|m2ts|ts)$/i;\nconst AUDIO_EXT = /\\.(mp3|wav|ogg|m4a|aac|flac)$/i;\n\ntype FfprobeRunner = (\n command: string,\n args: string[],\n options: { windowsHide: boolean },\n) => {\n status: number | null;\n stdout: string | Buffer;\n stderr: string | Buffer;\n error?: NodeJS.ErrnoException;\n};\n\ntype MediaCheck = { ok: true; unchecked?: string } | { ok: false; reason: string };\n\nconst defaultRunner = spawnSync as unknown as FfprobeRunner;\nconst FFPROBE_MISSING =\n \"not checked: ffprobe was not found. Install FFmpeg or set HYPERFRAMES_FFPROBE_PATH.\";\n\nexport function validateUploadedMedia(\n filePath: string,\n runner: FfprobeRunner = defaultRunner,\n): MediaCheck {\n const isVideo = VIDEO_EXT.test(filePath);\n const isAudio = AUDIO_EXT.test(filePath);\n if (!isVideo && !isAudio) {\n return { ok: true };\n }\n\n const ffprobe = findFfBinary(\"ffprobe\") ?? (runner === defaultRunner ? undefined : \"ffprobe\");\n if (!ffprobe) return { ok: true, unchecked: FFPROBE_MISSING };\n const result = runner(\n ffprobe,\n [\"-v\", \"error\", \"-show_entries\", \"stream=codec_type\", \"-of\", \"json\", \"--\", filePath],\n { windowsHide: true },\n );\n\n if (result.error && process.env[FFPROBE_PATH_ENV]?.trim()) {\n return {\n ok: false,\n reason: `${FFPROBE_PATH_ENV} names \"${ffprobe}\", which cannot run: fix it or unset it`,\n };\n }\n if (result.error?.code === \"ENOENT\") {\n return { ok: true, unchecked: FFPROBE_MISSING };\n }\n if (result.status !== 0) {\n return { ok: false, reason: \"ffprobe failed to read the media file\" };\n }\n\n return checkStreams(String(result.stdout || \"{}\"), isVideo, isAudio);\n}\n\nfunction checkStreams(stdout: string, isVideo: boolean, isAudio: boolean): MediaCheck {\n try {\n const parsed = JSON.parse(stdout) as { streams?: Array<{ codec_type?: string }> };\n const streams = parsed.streams ?? [];\n const hasVideo = streams.some((stream) => stream.codec_type === \"video\");\n const hasAudio = streams.some((stream) => stream.codec_type === \"audio\");\n\n if (isVideo && !hasVideo) {\n return { ok: false, reason: \"no supported video stream found\" };\n }\n if (isAudio && !hasAudio) {\n return { ok: false, reason: \"no supported audio stream found\" };\n }\n return { ok: true };\n } catch {\n return { ok: false, reason: \"ffprobe returned unreadable media metadata\" };\n }\n}\n\nexport function validateUploadedMediaBuffer(\n fileName: string,\n buffer: Uint8Array,\n runner: FfprobeRunner = defaultRunner,\n): MediaCheck {\n const tempDir = mkdtempSync(join(tmpdir(), \"hyperframes-upload-\"));\n const tempPath = join(tempDir, basename(fileName));\n\n try {\n writeFileSync(tempPath, buffer);\n return validateUploadedMedia(tempPath, runner);\n } finally {\n rmSync(tempDir, { recursive: true, force: true });\n }\n}\n","import { readdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { Buffer } from \"node:buffer\";\nimport { join, relative } from \"node:path\";\nimport { isProjectRootMissing, isSafePath, mkdirWithinProject } from \"./safePath.js\";\n\nconst DEFAULT_KEEP_PER_FILE = 10;\n\nexport interface BackupJournalResult {\n backupPath: string | null;\n error?: string;\n}\n\nfunction backupKeyForPath(path: string): string {\n return Buffer.from(path, \"utf-8\").toString(\"base64url\");\n}\n\nfunction timestampPrefix(): string {\n return new Date().toISOString().replace(/[:.]/g, \"-\");\n}\n\nexport function backupPathForResponse(\n projectDir: string,\n backupPath: string | null,\n): string | null {\n if (!backupPath) return null;\n const rel = relative(projectDir, backupPath);\n if (!rel || rel.startsWith(\"..\")) return null;\n return rel.split(\"\\\\\").join(\"/\");\n}\n\nexport function snapshotBeforeWrite(\n projectDir: string,\n absPath: string,\n options: { keepPerFile?: number } = {},\n): BackupJournalResult {\n if (!isSafePath(projectDir, absPath)) return { backupPath: null };\n\n try {\n const content = readFileSync(absPath);\n\n const relativePath = relative(projectDir, absPath);\n const backupDir = join(projectDir, \".hyperframes\", \"backup\");\n mkdirWithinProject(projectDir, backupDir);\n\n const backupKey = backupKeyForPath(relativePath);\n const backupPath = nextBackupPath(backupDir, backupKey);\n writeFileSync(backupPath, content);\n pruneBackups(backupDir, backupKey, options.keepPerFile ?? DEFAULT_KEEP_PER_FILE);\n return { backupPath };\n } catch (error) {\n if (isProjectRootMissing(error)) throw error;\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n (error.code === \"ENOENT\" || error.code === \"EISDIR\")\n ) {\n return { backupPath: null };\n }\n return { backupPath: null, error: error instanceof Error ? error.message : String(error) };\n }\n}\n\nfunction nextBackupPath(backupDir: string, backupKey: string): string {\n const base = `${timestampPrefix()}-${backupKey}`;\n let candidate = join(backupDir, base);\n let counter = 2;\n while (true) {\n try {\n readFileSync(candidate);\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n return candidate;\n }\n throw error;\n }\n candidate = join(backupDir, `${base}-${counter}`);\n counter += 1;\n }\n}\n\nfunction pruneBackups(backupDir: string, backupKey: string, keepPerFile: number): void {\n const keep = Math.max(1, Math.floor(keepPerFile));\n const suffix = `-${backupKey}`;\n const numberedSuffix = new RegExp(`-${backupKey}-\\\\d+$`);\n const matches = readdirSync(backupDir)\n .filter((name) => name.endsWith(suffix) || numberedSuffix.test(name))\n .map((name) => join(backupDir, name))\n .sort((a, b) => {\n return b.localeCompare(a);\n });\n\n for (const file of matches.slice(keep)) {\n try {\n unlinkSync(file);\n } catch {\n // Backup pruning is best-effort and must not block the user's write.\n }\n }\n}\n","import type { Context } from \"hono\";\n\nconst PROJECT_DIR_MISSING = { error: \"not found\", why: \"project_dir_missing\" };\n\nexport const projectDirMissing = (c: {\n json: (data: { error: string; why: string }, status: 404) => Response;\n}) => c.json(PROJECT_DIR_MISSING, 404);\n\nexport function replaceWithProjectDirMissing(c: Context, hostHeaders: Headers): void {\n hostHeaders.delete(\"content-type\");\n c.res = undefined;\n c.res = Response.json(PROJECT_DIR_MISSING, { status: 404, headers: hostHeaders });\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport { replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\nimport { backupPathForResponse, snapshotBeforeWrite } from \"./backupJournal.js\";\nimport {\n clearFileWriteReceipt,\n createWriteToken,\n fileContentVersion,\n recordFileWriteReceipt,\n} from \"./fileVersion.js\";\n\nexport interface FileMutationInput {\n sourceFile: string;\n absPath: string;\n before?: string;\n after: string;\n expectedVersion?: string;\n}\n\nexport interface AppliedFileMutation {\n sourceFile: string;\n changed: boolean;\n before: string;\n after: string;\n backupPath: string | null;\n version: string;\n writeToken: string | null;\n}\n\n/** Applies prepared HTML mutations with the same journal and receipt semantics as Studio. */\nexport function applyFileMutations(\n projectDir: string,\n mutations: readonly FileMutationInput[],\n requestToken?: string,\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void = (path, content) =>\n replaceFileAtomically(path, content, statSync(path).mode),\n): AppliedFileMutation[] {\n const prepared = mutations.map((mutation) => ({\n ...mutation,\n before: mutation.before ?? readFileSync(mutation.absPath, \"utf-8\"),\n }));\n const results: AppliedFileMutation[] = [];\n const attempted: Array<\n PreparedMutation & { version: string; writeToken: string; written: boolean }\n > = [];\n for (const mutation of prepared)\n assertExpectedVersion(mutation, readFileSync(mutation.absPath, \"utf-8\"));\n try {\n for (const mutation of prepared) {\n results.push(applyOneMutation(projectDir, mutation, requestToken, writeFile, attempted));\n }\n return results;\n } catch (error) {\n const rollbackErrors: unknown[] = [];\n for (const mutation of attempted.reverse()) {\n try {\n if (!mutation.written || readFileSync(mutation.absPath, \"utf-8\") === mutation.after)\n writeFile(mutation.absPath, mutation.before, \"utf-8\");\n clearFileWriteReceipt(mutation.absPath, mutation.version, mutation.writeToken);\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n }\n if (rollbackErrors.length > 0) {\n throw new AggregateError(\n [error, ...rollbackErrors],\n \"File mutation failed and rollback did not complete\",\n );\n }\n throw error;\n }\n}\n\ntype PreparedMutation = FileMutationInput & { before: string };\n\nfunction applyOneMutation(\n projectDir: string,\n mutation: PreparedMutation,\n requestToken: string | undefined,\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void,\n attempted: Array<PreparedMutation & { version: string; writeToken: string; written: boolean }>,\n): AppliedFileMutation {\n const current = readFileSync(mutation.absPath, \"utf-8\");\n assertExpectedVersion(mutation, current);\n if (mutation.after === mutation.before) {\n return {\n ...mutation,\n before: current,\n changed: false,\n backupPath: null,\n version: fileContentVersion(mutation.before),\n writeToken: null,\n };\n }\n const backup = snapshotBeforeWrite(projectDir, mutation.absPath);\n if (backup.error) throw new Error(`backup failed: ${backup.error}`);\n assertExpectedVersion(mutation, readFileSync(mutation.absPath, \"utf-8\"));\n const before = current;\n const version = fileContentVersion(mutation.after);\n const writeToken = createWriteToken(requestToken);\n const attempt = { ...mutation, before, version, writeToken, written: false };\n attempted.push(attempt);\n writeFile(mutation.absPath, mutation.after, \"utf-8\");\n attempt.written = true;\n recordFileWriteReceipt(mutation.absPath, {\n path: mutation.sourceFile,\n version,\n writeToken,\n overwrote: before,\n });\n return {\n ...mutation,\n before,\n changed: true,\n backupPath: backupPathForResponse(projectDir, backup.backupPath),\n version,\n writeToken,\n };\n}\n\nexport class FileChangedError extends Error {\n constructor(readonly sourceFile: string) {\n super(\"file changed since the timeline was read\");\n }\n}\n\nfunction assertExpectedVersion(mutation: PreparedMutation, current: string): void {\n const stale =\n mutation.expectedVersion === undefined\n ? current !== mutation.before\n : fileContentVersion(current) !== mutation.expectedVersion;\n if (stale) throw new FileChangedError(mutation.sourceFile);\n}\n","const FONT_STYLE_RE = /<style\\b[^>]*data-hf-studio-fonts=([\"'])true\\1[^>]*>([\\s\\S]*?)<\\/style>/i;\n\n// Braces only inside quoted strings; `<` nowhere: `</style` ends the block whatever the quoting.\nconst ONE_FONT_FACE_RULE =\n /^@font-face \\{(?:[^{}<\"'\\\\]|\"(?:[^\"\\\\<\\n\\r\\f]|\\\\[^<\\n\\r\\f])*\"|'(?:[^'\\\\<\\n\\r\\f]|\\\\[^<\\n\\r\\f])*')*\\}$/;\n\nexport function isStudioFontFaceCss(css: unknown): css is string {\n return typeof css === \"string\" && ONE_FONT_FACE_RULE.test(css);\n}\n\nexport function ensureStudioFontFaceCss(html: string, css: string): string {\n if (html.includes(css)) return html;\n const block = FONT_STYLE_RE.exec(html);\n if (block) {\n const next = `${(block[2] ?? \"\").trim()}\\n${css}`.trim();\n return html.replace(block[0], () => `<style data-hf-studio-fonts=\"true\">\\n${next}\\n</style>`);\n }\n const styleTag = `<style data-hf-studio-fonts=\"true\">\\n${css}\\n</style>`;\n if (/<\\/head>/i.test(html)) return html.replace(/<\\/head>/i, () => ` ${styleTag}\\n </head>`);\n return `${styleTag}\\n${html}`;\n}\n","import type { GsapMutationRequest } from \"./files.js\";\n\nexport type GsapMutationType = GsapMutationRequest[\"type\"];\ntype GsapMutationFamily = \"animation\" | \"keyframe\" | \"motion_path\" | \"structure\" | \"timing\";\ntype GsapParityEvidence = \"differential\" | \"behavioral\";\n\ninterface GsapMutationCapability {\n family: GsapMutationFamily;\n acorn: \"supported\";\n recast: \"supported\";\n parity: GsapParityEvidence;\n}\n\nconst differential = (family: GsapMutationFamily): GsapMutationCapability => ({\n family,\n acorn: \"supported\",\n recast: \"supported\",\n parity: \"differential\",\n});\nconst behavioral = (family: GsapMutationFamily): GsapMutationCapability => ({\n family,\n acorn: \"supported\",\n recast: \"supported\",\n parity: \"behavioral\",\n});\n\n/** Compile-time exhaustive over the request union; runtime tests match both dispatchers. */\nexport const GSAP_MUTATION_CAPABILITIES = {\n \"update-property\": differential(\"animation\"),\n \"update-properties\": differential(\"animation\"),\n \"update-from-property\": differential(\"animation\"),\n \"update-meta\": differential(\"animation\"),\n add: differential(\"animation\"),\n delete: differential(\"animation\"),\n \"add-property\": differential(\"animation\"),\n \"add-from-property\": differential(\"animation\"),\n \"remove-property\": differential(\"animation\"),\n \"remove-from-property\": differential(\"animation\"),\n \"add-keyframe\": differential(\"keyframe\"),\n \"remove-keyframe\": differential(\"keyframe\"),\n \"move-keyframe\": behavioral(\"keyframe\"),\n \"resize-keyframed-tween\": behavioral(\"keyframe\"),\n \"update-keyframe\": differential(\"keyframe\"),\n \"convert-to-keyframes\": behavioral(\"keyframe\"),\n \"remove-all-keyframes\": behavioral(\"keyframe\"),\n \"materialize-keyframes\": behavioral(\"keyframe\"),\n \"set-arc-path\": behavioral(\"motion_path\"),\n \"update-arc-segment\": behavioral(\"motion_path\"),\n \"update-motion-path-point\": differential(\"motion_path\"),\n \"add-motion-path-point\": differential(\"motion_path\"),\n \"remove-motion-path-point\": differential(\"motion_path\"),\n \"add-motion-path\": differential(\"motion_path\"),\n \"remove-arc-path\": behavioral(\"motion_path\"),\n \"add-with-keyframes\": behavioral(\"keyframe\"),\n \"replace-with-keyframes\": behavioral(\"keyframe\"),\n \"split-animations\": behavioral(\"structure\"),\n \"split-into-property-groups\": behavioral(\"structure\"),\n \"delete-all-for-selector\": behavioral(\"structure\"),\n \"consolidate-position-writes\": behavioral(\"structure\"),\n \"unroll-timeline\": behavioral(\"structure\"),\n \"shift-positions\": behavioral(\"timing\"),\n \"shift-positions-batch\": behavioral(\"timing\"),\n \"scale-positions\": behavioral(\"timing\"),\n} as const satisfies Record<GsapMutationType, GsapMutationCapability>;\n\nconst GSAP_WRITER_MIGRATION = Object.freeze({\n flag: \"HYPERFRAMES_GSAP_WRITER\",\n owner: \"studio-foundations\",\n deadline: \"2026-09-30\",\n graduationCriteria:\n \"Acorn is the default writer. Recast is retained one watch window as HYPERFRAMES_GSAP_WRITER=recast, then deleted (spec 2026-09-17 §5).\",\n});\n\nexport function resolveGsapWriter(env: { HYPERFRAMES_GSAP_WRITER?: string }): \"recast\" | \"acorn\" {\n const configured = env.HYPERFRAMES_GSAP_WRITER ?? \"acorn\";\n if (configured === \"recast\" || configured === \"acorn\") return configured;\n throw new Error(`Invalid ${GSAP_WRITER_MIGRATION.flag}=${configured}; expected recast or acorn`);\n}\n\n/** Ops whose acorn/recast parity rests on behavioral tests, not a byte-diff oracle. */\nexport function behavioralParityOps(): GsapMutationType[] {\n return (\n Object.entries(GSAP_MUTATION_CAPABILITIES) as Array<[GsapMutationType, GsapMutationCapability]>\n )\n .filter(([, capability]) => capability.parity !== \"differential\")\n .map(([type]) => type);\n}\n\nexport function renderGsapMutationCapabilityReport(): string {\n const rows = (\n Object.entries(GSAP_MUTATION_CAPABILITIES) as Array<[GsapMutationType, GsapMutationCapability]>\n ).map(\n ([type, capability]) =>\n `| ${type} | ${capability.family} | ${capability.acorn} | ${capability.recast} | ${capability.parity} |`,\n );\n return [\n \"# GSAP writer capability report\",\n \"\",\n `Owner: ${GSAP_WRITER_MIGRATION.owner}`,\n `Deadline: ${GSAP_WRITER_MIGRATION.deadline}`,\n `Flag: \\`${GSAP_WRITER_MIGRATION.flag}=recast|acorn\\` (default: acorn)`,\n \"\",\n \"| Operation | Family | Acorn | Recast | Parity evidence |\",\n \"| --- | --- | --- | --- | --- |\",\n ...rows,\n \"\",\n `Behavioral-only parity (no byte-diff oracle): ${behavioralParityOps().join(\", \") || \"none\"}`,\n \"\",\n ].join(\"\\n\");\n}\n","import type { Hono } from \"hono\";\nimport { parseHTML } from \"linkedom\";\nimport { createReadStream, existsSync, readFileSync, statSync } from \"node:fs\";\nimport { Readable } from \"node:stream\";\nimport { join, resolve } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport {\n AFTER_FONTS_SCRIPT_TYPE,\n addScenePartsManifest,\n RUNTIME_BOOTSTRAP_ATTR,\n insertBeforeCloseTag,\n insertRuntimeTag,\n stripEmbeddedRuntimeScripts,\n type BundleOptions,\n} from \"@hyperframes/core/compiler\";\nimport {\n STUDIO_PREVIEW_MARK_META,\n STUDIO_PREVIEW_ERRORS,\n} from \"@hyperframes/core/studio-preview-mark\";\nimport { PREVIEW_PROXY_BOX_PARAM, parsePreviewProxyBox } from \"@hyperframes/core\";\nimport { gsapCdnDist, motionPathPluginUrl } from \"@hyperframes/core/gsap-cdn\";\nimport { findStartTags, injectTagsAtHeadStart } from \"@hyperframes/core/compiler/html-document\";\nimport { isWithinProjectRoot } from \"@hyperframes/parsers/asset-resolution\";\nimport type { ResolvedProject, StudioApiAdapter } from \"../types.js\";\nimport {\n isPrivateProjectFile,\n isProjectRootMissing,\n resolveWithinProject,\n} from \"../helpers/safePath.js\";\nimport { getMimeType } from \"../helpers/mime.js\";\nimport { buildSubCompositionHtml, hasBaseElement } from \"../helpers/subComposition.js\";\nimport {\n createProjectSignature,\n resolveProjectAndSignature,\n resolveProjectSignature,\n} from \"../helpers/projectSignature.js\";\nimport {\n createStudioMotionRenderBodyScript,\n STUDIO_MOTION_PATH,\n} from \"../helpers/studioMotionRenderScript.js\";\nimport { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport { settledFileTag } from \"../helpers/fileVersion.js\";\nimport {\n recordPreviewBuilt,\n recordPreviewRead,\n recordPreviewReferences,\n} from \"../helpers/previewReads.js\";\nimport { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from \"../helpers/variablesPayload.js\";\nimport { injectPreviewVariables } from \"../helpers/previewVariables.js\";\nimport {\n resolveProxy,\n waitForProxy,\n ProxyCapacityError,\n ProxyTranscodeError,\n ProxyWaitTimeoutError,\n PROXY_PENDING_RETRY_AFTER_SECONDS,\n} from \"../helpers/proxyTranscoder.js\";\nimport {\n decideMediaProxyEligibility,\n isProxyVariantRequest,\n probeAssetCodec,\n recordProxyRequest,\n resolveProxyVariantRequest,\n PROXY_VARIANT_CONFIG,\n type ProxyVariant,\n} from \"../helpers/mediaCodecMap.js\";\nimport {\n isAutoProxyEnabled,\n injectMediaCodecMap,\n proxyEtagSalt,\n resolvePreviewMediaCodecProbeCache,\n type PreviewApiAdapter,\n} from \"../helpers/mediaProxyPreview.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\nimport { lazyPreviewImages } from \"../helpers/lazyPreviewImages.js\";\n\nconst PROJECT_SIGNATURE_META = \"hyperframes-project-signature\";\nconst GSAP_CDN_SCRIPT = `<script src=\"${gsapCdnDist()}gsap.min.js\"></script>`;\nconst GSAP_CUSTOM_EASE_CDN_SCRIPT = `<script src=\"${gsapCdnDist()}CustomEase.min.js\"></script>`;\nconst GSAP_MOTION_PATH_CDN_SCRIPT = `<script src=\"${motionPathPluginUrl()}\"></script>`;\n\nfunction injectProjectSignature(html: string, signature: string): string {\n const tag = `<meta name=\"${PROJECT_SIGNATURE_META}\" content=\"${signature}\">`;\n if (html.includes(`name=\"${PROJECT_SIGNATURE_META}\"`)) {\n return html.replace(\n new RegExp(`<meta\\\\s+name=[\"']${PROJECT_SIGNATURE_META}[\"'][^>]*>`, \"i\"),\n tag,\n );\n }\n return insertBeforeCloseTag(html, \"head\", `${tag}\\n`) ?? `${tag}\\n${html}`;\n}\n\nfunction readStudioMotionManifestContent(projectDir: string): string {\n const manifestPath = join(projectDir, STUDIO_MOTION_PATH);\n if (!existsSync(manifestPath)) return \"\";\n try {\n return readFileSync(manifestPath, \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\nfunction parseStudioMotionManifestContent(content: string): {\n hasMotion: boolean;\n hasCustomEase: boolean;\n} {\n try {\n const parsed = JSON.parse(content) as {\n motions?: Array<{ customEase?: unknown }>;\n };\n const motions = Array.isArray(parsed.motions) ? parsed.motions : [];\n return {\n hasMotion: motions.length > 0,\n hasCustomEase: motions.some((motion) => Boolean(motion?.customEase)),\n };\n } catch {\n return { hasMotion: false, hasCustomEase: false };\n }\n}\n\n/** Swaps any runtime already in the page for the preview runtime, placed as the bundler places it. */\nfunction withPreviewRuntime(html: string, runtimeUrl: string): string {\n const tag = `<script ${RUNTIME_BOOTSTRAP_ATTR}=\"1\" src=\"${runtimeUrl}\"></script>`;\n return insertRuntimeTag(stripEmbeddedRuntimeScripts(html), tag);\n}\n\nfunction injectScriptTagIntoHead(html: string, scriptTag: string): string {\n return insertBeforeCloseTag(html, \"head\", `${scriptTag}\\n`) ?? `${scriptTag}\\n${html}`;\n}\n\nfunction htmlHasGsap(html: string): boolean {\n // Only match GSAP references outside <template> elements — scripts inside\n // templates are inert when cloned and don't make GSAP globally available.\n const outsideTemplates = html.replace(/<template\\b[^>]*>[\\s\\S]*?<\\/template>/gi, \"\");\n return (\n /<script\\b[^>]*src=[\"'][^\"']*gsap/i.test(outsideTemplates) ||\n /\\/\\*\\s*inlined:.*gsap/i.test(outsideTemplates) ||\n /\\b(GreenSock|_gsScope)\\b/.test(outsideTemplates) ||\n /\\bgsap\\.(config|defaults|registerPlugin|version)\\b/.test(outsideTemplates)\n );\n}\n\nfunction htmlHasCustomEase(html: string): boolean {\n return (\n /<script\\b[^>]*src=[\"'][^\"']*CustomEase/i.test(html) ||\n /\\bwindow\\.CustomEase\\b/.test(html) ||\n /\\bCustomEase\\s*=\\s*/.test(html)\n );\n}\n\n// A composition that drives motion via GSAP's `motionPath` (e.g. a studio-created\n// motion path written into the single-source timeline) needs MotionPathPlugin\n// registered before the timeline first renders — otherwise the initial seek\n// throws \"Invalid property motionPath ... Missing plugin?\". Detect it anywhere in\n// the bundle (the plugin registers globally, so sub-composition usage counts too).\nfunction htmlUsesMotionPath(html: string): boolean {\n return /motionPath\\s*[:{]/.test(html);\n}\n\nfunction htmlHasMotionPathPlugin(html: string): boolean {\n return (\n /<script\\b[^>]*src=[\"'][^\"']*MotionPathPlugin/i.test(html) ||\n /\\bwindow\\.MotionPathPlugin\\b/.test(html) ||\n /\\bMotionPathPlugin\\s*=\\s*/.test(html)\n );\n}\n\nfunction injectMotionPathPluginIfNeeded(html: string): string {\n if (!htmlUsesMotionPath(html) || htmlHasMotionPathPlugin(html)) return html;\n // The plugin registers onto an already-loaded gsap, so it must come AFTER the\n // core gsap script — which often lives at body-end, not <head>. Insert it\n // directly after the gsap script tag; only fall back to <head> if none is found\n // (e.g. gsap is inlined).\n const gsap = findGsapCoreScript(html);\n if (gsap) {\n const version = gsap.src.match(/gsap@([\\d.]+)/)?.[1];\n const ordering = `${gsap.type ? ` type=\"${gsap.type}\"` : \"\"}${gsap.defer ? \" defer\" : \"\"}`;\n const pluginTag = `<script${ordering} src=\"${motionPathPluginUrl(version)}\"></script>`;\n return html.slice(0, gsap.end) + \"\\n\" + pluginTag + html.slice(gsap.end);\n }\n return injectScriptTagIntoHead(html, GSAP_MOTION_PATH_CDN_SCRIPT);\n}\n\nfunction isGsapCoreUrl(src: string): boolean {\n const base = \"http://localhost/\";\n return URL.canParse(src, base) && /\\/gsap(\\.min)?\\.js$/i.test(new URL(src, base).pathname);\n}\n\ntype GsapCoreScript = { src: string; type: string | null; defer: boolean; end: number };\n\nfunction findGsapCoreScript(html: string): GsapCoreScript | null {\n const scripts = [...parseHTML(html).document.querySelectorAll(\"script\")];\n // The scanner skips comments, raw text and templates, so its `<script` offsets line up with the DOM's scripts.\n const starts = findStartTags(html, \"script\");\n if (starts.length !== scripts.length) return null;\n const at = scripts.findIndex((script) =>\n isGsapCoreUrl(lowerCaseAttributes(script).get(\"src\") ?? \"\"),\n );\n if (at === -1) return null;\n const attributes = lowerCaseAttributes(scripts[at]!);\n const end = scriptCloseEnd(html, starts[at]!);\n if (end === 0) return null;\n return {\n src: attributes.get(\"src\")!,\n type: attributes.get(\"type\") ?? null,\n defer: attributes.has(\"defer\"),\n end,\n };\n}\n\nfunction lowerCaseAttributes(el: Element): Map<string, string> {\n return new Map([...el.attributes].map((a) => [a.name.toLowerCase(), a.value]));\n}\n\n/** Index just past the `</script>` that closes the script starting at `start`; 0 when it never closes. */\nfunction scriptCloseEnd(html: string, start: number): number {\n const close = /<\\/script/gi;\n close.lastIndex = start;\n const closeAt = close.exec(html)?.index;\n return closeAt === undefined ? 0 : html.indexOf(\">\", closeAt) + 1;\n}\n\nfunction injectStudioMotionDependencies(html: string, manifestContent: string): string {\n const manifest = parseStudioMotionManifestContent(manifestContent);\n if (!manifest.hasMotion) return html;\n let next = html;\n if (!htmlHasGsap(next)) next = injectScriptTagIntoHead(next, GSAP_CDN_SCRIPT);\n if (manifest.hasCustomEase && !htmlHasCustomEase(next)) {\n next = injectScriptTagIntoHead(next, GSAP_CUSTOM_EASE_CDN_SCRIPT);\n }\n return next;\n}\n\nfunction injectStudioMotionScript(\n html: string,\n projectDir: string,\n activeCompositionPath: string,\n): string {\n const manifestContent = readStudioMotionManifestContent(projectDir);\n const script = createStudioMotionRenderBodyScript(manifestContent, {\n activeCompositionPath,\n });\n if (!script) return html;\n const withDependencies = injectStudioMotionDependencies(html, manifestContent);\n const tag = `<script type=\"${AFTER_FONTS_SCRIPT_TYPE}\">${script.replace(/<\\/script/gi, \"<\\\\/script\")}</script>`;\n return insertBeforeCloseTag(withDependencies, \"body\", tag) ?? `${withDependencies}${tag}`;\n}\n\nconst GSAP_FALLBACK_ATTR = \"data-hf-gsap-fallback\";\nconst GSAP_CDN_FALLBACK_SCRIPT = `<script ${GSAP_FALLBACK_ATTR}>\n(function(){\n var cdnBase=\"${gsapCdnDist()}\";\n var loaded={};\n function loadFallback(file){\n if(loaded[file])return loaded[file];\n return loaded[file]=new Promise(function(ok,fail){\n var s=document.createElement(\"script\");\n s.src=cdnBase+file;s.hfGsapFallback=true;s.onload=ok;s.onerror=fail;\n document.head.appendChild(s);\n });\n }\n document.addEventListener(\"error\",function(e){\n var t=e.target;\n if(!t||t.tagName!==\"SCRIPT\"||!t.src||t.hfGsapFallback)return;\n var m=t.src.match(/gsap[^/]*\\\\/dist\\\\/(.+\\\\.js)/);\n if(m)loadFallback(m[1]).catch(function(){\n reportError(new Error(\"GSAP could not load from \"+t.src+\" or \"+cdnBase+m[1]+\", so this preview's animations will not play.\"));\n });\n },true);\n})();\n</script>`;\n\nfunction injectGsapCdnFallback(html: string): string {\n if (html.includes(GSAP_FALLBACK_ATTR)) return html;\n if (html.includes(\"<head>\")) return html.replace(\"<head>\", \"<head>\" + GSAP_CDN_FALLBACK_SCRIPT);\n return GSAP_CDN_FALLBACK_SCRIPT + html;\n}\n\n/**\n * Parse the `?variables=` query param. Absent/empty → null (no injection).\n * Invalid JSON or a non-object payload is a caller error — surfaced as a 400\n * by the routes rather than silently previewing with defaults.\n */\nfunction parsePreviewVariablesParam(\n raw: string | undefined,\n): { ok: true; values: Record<string, unknown> | null } | { ok: false; error: string } {\n if (raw === undefined || raw === \"\") return { ok: true, values: null };\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return { ok: false, error: \"variables must be valid JSON\" };\n }\n if (!isVariablesPayload(parsed)) {\n return { ok: false, error: VARIABLES_PAYLOAD_ERROR };\n }\n return { ok: true, values: parsed };\n}\n\n/** ETag salt so cached previews revalidate when the variable values change. */\nfunction variablesEtagSalt(raw: string | undefined): string {\n if (!raw) return \"\";\n return `:vars:${createHash(\"sha1\").update(raw).digest(\"hex\").slice(0, 12)}`;\n}\n\n/**\n * Read + parse `?variables=` for a preview route. `error` present → the\n * route should 400; otherwise `values` is the override object (or null when\n * the param is absent) and `raw` feeds the ETag salt.\n */\nfunction previewVariablesFromRequest(rawVariables: string | undefined):\n | { error: string }\n | {\n error?: undefined;\n raw: string | undefined;\n values: Record<string, unknown> | null;\n } {\n const parse = parsePreviewVariablesParam(rawVariables);\n if (!parse.ok) return { error: parse.error };\n return { raw: rawVariables, values: parse.values };\n}\n\n/** Captures screenshot right after a seek, so they get every image eager and no preview mark. */\nexport const PREVIEW_CAPTURE_PARAM = \"hf-capture\";\n\n// Studio's console capture attaches at the iframe's load; this keeps what was raised before it.\nconst EARLY_ERRORS_SCRIPT = `<script>(function(){var seen=window.${STUDIO_PREVIEW_ERRORS}=[];\naddEventListener(\"error\",function(e){seen.push(e.message||String(e))});})();</script>`;\n\nfunction injectStudioPreviewAugmentations(\n html: string,\n adapter: StudioApiAdapter,\n projectDir: string,\n activeCompositionPath: string,\n capture: boolean,\n): string {\n const marked = capture\n ? html\n : injectTagsAtHeadStart(\n lazyPreviewImages(html),\n `<meta name=\"${STUDIO_PREVIEW_MARK_META}\">${EARLY_ERRORS_SCRIPT}`,\n );\n return injectStudioMotionScript(\n injectMotionPathPluginIfNeeded(\n injectGsapCdnFallback(\n injectProjectSignature(marked, resolveProjectSignature(adapter, projectDir)),\n ),\n ),\n projectDir,\n activeCompositionPath,\n );\n}\n\nasync function transformPreviewHtml(\n html: string,\n adapter: StudioApiAdapter,\n project: { id: string; dir: string; title?: string; sessionId?: string },\n activeCompositionPath: string,\n): Promise<string> {\n if (!adapter.transformPreviewHtml) return html;\n try {\n return await adapter.transformPreviewHtml({\n html,\n project,\n activeCompositionPath,\n });\n } catch (err) {\n console.warn(\"[Studio] preview transform failed, using original HTML:\", err);\n return html;\n }\n}\n\nfunction resolveProjectMainHtml(\n projectDir: string,\n projectId: string,\n): { html: string; compositionPath: string } | null {\n const indexPath = join(projectDir, \"index.html\");\n const blockHtmlPath = join(projectDir, `${projectId}.html`);\n recordPreviewRead(projectDir, indexPath);\n recordPreviewRead(projectDir, blockHtmlPath);\n if (existsSync(indexPath)) {\n return {\n html: readFileSync(indexPath, \"utf-8\"),\n compositionPath: \"index.html\",\n };\n }\n if (existsSync(blockHtmlPath)) {\n return {\n html: readFileSync(blockHtmlPath, \"utf-8\"),\n compositionPath: `${projectId}.html`,\n };\n }\n return null;\n}\n\n/** The bundler options every adapter's `bundle()` uses. This route serves project files under a\n * `<base href>`, so assets keep their URLs: inlined base64 multiplies the document per reference.\n * The lint route owns linting, so the bundle skips its own contract lint. */\nexport const PREVIEW_BUNDLE_OPTIONS = {\n runtime: \"placeholder\",\n inlineAssets: false,\n staticGuard: false,\n sceneParts: true,\n} as const satisfies BundleOptions;\n\nconst previewBaseHref = (projectId: string) =>\n `/api/projects/${encodeURIComponent(projectId)}/preview/`;\n\nconst withPreviewBase = (html: string, projectId: string) =>\n hasBaseElement(html)\n ? html\n : injectTagsAtHeadStart(html, `<base href=\"${previewBaseHref(projectId)}\">`);\n\nexport function registerPreviewRoutes(api: Hono, adapter: PreviewApiAdapter): void {\n const previewCacheHeaders = (etag: string) => ({\n \"Cache-Control\": \"private, no-cache\",\n ETag: etag,\n });\n\n // One probe cache per server instance (this function runs once per\n // registered API), reused across every preview request so the mtime-cache\n // benefit in scanProjectMediaCodecMap actually applies.\n const mediaCodecProbeCache = resolvePreviewMediaCodecProbeCache(adapter);\n\n // A build is a function of the project content its ETag names, so it is served again until the\n // content changes, to a cold browser as well as a revalidating one.\n const builtPreviews = new Map<string, string>();\n const rememberPreview = (key: string, html: string) => {\n builtPreviews.delete(key);\n builtPreviews.set(key, html);\n if (builtPreviews.size > 4) builtPreviews.delete(builtPreviews.keys().next().value!);\n };\n\n // Concurrent requests for one document (an early prefetch and the player's own load) share a build.\n const previewBuilds = new Map<string, Promise<string | null>>();\n\n // fallow-ignore-next-line complexity\n async function buildPreview(\n project: ResolvedProject,\n previewVariables: Record<string, unknown> | null,\n builtKey: string,\n capture: boolean,\n signature: string,\n ): Promise<string | null> {\n const diskMain = resolveProjectMainHtml(project.dir, project.id);\n\n try {\n let bundled = await adapter.bundle(project.dir, {\n stampHfIds: true,\n onRead: (filePath) => recordPreviewRead(project.dir, filePath),\n });\n let mainCompositionPath = \"index.html\";\n if (!bundled) {\n if (!diskMain) return null;\n bundled = ensureHfIds(diskMain.html);\n mainCompositionPath = diskMain.compositionPath;\n }\n bundled = withPreviewRuntime(bundled, adapter.runtimeUrl);\n recordPreviewReferences(project.dir, bundled);\n recordPreviewBuilt(project.dir);\n\n // Inject <base> for relative asset resolution\n bundled = withPreviewBase(bundled, project.id);\n\n // Also covers elements the adapter injected; ids already present are kept.\n bundled = injectStudioPreviewAugmentations(\n ensureHfIds(await transformPreviewHtml(bundled, adapter, project, mainCompositionPath)),\n adapter,\n project.dir,\n mainCompositionPath,\n capture,\n );\n if (previewVariables) bundled = injectPreviewVariables(bundled, previewVariables);\n bundled = await injectMediaCodecMap(\n bundled,\n adapter,\n project.dir,\n mainCompositionPath,\n mediaCodecProbeCache,\n );\n bundled = addScenePartsManifest(bundled, [`meta[name=\"${PROJECT_SIGNATURE_META}\"]`]);\n if (createProjectSignature(project.dir) === signature) {\n rememberPreview(builtKey, bundled);\n if (!capture) adapter.previewDocuments?.write(builtKey, bundled);\n }\n return bundled;\n } catch {\n // Re-read disk on bundle failure so we serve the latest file content,\n // not the pre-request snapshot that may have been saved over.\n const fallback = resolveProjectMainHtml(project.dir, project.id);\n if (fallback) {\n const fallbackHtml = withPreviewBase(\n withPreviewRuntime(ensureHfIds(fallback.html), adapter.runtimeUrl),\n project.id,\n );\n let fallbackAugmented = injectStudioPreviewAugmentations(\n await transformPreviewHtml(fallbackHtml, adapter, project, fallback.compositionPath),\n adapter,\n project.dir,\n fallback.compositionPath,\n capture,\n );\n if (previewVariables) {\n fallbackAugmented = injectPreviewVariables(fallbackAugmented, previewVariables);\n }\n fallbackAugmented = await injectMediaCodecMap(\n fallbackAugmented,\n adapter,\n project.dir,\n fallback.compositionPath,\n mediaCodecProbeCache,\n );\n return fallbackAugmented;\n }\n return null;\n }\n }\n\n // Bundled composition preview\n // fallow-ignore-next-line complexity\n api.get(\"/projects/:id/preview\", async (c) => {\n const resolved = await resolveProjectAndSignature(adapter, c.req.param(\"id\"));\n if (!resolved) return c.json({ error: \"not found\" }, 404);\n const { project, signature } = resolved;\n\n // fallow-ignore-next-line code-duplication\n const vars = previewVariablesFromRequest(c.req.query(\"variables\"));\n if (vars.error !== undefined) return c.json({ error: vars.error }, 400);\n const previewVariables = vars.values;\n const capture = c.req.query(PREVIEW_CAPTURE_PARAM) !== undefined;\n\n const etag = `\"preview:${signature}${variablesEtagSalt(vars.raw)}${capture ? \":capture\" : \"\"}\"`;\n const ifNoneMatch = c.req.header(\"If-None-Match\");\n if (ifNoneMatch === etag) {\n return new Response(null, {\n status: 304,\n headers: previewCacheHeaders(etag),\n });\n }\n const builtKey = `${project.id}\\n${etag}`;\n const cached = builtPreviews.get(builtKey) ?? adapter.previewDocuments?.read(builtKey);\n if (cached) {\n rememberPreview(builtKey, cached);\n return c.html(cached, 200, previewCacheHeaders(etag));\n }\n let pending = previewBuilds.get(builtKey);\n if (!pending) {\n pending = buildPreview(project, previewVariables, builtKey, capture, signature).finally(() =>\n previewBuilds.delete(builtKey),\n );\n previewBuilds.set(builtKey, pending);\n }\n const html = await pending;\n if (!html) return c.text(\"not found\", 404);\n return c.html(html, 200, previewCacheHeaders(etag));\n });\n\n /** Ids minted from the raw file before the build rewrites attributes, so they match the source's;\n * in memory only, since a write here reaches the watcher as an outside edit. null: the file vanished. */\n function pinSubCompHfIds(compFile: string, compPath: string): string | undefined | null {\n if (!/\\.html?$/i.test(compPath)) return undefined;\n try {\n return ensureHfIds(readFileSync(compFile, \"utf-8\"));\n } catch {\n return null;\n }\n }\n\n // Sub-composition preview\n // fallow-ignore-next-line complexity\n api.get(\"/projects/:id/preview/comp/*\", async (c) => {\n const resolved = await resolveProjectAndSignature(adapter, c.req.param(\"id\"));\n if (!resolved) return c.json({ error: \"not found\" }, 404);\n const { project, signature } = resolved;\n\n // fallow-ignore-next-line code-duplication\n const vars = previewVariablesFromRequest(c.req.query(\"variables\"));\n if (vars.error !== undefined) return c.json({ error: vars.error }, 400);\n const previewVariables = vars.values;\n const compPath = requestSubPath(c.req.url, \"projects/:id/preview/comp\");\n const compFile = resolveWithinProject(project.dir, compPath);\n if (compFile) recordPreviewRead(project.dir, compFile);\n // The sub-composition document takes its head from the root.\n recordPreviewRead(project.dir, \"index.html\");\n if (!compFile || !existsSync(compFile) || !statSync(compFile).isFile()) {\n return c.text(\"not found\", 404);\n }\n\n // \"v2\" salts the etag for the hf-id-pinning change below: a client holding\n // a pre-pin cached response (preview-only ids, unstamped disk file) must\n // not revalidate to a 304 that skips the pin.\n const compPathHash = createHash(\"sha1\").update(compPath).digest(\"hex\");\n const capture = c.req.query(PREVIEW_CAPTURE_PARAM) !== undefined;\n const etag = `\"comp:v2:${compPathHash}:${signature}${variablesEtagSalt(vars.raw)}${capture ? \":capture\" : \"\"}\"`;\n const ifNoneMatch = c.req.header(\"If-None-Match\");\n if (ifNoneMatch === etag) {\n return new Response(null, {\n status: 304,\n headers: previewCacheHeaders(etag),\n });\n }\n\n const stamped = pinSubCompHfIds(compFile, compPath);\n if (stamped === null) return c.text(\"not found\", 404); // file removed between stat and read\n\n const baseHref = previewBaseHref(project.id);\n let html = buildSubCompositionHtml(\n project.dir,\n compPath,\n adapter.runtimeUrl,\n baseHref,\n stamped,\n );\n if (!html) return c.text(\"not found\", 404);\n recordPreviewReferences(project.dir, html);\n html = ensureHfIds(await transformPreviewHtml(html, adapter, project, compPath));\n html = injectStudioPreviewAugmentations(html, adapter, project.dir, compPath, capture);\n if (previewVariables) html = injectPreviewVariables(html, previewVariables);\n html = await injectMediaCodecMap(html, adapter, project.dir, compPath, mediaCodecProbeCache);\n return c.html(html, 200, previewCacheHeaders(etag));\n });\n\n // Static asset serving (with range request support for audio/video seeking)\n // fallow-ignore-next-line complexity\n api.get(\"/projects/:id/preview/*\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const subPath = requestSubPath(c.req.url, \"projects/:id/preview\");\n // Assets are read-only and should mirror the renderer: permit a path that\n // is lexically inside the project even if an explicit project symlink\n // targets a shared directory outside it. Composition source files still\n // use resolveWithinProject because saves write their data-hf-id values.\n const candidate = resolve(project.dir, subPath);\n const file = isWithinProjectRoot(project.dir, candidate) ? candidate : null;\n if (!file || isPrivateProjectFile(project.dir, file)) {\n return c.text(\"not found\", 404);\n }\n recordPreviewRead(project.dir, file);\n const stat = existsSync(file) ? statSync(file) : null;\n if (!stat?.isFile()) {\n return c.text(\"not found\", 404);\n }\n const contentType = getMimeType(subPath);\n const isText = /\\.(html|css|js|json|svg|txt|md|cube)$/i.test(subPath);\n\n // `?hf-proxy=` follows the asset's alpha-aware proxy variant. The\n // param value must be recognized (matching play/staticProjectServer),\n // only a video asset can be proxied, and only when auto-proxy is enabled\n // for this adapter/project. Checked BEFORE any transcode or 304 shortcut\n // so a bogus/disabled request never spawns ffmpeg.\n const proxyParam = c.req.query(\"hf-proxy\");\n const boxParam = c.req.query(PREVIEW_PROXY_BOX_PARAM);\n const proxyBox = boxParam === undefined ? undefined : parsePreviewProxyBox(boxParam);\n if (proxyBox === null || (proxyBox && proxyParam === undefined)) {\n return c.text(\"not found\", 404);\n }\n let proxyVariant: ProxyVariant | undefined;\n if (proxyParam !== undefined) {\n if (\n !isProxyVariantRequest(proxyParam) ||\n !contentType.startsWith(\"video/\") ||\n !isAutoProxyEnabled(adapter)\n ) {\n return c.text(\"not found\", 404);\n }\n const facts = await probeAssetCodec(file, undefined, mediaCodecProbeCache);\n const eligibility = decideMediaProxyEligibility(facts);\n if (!eligibility.eligible) {\n return c.text(`media proxy unavailable: ${eligibility.reason}`, 422);\n }\n if (!facts) return c.text(\"media proxy unavailable: unknown_codec\", 422);\n proxyVariant = resolveProxyVariantRequest(proxyParam, facts) ?? undefined;\n if (!proxyVariant) {\n return c.text(\"media proxy variant does not match asset\", 422);\n }\n }\n\n const tag = settledFileTag(stat);\n const etag = tag && `\"${tag}${proxyEtagSalt(proxyVariant, proxyBox)}\"`;\n const cacheHeaders: Record<string, string> = isText\n ? { \"Cache-Control\": \"no-store\" }\n : { \"Cache-Control\": \"private, no-cache\", ...(etag && { ETag: etag }) };\n\n if (!isText && etag) {\n const ifNoneMatch = c.req.header(\"If-None-Match\");\n if (ifNoneMatch === etag) {\n return new Response(null, { status: 304, headers: cacheHeaders });\n }\n }\n\n // Resolve to the cached proxy (transcoding on miss) only after the 404/304\n // shortcuts above — the source's own mtime+size already salts the etag,\n // so a 304 never needs to await a transcode at all.\n let servedPath = file;\n let servedContentType = contentType;\n if (proxyVariant !== undefined) {\n try {\n // A cached copy settles before any timer; a transcode never holds one of\n // the browser's few connections to this host. 202 until the copy lands.\n servedPath = await waitForProxy(resolveProxy(project.dir, file, proxyVariant, proxyBox), 0);\n } catch (err) {\n if (err instanceof ProxyWaitTimeoutError) {\n return c.text(\"media proxy is being made\", 202, {\n \"Retry-After\": String(PROXY_PENDING_RETRY_AFTER_SECONDS),\n \"Cache-Control\": \"no-store\",\n });\n }\n if (err instanceof ProxyCapacityError) {\n return c.text(err.message, 503, { \"Retry-After\": \"5\" });\n }\n if (isProjectRootMissing(err)) throw err;\n const message = err instanceof ProxyTranscodeError ? err.message : \"proxy transcode failed\";\n return c.text(message, 502);\n }\n // After the wait, not at the eligibility gate: one count per served proxy shares\n // a unit with `prewarmsRequested`; a 304, a 202 or a failure serves none.\n recordProxyRequest();\n servedContentType = PROXY_VARIANT_CONFIG[proxyVariant].contentType;\n }\n\n // Text is small and keeps its utf-8 round trip in memory. Binary media\n // streams only the requested window: Chrome refills a playing <video> or\n // <audio> with a fresh Range request every few hundred milliseconds, and a\n // 1KB slice of a multi-hundred-MB source must not readFileSync the whole\n // file on each one. The full read also blocked the event loop, so every\n // other Studio request (SSE, saves, the voice track) waited behind it.\n const textBuffer = isText ? Buffer.from(readFileSync(file, \"utf-8\"), \"utf-8\") : null;\n const totalSize = textBuffer ? textBuffer.length : statSync(servedPath).size;\n const bodyFor = (start: number, end: number): BodyInit =>\n textBuffer\n ? new Uint8Array(textBuffer.subarray(start, end + 1))\n : // Node's web stream type and the DOM one do not overlap for tsc on\n // every platform's lib set; the double cast is the documented bridge.\n (Readable.toWeb(\n createReadStream(servedPath, { start, end }),\n ) as unknown as ReadableStream);\n\n // Support byte-range requests so browsers can seek audio/video elements.\n const rangeHeader = c.req.header(\"Range\");\n const match = rangeHeader ? /bytes=(\\d+)-(\\d*)/.exec(rangeHeader) : null;\n if (match) {\n const start = parseInt(match[1]!, 10);\n const end = match[2] ? parseInt(match[2], 10) : totalSize - 1;\n const safeEnd = Math.min(end, totalSize - 1);\n if (start > safeEnd) {\n return new Response(null, {\n status: 416,\n headers: { ...cacheHeaders, \"Content-Range\": `bytes */${totalSize}` },\n });\n }\n return new Response(bodyFor(start, safeEnd), {\n status: 206,\n headers: {\n ...cacheHeaders,\n \"Content-Type\": servedContentType,\n \"Content-Range\": `bytes ${start}-${safeEnd}/${totalSize}`,\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(safeEnd - start + 1),\n },\n });\n }\n\n return new Response(totalSize > 0 ? bodyFor(0, totalSize - 1) : null, {\n headers: {\n ...cacheHeaders,\n \"Content-Type\": servedContentType,\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(totalSize),\n },\n });\n });\n}\n","import { readlinkSync } from \"node:fs\";\nimport { dirname, join, parse, relative, resolve } from \"node:path\";\nimport { parseHTML } from \"linkedom\";\nimport { STUDIO_SIGNATURE_MANIFEST_PATHS } from \"./projectSignature.js\";\nimport { realFilePath } from \"./safePath.js\";\n\nconst ALWAYS_AFFECTS = [\"hyperframes.json\", ...STUDIO_SIGNATURE_MANIFEST_PATHS];\n// A malformed inline URL must not turn ancestor tracking into an image-sized path walk.\nconst MAX_PREVIEW_PATH_LENGTH = 4096;\nconst SHOW_ELEMENT = 1;\nconst REFERENCE =\n /\\b(?:src|href|poster|data-composition-src)\\s*=\\s*(?:\"([^\"\\n]*)\"|'([^'\\n]*)')|url\\(\\s*(?:\"([^\"\\n]*)\"|'([^'\\n]*)'|([^\"'\\s)]+))/gi;\nconst REFERENCE_ATTRIBUTE = /\\b(?:src|href|poster|data-composition-src)$/i;\nconst isElement = (node: Node): node is Element => node.nodeType === 1;\n// macOS and Windows volumes ignore letter case by default, so it is not part of a path's identity there.\nconst pathKey =\n process.platform === \"darwin\" || process.platform === \"win32\"\n ? (path: string) => resolve(path).toLowerCase()\n : (path: string) => resolve(path);\n// ponytail: grows until restart, so a file a film stopped using still reloads; reset per build if that matters.\nconst readsByProject = new Map<string, Set<string>>();\nconst builtProjects = new Set<string>();\nconst projectKey = (projectDir: string) => pathKey(realFilePath(resolve(projectDir)));\nconst inRealProject = (projectDir: string, path: string) =>\n join(realFilePath(resolve(projectDir)), relative(resolve(projectDir), resolve(projectDir, path)));\n\nconst readLink = (path: string): string | null => {\n try {\n return readlinkSync(path);\n } catch {\n return null;\n }\n};\n\n// Walks `path` as the OS does, returning every link it passes and where it ends up.\nfunction linksOnTheWay(path: string): string[] {\n const passed: string[] = [];\n let at = parse(path).root;\n let rest = path.slice(at.length).split(/[\\\\/]+/);\n for (let hops = 0; rest.length > 0; ) {\n const part = rest.shift()!;\n if (!part || part === \".\") continue;\n if (part === \"..\") {\n at = dirname(at);\n continue;\n }\n const next = join(at, part);\n if (next.length > MAX_PREVIEW_PATH_LENGTH) return passed;\n const target = hops < 40 ? readLink(next) : null;\n if (target === null) {\n at = next;\n continue;\n }\n hops++;\n passed.push(next);\n const root = parse(target).root;\n if (root) at = root;\n rest = [...target.slice(root.length).split(/[\\\\/]+/), ...rest];\n }\n passed.push(at);\n return passed;\n}\n\n// A link's target can be created or retargeted later, so every read resolves it again.\nexport function recordPreviewRead(projectDir: string, filePath: string): void {\n if (filePath.length > MAX_PREVIEW_PATH_LENGTH) return;\n const key = projectKey(projectDir);\n let reads = readsByProject.get(key);\n if (!reads) readsByProject.set(key, (reads = new Set()));\n const read = inRealProject(projectDir, filePath);\n if (read.length > MAX_PREVIEW_PATH_LENGTH) return;\n for (const found of [read, ...linksOnTheWay(read)]) {\n for (let path = pathKey(found); !reads.has(path); path = dirname(path)) reads.add(path);\n }\n}\n\nexport function recordPreviewReferences(projectDir: string, html: string): void {\n const named = new Set<string>();\n const add = (reference: string) => {\n const url = reference.trim();\n if (!url || /^(?:[a-z][a-z0-9+.-]*:|[/#])/i.test(url)) return;\n const path = url.split(/[?#]/)[0] ?? \"\";\n let decoded = path;\n try {\n decoded = decodeURIComponent(path);\n } catch {\n // A malformed escape names the file literally.\n }\n if (decoded && decoded.length <= MAX_PREVIEW_PATH_LENGTH) named.add(decoded);\n };\n const scan = (text: string) => {\n for (const match of text.matchAll(REFERENCE)) {\n add(match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? \"\");\n }\n };\n const scanElement = (element: Element) => {\n for (const attribute of element.attributes) {\n if (REFERENCE_ATTRIBUTE.test(attribute.name)) add(attribute.value);\n }\n const style = element.getAttribute(\"style\");\n if (style) scan(style);\n if (element.localName === \"style\" || element.localName === \"script\") {\n scan(element.textContent ?? \"\");\n }\n };\n // The parser decodes attributes; walking also visits inert template descendants without cloning them.\n const { document } = parseHTML(html);\n for (const root of document.children) {\n scanElement(root);\n const elements = document.createTreeWalker(root, SHOW_ELEMENT);\n for (let node = elements.nextNode(); node; node = elements.nextNode()) {\n if (isElement(node)) scanElement(node);\n }\n }\n for (const path of named) recordPreviewRead(projectDir, path);\n}\n\nexport function recordPreviewBuilt(projectDir: string): void {\n for (const path of ALWAYS_AFFECTS) recordPreviewRead(projectDir, path);\n builtProjects.add(projectKey(projectDir));\n}\n\n// Every write counts until this process built the preview; a folder event counts when a loaded file is inside it.\nexport function affectsPreview(projectDir: string, changedPath: string): boolean {\n const key = projectKey(projectDir);\n if (!builtProjects.has(key)) return true;\n return readsByProject.get(key)?.has(pathKey(inRealProject(projectDir, changedPath))) ?? false;\n}\n","/**\n * Shared shape check for composition-variable payloads (`?variables=` on the\n * preview routes, `body.variables` on the render route) — one contract, one\n * error string, so the routes can't drift.\n */\n\nexport const VARIABLES_PAYLOAD_ERROR = \"variables must be a JSON object of {variableId: value}\";\n\nexport function isVariablesPayload(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/**\n * Inject preview variable overrides: `?variables=<json>` becomes\n * `window.__hfVariables` set before any composition script runs — the exact\n * global the engine sets via evaluateOnNewDocument at render time\n * (engine/src/services/frameCapture.ts), so preview-with-values cannot\n * diverge from render behavior. The runtime's getVariables() merges these\n * overrides over the declared defaults.\n */\nexport function injectPreviewVariables(html: string, values: Record<string, unknown>): string {\n // <-escape prevents a string value containing \"</script>\" from\n // breaking out of the injected tag.\n const json = JSON.stringify(values).replace(/</g, \"\\\\u003c\");\n const tag = `<script data-hf-preview-variables>window.__hfVariables=${json};</script>`;\n // Insert as early as possible without ever landing before the doctype —\n // content before <!doctype> flips the document into quirks mode, so the\n // fallback chain is <head…> → <html…> → after the doctype → prepend.\n for (const pattern of [/<head/i, /<html/i, /^\\s*<!doctype/i]) {\n const match = pattern.exec(html);\n if (match) {\n // If the first prefix has no closing >, no later prefix can close either.\n const end = html.indexOf(\">\", match.index + match[0].length);\n if (end < 0) continue;\n const at = end + 1;\n return html.slice(0, at) + tag + html.slice(at);\n }\n }\n return tag + html;\n}\n","import { findStartTags } from \"@hyperframes/core/compiler/html-document\";\nimport { parseHTML } from \"linkedom\";\nimport { STUDIO_PREVIEW_LAZY_ATTR } from \"@hyperframes/core/studio-preview-mark\";\n\n// A start that is not a plain number (a reference) counts as unknown and keeps the image eager.\nfunction startsAfterZero(el: Element): boolean {\n for (let node: Element | null = el; node; node = node.parentElement) {\n if (Number(node.getAttribute(\"data-start\")) > 0) return true;\n }\n return false;\n}\n\nconst hasLoading = (img: Element) =>\n Array.from(img.attributes).some((attr) => attr.name.toLowerCase() === \"loading\");\n\nexport function lazyPreviewImages(html: string): string {\n if (!/<!doctype|<html[\\s>]/i.test(html)) return html;\n const images = [...parseHTML(html).document.querySelectorAll(\"img\")];\n // The scanner skips comments and raw text, so its `<img` offsets line up with the DOM's images.\n const tags = findStartTags(html, \"img\");\n if (tags.length !== images.length) return html;\n const parts: string[] = [];\n let from = 0;\n images.forEach((img, i) => {\n if (hasLoading(img) || !startsAfterZero(img)) return;\n const at = (tags[i] ?? 0) + 4;\n parts.push(html.slice(from, at), ` loading=\"lazy\" ${STUDIO_PREVIEW_LAZY_ATTR}`);\n from = at;\n });\n parts.push(html.slice(from));\n return parts.join(\"\");\n}\n","import type { Hono } from \"hono\";\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { LintResult, StudioApiAdapter } from \"../types.js\";\nimport { isInHiddenOrVendorDir, walkDir } from \"../helpers/safePath.js\";\n\ntype LintFinding = LintResult[\"findings\"][number];\n\nasync function collectProjectFindings(\n adapter: StudioApiAdapter,\n projectDir: string,\n): Promise<{ findings: LintFinding[]; coveredFiles: Set<string> }> {\n const findings: LintFinding[] = [];\n const coveredFiles = new Set<string>();\n if (!adapter.lintProject) return { findings, coveredFiles };\n\n const result = await adapter.lintProject(projectDir);\n for (const entry of result.results) {\n coveredFiles.add(entry.file);\n for (const finding of entry.result.findings) {\n findings.push({ ...finding, file: entry.file });\n }\n }\n return { findings, coveredFiles };\n}\n\nasync function lintUncoveredHtml(\n adapter: StudioApiAdapter,\n projectDir: string,\n htmlFiles: string[],\n coveredFiles: Set<string>,\n): Promise<LintFinding[]> {\n const findings: LintFinding[] = [];\n for (const file of htmlFiles) {\n if (coveredFiles.has(file)) continue;\n const content = readFileSync(join(projectDir, file), \"utf-8\");\n const result = await adapter.lint(content, { filePath: file, isSubComposition: true });\n for (const finding of result?.findings ?? []) {\n findings.push({ ...finding, file });\n }\n }\n return findings;\n}\n\nexport function registerLintRoutes(api: Hono, adapter: StudioApiAdapter): void {\n api.get(\"/projects/:id/lint\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n try {\n const htmlFiles = walkDir(project.dir).filter(\n (f) => f.endsWith(\".html\") && !isInHiddenOrVendorDir(f),\n );\n const projectLint = await collectProjectFindings(adapter, project.dir);\n const extraFindings = await lintUncoveredHtml(\n adapter,\n project.dir,\n htmlFiles,\n projectLint.coveredFiles,\n );\n return c.json({ findings: [...projectLint.findings, ...extraFindings] });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return c.json({ error: `Lint failed: ${msg}` }, 500);\n }\n });\n}\n","import type { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport { existsSync, lstatSync, readFileSync, unlinkSync, readdirSync, statSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { StudioApiAdapter, RenderJobState } from \"../types.js\";\nimport { VALID_CANVAS_RESOLUTIONS, type CanvasResolution } from \"@hyperframes/parsers\";\nimport { formatRenderOutputTimestamp, parseFps } from \"@hyperframes/core\";\nimport {\n folderGone,\n isPrivateProjectFile,\n mkdirWithinProject,\n resolveWithinProject,\n} from \"../helpers/safePath.js\";\nimport { projectDirMissing } from \"../helpers/projectDirMissing.js\";\nimport { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from \"../helpers/variablesPayload.js\";\n\nconst VALID_RESOLUTIONS = new Set<string>(VALID_CANVAS_RESOLUTIONS);\nconst RENDER_MIME: Record<string, string> = {\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".mov\": \"video/quicktime\",\n};\nconst RENDER_EXTENSIONS = Object.keys(RENDER_MIME);\nconst RENDER_ARTIFACT_EXTENSIONS = [...RENDER_EXTENSIONS, \".meta.json\"];\n\nfunction resolveRenderArtifacts(directories: readonly string[], jobId: string): string[] | null {\n const artifacts = [...new Set(directories)]\n .filter(existsSync)\n .flatMap((directory) =>\n RENDER_ARTIFACT_EXTENSIONS.map((extension) =>\n resolveWithinProject(directory, `${jobId}${extension}`),\n ),\n );\n return artifacts.every((path) => path !== null) ? artifacts : null;\n}\n\nfunction contentDispositionHeader(disposition: \"inline\" | \"attachment\", filename: string): string {\n const fallback = filename.replace(/[^\\x20-\\x7e]|[\"\\\\]/g, \"_\");\n const encoded = encodeURIComponent(filename).replace(\n /[!'()*]/g,\n (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n return `${disposition}; filename=\"${fallback}\"; filename*=UTF-8''${encoded}`;\n}\n\nexport function registerRenderRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // Scoped job store — not shared across createStudioApi() calls\n const renderJobs = new Map<string, RenderJobState & { createdAt: number }>();\n\n // TTL cleanup for completed jobs (5 minutes)\n const TTL_MS = 300_000;\n const CLEANUP_INTERVAL_MS = 60_000;\n let cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n const cleanupEnabled = () =>\n typeof process !== \"undefined\" &&\n process.env.NODE_ENV !== \"production\" &&\n !process.argv.includes(\"build\");\n\n const cleanupFinishedJobs = () => {\n const now = Date.now();\n for (const [key, job] of renderJobs) {\n if (job.status !== \"rendering\" && now - job.createdAt > TTL_MS) {\n renderJobs.delete(key);\n }\n }\n if (renderJobs.size === 0 && cleanupTimer) {\n clearInterval(cleanupTimer);\n cleanupTimer = null;\n }\n };\n\n const ensureCleanupTimer = () => {\n if (cleanupTimer || !cleanupEnabled()) return;\n cleanupTimer = setInterval(cleanupFinishedJobs, CLEANUP_INTERVAL_MS);\n if (typeof cleanupTimer === \"object\" && \"unref\" in cleanupTimer) {\n cleanupTimer.unref();\n }\n };\n\n ensureCleanupTimer();\n\n // Start a render\n api.post(\"/projects/:id/render\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const body = (await c.req.json().catch(() => ({}))) as {\n // Polymorphic per design note in core.types.Fps:\n // number → integer fps (e.g. 30)\n // string → rational fps (e.g. \"30000/1001\" for NTSC 29.97)\n // Decimals are rejected on purpose so the exact denominator stays\n // unambiguous (29.97 ≠ 30000/1001 when ffmpeg consumes them).\n fps?: number | string;\n quality?: string;\n format?: string;\n resolution?: string;\n composition?: string;\n // Browser telemetry id, so the server-emitted render outcome is\n // attributed to the user who triggered the render (joinable funnel).\n telemetryDistinctId?: string;\n // Explicit \"this browser profile opted out\" flag. Distinct from simply\n // omitting the id: an OLD client omits it too, and that case falls back\n // to the install anonymousId. Only an explicit `true` suppresses.\n telemetryOptOut?: boolean;\n // Composition-variable overrides ({variableId: value}), injected as\n // window.__hfVariables — same channel as `hyperframes render --variables`.\n variables?: Record<string, unknown>;\n };\n const VALID_FORMATS = new Set([\"mp4\", \"webm\", \"mov\"]);\n const FORMAT_EXT: Record<string, string> = { mp4: \".mp4\", webm: \".webm\", mov: \".mov\" };\n const format = VALID_FORMATS.has(body.format ?? \"\") ? (body.format as string) : \"mp4\";\n\n // Default to 30 fps when unset or unparseable. The route stays lenient on\n // invalid fps values (matching the lenient handling of `resolution` and\n // `quality` already in this file) — the producer surfaces a clearer error\n // message if the caller really did mean to fail loudly.\n const fpsParse = body.fps === undefined ? null : parseFps(body.fps);\n const fps = fpsParse && fpsParse.ok ? fpsParse.value : { num: 30, den: 1 };\n const quality = [\"draft\", \"standard\", \"high\"].includes(body.quality ?? \"\")\n ? (body.quality as string)\n : \"standard\";\n const outputResolution = VALID_RESOLUTIONS.has(body.resolution ?? \"\")\n ? (body.resolution as CanvasResolution)\n : undefined;\n let composition: string | undefined;\n if (typeof body.composition === \"string\" && body.composition.length > 0) {\n // `body.composition` is attacker-controlled (from c.req.json()).\n // resolveWithinProject dereferences symlinks, so an in-project symlink\n // pointing outside the root can't smuggle the render target out.\n if (!resolveWithinProject(project.dir, body.composition)) {\n if (folderGone(project.dir)) return projectDirMissing(c);\n return c.json({ error: \"composition path must be within the project directory\" }, 400);\n }\n composition = body.composition;\n }\n\n // Unlike fps/quality (lenient with safe fallbacks), a malformed variables\n // payload means the user's values would be silently dropped — fail loudly.\n let variables: Record<string, unknown> | undefined;\n if (body.variables !== undefined) {\n if (!isVariablesPayload(body.variables)) {\n return c.json({ error: VARIABLES_PAYLOAD_ERROR }, 400);\n }\n variables = body.variables;\n }\n\n const now = new Date();\n const jobId = `${project.id}_${formatRenderOutputTimestamp(now)}`;\n const rendersDir = adapter.rendersDir(project);\n mkdirWithinProject(project.dir, rendersDir);\n const ext = FORMAT_EXT[format] ?? \".mp4\";\n const outputPath = join(rendersDir, `${jobId}${ext}`);\n\n const jobState = adapter.startRender({\n project,\n outputPath,\n format: format as \"mp4\" | \"webm\" | \"mov\",\n fps,\n quality,\n jobId,\n outputResolution,\n composition,\n variables,\n distinctId:\n typeof body.telemetryDistinctId === \"string\" ? body.telemetryDistinctId : undefined,\n telemetryOptOut: body.telemetryOptOut === true,\n });\n (jobState as RenderJobState & { createdAt: number }).createdAt = Date.now();\n renderJobs.set(jobId, jobState as RenderJobState & { createdAt: number });\n\n ensureCleanupTimer();\n\n return c.json({ jobId, status: \"rendering\" });\n });\n\n // SSE progress stream\n api.get(\"/render/:jobId/progress\", (c) => {\n const { jobId } = c.req.param();\n const job = renderJobs.get(jobId);\n if (!job) return c.json({ error: \"not found\" }, 404);\n\n return streamSSE(c, async (stream) => {\n while (true) {\n const current = renderJobs.get(jobId);\n if (!current) break;\n await stream.writeSSE({\n event: \"progress\",\n data: JSON.stringify({\n progress: current.progress,\n status: current.status,\n stage: current.stage,\n error: current.error,\n ...(current.status === \"complete\" && current.audioLoweredDb !== undefined\n ? { audioLoweredDb: current.audioLoweredDb }\n : {}),\n }),\n });\n if (current.status !== \"rendering\") break;\n await stream.sleep(500);\n }\n });\n });\n\n // Cancel an in-flight render. Marks the job cancelled immediately (so the\n // SSE stream terminates) and invokes the adapter's abort hook when present.\n api.post(\"/render/:jobId/cancel\", (c) => {\n const { jobId } = c.req.param();\n const job = renderJobs.get(jobId);\n if (!job) return c.json({ error: \"not found\" }, 404);\n if (job.status === \"rendering\") {\n job.status = \"cancelled\";\n job.cancel?.();\n }\n return c.json({ status: job.status });\n });\n\n const isPlainFile = (path: string): boolean => {\n try {\n return lstatSync(path).isFile();\n } catch {\n return false;\n }\n };\n\n function renderContentType(filePath: string): string {\n const ext = RENDER_EXTENSIONS.find((e) => filePath.endsWith(e));\n return (ext && RENDER_MIME[ext]) ?? \"video/mp4\";\n }\n\n // Serve render inline (for in-browser playback — opens in a new tab)\n // fallow-ignore-next-line code-duplication\n api.get(\"/render/:jobId/view\", (c) => {\n const { jobId } = c.req.param();\n const job = renderJobs.get(jobId);\n if (!job?.outputPath || !isPlainFile(job.outputPath)) {\n return c.json({ error: \"not found\" }, 404);\n }\n const contentType = renderContentType(job.outputPath);\n const filename = job.outputPath.split(\"/\").pop() ?? `render.mp4`;\n const content = readFileSync(job.outputPath);\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Content-Disposition\": contentDispositionHeader(\"inline\", filename),\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(content.length),\n },\n });\n });\n\n // Download render\n // fallow-ignore-next-line code-duplication\n api.get(\"/render/:jobId/download\", (c) => {\n const { jobId } = c.req.param();\n const job = renderJobs.get(jobId);\n if (!job?.outputPath || !isPlainFile(job.outputPath)) {\n return c.json({ error: \"not found\" }, 404);\n }\n const contentType = renderContentType(job.outputPath);\n const filename = job.outputPath.split(\"/\").pop() ?? `render.mp4`;\n const content = readFileSync(job.outputPath);\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Content-Disposition\": contentDispositionHeader(\"attachment\", filename),\n },\n });\n });\n\n async function renderDirectories(jobId: string): Promise<string[]> {\n const outputPath = renderJobs.get(jobId)?.outputPath;\n if (outputPath) return [dirname(outputPath)];\n\n const projects = await adapter.listProjects();\n return projects.map((project) => adapter.rendersDir(project));\n }\n\n // Delete render\n api.delete(\"/render/:jobId\", async (c) => {\n const { jobId } = c.req.param();\n if (jobId.includes(\"/\") || jobId.includes(\"\\\\\") || jobId.includes(\"\\0\")) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n const directories = await renderDirectories(jobId);\n const artifacts = resolveRenderArtifacts(directories, jobId);\n if (!artifacts) return c.json({ error: \"forbidden\" }, 403);\n\n for (const path of artifacts) {\n if (existsSync(path)) unlinkSync(path);\n }\n renderJobs.delete(jobId);\n return c.json({ deleted: true });\n });\n\n // Serve render file directly from disk (no in-memory map dependency)\n api.get(\"/projects/:id/renders/file/*\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const filename = c.req.path.split(\"/renders/file/\")[1];\n if (!filename) return c.json({ error: \"missing filename\" }, 400);\n const rendersDir = adapter.rendersDir(project);\n // Containment guard: the filename is attacker-controlled wildcard input, so\n // route it through the same chokepoint every other project-scoped path uses.\n // Literal `..` is collapsed upstream by the URL parser, but a bare join() +\n // readFileSync still followed an in-rendersDir symlink pointing outside the\n // dir; resolveWithinProject canonicalizes with realpath before serving.\n const fp = resolveWithinProject(rendersDir, filename);\n if (!fp || isPrivateProjectFile(project.dir, fp)) return c.json({ error: \"forbidden\" }, 403);\n if (!existsSync(fp)) return c.json({ error: \"not found\" }, 404);\n const contentType = renderContentType(fp);\n const content = readFileSync(fp);\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Content-Disposition\": contentDispositionHeader(\"inline\", filename),\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(content.length),\n },\n });\n });\n\n // List renders\n api.get(\"/projects/:id/renders\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const rendersDir = adapter.rendersDir(project);\n if (!existsSync(rendersDir)) return c.json({ renders: [] });\n const files = readdirSync(rendersDir)\n .filter((f) => f.endsWith(\".mp4\") || f.endsWith(\".webm\") || f.endsWith(\".mov\"))\n .flatMap((f) => {\n const fp = resolveWithinProject(rendersDir, f);\n return fp && !isPrivateProjectFile(project.dir, fp) ? [{ f, fp }] : [];\n })\n .map(({ f, fp }) => {\n const stat = statSync(fp);\n const rid = f.replace(/\\.(mp4|webm|mov)$/, \"\");\n const metaPath = join(rendersDir, `${rid}.meta.json`);\n let status: \"complete\" | \"failed\" = \"complete\";\n let durationMs: number | undefined;\n let audioLoweredDb: number | undefined;\n if (existsSync(metaPath)) {\n try {\n const meta = JSON.parse(readFileSync(metaPath, \"utf-8\"));\n // A stale failed sidecar can remain after a retry succeeds. An\n // existing output artifact is authoritative for the list view;\n // don't present a downloadable render as failed solely because\n // an earlier attempt left behind failed metadata.\n if (meta.status === \"failed\" && !existsSync(fp)) status = \"failed\";\n if (meta.durationMs) durationMs = meta.durationMs;\n if (typeof meta.audioLoweredDb === \"number\") audioLoweredDb = meta.audioLoweredDb;\n } catch {\n /* ignore */\n }\n }\n return {\n id: rid,\n filename: f,\n path: fp,\n size: stat.size,\n createdAt: stat.mtimeMs,\n status,\n durationMs,\n ...(audioLoweredDb !== undefined ? { audioLoweredDb } : {}),\n };\n })\n .sort((a, b) => b.createdAt - a.createdAt);\n // Register on-disk renders that aren't in the current session's job map\n // so they remain downloadable after a server restart.\n for (const file of files) {\n if (!renderJobs.has(file.id)) {\n renderJobs.set(file.id, {\n id: file.id,\n status: file.status,\n progress: 100,\n outputPath: file.path,\n createdAt: file.createdAt,\n } as RenderJobState & { createdAt: number });\n }\n }\n return c.json({ renders: files.map(({ path: _path, ...render }) => render) });\n });\n}\n","import type { Hono } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { open, stat } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { pinWithinProject } from \"../helpers/safePath.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\nimport { ThumbnailGenerationCoordinator } from \"./thumbnailGenerationCoordinator.js\";\n\nconst MAX_SOURCE_BYTES = 64 * 1024 * 1024;\nconst MAX_CACHE_BYTES = 8 * 1024 * 1024;\n\nlet sharpLoad: Promise<typeof import(\"sharp\").default> | undefined;\nfunction loadSharp() {\n sharpLoad ??= import(\"sharp\").then(\n (module) => module.default,\n (error: unknown) => {\n console.warn(\"[Studio] JPEG thumbnails are off: sharp could not load:\", error);\n throw error;\n },\n );\n return sharpLoad;\n}\n\nasync function generateThumbnail(path: string, signal: AbortSignal): Promise<Buffer> {\n const sharp = await loadSharp();\n const file = await open(path, \"r\");\n try {\n const info = await file.stat();\n if (!info.isFile() || info.size > MAX_SOURCE_BYTES) throw new Error(\"Unsupported image\");\n const source = Buffer.alloc(info.size);\n let offset = 0;\n while (offset < source.length) {\n signal.throwIfAborted();\n const { bytesRead } = await file.read(source, offset, source.length - offset, offset);\n if (!bytesRead) break;\n offset += bytesRead;\n }\n if (source[0] !== 0xff || source[1] !== 0xd8) throw new Error(\"Unsupported image\");\n const image = sharp(source.subarray(0, offset), { limitInputPixels: 40_000_000 });\n if ((await image.metadata()).format !== \"jpeg\") throw new Error(\"Unsupported image\");\n signal.throwIfAborted();\n const result = await image\n .rotate()\n .resize(240, 135, { fit: \"inside\", withoutEnlargement: true })\n .jpeg({ quality: 80 })\n .toBuffer();\n signal.throwIfAborted();\n return result;\n } finally {\n await file.close();\n }\n}\n\nasync function resolveSource(adapter: StudioApiAdapter, id: string, url: string) {\n const project = await adapter.resolveProject(id);\n if (!project) throw new HTTPException(404);\n const relative = requestSubPath(url, \"projects/:id/image-thumbnail\");\n if (!/\\.jpe?g$/i.test(relative)) throw new HTTPException(415);\n const path = pinWithinProject(project.dir, relative);\n if (!path) throw new HTTPException(404);\n const info = await stat(path).catch(() => {\n throw new HTTPException(404);\n });\n if (!info.isFile()) throw new HTTPException(404);\n if (info.size > MAX_SOURCE_BYTES) throw new HTTPException(413);\n return { path, info };\n}\n\nexport function registerImageThumbnailRoutes(api: Hono, adapter: StudioApiAdapter): void {\n const coordinator = new ThumbnailGenerationCoordinator(2);\n const cache = new Map<string, Buffer>();\n let cacheBytes = 0;\n const remember = (key: string, image: Buffer) => {\n cacheBytes -= cache.get(key)?.byteLength ?? 0;\n cache.delete(key);\n cache.set(key, image);\n cacheBytes += image.byteLength;\n while (cacheBytes > MAX_CACHE_BYTES || cache.size > 128) {\n const oldest = cache.keys().next().value;\n if (oldest === undefined) break;\n cacheBytes -= cache.get(oldest)?.byteLength ?? 0;\n cache.delete(oldest);\n }\n };\n api.get(\"/projects/:id/image-thumbnail/*\", async (c) => {\n try {\n const { path, info } = await resolveSource(adapter, c.req.param(\"id\"), c.req.url);\n const key = createHash(\"sha256\")\n .update(JSON.stringify([path, info.dev, info.ino, info.size, info.mtimeMs, info.ctimeMs]))\n .digest(\"hex\");\n const etag = `\"${key}\"`;\n c.header(\"ETag\", etag);\n c.header(\"Cache-Control\", \"private, no-cache\");\n c.header(\"X-Content-Type-Options\", \"nosniff\");\n if (c.req.header(\"If-None-Match\") === etag) return c.body(null, 304);\n let result = cache.get(key);\n if (result) remember(key, result);\n else {\n if (coordinator.protectedKeys().size >= 32) return c.text(\"thumbnail queue full\", 429);\n result =\n (await coordinator.acquire(key, c.req.raw.signal, async (signal) => {\n const image = await generateThumbnail(path, signal);\n remember(key, image);\n return image;\n })) ?? undefined;\n }\n if (!result) return c.text(\"image unavailable\", 422);\n c.header(\"Content-Type\", \"image/jpeg\");\n return c.body(new Uint8Array(result));\n } catch (error) {\n if (error instanceof HTTPException) return error.getResponse();\n return c.text(\"image unavailable\", 422);\n }\n });\n}\n","export type ThumbnailGenerationValue = Buffer | null;\nexport type ThumbnailGenerationWork = (signal: AbortSignal) => Promise<ThumbnailGenerationValue>;\n\ninterface GenerationEntry {\n key: string;\n controller: AbortController;\n leases: number;\n state: \"queued\" | \"active\";\n work: ThumbnailGenerationWork;\n promise: Promise<ThumbnailGenerationValue>;\n resolve: (value: ThumbnailGenerationValue) => void;\n reject: (reason: unknown) => void;\n}\n\n/** Sole server owner for same-key dedupe, concurrency, cancellation, and queue order. */\nexport class ThumbnailGenerationCoordinator {\n private readonly entries = new Map<string, GenerationEntry>();\n private readonly queue: GenerationEntry[] = [];\n private readonly activeEntries = new Set<GenerationEntry>();\n private active = 0;\n\n constructor(private readonly concurrency = 1) {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new RangeError(\"Thumbnail concurrency must be a positive integer\");\n }\n }\n\n acquire(\n key: string,\n signal: AbortSignal,\n work: ThumbnailGenerationWork,\n ): Promise<ThumbnailGenerationValue> {\n if (signal.aborted) return Promise.reject(new DOMException(\"Aborted\", \"AbortError\"));\n\n let entry = this.entries.get(key);\n if (!entry) {\n let resolve!: (value: ThumbnailGenerationValue) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<ThumbnailGenerationValue>((resolvePromise, rejectPromise) => {\n resolve = resolvePromise;\n reject = rejectPromise;\n });\n entry = {\n key,\n controller: new AbortController(),\n leases: 0,\n state: \"queued\",\n work,\n promise,\n resolve,\n reject,\n };\n this.entries.set(key, entry);\n this.queue.push(entry);\n }\n entry.leases++;\n this.pump();\n\n return this.lease(entry, signal);\n }\n\n protectedKeys(): ReadonlySet<string> {\n return new Set([...this.entries.keys(), ...[...this.activeEntries].map((entry) => entry.key)]);\n }\n\n private lease(entry: GenerationEntry, signal: AbortSignal): Promise<ThumbnailGenerationValue> {\n return new Promise((resolve, reject) => {\n let released = false;\n const release = () => {\n if (released) return;\n released = true;\n signal.removeEventListener(\"abort\", onAbort);\n entry.leases--;\n if (entry.leases > 0 || !this.entries.has(entry.key)) return;\n\n entry.controller.abort();\n if (this.entries.get(entry.key) === entry) this.entries.delete(entry.key);\n if (entry.state === \"queued\") {\n const index = this.queue.indexOf(entry);\n if (index >= 0) this.queue.splice(index, 1);\n entry.reject(new DOMException(\"Aborted\", \"AbortError\"));\n }\n };\n const onAbort = () => {\n release();\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n\n signal.addEventListener(\"abort\", onAbort, { once: true });\n entry.promise.then(\n (value) => {\n release();\n resolve(value);\n },\n (reason) => {\n release();\n reject(reason);\n },\n );\n });\n }\n\n private pump(): void {\n while (this.active < this.concurrency) {\n const entry = this.queue.shift();\n if (!entry) return;\n if (entry.leases === 0) continue;\n entry.state = \"active\";\n this.activeEntries.add(entry);\n this.active++;\n void this.run(entry);\n }\n }\n\n private async run(entry: GenerationEntry): Promise<void> {\n try {\n entry.resolve(await entry.work(entry.controller.signal));\n } catch (error) {\n entry.reject(error);\n } finally {\n this.active--;\n this.activeEntries.delete(entry);\n if (this.entries.get(entry.key) === entry) this.entries.delete(entry.key);\n this.pump();\n }\n }\n}\n\nexport const thumbnailGenerationCoordinator = new ThumbnailGenerationCoordinator(1);\n","import type { Hono } from \"hono\";\nimport {\n closeSync,\n type Dirent,\n fstatSync,\n openSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { STUDIO_MANUAL_EDITS_PATH } from \"../helpers/manualEditsRenderScript.js\";\nimport { compositionInputSignature } from \"../helpers/compositionInputs.js\";\nimport { createProjectSignature, resolveProjectAndSignature } from \"../helpers/projectSignature.js\";\nimport { STUDIO_MOTION_PATH } from \"../helpers/studioMotionRenderScript.js\";\nimport { thumbnailGenerationCoordinator } from \"./thumbnailGenerationCoordinator.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\nimport {\n isProjectRootMissing,\n mkdirWithinProject,\n resolveWithinProject,\n} from \"../helpers/safePath.js\";\nimport { proxyActivityMark } from \"../helpers/proxyTranscoder.js\";\nimport { PREVIEW_CAPTURE_PARAM } from \"./preview.js\";\n\nconst THUMBNAIL_CACHE_VERSION = \"v5\";\nconst THUMBNAIL_MAX_OUTPUT_WIDTH = 240;\nconst THUMBNAIL_MAX_OUTPUT_HEIGHT = 135;\nconst THUMBNAIL_CACHE_MAX_BYTES = 512 * 1024 * 1024;\nconst THUMBNAIL_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000;\nconst prunedCacheDirs = new Set<string>();\n\nexport function pruneThumbnailCache(\n cacheDir: string,\n protectedPaths: ReadonlySet<string>,\n now = Date.now(),\n): void {\n let entries: Dirent[];\n try {\n entries = readdirSync(cacheDir, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n throw err;\n }\n const files = entries.flatMap((entry) => {\n if (!entry.isFile()) return [];\n const path = join(cacheDir, entry.name);\n try {\n const stats = statSync(path);\n return [{ path, bytes: stats.size, mtimeMs: stats.mtimeMs }];\n } catch {\n return [];\n }\n });\n const retained = [];\n for (const file of files) {\n if (!protectedPaths.has(file.path) && now - file.mtimeMs > THUMBNAIL_CACHE_MAX_AGE_MS) {\n rmSync(file.path, { force: true });\n } else {\n retained.push(file);\n }\n }\n\n let bytes = retained.reduce((total, file) => total + file.bytes, 0);\n for (const file of retained.sort((left, right) => left.mtimeMs - right.mtimeMs)) {\n if (bytes <= THUMBNAIL_CACHE_MAX_BYTES) break;\n if (protectedPaths.has(file.path)) continue;\n try {\n unlinkSync(file.path);\n bytes -= file.bytes;\n } catch {\n // Another request may have pruned the same file.\n }\n }\n}\n\nfunction writeThumbnailAtomically(path: string, buffer: Buffer): void {\n const temporaryPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeFileSync(temporaryPath, buffer, { flag: \"wx\" });\n renameSync(temporaryPath, path);\n } finally {\n rmSync(temporaryPath, { force: true });\n }\n}\n\ntype FileRead = { data: Buffer; mtimeMs: number } | \"missing\" | \"not-a-file\";\n\n// One open for the stat and the read, so the file cannot change between the check and the use.\nfunction readFileOnce(file: string): FileRead {\n let fd: number;\n try {\n fd = openSync(file, \"r\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return \"missing\";\n if (code === \"ENOTDIR\") return \"not-a-file\";\n throw err;\n }\n try {\n const stat = fstatSync(fd);\n if (!stat.isFile()) return \"not-a-file\";\n return { data: readFileSync(fd), mtimeMs: stat.mtimeMs };\n } finally {\n closeSync(fd);\n }\n}\n\nfunction manifestKey(file: string): { key: string; mtimeMs: number } {\n const manifest = readFileOnce(file);\n if (typeof manifest === \"string\") return { key: \"\", mtimeMs: -Infinity };\n const hash = createHash(\"sha1\").update(manifest.data).digest(\"hex\").slice(0, 16);\n return { key: `_${hash}`, mtimeMs: Math.round(manifest.mtimeMs) };\n}\n\nexport function registerThumbnailRoutes(api: Hono, adapter: StudioApiAdapter): void {\n api.get(\"/projects/:id/thumbnail/*\", async (c) => {\n if (!adapter.generateThumbnail) {\n return c.json({ error: \"Thumbnails not available\" }, 501);\n }\n const resolved = await resolveProjectAndSignature(adapter, c.req.param(\"id\"));\n if (!resolved) return c.json({ error: \"not found\" }, 404);\n const { project, signature: projectSignature } = resolved;\n\n let compPath = requestSubPath(c.req.url, \"projects/:id/thumbnail\");\n if (compPath && !compPath.includes(\".\")) compPath += \".html\";\n const htmlFile = resolveWithinProject(project.dir, compPath);\n const source = htmlFile ? readFileOnce(htmlFile) : \"not-a-file\";\n if (source === \"not-a-file\") return c.json({ error: \"not found\" }, 404);\n // Keyed on what this composition renders from, so editing one scene leaves the others cached.\n const inputSignature = compositionInputSignature(project.dir, compPath, projectSignature);\n\n const url = new URL(c.req.url, `http://${c.req.header(\"host\") || \"localhost\"}`);\n const rawSeekTime = url.searchParams.get(\"t\");\n const parsedSeekTime = rawSeekTime == null ? Number.NaN : parseFloat(rawSeekTime);\n const seekTime = Number.isFinite(parsedSeekTime) ? parsedSeekTime : 0.5;\n const vpWidth = parseInt(url.searchParams.get(\"w\") || \"0\") || 0;\n const vpHeight = parseInt(url.searchParams.get(\"h\") || \"0\") || 0;\n const selector = url.searchParams.get(\"selector\") || undefined;\n const format = url.searchParams.get(\"format\") === \"png\" ? \"png\" : \"jpeg\";\n const contentType = format === \"png\" ? \"image/png\" : \"image/jpeg\";\n const requestedOutput = url.searchParams.get(\"output\");\n // PNG is the legacy source-density capture contract. Callers can opt either\n // format into the bounded preview contract explicitly.\n const outputMode =\n requestedOutput === \"source\" || (requestedOutput !== \"preview\" && format === \"png\")\n ? \"source\"\n : \"preview\";\n const rawSelectorIndex = Number.parseInt(url.searchParams.get(\"selectorIndex\") || \"0\", 10);\n const selectorIndex =\n Number.isFinite(rawSelectorIndex) && rawSelectorIndex > 0 ? rawSelectorIndex : undefined;\n const urlVersion = url.searchParams.get(\"v\") || \"\";\n\n // Determine composition dimensions from HTML\n let compW = vpWidth || 1920;\n let compH = vpHeight || 1080;\n let sourceMtime = 0;\n // Content-hash the composition HTML into the cache key — ALWAYS, even when\n // explicit w/h are supplied. The old code only read the file when `!vpWidth`,\n // so Studio thumbnail requests (which pass dimensions) kept the source out of\n // the key entirely (sourceMtime=0) and served a stale thumbnail after every\n // edit, even on a hard reload. Keyed on content (like manualEdits/motion), not\n // just mtime, so a restore/copy with a preserved mtime can't serve stale.\n let sourceKey = \"\";\n if (source !== \"missing\") {\n const html = source.data.toString(\"utf-8\");\n sourceKey = `_${createHash(\"sha1\").update(html).digest(\"hex\").slice(0, 16)}`;\n sourceMtime = Math.round(source.mtimeMs);\n if (!vpWidth) {\n const wMatch = html.match(/data-width=[\"'](\\d+)[\"']/);\n const hMatch = html.match(/data-height=[\"'](\\d+)[\"']/);\n if (wMatch?.[1]) compW = parseInt(wMatch[1]);\n if (hMatch?.[1]) compH = parseInt(hMatch[1]);\n }\n }\n const manualEdits = manifestKey(join(project.dir, STUDIO_MANUAL_EDITS_PATH));\n const motion = manifestKey(join(project.dir, STUDIO_MOTION_PATH));\n sourceMtime = Math.max(sourceMtime, manualEdits.mtimeMs, motion.mtimeMs);\n\n const projectUrl = `http://${c.req.header(\"host\")}/api/projects/${encodeURIComponent(project.id)}`;\n const previewPath =\n compPath === \"index.html\"\n ? `${projectUrl}/preview`\n : `${projectUrl}/preview/comp/${compPath.split(\"/\").map(encodeURIComponent).join(\"/\")}`;\n const previewUrl = `${previewPath}?${PREVIEW_CAPTURE_PARAM}=1`;\n\n // Cache\n const cacheDir = join(project.dir, \".thumbnails\");\n const selectorKey = selector\n ? `_${createHash(\"sha1\").update(selector).digest(\"hex\").slice(0, 16)}_${selectorIndex ?? 0}`\n : \"\";\n const urlVersionKey = urlVersion\n ? `_${urlVersion.replace(/[^a-zA-Z0-9_-]+/g, \"_\").slice(0, 32)}`\n : \"\";\n const inputSignatureKey = `_${createHash(\"sha1\").update(inputSignature).digest(\"hex\").slice(0, 16)}`;\n const outputScale =\n outputMode === \"source\"\n ? 1\n : Math.min(1, THUMBNAIL_MAX_OUTPUT_WIDTH / compW, THUMBNAIL_MAX_OUTPUT_HEIGHT / compH);\n const outputWidth = Math.max(1, Math.round(compW * outputScale));\n const outputHeight = Math.max(1, Math.round(compH * outputScale));\n const cacheKey = `${THUMBNAIL_CACHE_VERSION}${urlVersionKey}${inputSignatureKey}${manualEdits.key}${motion.key}${sourceKey}_${format}_${outputMode}_${compPath.replace(/\\//g, \"_\")}_${compW}x${compH}_${outputWidth}x${outputHeight}_${sourceMtime}_${seekTime.toFixed(2)}${selectorKey}.${format === \"png\" ? \"png\" : \"jpg\"}`;\n const cachePath = join(cacheDir, cacheKey);\n if (!prunedCacheDirs.has(cacheDir)) {\n prunedCacheDirs.add(cacheDir);\n pruneThumbnailCache(\n cacheDir,\n new Set([...thumbnailGenerationCoordinator.protectedKeys(), cachePath]),\n );\n }\n const cached = readFileOnce(cachePath);\n if (typeof cached === \"object\") {\n return new Response(new Uint8Array(cached.data), {\n headers: { \"Content-Type\": contentType, \"Cache-Control\": \"no-cache\" },\n });\n }\n if (url.searchParams.get(\"cached\") === \"1\")\n return c.body(null, 204, { \"Cache-Control\": \"no-cache\" });\n\n try {\n const buffer = await thumbnailGenerationCoordinator.acquire(\n cachePath,\n c.req.raw.signal,\n async (signal) => {\n const previewCopiesAtStart = proxyActivityMark(project.dir);\n const generated = await adapter.generateThumbnail!({\n project,\n compPath,\n seekTime,\n width: compW,\n height: compH,\n outputWidth,\n outputHeight,\n previewUrl,\n selector,\n format,\n selectorIndex,\n signal,\n });\n if (!generated) return null;\n const previewCopiesAtEnd = proxyActivityMark(project.dir);\n const afterGeneration = await resolveProjectAndSignature(adapter, project.id);\n const inputsUnchanged = (signature: string) =>\n compositionInputSignature(project.dir, compPath, signature) === inputSignature;\n // Both the adapter's signature and a fresh one: the adapter's can lag the watcher.\n if (\n previewCopiesAtStart === null ||\n previewCopiesAtEnd !== previewCopiesAtStart ||\n afterGeneration?.project.dir !== project.dir ||\n !inputsUnchanged(afterGeneration.signature) ||\n !inputsUnchanged(createProjectSignature(project.dir))\n ) {\n // The browser may have rendered content written after this request\n // captured its cache identity. Return the pixels to this caller,\n // but never file them under a signature they do not prove.\n return generated;\n }\n mkdirWithinProject(project.dir, cacheDir);\n writeThumbnailAtomically(cachePath, generated);\n return generated;\n },\n );\n if (!buffer) {\n return c.json(\n { error: \"Thumbnail generation failed — Chrome browser may not be available\" },\n 500,\n );\n }\n pruneThumbnailCache(cacheDir, thumbnailGenerationCoordinator.protectedKeys());\n return new Response(new Uint8Array(buffer), {\n headers: { \"Content-Type\": contentType, \"Cache-Control\": \"no-cache\" },\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return new Response(null, { status: 499 });\n }\n if (isProjectRootMissing(err)) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n return c.json({ error: `Thumbnail generation failed: ${msg}` }, 500);\n }\n });\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { isWithinProjectRoot } from \"@hyperframes/parsers/asset-resolution\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport {\n decodeAudioPeaks,\n buildWaveformCacheKey,\n writeWaveformCache,\n isWaveformCacheDirectory,\n} from \"../helpers/waveform.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\n\nexport function registerWaveformRoutes(api: Hono, adapter: StudioApiAdapter): void {\n api.get(\"/projects/:id/waveform/*\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const assetPath = requestSubPath(c.req.url, \"projects/:id/waveform\");\n const audioPath = resolve(project.dir, assetPath);\n if (!isWithinProjectRoot(project.dir, audioPath)) {\n return c.json({ error: \"file not found\" }, 404);\n }\n const stats = statSync(audioPath, { throwIfNoEntry: false });\n if (!stats) return c.json({ error: \"file not found\" }, 404);\n\n const cacheDir = join(project.dir, \".waveform-cache\");\n // Keyed on the file's size and mtime as well as its name, so re-encoding an\n // asset in place invalidates its peaks instead of drawing the old ones.\n const cachePath = join(cacheDir, buildWaveformCacheKey(assetPath, stats));\n\n try {\n if (isWaveformCacheDirectory(cacheDir) && existsSync(cachePath)) {\n const peaks = JSON.parse(readFileSync(cachePath, \"utf-8\")) as number[];\n return c.json({ peaks });\n }\n } catch {\n // corrupt or inaccessible cache — regenerate\n }\n\n let peaks: number[];\n try {\n peaks = await decodeAudioPeaks(audioPath);\n } catch {\n return c.json({ error: \"failed to decode audio\" }, 500);\n }\n\n try {\n writeWaveformCache(cachePath, peaks);\n } catch {\n // cache write failure is non-fatal\n }\n\n return c.json({ peaks });\n });\n}\n","import { execFile } from \"node:child_process\";\nimport { readFileSync, rmSync, statSync } from \"node:fs\";\nimport { basename, dirname, join, relative, sep } from \"node:path\";\nimport type { Hono } from \"hono\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { mkdirWithinProject, pinWithinProject } from \"../helpers/safePath.js\";\nimport {\n atomicTempPath,\n createFileAtomically,\n replaceFileAtomically,\n} from \"@hyperframes/core/atomic-file\";\nimport { backupPathForResponse, snapshotBeforeWrite } from \"../helpers/backupJournal.js\";\nimport {\n createWriteToken,\n fileContentVersion,\n recordFileWriteReceipt,\n} from \"../helpers/fileVersion.js\";\nimport {\n applyFreezeFrameToHtml,\n freezeExtractArgs,\n freezeStillFileName,\n randomStillToken,\n readFreezeSource,\n type FreezeSource,\n} from \"../helpers/freezeFrame.js\";\nimport type { SourceMutationTarget } from \"../helpers/sourceMutation.js\";\n\nexport type FrameExtractor = (args: string[]) => Promise<{ ok: boolean; error?: string }>;\n\nconst EXTRACT_TIMEOUT_MS = 30_000;\n\nconst ffmpegExtractor: FrameExtractor = (args) => {\n const ffmpeg = findFfBinary(\"ffmpeg\", { configuredMustExist: true });\n if (!ffmpeg) return Promise.resolve({ ok: false, error: \"ffmpeg not found\" });\n return new Promise((resolvePromise) => {\n execFile(\n ffmpeg,\n args,\n { timeout: EXTRACT_TIMEOUT_MS, windowsHide: true },\n (error, _o, stderr) =>\n resolvePromise(\n error ? { ok: false, error: String(stderr || error.message) } : { ok: true },\n ),\n );\n });\n};\n\ninterface FreezeFrameRequest {\n path: string;\n expectedVersion: string;\n target: SourceMutationTarget;\n playhead: number;\n transactionToken?: string;\n}\n\nfunction isFreezeFrameRequest(value: unknown): value is FreezeFrameRequest {\n if (typeof value !== \"object\" || value === null) return false;\n const body: Partial<Record<keyof FreezeFrameRequest, unknown>> = value;\n return (\n typeof body.path === \"string\" &&\n body.path.length > 0 &&\n typeof body.expectedVersion === \"string\" &&\n typeof body.target === \"object\" &&\n body.target !== null &&\n typeof body.playhead === \"number\" &&\n Number.isFinite(body.playhead)\n );\n}\n\nconst FREEZE_DIR = [\"assets\", \"freeze\"];\n\ntype Failure = { error: string; status: 403 | 404 | 409 | 500 };\n\nfunction readExpected(absPath: string, expectedVersion: string): { content: string } | Failure {\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n return { error: \"not found\", status: 404 };\n }\n return fileContentVersion(content) === expectedVersion\n ? { content }\n : { error: \"file conflict\", status: 409 };\n}\n\nfunction readFrame(path: string): Buffer | null {\n try {\n return readFileSync(path);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n}\n\nfunction publishStill(path: string, frame: Buffer): boolean {\n try {\n createFileAtomically(path, frame);\n return true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") return false;\n throw error;\n }\n}\n\nasync function extractThenPublishWhole(\n extract: FrameExtractor,\n mediaPath: string,\n mediaTime: number,\n imagePath: string,\n): Promise<Failure | null> {\n const unseenByHistory = atomicTempPath(imagePath);\n try {\n const extracted = await extract(freezeExtractArgs(mediaPath, mediaTime, unseenByHistory));\n const frame = extracted.ok ? readFrame(unseenByHistory) : null;\n if (!frame?.length) {\n const reason = extracted.ok ? \"no frame at this time\" : (extracted.error ?? \"ffmpeg failed\");\n return { error: `Could not extract the frame: ${reason}`, status: 500 };\n }\n if (publishStill(imagePath, frame)) return null;\n return { error: `freeze still already exists: ${basename(imagePath)}`, status: 409 };\n } finally {\n rmSync(unseenByHistory, { force: true });\n }\n}\n\nasync function extractStill(\n projectDir: string,\n absPath: string,\n source: FreezeSource,\n playhead: number,\n tools: { extract: FrameExtractor; stillToken: () => string },\n): Promise<{ imageSrc: string; stillPath: string; imagePath: string } | Failure> {\n const fileDir = dirname(absPath);\n const mediaPath = pinWithinProject(projectDir, relative(projectDir, join(fileDir, source.src)));\n if (!mediaPath) return { error: `forbidden media path: ${source.src}`, status: 403 };\n const freezeDir = join(projectDir, ...FREEZE_DIR);\n const fileName = freezeStillFileName(source.id, playhead, tools.stillToken());\n mkdirWithinProject(projectDir, freezeDir);\n const imagePath = pinWithinProject(projectDir, join(...FREEZE_DIR, fileName));\n if (!imagePath || dirname(imagePath) !== freezeDir) {\n return { error: `forbidden freeze path: ${fileName}`, status: 403 };\n }\n const failed = await extractThenPublishWhole(\n tools.extract,\n mediaPath,\n source.mediaTime,\n imagePath,\n );\n if (failed) return failed;\n const depth = relative(projectDir, fileDir).split(sep).filter(Boolean).length;\n const stillPath = `${FREEZE_DIR.join(\"/\")}/${fileName}`;\n return { imageSrc: `${\"../\".repeat(depth)}${stillPath}`, stillPath, imagePath };\n}\n\nfunction writeFolded(\n projectDir: string,\n absPath: string,\n path: string,\n before: string,\n after: string,\n options: { token?: string },\n): { version: string; writeToken: string; backupPath: string | null } | Failure {\n if (readFileSync(absPath, \"utf-8\") !== before) {\n return { error: `file conflict: ${path}`, status: 409 };\n }\n const backup = snapshotBeforeWrite(projectDir, absPath);\n if (backup.error) return { error: `Failed to create backup: ${backup.error}`, status: 500 };\n const writeToken = createWriteToken(options.token);\n replaceFileAtomically(absPath, after, statSync(absPath).mode);\n const version = fileContentVersion(after);\n recordFileWriteReceipt(absPath, { path, version, writeToken, overwrote: before });\n return { version, writeToken, backupPath: backupPathForResponse(projectDir, backup.backupPath) };\n}\n\n/** POST: extract the frame under the playhead and fold split + still + shift into one file write. */\nexport function registerFreezeFrameRoutes(\n api: Hono,\n adapter: StudioApiAdapter,\n extract: FrameExtractor = ffmpegExtractor,\n stillToken: () => string = randomStillToken,\n): void {\n // A straight line of request guards, each its own early return.\n // fallow-ignore-next-line complexity\n api.post(\"/projects/:id/file-mutations/freeze-frame\", async (c) => {\n const body: unknown = await c.req.json().catch(() => null);\n if (!isFreezeFrameRequest(body)) {\n return c.json({ error: \"path, expectedVersion, target and playhead required\" }, 400);\n }\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const absPath = pinWithinProject(project.dir, body.path);\n if (!absPath) return c.json({ error: `forbidden path: ${body.path}` }, 403);\n\n const read = readExpected(absPath, body.expectedVersion);\n if (\"error\" in read) return c.json({ error: `${read.error}: ${body.path}` }, read.status);\n const before = read.content;\n\n const source = readFreezeSource(before, body.target, body.playhead);\n if (!source) return c.json({ error: \"Move the playhead inside a video clip to freeze\" }, 400);\n const still = await extractStill(project.dir, absPath, source, body.playhead, {\n extract,\n stillToken,\n });\n if (\"error\" in still) return c.json({ error: still.error }, still.status);\n const { imageSrc, stillPath, imagePath } = still;\n const folded = applyFreezeFrameToHtml(before, {\n target: body.target,\n playhead: body.playhead,\n imageSrc,\n });\n const failAndRemoveStill = (error: string, status: 400 | Failure[\"status\"]) => {\n rmSync(imagePath, { force: true });\n return c.json({ error }, status);\n };\n if (!folded) return failAndRemoveStill(\"Freeze target was not found in the file\", 400);\n const written = writeFolded(project.dir, absPath, body.path, before, folded.html, {\n token: body.transactionToken ?? c.req.header(\"X-Hyperframes-Write-Token\"),\n });\n if (\"error\" in written) return failAndRemoveStill(written.error, written.status);\n const { version, writeToken, backupPath } = written;\n return c.json({\n ok: true,\n path: body.path,\n before,\n after: folded.html,\n version,\n writeToken,\n backupPath,\n freezeId: folded.freezeId,\n imageSrc,\n stillPath,\n });\n });\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport { readMediaOffsetSeconds } from \"@hyperframes/parsers/media-duration\";\nimport { resolveRateSpec, sourceTimeAt } from \"@hyperframes/core/speed-ramp\";\nimport { MEDIA_LINK_ATTR as LINK_ATTR, relinkSplitHalves } from \"@hyperframes/core/media-link\";\nimport {\n findTargetElement,\n isHTMLElement,\n nextUniqueId,\n parseSourceDocument,\n splitElementInHtml,\n type SourceMutationTarget,\n} from \"./sourceMutation.js\";\n\nconst FREEZE_HOLD_SECONDS = 2;\nconst EPSILON = 1e-3;\n\nconst round3 = (value: number) => Math.round(value * 1000) / 1000;\n\nfunction numberAttr(el: Element, name: string): number | null {\n const raw = el.getAttribute(name);\n if (raw === null || raw.trim() === \"\") return null;\n const value = Number(raw);\n return Number.isFinite(value) ? value : null;\n}\n\nfunction trackOf(el: Element): number {\n return numberAttr(el, \"data-track-index\") ?? numberAttr(el, \"data-layer\") ?? 0;\n}\n\n/** Media seconds shown at `playhead`: the clip's in-point plus the source its rate (or rate lane) has consumed. */\nexport function freezeFrameMediaTime(input: {\n clipStart: number;\n playhead: number;\n mediaStart: number;\n playbackRate: number;\n automation: string | null;\n}): number {\n const rate = resolveRateSpec(input.automation, input.playbackRate);\n return input.mediaStart + sourceTimeAt(rate, Math.max(0, input.playhead - input.clipStart));\n}\n\nexport function freezeExtractArgs(src: string, mediaTime: number, output: string): string[] {\n return [\n \"-y\",\n \"-ss\",\n String(round3(mediaTime)),\n \"-i\",\n src,\n \"-frames:v\",\n \"1\",\n \"-c:v\",\n \"png\",\n \"-f\",\n \"image2\",\n \"-update\",\n \"1\",\n output,\n ];\n}\n\nexport const randomStillToken = (): string => randomBytes(4).toString(\"hex\");\n\nexport function freezeStillFileName(\n clipId: string,\n playhead: number,\n token: string = randomStillToken(),\n): string {\n const stem = clipId.replace(/[^A-Za-z0-9_-]/g, \"_\").slice(0, 48) || \"clip\";\n const idHash = createHash(\"sha256\").update(clipId).digest(\"hex\").slice(0, 10);\n return `${stem}-${idHash}-${Math.round(playhead * 1000)}-${token}.png`;\n}\n\nexport interface FreezeSource {\n id: string;\n src: string;\n mediaTime: number;\n}\n\n/** The video to freeze and the media time under the playhead, read from the source file. */\nexport function readFreezeSource(\n html: string,\n target: SourceMutationTarget,\n playhead: number,\n): FreezeSource | null {\n const { document } = parseSourceDocument(html);\n const el = findTargetElement(document, target);\n if (!el || el.tagName.toLowerCase() !== \"video\") return null;\n const src = el.getAttribute(\"src\");\n const start = numberAttr(el, \"data-start\");\n const duration = numberAttr(el, \"data-duration\");\n if (!src || start === null || duration === null) return null;\n if (playhead <= start + EPSILON || playhead >= start + duration - EPSILON) return null;\n return {\n id: el.getAttribute(\"id\") || \"clip\",\n src,\n mediaTime: freezeFrameMediaTime({\n clipStart: start,\n playhead,\n mediaStart: readMediaOffsetSeconds((name) => el.getAttribute(name)),\n playbackRate: numberAttr(el, \"data-playback-rate\") ?? 1,\n automation: el.getAttribute(\"data-automation\"),\n }),\n };\n}\n\nfunction targetOf(el: Element): SourceMutationTarget {\n const hfId = el.getAttribute(\"data-hf-id\");\n return { ...(hfId ? { hfId } : {}), id: el.getAttribute(\"id\") };\n}\n\nfunction spans(el: Element, time: number): boolean {\n const start = numberAttr(el, \"data-start\");\n const duration = numberAttr(el, \"data-duration\");\n if (start === null || duration === null) return false;\n return time > start + EPSILON && time < start + duration - EPSILON;\n}\n\nfunction shiftTracks(document: Document, tracks: Set<number>, from: number, by: number): void {\n for (const el of document.querySelectorAll(\"[data-start]\")) {\n if (el.hasAttribute(\"data-composition-id\") || !tracks.has(trackOf(el))) continue;\n const start = numberAttr(el, \"data-start\");\n if (start === null || start < from - EPSILON) continue;\n el.setAttribute(\"data-start\", String(round3(start + by)));\n }\n}\n\nfunction growRootToFit(document: Document): void {\n const root = document.querySelector(\"[data-composition-id]\");\n const rootDuration = root ? numberAttr(root, \"data-duration\") : null;\n if (!root || rootDuration === null) return;\n let end = rootDuration;\n for (const el of root.querySelectorAll(\"[data-start][data-duration]\")) {\n const start = numberAttr(el, \"data-start\");\n const duration = numberAttr(el, \"data-duration\");\n if (start !== null && duration !== null) end = Math.max(end, start + duration);\n }\n if (end > rootDuration + EPSILON) root.setAttribute(\"data-duration\", String(round3(end)));\n}\n\nconst COPIED_PICTURE_ATTRS = [\"class\", \"style\", \"data-color-grading\"];\n\nfunction buildStill(\n document: Document,\n video: Element,\n input: { id: string; imageSrc: string; playhead: number; holdSeconds: number },\n): Element {\n const img = document.createElement(\"img\");\n img.setAttribute(\"id\", input.id);\n for (const name of COPIED_PICTURE_ATTRS) {\n const value = video.getAttribute(name);\n if (value !== null) img.setAttribute(name, value);\n }\n if (!img.classList.contains(\"clip\")) img.classList.add(\"clip\");\n img.setAttribute(\"src\", input.imageSrc);\n img.setAttribute(\"alt\", \"\");\n img.setAttribute(\"data-start\", String(round3(input.playhead)));\n img.setAttribute(\"data-duration\", String(input.holdSeconds));\n img.setAttribute(\"data-track-index\", String(trackOf(video)));\n img.setAttribute(\"data-timeline-label\", \"Freeze\");\n return img;\n}\n\nexport interface FreezeFrameResult {\n html: string;\n freezeId: string;\n}\n\n/**\n * Split the video at the playhead, put a still of that frame in the gap and push the rest of its\n * track (and a linked partner's, which is split too and left silent for the hold) right by the hold.\n */\nfunction linkedPartners(document: Document, video: Element): Element[] {\n const link = video.getAttribute(LINK_ATTR);\n if (!link) return [];\n return Array.from(document.querySelectorAll(`[${LINK_ATTR}]`)).filter(\n (el) => el !== video && el.getAttribute(LINK_ATTR) === link,\n );\n}\n\n/** Split every element at `time`, in order; the new right halves' ids, or null if one missed. */\nfunction splitAll(\n html: string,\n elements: readonly Element[],\n time: number,\n): { html: string; rightHalfIds: string[] } | null {\n const rightHalfIds: string[] = [];\n let next = html;\n for (const el of elements) {\n const split = splitElementInHtml(\n next,\n targetOf(el),\n time,\n `${el.getAttribute(\"id\") || \"clip\"}-split`,\n {\n start: numberAttr(el, \"data-start\") ?? 0,\n duration: numberAttr(el, \"data-duration\") ?? 0,\n track: trackOf(el),\n },\n );\n if (!split.matched || !split.newId) return null;\n next = split.html;\n rightHalfIds.push(split.newId);\n }\n return { html: next, rightHalfIds };\n}\n\n/**\n * Split the video at the playhead, put a still of that frame in the gap and push the rest of its\n * track (and a linked partner's, which is split too and left silent for the hold) right by the hold.\n */\nexport function applyFreezeFrameToHtml(\n html: string,\n input: {\n target: SourceMutationTarget;\n playhead: number;\n imageSrc: string;\n holdSeconds?: number;\n },\n): FreezeFrameResult | null {\n const hold = input.holdSeconds ?? FREEZE_HOLD_SECONDS;\n const { document: before } = parseSourceDocument(html);\n const video = findTargetElement(before, input.target);\n if (!video || !isHTMLElement(video) || !spans(video, input.playhead)) return null;\n const partners = linkedPartners(before, video);\n const tracks = new Set([trackOf(video), ...partners.map(trackOf)]);\n const cut = splitAll(\n html,\n [video, ...partners.filter((el) => spans(el, input.playhead))],\n input.playhead,\n );\n if (!cut) return null;\n\n const { document, wrappedFragment } = parseSourceDocument(cut.html);\n relinkSplitHalves(document, cut.rightHalfIds);\n shiftTracks(document, tracks, input.playhead, hold);\n const leftHalf = findTargetElement(document, input.target);\n if (!leftHalf?.parentElement) return null;\n const freezeId = nextUniqueId(document, `${video.getAttribute(\"id\") || \"clip\"}-freeze`);\n const still = buildStill(document, leftHalf, {\n id: freezeId,\n imageSrc: input.imageSrc,\n playhead: input.playhead,\n holdSeconds: hold,\n });\n leftHalf.parentElement.insertBefore(still, leftHalf.nextSibling);\n growRootToFit(document);\n return {\n html: ensureHfIds(wrappedFragment ? document.body.innerHTML || \"\" : document.toString()),\n freezeId,\n };\n}\n","import { existsSync } from \"node:fs\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport {\n absoluteLoudnessPlan,\n DEFAULT_TARGET_LUFS,\n measureAudio,\n requiredFfmpeg,\n resolveLocalAudioPath,\n type LoudnessMeasurement,\n type MeasuredWindow,\n} from \"../helpers/loudness.js\";\n\nexport type MeasureLoudness = (\n file: string,\n window: MeasuredWindow,\n) => Promise<LoudnessMeasurement>;\n\ninterface NormalizeRequest {\n id: string;\n src: string;\n window: MeasuredWindow;\n volume: number;\n targetLufs: number;\n}\n\nconst defaultMeasure: MeasureLoudness = (file, window) =>\n measureAudio(requiredFfmpeg(), file, window);\n\nclass InvalidField extends Error {}\n\nfunction numberField(\n body: Record<string, unknown>,\n name: string,\n fallback: number,\n valid: (value: number) => boolean,\n): number {\n const raw = body[name];\n if (raw === undefined || raw === null) return fallback;\n if (typeof raw === \"number\" && Number.isFinite(raw) && valid(raw)) return raw;\n throw new InvalidField(`${name} is out of range`);\n}\n\nfunction readNormalizeRequest(body: Record<string, unknown>): NormalizeRequest {\n const src = typeof body.src === \"string\" ? body.src.trim() : \"\";\n if (!src) throw new InvalidField(\"src is required\");\n const duration = numberField(body, \"duration\", 0, (v) => v > 0);\n return {\n id: typeof body.id === \"string\" && body.id ? body.id : src,\n src,\n window: {\n mediaStart: numberField(body, \"mediaStart\", 0, (v) => v >= 0),\n duration: duration > 0 ? duration : null,\n playbackRate: numberField(body, \"playbackRate\", 1, (v) => v > 0),\n },\n volume: numberField(body, \"volume\", 1, (v) => v >= 0),\n targetLufs: numberField(body, \"targetLufs\", DEFAULT_TARGET_LUFS, (v) => v < 0),\n };\n}\n\nfunction parseNormalizeRequest(body: Record<string, unknown>): NormalizeRequest | string {\n try {\n return readNormalizeRequest(body);\n } catch (error) {\n if (error instanceof InvalidField) return error.message;\n throw error;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Measure one clip's played window and answer the `data-volume` that brings it\n * to the target. Measure-only: Studio writes the attribute through its own\n * edit path so the change is one undo step like any other.\n */\nexport function registerLoudnessRoutes(\n api: Hono,\n adapter: StudioApiAdapter,\n measure: MeasureLoudness = defaultMeasure,\n): void {\n api.post(\"/projects/:id/loudness/normalize\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const body: unknown = await c.req.json().catch(() => null);\n if (!isRecord(body)) return c.json({ error: \"invalid body\" }, 400);\n const request = parseNormalizeRequest(body);\n if (typeof request === \"string\") return c.json({ error: request }, 400);\n\n let file: string;\n try {\n file = resolveLocalAudioPath(project.dir, request.src);\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);\n }\n if (!existsSync(file)) return c.json({ error: \"file not found\" }, 404);\n\n try {\n const measurement = await measure(file, request.window);\n const plan = absoluteLoudnessPlan(\n { id: request.id, volume: request.volume, ...measurement },\n request.targetLufs,\n );\n return c.json({ plan });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 422);\n }\n });\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { isWithinProjectRoot } from \"@hyperframes/parsers/asset-resolution\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isWaveformCacheDirectory, writeWaveformCache } from \"../helpers/waveform.js\";\nimport { buildPeakMapCacheKey, decodePeakMap, PEAK_BIN_SECONDS } from \"../helpers/peakMap.js\";\nimport { requestSubPath } from \"../helpers/requestSubPath.js\";\n\ntype DecodePeaks = (mediaPath: string) => Promise<number[]>;\n\nconst decodesInFlight = new Map<string, Promise<number[]>>();\n\nfunction decodeOnce(cachePath: string, mediaPath: string, decode: DecodePeaks): Promise<number[]> {\n const pending = decodesInFlight.get(cachePath);\n if (pending) return pending;\n const started = decode(mediaPath).finally(() => decodesInFlight.delete(cachePath));\n decodesInFlight.set(cachePath, started);\n return started;\n}\n\nfunction readCachedBins(cacheDir: string, cachePath: string): number[] | null {\n try {\n if (!isWaveformCacheDirectory(cacheDir) || !existsSync(cachePath)) return null;\n const parsed: unknown = JSON.parse(readFileSync(cachePath, \"utf-8\"));\n return Array.isArray(parsed) && parsed.every((n) => typeof n === \"number\") ? parsed : null;\n } catch {\n return null;\n }\n}\n\n/** Absolute per-bin sample peaks for one media file, so the timeline can mark where a clip redlines. */\nexport function registerPeakRoutes(\n api: Hono,\n adapter: StudioApiAdapter,\n decode: DecodePeaks = decodePeakMap,\n): void {\n api.get(\"/projects/:id/peaks/*\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const assetPath = requestSubPath(c.req.url, \"projects/:id/peaks\");\n const mediaPath = resolve(project.dir, assetPath);\n if (!isWithinProjectRoot(project.dir, mediaPath))\n return c.json({ error: \"file not found\" }, 404);\n const stats = statSync(mediaPath, { throwIfNoEntry: false });\n if (!stats?.isFile()) return c.json({ error: \"file not found\" }, 404);\n\n const cacheDir = join(project.dir, \".waveform-cache\");\n const cachePath = join(cacheDir, buildPeakMapCacheKey(assetPath, stats));\n const cached = readCachedBins(cacheDir, cachePath);\n if (cached) return c.json({ binSeconds: PEAK_BIN_SECONDS, bins: cached });\n\n let bins: number[];\n try {\n bins = await decodeOnce(cachePath, mediaPath, decode);\n } catch {\n return c.json({ error: \"failed to decode audio\" }, 500);\n }\n try {\n writeWaveformCache(cachePath, bins);\n } catch {\n // A cache that cannot be written only costs the next request a decode.\n }\n return c.json({ binSeconds: PEAK_BIN_SECONDS, bins });\n });\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\n\nexport const PEAK_BIN_SECONDS = 0.05;\nconst PEAK_SAMPLE_RATE = 48_000;\nconst execFileAsync = promisify(execFile);\nconst PEAK_MAP_CACHE_VERSION = \"peaks-v2\";\n\n/**\n * Running max-abs per bin over interleaved f32le at the source's own channel\n * count. Native channels, not `-ac 2`: ffmpeg's mono upmix pans at -3 dB,\n * which would hide a clip that really does reach 0 dBFS.\n */\nexport interface PeakAccumulator {\n bins: number[];\n frame: number;\n carry: Buffer;\n framesPerBin: number;\n channels: number;\n}\n\nexport function createPeakAccumulator(\n sampleRate = PEAK_SAMPLE_RATE,\n binSeconds = PEAK_BIN_SECONDS,\n channels = 2,\n): PeakAccumulator {\n return {\n bins: [],\n frame: 0,\n carry: Buffer.alloc(0),\n framesPerBin: Math.max(1, Math.round(sampleRate * binSeconds)),\n channels: Math.max(1, channels),\n };\n}\n\nfunction framePeak(data: Buffer, offset: number, channels: number): number {\n let peak = 0;\n for (let ch = 0; ch < channels; ch++) {\n peak = Math.max(peak, Math.abs(data.readFloatLE(offset + ch * 4)));\n }\n return peak;\n}\n\nexport function accumulatePeaks(acc: PeakAccumulator, chunk: Buffer): void {\n const data = acc.carry.length > 0 ? Buffer.concat([acc.carry, chunk]) : chunk;\n const frameBytes = 4 * acc.channels;\n const whole = data.length - (data.length % frameBytes);\n for (let offset = 0; offset < whole; offset += frameBytes) {\n const peak = framePeak(data, offset, acc.channels);\n const bin = Math.floor(acc.frame / acc.framesPerBin);\n if (acc.bins.length <= bin) acc.bins.push(0);\n if (peak > (acc.bins[bin] ?? 0)) acc.bins[bin] = peak;\n acc.frame += 1;\n }\n acc.carry = Buffer.from(data.subarray(whole));\n}\n\n/** Linear sample peak per bin, NOT normalized — the level is the point. */\nexport function finishPeaks(acc: PeakAccumulator): number[] {\n return acc.bins.map((peak) => Number(peak.toFixed(4)));\n}\n\nasync function probeChannels(mediaPath: string): Promise<number> {\n const { stdout } = await execFileAsync(\n findFfBinary(\"ffprobe\") ?? \"ffprobe\",\n [\n \"-v\",\n \"error\",\n \"-select_streams\",\n \"a:0\",\n \"-show_entries\",\n \"stream=channels\",\n \"-of\",\n \"csv=p=0\",\n \"--\",\n mediaPath,\n ],\n { encoding: \"utf8\", timeout: 30_000, windowsHide: true },\n );\n const channels = Number.parseInt(stdout.trim(), 10);\n if (!Number.isFinite(channels) || channels < 1) throw new Error(\"no audio stream\");\n return channels;\n}\n\nexport async function decodePeakMap(mediaPath: string): Promise<number[]> {\n const channels = await probeChannels(mediaPath);\n return new Promise((resolvePromise, reject) => {\n const proc = spawn(\n findFfBinary(\"ffmpeg\") ?? \"ffmpeg\",\n [\n \"-v\",\n \"error\",\n \"-i\",\n mediaPath,\n \"-map\",\n \"0:a:0\",\n \"-vn\",\n \"-ar\",\n String(PEAK_SAMPLE_RATE),\n \"-f\",\n \"f32le\",\n \"pipe:1\",\n ],\n { stdio: [\"ignore\", \"pipe\", \"ignore\"], windowsHide: true },\n );\n const acc = createPeakAccumulator(PEAK_SAMPLE_RATE, PEAK_BIN_SECONDS, channels);\n proc.stdout?.on(\"data\", (chunk: Buffer) => accumulatePeaks(acc, chunk));\n proc.on(\"close\", (code) => {\n if (code !== 0) {\n reject(new Error(`ffmpeg failed decoding audio (exit ${code})`));\n return;\n }\n if (acc.frame === 0) {\n reject(new Error(\"ffmpeg produced no audio samples\"));\n return;\n }\n resolvePromise(finishPeaks(acc));\n });\n proc.on(\"error\", reject);\n });\n}\n\n/** Keyed on content (size + mtime) like the waveform cache, under its own version prefix. */\nexport function buildPeakMapCacheKey(\n assetPath: string,\n fingerprint: { size: number; mtimeMs: number },\n): string {\n const name = assetPath.replace(/[/\\\\]/g, \"_\");\n return `${PEAK_MAP_CACHE_VERSION}_${name}_${fingerprint.size}-${Math.round(fingerprint.mtimeMs)}.json`;\n}\n","import { closeSync, constants, fstatSync, openSync, readSync } from \"node:fs\";\nimport type { Hono } from \"hono\";\nimport {\n collectFontFileEntries,\n fontDirectories,\n getSystemProfilerFamilies,\n locateSystemFont,\n SYSTEM_FONT_SIZE_LIMIT,\n} from \"@hyperframes/core/fonts/system-locator\";\n\nconst MAX_FONT_RESULTS = 2000;\nconst GOOGLE_FONTS_METADATA_URL = \"https://fonts.google.com/metadata/fonts\";\nconst GOOGLE_FONTS_FETCH_TIMEOUT_MS = 3000;\nlet cachedFonts: string[] | null = null;\nlet cachedGoogleFonts: string[] | null = null;\n\nconst GOOGLE_FONT_FALLBACKS = [\n \"Inter\",\n \"Roboto\",\n \"Open Sans\",\n \"Montserrat\",\n \"Poppins\",\n \"Lato\",\n \"Oswald\",\n \"Raleway\",\n \"Nunito\",\n \"Playfair Display\",\n \"Merriweather\",\n \"Source Sans 3\",\n \"Source Serif 4\",\n \"Source Code Pro\",\n \"DM Sans\",\n \"Space Grotesk\",\n \"Space Mono\",\n \"Bebas Neue\",\n \"Outfit\",\n \"JetBrains Mono\",\n];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction collectFontsFromDir(dir: string): string[] {\n return collectFontFileEntries(dir).map((e) => e.family);\n}\n\nfunction listInstalledFontFamilies(): string[] {\n if (cachedFonts) return cachedFonts;\n const families = new Set<string>();\n\n for (const family of getSystemProfilerFamilies()) {\n families.add(family);\n if (families.size >= MAX_FONT_RESULTS) break;\n }\n\n for (const dir of fontDirectories()) {\n for (const family of collectFontsFromDir(dir)) {\n families.add(family);\n if (families.size >= MAX_FONT_RESULTS) break;\n }\n if (families.size >= MAX_FONT_RESULTS) break;\n }\n\n cachedFonts = Array.from(families).sort((a, b) => a.localeCompare(b));\n return cachedFonts;\n}\n\nfunction parseGoogleFontMetadata(value: unknown): string[] {\n if (!isRecord(value) || !Array.isArray(value.familyMetadataList)) return [];\n const families: string[] = [];\n for (const entry of value.familyMetadataList) {\n if (!isRecord(entry) || typeof entry.family !== \"string\") continue;\n families.push(entry.family);\n }\n return families;\n}\n\nfunction stripGoogleJsonGuard(raw: string): string {\n const prefix = \")]}'\";\n if (!raw.startsWith(prefix)) return raw;\n\n let index = prefix.length;\n while (\n index < raw.length &&\n (raw[index] === \" \" ||\n raw[index] === \"\\n\" ||\n raw[index] === \"\\r\" ||\n raw[index] === \"\\t\" ||\n raw[index] === \"\\f\")\n ) {\n index += 1;\n }\n\n return raw.slice(index);\n}\n\nasync function listGoogleFontFamilies(): Promise<string[]> {\n if (cachedGoogleFonts) return cachedGoogleFonts;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), GOOGLE_FONTS_FETCH_TIMEOUT_MS);\n\n try {\n const response = await fetch(GOOGLE_FONTS_METADATA_URL, { signal: controller.signal });\n if (!response.ok) {\n cachedGoogleFonts = GOOGLE_FONT_FALLBACKS;\n return cachedGoogleFonts;\n }\n const raw = await response.text();\n const jsonText = stripGoogleJsonGuard(raw);\n const families = parseGoogleFontMetadata(JSON.parse(jsonText));\n cachedGoogleFonts = families.length > 0 ? families : GOOGLE_FONT_FALLBACKS;\n } catch {\n cachedGoogleFonts = GOOGLE_FONT_FALLBACKS;\n } finally {\n clearTimeout(timer);\n }\n\n return cachedGoogleFonts;\n}\n\nexport function registerFontRoutes(api: Hono): void {\n api.get(\"/fonts\", (c) => c.json({ fonts: listInstalledFontFamilies() }));\n api.get(\"/fonts/google\", async (c) => c.json({ fonts: await listGoogleFontFamilies() }));\n\n // fallow-ignore-next-line complexity\n api.get(\"/fonts/file\", (c) => {\n const family = c.req.query(\"family\");\n if (!family) return c.json({ error: \"family parameter required\" }, 400);\n\n const located = locateSystemFont(family);\n if (!located) return c.json({ error: \"font not found\" }, 404);\n\n let fd: number;\n try {\n fd = openSync(located.path, constants.O_RDONLY | constants.O_NOFOLLOW);\n } catch {\n return c.json({ error: \"font file not accessible\" }, 404);\n }\n try {\n const stat = fstatSync(fd);\n if (stat.size > SYSTEM_FONT_SIZE_LIMIT) {\n return c.json({ error: \"font file too large\" }, 413);\n }\n const buffer = Buffer.alloc(stat.size);\n readSync(fd, buffer, 0, stat.size, 0);\n const mimeType =\n located.format === \"otf\"\n ? \"font/otf\"\n : located.format === \"woff2\"\n ? \"font/woff2\"\n : located.format === \"woff\"\n ? \"font/woff\"\n : located.format === \"ttc\"\n ? \"font/collection\"\n : \"font/ttf\";\n\n const fileName = `${family.replace(/[^a-zA-Z0-9 -]/g, \"\")}.${located.format}`;\n return new Response(buffer, {\n headers: {\n \"Content-Type\": mimeType,\n \"Content-Disposition\": `attachment; filename=\"${fileName}\"`,\n },\n });\n } catch {\n return c.json({ error: \"failed to read font file\" }, 500);\n } finally {\n closeSync(fd);\n }\n });\n}\n","import type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { projectDirMissing } from \"../helpers/projectDirMissing.js\";\nimport { folderGone, isProjectRootMissing } from \"../helpers/safePath.js\";\n\nexport function registerRegistryRoutes(api: Hono, adapter: StudioApiAdapter): void {\n api.get(\"/registry/blocks\", async (c) => {\n if (!adapter.listRegistryCatalog) {\n return c.json({ error: \"Registry not available\" }, 501);\n }\n const items = await adapter.listRegistryCatalog();\n return c.json(items);\n });\n\n // fallow-ignore-next-line complexity\n api.post(\"/projects/:id/registry/install\", async (c) => {\n if (!adapter.installRegistryBlock) {\n return c.json({ error: \"Installing catalog items needs hyperframes preview\" }, 501);\n }\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"Project not found\" }, 404);\n if (folderGone(project.dir)) return projectDirMissing(c);\n\n const body = await c.req.json<{ blockName?: string }>().catch(() => null);\n if (!body?.blockName) {\n return c.json({ error: \"blockName is required\" }, 400);\n }\n\n try {\n const result = await adapter.installRegistryBlock({ project, blockName: body.blockName });\n return c.json(result);\n } catch (err) {\n if (isProjectRootMissing(err)) return projectDirMissing(c);\n const message = err instanceof Error ? err.message : \"Install failed\";\n return c.json({ error: message }, 500);\n }\n });\n}\n","import type { Hono } from \"hono\";\nimport type {\n StudioApiAdapter,\n StudioSelectionResponse,\n StudioSelectionSnapshot,\n} from \"../types.js\";\n\ninterface StoredSelection {\n selection: StudioSelectionSnapshot;\n updatedAt: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return isRecord(value) && Object.values(value).every((v) => typeof v === \"string\");\n}\n\nfunction hasString(value: Record<string, unknown>, key: string): boolean {\n return typeof value[key] === \"string\";\n}\n\nfunction hasRequiredStrings(value: Record<string, unknown>, keys: string[]): boolean {\n return keys.every((key) => hasString(value, key));\n}\n\nfunction hasOptionalString(value: Record<string, unknown>, key: string): boolean {\n return value[key] === undefined || typeof value[key] === \"string\";\n}\n\nfunction hasOptionalNullableString(value: Record<string, unknown>, key: string): boolean {\n return value[key] == null || typeof value[key] === \"string\";\n}\n\nfunction hasOptionalNumber(value: Record<string, unknown>, key: string): boolean {\n return value[key] === undefined || isFiniteNumber(value[key]);\n}\n\nfunction isBoundingBox(value: unknown): value is StudioSelectionSnapshot[\"boundingBox\"] {\n return (\n isRecord(value) && [\"x\", \"y\", \"width\", \"height\"].every((key) => isFiniteNumber(value[key]))\n );\n}\n\nfunction isTarget(value: unknown): value is StudioSelectionSnapshot[\"target\"] {\n if (!isRecord(value)) return false;\n return (\n hasOptionalNullableString(value, \"id\") &&\n hasOptionalString(value, \"hfId\") &&\n hasOptionalString(value, \"selector\") &&\n hasOptionalNumber(value, \"selectorIndex\")\n );\n}\n\nfunction isTextField(value: unknown): value is StudioSelectionSnapshot[\"textFields\"][number] {\n return (\n isRecord(value) &&\n hasRequiredStrings(value, [\"key\", \"label\", \"value\", \"tagName\"]) &&\n [\"self\", \"child\", \"text-node\"].includes(value.source as string)\n );\n}\n\nfunction isTextFields(value: unknown): value is StudioSelectionSnapshot[\"textFields\"] {\n return Array.isArray(value) && value.every(isTextField);\n}\n\nfunction isSelectionSnapshot(value: unknown): value is StudioSelectionSnapshot {\n if (!isRecord(value)) return false;\n\n const checks = [\n value.schemaVersion === 1 &&\n hasRequiredStrings(value, [\n \"projectId\",\n \"compositionPath\",\n \"sourceFile\",\n \"label\",\n \"tagName\",\n \"thumbnailUrl\",\n ]),\n isFiniteNumber(value.currentTime),\n isTarget(value.target),\n isBoundingBox(value.boundingBox),\n value.textContent === null || typeof value.textContent === \"string\",\n isStringRecord(value.dataAttributes),\n isStringRecord(value.inlineStyles),\n isStringRecord(value.computedStyles),\n isTextFields(value.textFields),\n isRecord(value.capabilities),\n ];\n\n return checks.every(Boolean);\n}\n\nexport function registerSelectionRoutes(api: Hono, adapter: StudioApiAdapter): void {\n const selections = new Map<string, StoredSelection>();\n\n api.get(\"/projects/:id/selection\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n const stored = selections.get(project.id);\n return c.json({\n selection: stored?.selection ?? null,\n updatedAt: stored?.updatedAt ?? null,\n } satisfies StudioSelectionResponse);\n });\n\n api.put(\"/projects/:id/selection\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"invalid json\" }, 400);\n }\n if (!isRecord(body) || !(\"selection\" in body)) {\n return c.json({ error: \"missing selection\" }, 400);\n }\n\n if (body.selection === null) {\n selections.delete(project.id);\n return c.json({ ok: true, selection: null, updatedAt: null });\n }\n\n if (!isSelectionSnapshot(body.selection)) {\n return c.json({ error: \"invalid selection\" }, 400);\n }\n\n const selection = { ...body.selection, projectId: project.id };\n const updatedAt = new Date().toISOString();\n selections.set(project.id, { selection, updatedAt });\n return c.json({ ok: true, selection, updatedAt });\n });\n}\n","import type { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport { existsSync } from \"node:fs\";\nimport { basename, dirname, extname, join, posix } from \"node:path\";\nimport type { MediaProcessingJobState, StudioApiAdapter } from \"../types.js\";\nimport { requestedProjectPath } from \"../helpers/requestSubPath.js\";\nimport { mkdirWithinProject, pinWithinProject, resolveWithinProject } from \"../helpers/safePath.js\";\nimport { probeMediaMetadata } from \"../helpers/mediaMetadata.js\";\n\nconst VIDEO_EXTENSIONS = new Set([\n \".mp4\",\n \".mov\",\n \".webm\",\n \".mkv\",\n \".avi\",\n \".m4v\",\n \".mxf\",\n \".mts\",\n \".m2ts\",\n \".ts\",\n]);\nconst IMAGE_EXTENSIONS = new Set([\".jpg\", \".jpeg\", \".png\", \".webp\"]);\nconst VIDEO_OUTPUT_EXTENSIONS = new Set([\".webm\", \".mov\"]);\nconst QUALITIES = new Set([\"fast\", \"balanced\", \"best\"]);\nconst DEVICES = new Set([\"auto\", \"cpu\", \"coreml\", \"cuda\"]);\n\ntype BackgroundRemovalQuality = \"fast\" | \"balanced\" | \"best\";\ntype BackgroundRemovalDevice = \"auto\" | \"cpu\" | \"coreml\" | \"cuda\";\n\ninterface BackgroundRemovalBody {\n inputPath?: string;\n outputPath?: string;\n createBackgroundPlate?: boolean;\n quality?: string;\n device?: string;\n}\n\ntype JobWithCreatedAt = MediaProcessingJobState & { createdAt: number };\ntype ProbeMediaMetadata = typeof probeMediaMetadata;\n\nfunction isVideoPath(path: string): boolean {\n return VIDEO_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\nfunction isImagePath(path: string): boolean {\n return IMAGE_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\nfunction containsNullByte(path: string): boolean {\n return path.includes(\"\\0\");\n}\n\nfunction slugFileBase(path: string): string {\n const name = basename(path, extname(path))\n .replace(/[^a-zA-Z0-9._-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return name || \"media\";\n}\n\nfunction uniqueAssetPath(\n projectDir: string,\n assetPath: string,\n taken: ReadonlySet<string>,\n): string {\n const ext = extname(assetPath);\n const withoutExt = assetPath.slice(0, -ext.length);\n let candidate = assetPath;\n for (let index = 2; taken.has(candidate) || existsSync(join(projectDir, candidate)); index++) {\n candidate = `${withoutExt}-${index}${ext}`;\n }\n return candidate;\n}\n\nfunction defaultOutputPath(\n projectDir: string,\n inputPath: string,\n taken: ReadonlySet<string>,\n): string {\n const ext = isImagePath(inputPath) ? \".png\" : \".webm\";\n return uniqueAssetPath(\n projectDir,\n `assets/cutouts/${slugFileBase(inputPath)}-cutout${ext}`,\n taken,\n );\n}\n\nfunction defaultPlatePath(\n projectDir: string,\n inputPath: string,\n taken: ReadonlySet<string>,\n): string {\n return uniqueAssetPath(projectDir, `assets/cutouts/${slugFileBase(inputPath)}-plate.webm`, taken);\n}\n\nfunction outputsInFlight(mediaJobs: Map<string, JobWithCreatedAt>): Set<string> {\n const running = [...mediaJobs.values()].filter((job) => job.status === \"processing\");\n return new Set(\n running.flatMap((job) => [job.outputAssetPath, job.backgroundOutputAssetPath ?? \"\"]),\n );\n}\n\nfunction makeJobId(projectId: string, mediaJobs: Map<string, JobWithCreatedAt>): string {\n const stamp = new Date()\n .toISOString()\n .replace(/[-:.TZ]/g, \"\")\n .slice(0, 14);\n const safeProject = projectId.replace(/[^a-zA-Z0-9_-]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n const base = `${safeProject || \"project\"}_remove-bg_${stamp}`;\n if (!mediaJobs.has(base)) return base;\n for (let index = 2; ; index++) {\n const candidate = `${base}-${index}`;\n if (!mediaJobs.has(candidate)) return candidate;\n }\n}\n\nfunction normalizeQuality(value: string | undefined): BackgroundRemovalQuality {\n return QUALITIES.has(value ?? \"\") ? (value as BackgroundRemovalQuality) : \"balanced\";\n}\n\nfunction normalizeDevice(value: string | undefined): BackgroundRemovalDevice {\n return DEVICES.has(value ?? \"\") ? (value as BackgroundRemovalDevice) : \"auto\";\n}\n\nexport function registerMediaRoutes(\n api: Hono,\n adapter: StudioApiAdapter,\n options: { probeMediaMetadata?: ProbeMediaMetadata } = {},\n): void {\n const mediaJobs = new Map<string, JobWithCreatedAt>();\n const TTL_MS = 300_000;\n const readMediaMetadata = options.probeMediaMetadata ?? probeMediaMetadata;\n\n function cleanupFinishedJobs(): void {\n const now = Date.now();\n for (const [id, job] of mediaJobs) {\n if ((job.status === \"complete\" || job.status === \"failed\") && now - job.createdAt > TTL_MS) {\n mediaJobs.delete(id);\n }\n }\n }\n\n api.get(\"/projects/:id/media/metadata\", async (c) => {\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const assetPath = requestedProjectPath(project.dir, c.req.query(\"path\") ?? \"\");\n if (!assetPath) return c.json({ error: \"path required\" }, 400);\n if (containsNullByte(assetPath)) return c.json({ error: \"forbidden\" }, 403);\n if (/^(?:https?:|data:|blob:)/i.test(assetPath)) {\n return c.json({ error: \"media metadata requires a project-local asset\" }, 400);\n }\n\n const filePath = resolveWithinProject(project.dir, assetPath);\n if (!filePath) return c.json({ error: \"forbidden\" }, 403);\n if (!existsSync(filePath)) return c.json({ error: \"media not found\" }, 404);\n\n return c.json({ path: assetPath, metadata: await readMediaMetadata(filePath) });\n });\n\n api.post(\n \"/projects/:id/media/remove-background\",\n // fallow-ignore-next-line complexity\n async (c) => {\n cleanupFinishedJobs();\n if (!adapter.startBackgroundRemoval) {\n return c.json({ error: \"background removal is not available in this Studio server\" }, 501);\n }\n\n // fallow-ignore-next-line code-duplication\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n const body = (await c.req.json().catch(() => ({}))) as BackgroundRemovalBody;\n const inputAssetPath = body.inputPath\n ? requestedProjectPath(project.dir, body.inputPath)\n : \"\";\n if (!inputAssetPath) return c.json({ error: \"inputPath required\" }, 400);\n if (containsNullByte(inputAssetPath)) return c.json({ error: \"forbidden\" }, 403);\n if (/^(?:https?:|data:|blob:)/i.test(inputAssetPath)) {\n return c.json({ error: \"background removal requires a project-local media asset\" }, 400);\n }\n\n const inputPath = resolveWithinProject(project.dir, inputAssetPath);\n if (!inputPath) return c.json({ error: \"forbidden\" }, 403);\n if (!existsSync(inputPath)) return c.json({ error: \"input media not found\" }, 404);\n\n const inputIsVideo = isVideoPath(inputAssetPath);\n const inputIsImage = isImagePath(inputAssetPath);\n if (!inputIsVideo && !inputIsImage) {\n return c.json({ error: \"background removal supports video or image assets only\" }, 400);\n }\n\n const requestedOutput = body.outputPath\n ? posix.normalize(requestedProjectPath(project.dir, body.outputPath))\n : \"\";\n if (requestedOutput && containsNullByte(requestedOutput)) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n if (requestedOutput && !resolveWithinProject(project.dir, requestedOutput)) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n const taken = outputsInFlight(mediaJobs);\n const outputAssetPath = requestedOutput\n ? uniqueAssetPath(project.dir, requestedOutput, taken)\n : defaultOutputPath(project.dir, inputAssetPath, taken);\n const outputPath = pinWithinProject(project.dir, outputAssetPath);\n if (!outputPath) return c.json({ error: \"forbidden\" }, 403);\n if (inputIsVideo && !VIDEO_OUTPUT_EXTENSIONS.has(extname(outputAssetPath).toLowerCase())) {\n return c.json({ error: \"video background removal output must be .webm or .mov\" }, 400);\n }\n if (inputIsImage && extname(outputAssetPath).toLowerCase() !== \".png\") {\n return c.json({ error: \"image background removal output must be .png\" }, 400);\n }\n\n let backgroundOutputAssetPath: string | undefined;\n let backgroundOutputPath: string | undefined;\n if (body.createBackgroundPlate) {\n if (!inputIsVideo) {\n return c.json({ error: \"background plates are only supported for video inputs\" }, 400);\n }\n taken.add(outputAssetPath);\n backgroundOutputAssetPath = defaultPlatePath(project.dir, inputAssetPath, taken);\n backgroundOutputPath =\n pinWithinProject(project.dir, backgroundOutputAssetPath) ?? undefined;\n if (!backgroundOutputPath) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n }\n\n mkdirWithinProject(project.dir, dirname(outputPath));\n if (backgroundOutputPath) mkdirWithinProject(project.dir, dirname(backgroundOutputPath));\n\n const jobId = makeJobId(project.id, mediaJobs);\n const state = adapter.startBackgroundRemoval({\n project,\n inputPath,\n inputAssetPath,\n outputPath,\n outputAssetPath,\n backgroundOutputPath,\n backgroundOutputAssetPath,\n quality: normalizeQuality(body.quality),\n device: normalizeDevice(body.device),\n jobId,\n }) as JobWithCreatedAt;\n state.createdAt = Date.now();\n mediaJobs.set(jobId, state);\n\n return c.json({\n jobId,\n status: state.status,\n outputPath: outputAssetPath,\n backgroundOutputPath: backgroundOutputAssetPath,\n });\n },\n );\n\n api.get(\"/media-jobs/:jobId/progress\", (c) => {\n cleanupFinishedJobs();\n const { jobId } = c.req.param();\n const job = mediaJobs.get(jobId);\n if (!job) return c.json({ error: \"not found\" }, 404);\n\n return streamSSE(c, async (stream) => {\n while (true) {\n const current = mediaJobs.get(jobId);\n if (!current) break;\n await stream.writeSSE({\n event: \"progress\",\n data: JSON.stringify({\n id: current.id,\n status: current.status,\n progress: current.progress,\n stage: current.stage,\n outputPath: current.outputAssetPath,\n backgroundOutputPath: current.backgroundOutputAssetPath,\n error: current.error,\n provider: current.provider,\n framesProcessed: current.framesProcessed,\n durationSeconds: current.durationSeconds,\n avgMsPerFrame: current.avgMsPerFrame,\n }),\n });\n if (current.status === \"complete\" || current.status === \"failed\") break;\n await stream.sleep(500);\n }\n });\n });\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Hono } from \"hono\";\n\n// Non-project-scoped route: the media-use global asset cache (~/.media). Lets the\n// Studio Asset tab show assets resolved in OTHER projects (cross-project reuse).\n// Reads ONLY the global manifest — no path params, no arbitrary fs access.\n\nexport interface GlobalAssetRecord {\n id?: string;\n type?: string;\n description?: string;\n sha?: string;\n cached_path?: string;\n entity?: string;\n}\n\n/** Parse the global manifest (~/.media/manifest.jsonl) into reusable records. */\nexport function readGlobalAssets(home = homedir()): GlobalAssetRecord[] {\n const manifestPath = join(home, \".media\", \"manifest.jsonl\");\n if (!existsSync(manifestPath)) return [];\n const out: GlobalAssetRecord[] = [];\n for (const line of readFileSync(manifestPath, \"utf8\").split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const rec = JSON.parse(line);\n if (rec && rec.reusable) out.push(rec);\n } catch {\n // skip malformed lines — a torn write shouldn't 500 the panel\n }\n }\n return out;\n}\n\n// Fields the Studio panel actually renders. Deliberately omits cached_path —\n// an absolute ~/.media filesystem path has no business reaching the browser (m13).\nexport function toPublicAsset(r: GlobalAssetRecord): GlobalAssetRecord {\n return { id: r.id, type: r.type, description: r.description, sha: r.sha, entity: r.entity };\n}\n\nexport function registerGlobalAssetRoutes(api: Hono): void {\n api.get(\"/assets/global\", (c) => c.json({ assets: readGlobalAssets().map(toPublicAsset) }));\n}\n","import type { Context, Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { createWriteToken } from \"../helpers/fileVersion.js\";\nimport {\n MAX_WINDOW_IDLE_MS,\n UNDO_MODES,\n type HistoryWindow,\n type ProjectHistory,\n} from \"../history/projectHistory.js\";\nimport type { HistoryWho } from \"../history/historyLog.js\";\n\nconst YOU: HistoryWho = { kind: \"person\", name: \"You\" };\n\nasync function historyOf(adapter: StudioApiAdapter, c: Context): Promise<ProjectHistory | null> {\n const project = await adapter.resolveProject(c.req.param(\"id\") ?? \"\");\n return project ? ((await adapter.history?.(project)) ?? null) : null;\n}\n\nasync function bodyOf(c: Context): Promise<Record<string, unknown>> {\n const body = await c.req.json().catch(() => null);\n return body && typeof body === \"object\" ? (body as Record<string, unknown>) : {};\n}\n\nconst text = (value: unknown) => (typeof value === \"string\" && value ? value : null);\n\n/** Studio's write token, so the watcher's echo of an undo reads as Studio's own write. */\nfunction writing(c: Context): { writeToken?: string } {\n const header = c.req.header(\"X-Hyperframes-Write-Token\");\n return header ? { writeToken: createWriteToken(header) } : {};\n}\n\n/** An agent names itself (`who: {kind: \"agent\", name}`); anyone else is the person at Studio. */\nfunction whoOf(body: Record<string, unknown>): HistoryWho {\n const who = body.who as { kind?: unknown; name?: unknown } | undefined;\n const name = text(who?.name);\n return who?.kind === \"agent\" && name ? { kind: \"agent\", name } : YOU;\n}\n\n/** How long a window or a coalescing claim may wait for its next write; past the cap a timer overflows. */\nfunction idleOf(body: Record<string, unknown>): number | undefined {\n const idleMs = body.idleMs;\n return typeof idleMs === \"number\" && idleMs > 0\n ? Math.min(idleMs, MAX_WINDOW_IDLE_MS)\n : undefined;\n}\n\n/** `{ [path]: version }` from a request body, keeping only string pairs. */\nfunction versionsOf(value: unknown): Record<string, string> | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const pairs = Object.entries(value).filter(\n (pair): pair is [string, string] => typeof pair[1] === \"string\",\n );\n return pairs.length ? Object.fromEntries(pairs) : undefined;\n}\n\n/** What Cmd+Z or Cmd+Shift+Z would revert next, so Studio can name it on its buttons. */\nfunction nextStep(history: ProjectHistory, direction: \"back\" | \"forward\") {\n const target = history.next(direction, YOU);\n if (!target) return null;\n const paths = target.files.map((file) => file.path);\n return { id: target.id, label: target.label, endedAt: target.endedAt, paths };\n}\n\n/** Runs `task` on the project's history; no history is a 404, an engine refusal (\"no longer kept\") a 409. */\nasync function withHistory(\n adapter: StudioApiAdapter,\n c: Context,\n task: (history: ProjectHistory, body: Record<string, unknown>) => Promise<unknown> | unknown,\n) {\n const history = await historyOf(adapter, c);\n if (!history) return c.json({ error: \"This project has no history here.\" }, 404);\n try {\n return c.json((await task(history, await bodyOf(c))) ?? null);\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n}\n\n/** Studio's history: list, Cmd+Z and Shift+Z, undo with the conflict choice, restore, peek, pin, edit windows. */\nexport function registerHistoryRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // ponytail: a window whose close never arrives ends itself when idle; its entry here stays until the server stops.\n const windows = new Map<string, { history: ProjectHistory; window: HistoryWindow }>();\n const base = \"/projects/:id/history\";\n\n api.get(base, (c) =>\n withHistory(adapter, c, (history) => {\n const entries = history.list();\n return { entries, back: nextStep(history, \"back\"), forward: nextStep(history, \"forward\") };\n }),\n );\n api.post(`${base}/step`, (c) =>\n withHistory(adapter, c, (history, body) =>\n history.step(body.direction === \"forward\" ? \"forward\" : \"back\", YOU, writing(c)),\n ),\n );\n api.post(`${base}/undo`, (c) =>\n withHistory(adapter, c, (history, body) => {\n const mode = UNDO_MODES.find((known) => known === body.mode);\n return history.undo(text(body.entryId) ?? \"\", { who: whoOf(body), mode, ...writing(c) });\n }),\n );\n api.post(`${base}/restore`, (c) =>\n withHistory(adapter, c, (history, body) =>\n history.restore(text(body.point) ?? \"\", whoOf(body), writing(c)),\n ),\n );\n api.get(`${base}/peek/:point`, (c) =>\n withHistory(adapter, c, (history) => ({ files: history.peek(c.req.param(\"point\")) })),\n );\n api.post(`${base}/pin`, (c) =>\n withHistory(adapter, c, (history, body) => {\n history.pin(text(body.entryId) ?? \"\", body.pinned === true);\n return { ok: true };\n }),\n );\n api.get(`${base}/blob/:hash`, async (c) => {\n const history = await historyOf(adapter, c);\n const hash = c.req.param(\"hash\") ?? \"\";\n const missing = () =>\n c.json({ error: \"That file is not kept in this project's history.\" }, 404);\n if (!history || !/^[0-9a-f]{64}$/.test(hash)) return missing();\n const bytes = await history.readBlob(hash).catch(() => null);\n return bytes ? c.body(new Uint8Array(bytes)) : missing();\n });\n // Studio records after it writes, under the edit's label; a gesture with no idleMs holds until another key.\n api.post(`${base}/claim`, (c) =>\n withHistory(adapter, c, async (history, body) => {\n const paths = Array.isArray(body.paths) ? body.paths.filter((path) => text(path)) : [];\n const coalesceKey = text(body.coalesceKey) ?? undefined;\n const overwrote = versionsOf(body.overwrote);\n const claimed = await history.claim(YOU, text(body.label) ?? \"Edited in Studio\", paths, {\n ...(coalesceKey && { coalesceKey, idleMs: idleOf(body) ?? Infinity }),\n ...(overwrote && { overwrote }),\n });\n return { claimed };\n }),\n );\n api.post(`${base}/window`, (c) =>\n withHistory(adapter, c, async (history, body) => {\n const idleMs = idleOf(body);\n const window = await history.beginWindow(\n whoOf(body),\n text(body.label) ?? \"Edited in Studio\",\n idleMs ? { idleMs } : undefined,\n );\n windows.set(window.id, { history, window });\n // The window's id is its last entry's id, unless nothing was left after its last part.\n return { windowId: window.id, startedAt: window.startedAt };\n }),\n );\n api.post(`${base}/window/:windowId/close`, (c) =>\n withHistory(adapter, c, async (history) => {\n const id = c.req.param(\"windowId\") ?? \"\";\n const held = windows.get(id);\n if (held?.history !== history) throw new Error(\"That window is not open in this project.\");\n windows.delete(id);\n return { entry: await held.window.close() };\n }),\n );\n}\n","import { sameInstant } from \"@hyperframes/core/clip-facts\";\nimport { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport {\n findTargetElement,\n dedupeClonedCompositionId,\n isHTMLElement,\n nextUniqueId,\n parseSourceDocument,\n type SourceMutationTarget,\n} from \"./sourceMutation.js\";\n\nexport interface DuplicateElementResult {\n html: string;\n matched: boolean;\n newId: string | null;\n}\n\nexport function duplicateElementInHtml(\n source: string,\n target: SourceMutationTarget,\n newId: string,\n at: number,\n): DuplicateElementResult {\n const { document, wrappedFragment } = parseSourceDocument(source);\n const element = findTargetElement(document, target);\n if (!element || !element.parentElement) return { html: source, matched: false, newId: null };\n const duration = numericAttribute(element, \"data-duration\");\n const track = numericAttribute(element, \"data-track-index\") ?? 0;\n if (duration === null || numericAttribute(element, \"data-start\") === null) {\n return { html: source, matched: false, newId: null };\n }\n const uniqueId = nextUniqueId(document, newId);\n rippleElements(document, element, at, duration, track);\n const clone = element.cloneNode(true);\n if (!isHTMLElement(clone)) return { html: source, matched: false, newId: null };\n clone.setAttribute(\"id\", uniqueId);\n dedupeClonedCompositionId(document, clone);\n stripStableIds(clone);\n clone.setAttribute(\"data-start\", String(at));\n element.parentElement.insertBefore(clone, element.nextSibling);\n const html = wrappedFragment ? document.body.innerHTML || \"\" : document.toString();\n return { html: ensureHfIds(html), matched: true, newId: uniqueId };\n}\n\nfunction rippleElements(\n document: Document,\n element: Element,\n at: number,\n duration: number,\n track: number,\n): void {\n for (const candidate of Array.from(document.querySelectorAll(\"[data-start][data-duration]\"))) {\n if (candidate === element || candidate.getAttribute(\"data-track-index\") !== String(track)) {\n continue;\n }\n const start = numericAttribute(candidate, \"data-start\");\n if (start === null) continue;\n const metInsertionPoint = sameInstant(start, at);\n if (start < at && !metInsertionPoint) continue;\n candidate.setAttribute(\"data-start\", String((metInsertionPoint ? at : start) + duration));\n }\n}\n\nfunction stripStableIds(element: Element): void {\n element.removeAttribute(\"data-hf-id\");\n for (const child of Array.from(element.querySelectorAll(\"[data-hf-id]\"))) {\n child.removeAttribute(\"data-hf-id\");\n }\n}\n\nfunction numericAttribute(element: Element, name: string): number | null {\n const value = Number(element.getAttribute(name));\n return Number.isFinite(value) ? value : null;\n}\n","import { createHash } from \"node:crypto\";\nimport { readFileSync, readdirSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\nimport { mkdirWithinProject } from \"./safePath.js\";\nimport type { PreviewDocumentStore } from \"./mediaProxyPreview.js\";\n\n/** One built preview document under the project's `.hyperframes/preview`. `salt` names the server build, so new\n * code never reads a document an older build wrote. A failed read or write only costs a rebuild. */\nexport function createPreviewDocumentStore(projectDir: string, salt: string): PreviewDocumentStore {\n const dir = join(projectDir, \".hyperframes\", \"preview\");\n const fileFor = (key: string) =>\n join(dir, `${createHash(\"sha256\").update(`${salt}\\n${key}`).digest(\"hex\").slice(0, 32)}.html`);\n return {\n read(key) {\n try {\n return readFileSync(fileFor(key), \"utf-8\");\n } catch {\n return null;\n }\n },\n write(key, html) {\n try {\n mkdirWithinProject(projectDir, dir);\n const file = fileFor(key);\n replaceFileAtomically(file, html, 0o644);\n for (const name of readdirSync(dir)) {\n if (join(dir, name) !== file) rmSync(join(dir, name), { force: true });\n }\n } catch {\n // A document that fails to persist is rebuilt on the next open.\n }\n },\n };\n}\n","export interface ThumbnailOutputDimensions {\n width: number;\n height: number;\n outputWidth: number;\n outputHeight: number;\n}\n\n/** Sole adapter rule for capturing authored layout at bounded physical dimensions. */\nexport function thumbnailDeviceScaleFactor({\n width,\n height,\n outputWidth,\n outputHeight,\n}: ThumbnailOutputDimensions): number {\n const dimensions = [width, height, outputWidth, outputHeight];\n if (dimensions.some((value) => !Number.isFinite(value) || value <= 0)) {\n throw new RangeError(\"Thumbnail dimensions must be positive finite numbers\");\n }\n return Math.min(1, outputWidth / width, outputHeight / height);\n}\n","import type { MediaProcessingJobState, StudioApiAdapter } from \"../types.js\";\n\nexport type BackgroundRemovalJobOptions = Parameters<\n NonNullable<StudioApiAdapter[\"startBackgroundRemoval\"]>\n>[0];\n\nexport type BackgroundRemovalProgressEvent =\n | { kind: \"info\"; message: string }\n | { kind: \"metadata\"; width: number; height: number; fps: number; frameCount: number }\n | { kind: \"frame\"; index: number; total: number; avgMsPerFrame: number };\n\nexport type BackgroundRemovalRender = (options: {\n inputPath: string;\n outputPath: string;\n backgroundOutputPath?: string;\n device?: BackgroundRemovalJobOptions[\"device\"];\n quality?: BackgroundRemovalJobOptions[\"quality\"];\n onProgress?: (event: BackgroundRemovalProgressEvent) => void;\n}) => Promise<{\n provider: string;\n framesProcessed: number;\n durationSeconds: number;\n avgMsPerFrame: number;\n}>;\n\nexport function createBackgroundRemovalJob(\n opts: BackgroundRemovalJobOptions,\n render: BackgroundRemovalRender,\n): MediaProcessingJobState {\n const state: MediaProcessingJobState = {\n id: opts.jobId,\n status: \"processing\",\n progress: 0,\n stage: \"Preparing background removal\",\n inputAssetPath: opts.inputAssetPath,\n outputAssetPath: opts.outputAssetPath,\n outputPath: opts.outputPath,\n ...(opts.backgroundOutputPath ? { backgroundOutputPath: opts.backgroundOutputPath } : {}),\n ...(opts.backgroundOutputAssetPath\n ? { backgroundOutputAssetPath: opts.backgroundOutputAssetPath }\n : {}),\n };\n\n void (async () => {\n try {\n const result = await render({\n inputPath: opts.inputPath,\n outputPath: opts.outputPath,\n backgroundOutputPath: opts.backgroundOutputPath,\n device: opts.device,\n quality: opts.quality,\n onProgress: (event) => updateBackgroundRemovalProgress(state, event),\n });\n state.status = \"complete\";\n state.progress = 100;\n state.stage = \"Complete\";\n state.provider = result.provider;\n state.framesProcessed = result.framesProcessed;\n state.durationSeconds = result.durationSeconds;\n state.avgMsPerFrame = result.avgMsPerFrame;\n } catch (err) {\n state.status = \"failed\";\n state.error = err instanceof Error ? err.message : String(err);\n state.stage = \"Failed\";\n }\n })();\n\n return state;\n}\n\nfunction updateBackgroundRemovalProgress(\n state: MediaProcessingJobState,\n event: BackgroundRemovalProgressEvent,\n): void {\n if (event.kind === \"info\") {\n state.stage = event.message;\n return;\n }\n if (event.kind === \"metadata\") {\n state.stage = `Source ${event.width}×${event.height}`;\n state.progress = 2;\n return;\n }\n state.progress = event.total ? Math.min(99, Math.floor((event.index / event.total) * 100)) : 0;\n state.stage = event.total\n ? `Removing background ${event.index}/${event.total}`\n : `Removing background frame ${event.index}`;\n state.framesProcessed = event.index;\n state.avgMsPerFrame = event.avgMsPerFrame;\n}\n"],"mappings":"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","names":["existsSync","lstatSync","readFileSync","unlinkSync","rmSync","statSync","renameSync","readdirSync","resolve","dirname","join","sep","readFileSync","parseHTML","join","existsSync","parseHTML","parseHTML","existsSync","readFileSync","parseHTML","text","replaceFileAtomically","existsSync","dirname","join","mkdtempSync","rmSync","writeFileSync","join","findFfBinary","readFileSync","writeFileSync","Buffer","join","relative","Buffer","relative","readFileSync","join","writeFileSync","readFileSync","statSync","statSync","readFileSync","parseHTML","dirname","lstatSync","resolve","statSync","existsSync","readFileSync","join","replaceFileAtomically","readdirSync","text","sep","pattern","parseHTML","round3","targetSelector","updateAnimationInScript","addAnimationToScript","removeAnimationFromScript","addKeyframeToScript","removeKeyframeFromScript","moveKeyframeInScript","resizeKeyframedTweenInScript","updateKeyframeInScript","removeAllKeyframesFromScript","unrollDynamicAnimations","setArcPathInScript","updateArcSegmentInScript","updateMotionPathPointInScript","addMotionPathPointInScript","removeMotionPathPointInScript","addMotionPathToScript","removeArcPathFromScript","addAnimationWithKeyframesToScript","splitAnimationsInScript","dedupePositionWritesInScript","stat","rmSync","unlinkSync","currentVersion","version","renameSync","parseHTML","existsSync","readFileSync","statSync","join","resolve","createHash","RUNTIME_BOOTSTRAP_ATTR","insertBeforeCloseTag","stripEmbeddedRuntimeScripts","gsapCdnDist","findStartTags","ensureHfIds","readlinkSync","dirname","join","relative","resolve","parseHTML","resolve","join","relative","readlinkSync","dirname","text","parseHTML","parseHTML","gsapCdnDist","insertBeforeCloseTag","join","existsSync","readFileSync","RUNTIME_BOOTSTRAP_ATTR","stripEmbeddedRuntimeScripts","parseHTML","findStartTags","createHash","parse","ensureHfIds","statSync","resolve","stat","readFileSync","join","readFileSync","join","existsSync","lstatSync","readFileSync","unlinkSync","readdirSync","statSync","dirname","join","existsSync","join","lstatSync","readFileSync","dirname","unlinkSync","readdirSync","stat","statSync","createHash","resolve","relative","createHash","closeSync","fstatSync","openSync","readFileSync","readdirSync","renameSync","rmSync","statSync","unlinkSync","writeFileSync","join","createHash","randomUUID","readdirSync","join","statSync","rmSync","unlinkSync","randomUUID","writeFileSync","renameSync","openSync","stat","fstatSync","readFileSync","closeSync","createHash","existsSync","readFileSync","statSync","join","resolve","isWithinProjectRoot","resolve","isWithinProjectRoot","statSync","join","existsSync","peaks","readFileSync","readFileSync","rmSync","statSync","basename","dirname","join","relative","sep","findFfBinary","createFileAtomically","replaceFileAtomically","createHash","ensureHfIds","createHash","ensureHfIds","findFfBinary","readFileSync","createFileAtomically","basename","rmSync","dirname","relative","join","sep","replaceFileAtomically","statSync","existsSync","existsSync","existsSync","readFileSync","statSync","join","resolve","isWithinProjectRoot","execFile","spawn","findFfBinary","existsSync","readFileSync","resolve","isWithinProjectRoot","statSync","join","closeSync","fstatSync","openSync","isRecord","stat","isRecord","streamSSE","existsSync","basename","dirname","join","basename","existsSync","join","dirname","streamSSE","existsSync","readFileSync","join","ensureHfIds","ensureHfIds","createHash","readFileSync","readdirSync","rmSync","join","replaceFileAtomically","join","createHash","readFileSync","replaceFileAtomically","readdirSync","rmSync"]}
|