@hyperframes/studio-server 0.7.62 → 0.7.64

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/createStudioApi.ts","../src/routes/projects.ts","../src/helpers/safePath.ts","../src/helpers/projectSignature.ts","../src/routes/storyboard.ts","../src/routes/files.ts","../src/helpers/mime.ts","../src/helpers/waveform.ts","../src/helpers/mediaValidation.ts","../src/helpers/backupJournal.ts","../src/helpers/fileVersion.ts","../src/helpers/compositionInsertion.ts","../src/routes/preview.ts","../src/helpers/subComposition.ts","../src/helpers/hfIdPersist.ts","../src/helpers/variablesPayload.ts","../src/routes/lint.ts","../src/routes/render.ts","../src/routes/thumbnail.ts","../src/routes/waveform.ts","../src/routes/fonts.ts","../src/routes/registry.ts","../src/routes/selection.ts","../src/routes/media.ts","../src/routes/globalAssets.ts","../src/helpers/backgroundRemovalJob.ts"],"sourcesContent":["import { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"./types.js\";\nimport { registerProjectRoutes } from \"./routes/projects.js\";\nimport { registerStoryboardRoutes } from \"./routes/storyboard.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 { registerThumbnailRoutes } from \"./routes/thumbnail.js\";\nimport { registerWaveformRoutes } from \"./routes/waveform.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\";\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\n registerProjectRoutes(api, adapter);\n registerStoryboardRoutes(api, adapter);\n registerFileRoutes(api, adapter);\n registerPreviewRoutes(api, adapter);\n registerLintRoutes(api, adapter);\n registerRenderRoutes(api, adapter);\n registerThumbnailRoutes(api, adapter);\n registerSelectionRoutes(api, adapter);\n registerMediaRoutes(api, adapter);\n registerWaveformRoutes(api, adapter);\n registerFontRoutes(api);\n registerRegistryRoutes(api, adapter);\n registerGlobalAssetRoutes(api);\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, walkDir } from \"../helpers/safePath.js\";\nimport { resolveProjectSignature } from \"../helpers/projectSignature.js\";\n\nconst COMPOSITION_ID_RE = /data-composition-id\\s*=/;\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 COMPOSITION_ID_RE.test(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\n // that refresh themselves when files change on disk (the storyboard board\n // re-fetches when this differs from the signature its data was loaded with).\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);\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","import { join } from \"node:path\";\nimport { readdirSync } from \"node:fs\";\n\n// `isSafePath` lives at the package root so non-studio-api layers (compiler,\n// CLI, engine) can share it without a backwards dependency on studio-api.\n// Re-exported here for back-compat with existing `../helpers/safePath.js` imports.\nexport { isSafePath, resolveWithinProject } from \"@hyperframes/core\";\n\nconst IGNORE_DIRS = new Set([\".thumbnails\", \"node_modules\", \".git\"]);\n\nfunction shouldIgnoreDir(rel: string): boolean {\n return rel === \".hyperframes/backup\";\n}\n\n/**\n * True when any directory segment of a relative path is a dot-directory or\n * node_modules. Projects that vendor tooling assets under dot-directories\n * (.hyperframes/, .cache/, …) ship example/preset HTML that must not surface\n * as project compositions or studio lint targets (#1384). The file tree is\n * deliberately not filtered — this only gates discovery.\n */\nexport function isInHiddenOrVendorDir(relPath: string): boolean {\n const segments = relPath.split(\"/\");\n return segments.slice(0, -1).some((seg) => seg.startsWith(\".\") || seg === \"node_modules\");\n}\n\n/** Recursively walk a directory and return relative file paths. */\nexport function walkDir(dir: string, prefix = \"\"): string[] {\n const files: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (IGNORE_DIRS.has(entry.name) || shouldIgnoreDir(rel)) continue;\n if (entry.isDirectory()) {\n files.push(...walkDir(join(dir, entry.name), rel));\n } else {\n files.push(rel);\n }\n }\n return files;\n}\n","import { createHash } from \"node:crypto\";\nimport { lstatSync, readFileSync, readdirSync } from \"node:fs\";\nimport { extname, isAbsolute, relative, resolve } from \"node:path\";\nimport type { ResolvedProject, StudioApiAdapter } from \"../types.js\";\n\nconst SIGNATURE_TEXT_EXTENSIONS = new Set([\n \".cjs\",\n \".css\",\n \".html\",\n \".js\",\n \".json\",\n \".jsx\",\n \".mjs\",\n \".svg\",\n \".ts\",\n \".tsx\",\n]);\nconst SIGNATURE_EXCLUDED_DIRS = new Set([\n \".cache\",\n \".git\",\n \".hyperframes\",\n \".next\",\n \".vite\",\n \"build\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n \"outputs\",\n \"renders\",\n]);\nconst MAX_SIGNATURE_TEXT_BYTES = 2_000_000;\nconst STUDIO_SIGNATURE_MANIFEST_PATHS = [\n \".hyperframes/studio-manual-edits.json\",\n \".hyperframes/studio-motion.json\",\n] as const;\n\ninterface ProjectSignatureFile {\n file: string;\n mtimeMs: number;\n size: number;\n textContentEligible: boolean;\n}\n\ninterface ProjectSignatureCacheEntry {\n fingerprint: string;\n signature: string;\n}\n\nconst projectSignatureCache = new Map<string, ProjectSignatureCacheEntry>();\n\nfunction isPathWithin(parentDir: string, childPath: string): boolean {\n const childRelativePath = relative(parentDir, childPath);\n return (\n childRelativePath === \"\" ||\n (!childRelativePath.startsWith(\"..\") && !isAbsolute(childRelativePath))\n );\n}\n\nfunction isTextContentEligible(file: string, size: number): boolean {\n return (\n SIGNATURE_TEXT_EXTENSIONS.has(extname(file).toLowerCase()) && size <= MAX_SIGNATURE_TEXT_BYTES\n );\n}\n\nfunction collectProjectSignatureFiles(\n projectDir: string,\n dir: string,\n files: ProjectSignatureFile[],\n): void {\n let entries: string[];\n try {\n entries = readdirSync(dir).sort();\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (SIGNATURE_EXCLUDED_DIRS.has(entry)) continue;\n const file = resolve(dir, entry);\n if (!isPathWithin(projectDir, file)) continue;\n let stat: ReturnType<typeof lstatSync>;\n try {\n stat = lstatSync(file);\n } catch {\n continue;\n }\n if (stat.isSymbolicLink()) continue;\n if (stat.isDirectory()) {\n collectProjectSignatureFiles(projectDir, file, files);\n } else if (stat.isFile()) {\n files.push({\n file,\n mtimeMs: stat.mtimeMs,\n size: stat.size,\n textContentEligible: isTextContentEligible(file, stat.size),\n });\n }\n }\n}\n\nfunction collectProjectSignatureManifestFiles(\n projectDir: string,\n files: ProjectSignatureFile[],\n): void {\n const seen = new Set(files.map((entry) => entry.file));\n for (const manifestPath of STUDIO_SIGNATURE_MANIFEST_PATHS) {\n const file = resolve(projectDir, manifestPath);\n if (seen.has(file) || !isPathWithin(projectDir, file)) continue;\n let stat: ReturnType<typeof lstatSync>;\n try {\n stat = lstatSync(file);\n } catch {\n continue;\n }\n if (stat.isSymbolicLink() || !stat.isFile()) continue;\n files.push({\n file,\n mtimeMs: stat.mtimeMs,\n size: stat.size,\n textContentEligible: isTextContentEligible(file, stat.size),\n });\n seen.add(file);\n }\n}\n\nfunction createProjectFingerprint(projectDir: string, files: ProjectSignatureFile[]): string {\n const hash = createHash(\"sha256\");\n for (const entry of files) {\n hash.update(relative(projectDir, entry.file));\n hash.update(\"\\0\");\n hash.update(String(entry.size));\n hash.update(\"\\0\");\n hash.update(String(entry.mtimeMs));\n hash.update(\"\\0\");\n hash.update(entry.textContentEligible ? \"text\" : \"binary\");\n hash.update(\"\\0\");\n }\n return hash.digest(\"hex\").slice(0, 24);\n}\n\n/**\n * Resolve the project signature through the adapter's cached path when the host\n * provides one (the CLI invalidates its cache from the file watcher), falling\n * back to a direct computation.\n */\nexport function resolveProjectSignature(adapter: StudioApiAdapter, projectDir: string): string {\n return adapter.getProjectSignature?.(projectDir) ?? createProjectSignature(projectDir);\n}\n\n/** The shared route opening: resolve the project (null → caller 404s) with its signature. */\nexport async function resolveProjectAndSignature(\n adapter: StudioApiAdapter,\n projectId: string,\n): Promise<{ project: ResolvedProject; signature: string } | null> {\n const project = await adapter.resolveProject(projectId);\n if (!project) return null;\n return { project, signature: resolveProjectSignature(adapter, project.dir) };\n}\n\n/**\n * Creates a stable preview cache-busting signature for project source plus Studio manifests.\n */\nexport function createProjectSignature(projectDir: string): string {\n const normalizedProjectDir = resolve(projectDir);\n const files: ProjectSignatureFile[] = [];\n collectProjectSignatureFiles(normalizedProjectDir, normalizedProjectDir, files);\n collectProjectSignatureManifestFiles(normalizedProjectDir, files);\n files.sort((a, b) => a.file.localeCompare(b.file));\n\n const fingerprint = createProjectFingerprint(normalizedProjectDir, files);\n const cached = projectSignatureCache.get(normalizedProjectDir);\n if (cached?.fingerprint === fingerprint) return cached.signature;\n\n const hash = createHash(\"sha256\");\n for (const entry of files) {\n const relativePath = relative(normalizedProjectDir, entry.file);\n hash.update(relativePath);\n hash.update(\"\\0\");\n hash.update(String(entry.size));\n hash.update(\"\\0\");\n if (entry.textContentEligible) {\n try {\n hash.update(readFileSync(entry.file));\n } catch {\n hash.update(String(entry.mtimeMs));\n }\n } else {\n hash.update(String(entry.mtimeMs));\n }\n hash.update(\"\\0\");\n }\n const signature = hash.digest(\"hex\").slice(0, 24);\n projectSignatureCache.set(normalizedProjectDir, { fingerprint, signature });\n return signature;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { resolveWithinProject } from \"../helpers/safePath.js\";\nimport { resolveProjectAndSignature } from \"../helpers/projectSignature.js\";\nimport {\n parseStoryboard,\n SCRIPT_FILENAME,\n STORYBOARD_FILENAME,\n type StoryboardFrame,\n} from \"@hyperframes/core/storyboard\";\n\n/** A frame enriched with disk-resolution info the Studio needs to render tiles. */\ninterface ResolvedStoryboardFrame extends StoryboardFrame {\n /** Whether `src` resolves to an existing file inside the project. */\n srcExists: boolean;\n}\n\nfunction resolveFrames(projectDir: string, frames: StoryboardFrame[]): ResolvedStoryboardFrame[] {\n return frames.map((frame) => {\n let srcExists = false;\n if (frame.src) {\n const abs = resolveWithinProject(projectDir, frame.src);\n srcExists = abs ? existsSync(abs) : false;\n }\n return { ...frame, srcExists };\n });\n}\n\n/** Read the companion SCRIPT.md narration doc if it exists alongside the storyboard. */\nfunction readScript(projectDir: string): { exists: boolean; path: string; content: string } {\n const abs = resolveWithinProject(projectDir, SCRIPT_FILENAME);\n if (abs && existsSync(abs)) {\n try {\n return { exists: true, path: SCRIPT_FILENAME, content: readFileSync(abs, \"utf-8\") };\n } catch {\n /* fall through to absent */\n }\n }\n return { exists: false, path: SCRIPT_FILENAME, content: \"\" };\n}\n\nexport function registerStoryboardRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // Parsed storyboard manifest for a project. Markdown (STORYBOARD.md) stays\n // canonical on disk; this returns the derived, normalized structure. When the\n // file is absent we return `exists: false` with empty frames rather than 404,\n // so the Studio can render an opt-in empty state.\n api.get(\"/projects/:id/storyboard\", async (c) => {\n // The signature lets the board bust poster caches and lets the client tell\n // whether this payload is already current (see /projects/:id/signature).\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 const abs = resolveWithinProject(project.dir, STORYBOARD_FILENAME);\n if (!abs || !existsSync(abs)) {\n return c.json({\n exists: false,\n path: STORYBOARD_FILENAME,\n globals: { extra: {} },\n frames: [],\n warnings: [],\n script: readScript(project.dir),\n signature,\n });\n }\n\n let source: string;\n try {\n source = readFileSync(abs, \"utf-8\");\n } catch {\n return c.json({ error: \"failed to read storyboard\" }, 500);\n }\n\n const manifest = parseStoryboard(source);\n return c.json({\n exists: true,\n path: STORYBOARD_FILENAME,\n globals: manifest.globals,\n frames: resolveFrames(project.dir, manifest.frames),\n warnings: manifest.warnings,\n script: readScript(project.dir),\n signature,\n });\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 ftruncateSync,\n openSync,\n readFileSync,\n writeFileSync,\n writeSync,\n mkdirSync,\n unlinkSync,\n rmSync,\n statSync,\n renameSync,\n readdirSync,\n} from \"node:fs\";\nimport { resolve, dirname, join } from \"node:path\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isAudioFile } from \"../helpers/mime.js\";\nimport { generateWaveformCache } from \"../helpers/waveform.js\";\nimport { validateUploadedMediaBuffer } from \"../helpers/mediaValidation.js\";\nimport { isSafePath, resolveWithinProject } from \"../helpers/safePath.js\";\nimport { backupPathForResponse, snapshotBeforeWrite } from \"../helpers/backupJournal.js\";\nimport {\n createWriteToken,\n fileContentVersion,\n recordFileWriteReceipt,\n} from \"../helpers/fileVersion.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 { 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 removeArcPathFromScript,\n addAnimationWithKeyframesToScript,\n splitAnimationsInScript,\n splitIntoPropertyGroupsFromScript,\n shiftPositionsInScript,\n scalePositionsInScript,\n dedupePositionWritesInScript,\n} from \"@hyperframes/parsers/gsap-writer-acorn\";\nimport {\n removeElementFromHtml,\n patchElementInHtml,\n probeElementInSource,\n splitElementInHtml,\n wrapElementsInHtml,\n unwrapElementsFromHtml,\n isHTMLElement,\n type PatchOperation,\n type ElementRebase,\n} from \"../helpers/sourceMutation.js\";\nimport { parseHTML } from \"linkedom\";\nimport {\n CompositionInsertionError,\n insertCompositionIntoSource,\n} from \"../helpers/compositionInsertion.js\";\n\n// ── Server cutover flag ─────────────────────────────────────────────────────\n\n/**\n * Mirror of the client STUDIO_SDK_CUTOVER_ENABLED flag for server-side writer\n * selection. When true, the acorn writer handles GSAP mutations; otherwise the\n * recast writer (gsapParser.ts) is used. Default false → recast.\n *\n * Enable with: STUDIO_SDK_CUTOVER_ENABLED=true (or =1)\n * Mirrors the client Vite env var name so one env switch flips both sides.\n */\nfunction isAcornGsapWriterEnabled(): boolean {\n const val = process.env[\"STUDIO_SDK_CUTOVER_ENABLED\"];\n return val === \"true\" || val === \"1\";\n}\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 when STUDIO_SDK_CUTOVER_ENABLED is off).\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 path: string;\n query: (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/** Resolve project + safe absolute path for any project-scoped route. */\nasync function resolveProjectPath(\n c: RouteContext,\n adapter: StudioApiAdapter,\n pathPrefix: (projectId: string) => string,\n opts?: { mustExist?: 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 const filePath = decodeURIComponent(c.req.path.replace(pathPrefix(project.id), \"\"));\n if (filePath.includes(\"\\0\")) {\n return { error: c.json({ error: \"forbidden\" }, 403) } as const;\n }\n\n const absPath = resolveWithinProject(project.dir, filePath);\n if (!absPath) {\n return { error: c.json({ error: \"forbidden\" }, 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 },\n) {\n return resolveProjectPath(c, adapter, (id) => `/projects/${id}/files/`, opts);\n}\n\nfunction resolveFileMutationContext(c: RouteContext, adapter: StudioApiAdapter, operation: string) {\n return resolveProjectPath(c, adapter, (id) => `/projects/${id}/file-mutations/${operation}/`);\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}\n\ninterface AtomicCutFileRequest {\n path: string;\n expectedVersion: string;\n targets: AtomicCutTarget[];\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 );\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\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. Studio Server is intentionally single-process; within that\n * process the final snapshots/writes are synchronous, so another route cannot\n * interleave once the commit section begins. A multi-process deployment must\n * replace this process-local guarantee with a shared per-project file lock.\n */\nexport function commitElementPatchBatches(\n projectDir: string,\n batches: ElementPatchBatchRequest[],\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void = writeFileSync,\n):\n | { error: \"duplicate\" | \"forbidden\" | \"not-found\"; sourceFile: string }\n | { durable: boolean; files: ElementPatchBatchFileResult[] } {\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 = resolveWithinProject(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 files: ElementPatchBatchFileResult[] = [];\n const attemptedWrites: typeof prepared = [];\n try {\n for (const file of prepared) {\n if (file.after === file.before) {\n files.push({\n sourceFile: file.sourceFile,\n changed: false,\n matched: file.matched,\n before: file.before,\n after: file.before,\n });\n continue;\n }\n const backup = snapshotBeforeWrite(projectDir, file.absPath);\n if (backup.error) {\n throw new Error(`Failed to create backup for ${file.sourceFile}: ${backup.error}`);\n }\n attemptedWrites.push(file);\n writeFile(file.absPath, file.after, \"utf-8\");\n files.push({\n sourceFile: file.sourceFile,\n changed: true,\n matched: file.matched,\n before: file.before,\n after: file.after,\n backupPath: backupPathForResponse(projectDir, backup.backupPath),\n });\n }\n } catch (error) {\n const rollbackErrors: unknown[] = [];\n for (const file of attemptedWrites.reverse()) {\n try {\n writeFile(file.absPath, file.before, \"utf-8\");\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n }\n if (rollbackErrors.length > 0) {\n throw new AggregateError(\n [error, ...rollbackErrors],\n \"Element patch batch failed and rollback did not complete\",\n );\n }\n throw error;\n }\n return { durable: true, files };\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 backup = snapshotBeforeWrite(projectDir, absPath);\n if (backup.error) console.warn(`Failed to create backup for ${filePath}: ${backup.error}`);\n writeFileSync(absPath, next, \"utf-8\");\n return c.json({\n ok: true,\n changed: true,\n content: next,\n path: filePath,\n backupPath: backupPathForResponse(projectDir, backup.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: \"duplicate\" | \"forbidden\" | \"not-found\",\n sourceFile: string,\n): Response {\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. */\nfunction ensureDir(filePath: string) {\n const dir = dirname(filePath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\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 readdirSync(dir, { withFileTypes: true })) {\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\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 filename/path and replaces.\n */\nfunction updateReferences(projectDir: string, oldPath: string, newPath: string): 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 let updatedCount = 0;\n for (const file of textFiles) {\n const content = readFileSync(file, \"utf-8\");\n\n // Only replace full relative paths — never bare filenames, which can\n // corrupt unrelated content (e.g. \"logo.png\" inside \"my-logo.png\").\n if (!content.includes(oldPath)) continue;\n\n const updated = content.split(oldPath).join(newPath);\n if (updated !== content) {\n writeFileSync(file, updated, \"utf-8\");\n updatedCount++;\n }\n }\n return updatedCount;\n}\n\n// ── GSAP script extraction ──────────────────────────────────────────────────\n\n/**\n * Parse an HTML string with linkedom, locate the inline `<script>` that\n * contains GSAP timeline code, and return both its text content and a\n * function that replaces that script block and serialises back to HTML.\n */\nfunction extractGsapScriptBlock(html: string): {\n scriptText: string;\n document: Document;\n replaceScript: (newText: string) => string;\n} | null {\n const { document } = parseHTML(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 for (const script of scripts) {\n const content = script.textContent || \"\";\n if (\n content.includes(\"gsap.timeline\") ||\n content.includes(\".set(\") ||\n content.includes(\".to(\")\n ) {\n return {\n scriptText: content,\n document,\n replaceScript(newText: string): string {\n script.textContent = newText;\n return document.toString();\n },\n };\n }\n }\n return null;\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\ntype 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 }\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\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 that has keyframes whose first percentage 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): Promise<GsapMutationResult | Response> {\n // When the server cutover flag is enabled, delegate to the acorn writer;\n // otherwise use the recast writer (gsapParser.ts) as the default.\n if (!isAcornGsapWriterEnabled()) {\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 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\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 html = html.includes(\"</body>\")\n ? html.replace(\"</body>\", `${bootstrap}\\n</body>`)\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\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\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\n for (const mutation of mutations) {\n const result = await executeGsapMutation(mutation, block, respond);\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 const parser = await loadGsapParser();\n newScript = parser.syncPositionHoldsBeforeKeyframes(newScript);\n }\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 backup = snapshotBeforeWrite(res.project.dir, res.absPath);\n if (backup.error) console.warn(`Failed to create backup for ${res.filePath}: ${backup.error}`);\n backupPath = backupPathForResponse(res.project.dir, backup.backupPath);\n writeFileSync(res.absPath, newHtml, \"utf-8\");\n }\n\n const responsePayload: Record<string, unknown> = {\n ok: true,\n changed,\n mutated: changed,\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 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 \"remove-arc-path\": {\n return removeArcPathFromScript(block.scriptText, body.animationId);\n }\n case \"add-with-keyframes\": {\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 const script = removeAnimationFromScript(block.scriptText, body.animationId);\n const added = addAnimationWithKeyframesToScript(\n script,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n );\n return added.script;\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\": {\n const { targetSelector, delta } = body;\n if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;\n return shiftPositionsInScript(block.scriptText, targetSelector, delta);\n }\n case \"shift-positions-batch\": {\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);\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 return scalePositionsInScript(\n block.scriptText,\n targetSelector,\n oldStart,\n oldDuration,\n newStart,\n newDuration,\n );\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 );\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 const script = removeAnimationFromScript(block.scriptText, body.animationId);\n const added = addAnimationWithKeyframesToScript(\n script,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n );\n return added.script;\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);\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);\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 );\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): Promise<FoldedAtomicCutFile | Response> {\n let after = before;\n let splitCount = 0;\n const skippedSelectors = new Set<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 });\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\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 );\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 const parser = await loadGsapParser();\n script = parser.syncPositionHoldsBeforeKeyframes(script);\n after = block.replaceScript(script);\n }\n }\n\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\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}> {\n const MAX_UPLOAD_BYTES = 500 * 1024 * 1024; // 500 MB per file\n const uploaded: string[] = [];\n const skipped: string[] = [];\n const invalid: 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 if (existsSync(finalPath)) {\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 let n = 2;\n const MAX_COPY_INDEX = 10000;\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 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 writeFileSync(finalPath, buffer);\n const relativePath = subDir ? join(subDir, finalName) : finalName;\n uploaded.push(relativePath);\n if (isAudioFile(finalName)) {\n generateWaveformCache(projectDir, relativePath).catch(() => {});\n }\n }\n\n return { uploaded, skipped, invalid };\n}\n\n// ── Route registration ──────────────────────────────────────────────────────\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 if (!existsSync(res.absPath)) {\n if (c.req.query(\"optional\") === \"1\") {\n return c.json({ filename: res.filePath, content: \"\" });\n }\n return c.json({ error: \"not found\" }, 404);\n }\n\n const content = readFileSync(res.absPath, \"utf-8\");\n const version = fileContentVersion(content);\n c.header(\"ETag\", version);\n return c.json({ filename: res.filePath, content, version });\n });\n\n // ── Write (overwrite) ──\n\n api.put(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter);\n if (\"error\" in res) return res.error;\n\n const body = await c.req.text();\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: string | null = null;\n try {\n currentContent = readFileSync(res.absPath, \"utf-8\");\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,\n },\n 428,\n );\n }\n\n let backup: ReturnType<typeof snapshotBeforeWrite> = { backupPath: null };\n if (createOnly) {\n ensureDir(res.absPath);\n let fd: number;\n try {\n fd = openSync(res.absPath, \"wx\");\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, \"utf-8\");\n return c.json(\n {\n error: \"file conflict\",\n path: res.filePath,\n currentVersion: fileContentVersion(currentContent),\n currentContent,\n },\n 409,\n );\n }\n try {\n writeSync(fd, body, 0, \"utf-8\");\n } finally {\n closeSync(fd);\n }\n } else {\n let fd: number;\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, \"utf-8\");\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,\n },\n 409,\n );\n }\n backup = snapshotBeforeWrite(res.project.dir, res.absPath);\n if (backup.error)\n console.warn(`Failed to create backup for ${res.filePath}: ${backup.error}`);\n ftruncateSync(fd, 0);\n writeSync(fd, body, 0, \"utf-8\");\n } finally {\n 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 });\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 if (existsSync(res.absPath)) {\n return c.json({ error: \"already exists\" }, 409);\n }\n\n ensureDir(res.absPath);\n const body = await c.req.text().catch(() => \"\");\n writeFileSync(res.absPath, body, \"utf-8\");\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) console.warn(`Failed to create backup for ${res.filePath}: ${backup.error}`);\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 writeFileSync(ctx.absPath, insertion.html, \"utf-8\");\n const version = fileContentVersion(insertion.html);\n const writeToken = createWriteToken(c.req.header(\"X-Hyperframes-Write-Token\"));\n recordFileWriteReceipt(ctx.absPath, { path: ctx.filePath, version, writeToken });\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 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\n return serializeAtomicCut(async () => {\n const seen = new Set<string>();\n const prepared: FoldedAtomicCutFile[] = [];\n for (const file of files) {\n const absPath = resolveWithinProject(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);\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 writeFileSync(file.absPath, file.after, \"utf-8\");\n written.push(file);\n recordFileWriteReceipt(file.absPath, {\n path: file.path,\n version: fileContentVersion(file.after),\n writeToken,\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 writeFileSync(file.absPath, file.before, \"utf-8\");\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 backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);\n if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);\n writeFileSync(ctx.absPath, result.html, \"utf-8\");\n const version = fileContentVersion(result.html);\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: backupPathForResponse(ctx.project.dir, backup.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 }>(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 unsafeFields = findUnsafeDomPatchValues(parsed.body);\n if (unsafeFields.length > 0) {\n return rejectUnsafeMutationValues(c, unsafeFields);\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 { html: patched, matched } = patchElementInHtml(\n originalContent,\n parsed.target,\n parsed.body.operations,\n );\n if (patched === originalContent) {\n return c.json({\n ok: true,\n changed: false,\n matched,\n content: originalContent,\n path: ctx.filePath,\n });\n }\n const backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);\n if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);\n writeFileSync(ctx.absPath, patched, \"utf-8\");\n return c.json({\n ok: true,\n changed: true,\n matched,\n content: patched,\n path: ctx.filePath,\n backupPath: backupPathForResponse(ctx.project.dir, backup.backupPath),\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 = commitElementPatchBatches(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 = commitElementPatchBatches(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 );\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 backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);\n if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);\n writeFileSync(ctx.absPath, result.html, \"utf-8\");\n return c.json({\n ok: true,\n changed: true,\n groupId: result.groupId,\n content: result.html,\n path: ctx.filePath,\n backupPath: backupPathForResponse(ctx.project.dir, backup.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<{ target?: MutationTarget }>(c);\n if (\"error\" in parsed) return parsed.error;\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);\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 // ── 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 ensureDir(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);\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(destAbs);\n writeFileSync(destAbs, readFileSync(srcAbs));\n\n return c.json({ ok: true, path: copyPath }, 201);\n });\n\n // ── Upload (binary assets via multipart form) ──\n\n const MAX_UPLOAD_BYTES = 500 * 1024 * 1024; // 500 MB per file\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\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 if (subDir && !existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });\n\n const formData = await c.req.formData();\n const result = await processUploadedFiles(formData, targetDir, project.dir);\n\n return c.json(\n { ok: true, files: result.uploaded, skipped: result.skipped, invalid: result.invalid },\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, (id) => `/projects/${id}/gsap-animations/`, {\n mustExist: true,\n });\n if (\"error\" in res) return res.error;\n\n const html = readFileSync(res.absPath, \"utf-8\");\n const block = extractGsapScriptBlock(html);\n if (!block) {\n return c.json({\n animations: [],\n timelineVar: \"tl\",\n preamble: \"\",\n postamble: \"\",\n });\n }\n\n const parsed = parseGsapScriptAcorn(block.scriptText);\n return c.json(parsed);\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, (id) => `/projects/${id}/gsap-mutations/`, {\n mustExist: 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(\n c,\n adapter,\n (id) => `/projects/${id}/gsap-mutations-batch/`,\n { mustExist: 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(\n c,\n adapter,\n (id) => `/projects/${id}/gsap-mutation-rollback/`,\n { mustExist: 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 writeFileSync(res.absPath, body.restore, \"utf-8\");\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 { spawn } from \"node:child_process\";\nimport { existsSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { 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\nexport function buildWaveformCacheKey(assetPath: string): string {\n return `${WAVEFORM_CACHE_VERSION}_${assetPath.replace(/[/\\\\]/g, \"_\")}.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\"] },\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 cacheDir = join(projectDir, \".waveform-cache\");\n const cachePath = join(cacheDir, buildWaveformCacheKey(assetPath));\n if (existsSync(cachePath)) return;\n\n const peaks = await decodeAudioPeaks(audioPath);\n mkdirSync(cacheDir, { recursive: true });\n writeFileSync(cachePath, JSON.stringify(peaks));\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\";\n\nconst VIDEO_EXT = /\\.(mp4|webm|mov|mkv|avi|m4v|mxf|mts|m2ts|ts)$/i;\nconst AUDIO_EXT = /\\.(mp3|wav|ogg|m4a|aac)$/i;\n\ntype FfprobeRunner = (\n command: string,\n args: string[],\n) => {\n status: number | null;\n stdout: string | Buffer;\n stderr: string | Buffer;\n error?: NodeJS.ErrnoException;\n};\n\nexport function validateUploadedMedia(\n filePath: string,\n runner: FfprobeRunner = spawnSync as unknown as FfprobeRunner,\n): { ok: true } | { ok: false; reason: string } {\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 result = runner(\"ffprobe\", [\n \"-v\",\n \"error\",\n \"-show_entries\",\n \"stream=codec_type\",\n \"-of\",\n \"json\",\n filePath,\n ]);\n\n if (result.error?.code === \"ENOENT\") {\n return { ok: true };\n }\n if (result.status !== 0) {\n return { ok: false, reason: \"ffprobe failed to read the media file\" };\n }\n\n try {\n const parsed = JSON.parse(String(result.stdout || \"{}\")) as {\n streams?: Array<{ codec_type?: string }>;\n };\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 = spawnSync as unknown as FfprobeRunner,\n): { ok: true } | { ok: false; reason: string } {\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 { mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { Buffer } from \"node:buffer\";\nimport { join, relative } from \"node:path\";\nimport { isSafePath } 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 mkdirSync(backupDir, { recursive: true });\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 (\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 { createHash, randomUUID } from \"node:crypto\";\n\nexport interface FileWriteReceipt {\n path: string;\n version: string;\n writeToken: string;\n}\n\ninterface StoredReceipt extends FileWriteReceipt {\n recordedAt: number;\n}\n\nconst RECEIPT_TTL_MS = 10_000;\nconst receipts = new Map<string, StoredReceipt[]>();\n\n/** Strong content version used as both the JSON version and HTTP ETag. */\nexport function fileContentVersion(content: string): string {\n return `\"sha256:${createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\")}\"`;\n}\n\nexport function createWriteToken(requestToken?: string): string {\n const token = requestToken?.trim();\n return token && token.length <= 200 ? token : randomUUID();\n}\n\nexport function recordFileWriteReceipt(absPath: string, receipt: FileWriteReceipt): void {\n const now = Date.now();\n const current = (receipts.get(absPath) ?? []).filter(\n (entry) => now - entry.recordedAt < RECEIPT_TTL_MS,\n );\n current.push({ ...receipt, recordedAt: now });\n receipts.set(absPath, current);\n}\n\n/** Attach one API write's identity to the corresponding filesystem-watch echo. */\nexport function consumeFileWriteReceipt(absPath: string): FileWriteReceipt | null {\n const now = Date.now();\n const current = (receipts.get(absPath) ?? []).filter(\n (entry) => now - entry.recordedAt < RECEIPT_TTL_MS,\n );\n const receipt = current.shift() ?? null;\n if (current.length > 0) receipts.set(absPath, current);\n else receipts.delete(absPath);\n if (!receipt) return null;\n const { path, version, writeToken } = receipt;\n return { path, version, writeToken };\n}\n\nexport function resetFileWriteReceipts(): void {\n receipts.clear();\n}\n","import { existsSync, readFileSync, realpathSync } from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport { dirname, relative, resolve, sep } from \"node:path\";\nimport { parseHTML } from \"linkedom\";\nimport { isSafePath, 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\nfunction 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 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 = realpathSync(candidate);\n if (!isSafePath(realpathSync(projectDir), canonical)) {\n throw new CompositionInsertionError(\"Composition source escapes the project\", 400);\n }\n return canonical;\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 = readFileSync(file, \"utf-8\");\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 = readFileSync(sourceAbs, \"utf-8\");\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 type { Hono } from \"hono\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { injectScriptsIntoHtml, stripEmbeddedRuntimeScripts } from \"@hyperframes/core/compiler\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { resolveWithinProject } from \"../helpers/safePath.js\";\nimport { getMimeType } from \"../helpers/mime.js\";\nimport { buildSubCompositionHtml } from \"../helpers/subComposition.js\";\nimport {\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 { persistHfIdsIfNeeded, stampFileHfIds } from \"../helpers/hfIdPersist.js\";\nimport { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from \"../helpers/variablesPayload.js\";\nimport {\n resolveProxy,\n ProxyCapacityError,\n ProxyTranscodeError,\n} from \"../helpers/proxyTranscoder.js\";\nimport {\n decideMediaProxyEligibility,\n isProxyVariantRequest,\n probeAssetCodec,\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\";\n\nconst PROJECT_SIGNATURE_META = \"hyperframes-project-signature\";\nconst GSAP_CDN_VERSION = \"3.15.0\";\nconst GSAP_CDN_SCRIPT = `<script src=\"https://cdn.jsdelivr.net/npm/gsap@${GSAP_CDN_VERSION}/dist/gsap.min.js\"></script>`;\nconst GSAP_CUSTOM_EASE_CDN_SCRIPT = `<script src=\"https://cdn.jsdelivr.net/npm/gsap@${GSAP_CDN_VERSION}/dist/CustomEase.min.js\"></script>`;\nconst GSAP_MOTION_PATH_CDN_SCRIPT = `<script src=\"https://cdn.jsdelivr.net/npm/gsap@${GSAP_CDN_VERSION}/dist/MotionPathPlugin.min.js\"></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 if (html.includes(\"</head>\")) return html.replace(\"</head>\", `${tag}\\n</head>`);\n return `${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\nfunction injectScriptTagIntoHead(html: string, scriptTag: string): string {\n if (html.includes(\"</head>\")) return html.replace(\"</head>\", `${scriptTag}\\n</head>`);\n return `${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 gsapScript = /<script\\b[^>]*\\bsrc=[\"'][^\"']*\\/gsap(\\.min)?\\.js[\"'][^>]*>\\s*<\\/script>/i;\n const match = html.match(gsapScript);\n if (match) {\n // Match the plugin version to the composition's own gsap so the plugin\n // registers cleanly (a minor-version skew triggers a GSAP compatibility warning).\n const version = match[0].match(/gsap@([\\d.]+)/)?.[1] ?? GSAP_CDN_VERSION;\n const pluginTag = `<script src=\"https://cdn.jsdelivr.net/npm/gsap@${version}/dist/MotionPathPlugin.min.js\"></script>`;\n const end = html.indexOf(match[0]) + match[0].length;\n return html.slice(0, end) + \"\\n\" + pluginTag + html.slice(end);\n }\n return injectScriptTagIntoHead(html, GSAP_MOTION_PATH_CDN_SCRIPT);\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 return injectScriptsIntoHtml(\n injectStudioMotionDependencies(html, manifestContent),\n [],\n [script],\n false,\n );\n}\n\nconst GSAP_CDN_FALLBACK_SCRIPT = `<script data-hf-gsap-fallback>\n(function(){\n var cdnBase=\"https://cdn.jsdelivr.net/npm/gsap@${GSAP_CDN_VERSION}/dist/\";\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.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)return;\n var m=t.src.match(/gsap[^/]*\\\\/dist\\\\/(.+\\\\.js)/);\n if(m)loadFallback(m[1]);\n },true);\n})();\n</script>`;\n\nfunction injectGsapCdnFallback(html: string): string {\n if (html.includes(\"data-hf-gsap-fallback\")) 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 * 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 */\nfunction 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 const at = match.index + match[0].length;\n return html.slice(0, at) + tag + html.slice(at);\n }\n }\n return tag + 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\nfunction injectStudioPreviewAugmentations(\n html: string,\n adapter: StudioApiAdapter,\n projectDir: string,\n activeCompositionPath: string,\n): string {\n return injectStudioMotionScript(\n injectMotionPathPluginIfNeeded(\n injectGsapCdnFallback(\n injectProjectSignature(html, 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 if (existsSync(indexPath)) {\n return {\n html: readFileSync(indexPath, \"utf-8\"),\n compositionPath: \"index.html\",\n };\n }\n const blockHtmlPath = join(projectDir, `${projectId}.html`);\n if (existsSync(blockHtmlPath)) {\n return {\n html: readFileSync(blockHtmlPath, \"utf-8\"),\n compositionPath: `${projectId}.html`,\n };\n }\n return null;\n}\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 // 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\n const etag = `\"preview:${signature}${variablesEtagSalt(vars.raw)}\"`;\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 // Normalize + persist data-hf-id to disk before bundle reads it. Idempotent.\n const diskMain = resolveProjectMainHtml(project.dir, project.id);\n const normalizedDisk = diskMain\n ? persistHfIdsIfNeeded(join(project.dir, diskMain.compositionPath), diskMain.html)\n : null;\n\n try {\n let bundled = await adapter.bundle(project.dir);\n let mainCompositionPath = \"index.html\";\n if (!bundled) {\n if (!diskMain) return c.text(\"not found\", 404);\n // Disk HTML may carry a baked inline runtime from a prior export; strip\n // it so the preview runtime injected below isn't double-loaded (the\n // bundled path already strips via htmlBundler). Idempotent if absent.\n bundled = stripEmbeddedRuntimeScripts(normalizedDisk ?? diskMain.html);\n mainCompositionPath = diskMain.compositionPath;\n }\n\n // Inject runtime if not already present (check URL pattern and bundler attribute)\n if (\n !bundled.includes(\"hyperframe.runtime\") &&\n !bundled.includes(\"hyperframes-preview-runtime\")\n ) {\n const runtimeTag = `<script src=\"${adapter.runtimeUrl}\"></script>`;\n bundled = bundled.includes(\"</body>\")\n ? bundled.replace(\"</body>\", `${runtimeTag}\\n</body>`)\n : bundled + `\\n${runtimeTag}`;\n }\n\n // Inject <base> for relative asset resolution\n const baseHref = `/api/projects/${project.id}/preview/`;\n if (!bundled.includes(\"<base\")) {\n bundled = bundled.replace(/<head>/i, `<head><base href=\"${baseHref}\">`);\n }\n\n // ensureHfIds runs after transformPreviewHtml in case the adapter injected\n // new elements. On the no-bundle path bundled=normalizedDisk (already tagged)\n // so this is idempotent. On the bundled path the bundler may return untagged\n // HTML (stale cache); because ids are content-keyed the minted ids will match\n // the ids already written to disk by persistHfIdsIfNeeded above.\n bundled = injectStudioPreviewAugmentations(\n ensureHfIds(await transformPreviewHtml(bundled, adapter, project, mainCompositionPath)),\n adapter,\n project.dir,\n mainCompositionPath,\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 return c.html(bundled, 200, previewCacheHeaders(etag));\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 = persistHfIdsIfNeeded(\n join(project.dir, fallback.compositionPath),\n fallback.html,\n );\n let fallbackAugmented = injectStudioPreviewAugmentations(\n await transformPreviewHtml(fallbackHtml, adapter, project, fallback.compositionPath),\n adapter,\n project.dir,\n fallback.compositionPath,\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 c.html(fallbackAugmented, 200, previewCacheHeaders(etag));\n }\n return c.text(\"not found\", 404);\n }\n });\n\n /**\n * Pin hf-ids to the RAW sub-comp file before the build pipeline mutates\n * attributes (rewriteRelativePaths etc.) — minting is content-keyed over\n * attrs, so stamping only AFTER the rewrite mints preview-only ids that\n * exist nowhere in the source. Pinned ids ride through the rewrite\n * unchanged, keeping the served DOM, the disk file, and the studio SDK\n * session in one id space. Mirrors the main-preview route's\n * persistHfIdsIfNeeded call.\n *\n * Gated to composition files: the wildcard route serves any project path,\n * and stamping a non-HTML file (SVG, etc.) would corrupt it on disk.\n *\n * Returns the stamped content to thread into the build (so served ids match\n * the mint even when the disk write is skipped — read-only fs), undefined\n * for non-HTML paths, or null when the file vanished after the caller's\n * stat. stampFileHfIds does its validation, read, and write through one\n * file descriptor, so there is no check/read/write path gap to race.\n */\n function pinSubCompHfIds(compFile: string, compPath: string): string | undefined | null {\n if (!/\\.html?$/i.test(compPath)) return undefined;\n return stampFileHfIds(compFile);\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 = decodeURIComponent(\n c.req.path.replace(`/projects/${project.id}/preview/comp/`, \"\").split(\"?\")[0] ?? \"\",\n );\n const compFile = resolveWithinProject(project.dir, compPath);\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 etag = `\"comp:v2:${compPath}:${signature}${variablesEtagSalt(vars.raw)}\"`;\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 = `/api/projects/${project.id}/preview/`;\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 html = ensureHfIds(await transformPreviewHtml(html, adapter, project, compPath));\n html = injectStudioPreviewAugmentations(html, adapter, project.dir, compPath);\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 = decodeURIComponent(\n c.req.path.replace(`/projects/${project.id}/preview/`, \"\").split(\"?\")[0] ?? \"\",\n );\n const file = resolveWithinProject(project.dir, subPath);\n if (!file) {\n return c.text(\"not found\", 404);\n }\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 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);\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 etag = `\"${stat.mtimeMs.toString(36)}-${stat.size.toString(36)}${proxyEtagSalt(proxyVariant)}\"`;\n const cacheHeaders: Record<string, string> = isText\n ? { \"Cache-Control\": \"no-store\" }\n : {\n \"Cache-Control\": \"private, max-age=3600, must-revalidate\",\n ETag: etag,\n };\n\n if (!isText) {\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 servedPath = await resolveProxy(project.dir, file, proxyVariant);\n } catch (err) {\n if (err instanceof ProxyCapacityError) {\n return c.text(err.message, 503, { \"Retry-After\": \"5\" });\n }\n const message = err instanceof ProxyTranscodeError ? err.message : \"proxy transcode failed\";\n return c.text(message, 502);\n }\n servedContentType = PROXY_VARIANT_CONFIG[proxyVariant].contentType;\n }\n\n const buffer: Buffer = isText\n ? Buffer.from(readFileSync(file, \"utf-8\"), \"utf-8\")\n : readFileSync(servedPath);\n const totalSize = buffer.length;\n\n // Support byte-range requests so browsers can seek audio/video elements.\n const rangeHeader = c.req.header(\"Range\");\n if (rangeHeader) {\n const match = /bytes=(\\d+)-(\\d*)/.exec(rangeHeader);\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 const chunkSize = safeEnd - start + 1;\n return new Response(new Uint8Array(buffer.slice(start, safeEnd + 1)), {\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(chunkSize),\n },\n });\n }\n }\n\n return new Response(new Uint8Array(buffer), {\n headers: {\n ...cacheHeaders,\n \"Content-Type\": servedContentType,\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(totalSize),\n },\n });\n });\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 { stripEmbeddedRuntimeScripts } from \"@hyperframes/core/compiler\";\n\n/**\n * Detect whether `html` is a full document (has `<html>`, `<head>`, or\n * `<!doctype`), as opposed to a `<template>`-wrapped fragment.\n * Anchored to start-of-string (ignoring leading whitespace) so stray\n * occurrences inside script/template content don't false-positive.\n */\nfunction isFullHtmlDocument(html: string): boolean {\n return /^\\s*(?:<!doctype\\s|<html[\\s>])/i.test(html);\n}\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 */\nfunction rewriteRelativePaths(root: ParentNode, compPath: string): void {\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 );\n rewriteInlineStyleAssetUrls(\n root.querySelectorAll(\"[style]\"),\n compPath,\n (el: Element) => el.getAttribute(\"style\"),\n (el: Element, value: string) => el.setAttribute(\"style\", value),\n );\n for (const styleEl of root.querySelectorAll(\"style\")) {\n styleEl.textContent = rewriteCssAssetUrls(styleEl.textContent || \"\", compPath);\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): {\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);\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, \"&amp;\").replace(/\"/g, \"&quot;\");\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\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 pinned ids even when the persist-to-disk write\n // was skipped (read-only fs, concurrent-save TOCTOU guard).\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);\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);\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);\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\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)) {\n const indexHtml = readFileSync(indexPath, \"utf-8\");\n const headMatch = indexHtml.match(/<head[^>]*>([\\s\\S]*?)<\\/head>/i);\n headContent = headMatch?.[1] ?? \"\";\n }\n\n // Inject <base> for relative asset resolution (before other tags)\n if (baseHref && !headContent.includes(\"<base\")) {\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 // Ensure runtime is present (might differ from the one in index.html)\n if (\n !headContent.includes(\"hyperframe.runtime\") &&\n !headContent.includes(\"hyperframes-preview-runtime\")\n ) {\n headContent += `\\n<script data-hyperframes-preview-runtime=\"1\" src=\"${runtimeUrl}\"></script>`;\n }\n\n // Fallback: if no index.html head was found, add minimal deps\n if (!headContent.includes(\"gsap\")) {\n headContent += `\\n<script src=\"https://cdn.jsdelivr.net/npm/gsap@3/dist/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","import { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport {\n closeSync,\n constants,\n fstatSync,\n ftruncateSync,\n openSync,\n readFileSync,\n writeFileSync,\n writeSync,\n} from \"node:fs\";\n\n/**\n * Ensure `html` has `data-hf-id` attributes minted, and write the result back\n * to `filePath` if new ids were added.\n *\n * **Invariant:** `html` must be the raw file content read from `filePath` just\n * before this call. If `html` is constructed or transformed HTML the TOCTOU\n * guard (`current === html`) will never match and writes will silently be\n * skipped — no ids will reach disk.\n */\nexport function persistHfIdsIfNeeded(filePath: string, html: string): string {\n const normalized = ensureHfIds(html);\n // Use attribute count instead of string equality: linkedom serialization may\n // normalize quote style and whitespace even when no ids were actually minted,\n // which would cause spurious writes on every request.\n const idsBefore = (html.match(/\\bdata-hf-id=/g) ?? []).length;\n const idsAfter = (normalized.match(/\\bdata-hf-id=/g) ?? []).length;\n if (idsAfter > idsBefore) {\n try {\n // Re-read before writing to guard against concurrent user saves. If the\n // file changed since we read it, skip the write — serving with ids is\n // still correct; the next request will re-persist. Best-effort only: a\n // user save landing between readFileSync and writeFileSync below can\n // still be overwritten (microsecond window).\n const current = readFileSync(filePath, \"utf-8\");\n if (current === html) {\n writeFileSync(filePath, normalized, \"utf-8\");\n }\n } catch (err) {\n // Non-fatal — serve with ids even if the disk write fails (e.g. read-only\n // filesystem, sandboxed environment). Log so the failure is diagnosable.\n console.warn(\"[hyperframes] persistHfIdsIfNeeded: failed to write ids to disk:\", err);\n }\n }\n return normalized;\n}\n\nfunction openNoFollow(filePath: string, flags: number): number | null {\n // O_NOFOLLOW is undefined on Windows; opening without it is the platform norm there.\n const noFollow = constants.O_NOFOLLOW ?? 0;\n try {\n return openSync(filePath, flags | noFollow);\n } catch {\n return null;\n }\n}\n\n/**\n * Read `filePath`, mint any missing `data-hf-id`s, write the stamped content\n * back if new ids were added, and return the stamped content — all through ONE\n * file descriptor. Unlike the check-path / read-path / write-path sequence a\n * route handler would otherwise do, the validation (fstat), read, and write\n * all target the same open inode, so the path cannot be swapped (e.g. for a\n * symlink) between validation and write (CodeQL js/file-system-race).\n *\n * Falls back to read-only stamping when the file isn't writable (read-only\n * fs, sandbox) — serving stamped content without persisting is still correct;\n * ids are content-keyed so the SDK mints the same ones from the same bytes.\n *\n * Returns null when the file is missing, unreadable, or not a regular file.\n *\n * Best-effort on concurrent saves: a user save landing between the read and\n * the write below can still be overwritten (same microsecond window\n * persistHfIdsIfNeeded documents) — the next save simply re-persists.\n */\nexport function stampFileHfIds(filePath: string): string | null {\n let fd = openNoFollow(filePath, constants.O_RDWR);\n let writable = true;\n if (fd === null) {\n fd = openNoFollow(filePath, constants.O_RDONLY);\n writable = false;\n }\n if (fd === null) return null;\n try {\n if (!fstatSync(fd).isFile()) return null;\n const html = readFileSync(fd, \"utf-8\");\n const normalized = ensureHfIds(html);\n // Attribute count, not string equality — linkedom serialization normalizes\n // quote style/whitespace even when no ids were minted (see persistHfIdsIfNeeded).\n const idsBefore = (html.match(/\\bdata-hf-id=/g) ?? []).length;\n const idsAfter = (normalized.match(/\\bdata-hf-id=/g) ?? []).length;\n if (writable && idsAfter > idsBefore) {\n ftruncateSync(fd, 0);\n writeSync(fd, normalized, 0, \"utf-8\");\n }\n return normalized;\n } catch (err) {\n console.warn(\"[hyperframes] stampFileHfIds: failed to stamp ids:\", err);\n return null;\n } finally {\n closeSync(fd);\n }\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","import type { Hono } from \"hono\";\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isInHiddenOrVendorDir, walkDir } from \"../helpers/safePath.js\";\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 allFindings: Array<{\n severity: string;\n message: string;\n file?: string;\n fixHint?: string;\n }> = [];\n for (const file of htmlFiles) {\n const content = readFileSync(join(project.dir, file), \"utf-8\");\n const result = await adapter.lint(content, { filePath: file });\n if (result?.findings) {\n for (const f of result.findings) {\n allFindings.push({ ...f, file });\n }\n }\n }\n return c.json({ findings: allFindings });\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, readFileSync, mkdirSync, 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 { resolveWithinProject } from \"../helpers/safePath.js\";\nimport { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from \"../helpers/variablesPayload.js\";\n\nconst VALID_RESOLUTIONS = new Set<string>(VALID_CANVAS_RESOLUTIONS);\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 // 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 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 if (!existsSync(rendersDir)) mkdirSync(rendersDir, { recursive: true });\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 });\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 }),\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 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 || !existsSync(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\": `inline; filename=\"${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 || !existsSync(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\": `attachment; filename=\"${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) 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\": `inline; filename=\"${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 .map((f) => {\n const fp = join(rendersDir, f);\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 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 } catch {\n /* ignore */\n }\n }\n return {\n id: rid,\n filename: f,\n size: stat.size,\n createdAt: stat.mtimeMs,\n status,\n durationMs,\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: join(rendersDir, file.filename),\n createdAt: file.createdAt,\n } as RenderJobState & { createdAt: number });\n }\n }\n return c.json({ renders: files });\n });\n}\n","import type { Hono } from \"hono\";\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { STUDIO_MANUAL_EDITS_PATH } from \"../helpers/manualEditsRenderScript.js\";\nimport { STUDIO_MOTION_PATH } from \"../helpers/studioMotionRenderScript.js\";\n\nconst THUMBNAIL_CACHE_VERSION = \"v4\";\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 project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n let compPath = decodeURIComponent(\n c.req.path.replace(`/projects/${project.id}/thumbnail/`, \"\").split(\"?\")[0] ?? \"\",\n );\n if (compPath && !compPath.includes(\".\")) compPath += \".html\";\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 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 const htmlFile = join(project.dir, compPath);\n if (existsSync(htmlFile)) {\n const html = readFileSync(htmlFile, \"utf-8\");\n sourceKey = `_${createHash(\"sha1\").update(html).digest(\"hex\").slice(0, 16)}`;\n sourceMtime = Math.round(statSync(htmlFile).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 manualEditsFile = join(project.dir, STUDIO_MANUAL_EDITS_PATH);\n let manualEditsKey = \"\";\n if (existsSync(manualEditsFile)) {\n const manualEditsContent = readFileSync(manualEditsFile, \"utf-8\");\n manualEditsKey = `_${createHash(\"sha1\").update(manualEditsContent).digest(\"hex\").slice(0, 16)}`;\n sourceMtime = Math.max(sourceMtime, Math.round(statSync(manualEditsFile).mtimeMs));\n }\n const motionFile = join(project.dir, STUDIO_MOTION_PATH);\n let motionKey = \"\";\n if (existsSync(motionFile)) {\n const motionContent = readFileSync(motionFile, \"utf-8\");\n motionKey = `_${createHash(\"sha1\").update(motionContent).digest(\"hex\").slice(0, 16)}`;\n sourceMtime = Math.max(sourceMtime, Math.round(statSync(motionFile).mtimeMs));\n }\n\n const previewUrl =\n compPath === \"index.html\"\n ? `http://${c.req.header(\"host\")}/api/projects/${project.id}/preview`\n : `http://${c.req.header(\"host\")}/api/projects/${project.id}/preview/comp/${compPath}`;\n\n // Cache\n const cacheDir = join(project.dir, \".thumbnails\");\n const selectorKey = selector\n ? `_${selector.replace(/[^a-zA-Z0-9_-]+/g, \"_\").slice(0, 80)}_${selectorIndex ?? 0}`\n : \"\";\n const urlVersionKey = urlVersion\n ? `_${urlVersion.replace(/[^a-zA-Z0-9_-]+/g, \"_\").slice(0, 32)}`\n : \"\";\n const cacheKey = `${THUMBNAIL_CACHE_VERSION}${urlVersionKey}${manualEditsKey}${motionKey}${sourceKey}_${format}_${compPath.replace(/\\//g, \"_\")}_${compW}x${compH}_${sourceMtime}_${seekTime.toFixed(2)}${selectorKey}.${format === \"png\" ? \"png\" : \"jpg\"}`;\n const cachePath = join(cacheDir, cacheKey);\n if (existsSync(cachePath)) {\n return new Response(new Uint8Array(readFileSync(cachePath)), {\n headers: { \"Content-Type\": contentType, \"Cache-Control\": \"no-cache\" },\n });\n }\n\n try {\n const buffer = await adapter.generateThumbnail({\n project,\n compPath,\n seekTime,\n width: compW,\n height: compH,\n previewUrl,\n selector,\n format,\n selectorIndex,\n });\n if (!buffer) {\n return c.json(\n { error: \"Thumbnail generation failed — Chrome browser may not be available\" },\n 500,\n );\n }\n if (!existsSync(cacheDir)) mkdirSync(cacheDir, { recursive: true });\n writeFileSync(cachePath, buffer);\n return new Response(new Uint8Array(buffer), {\n headers: { \"Content-Type\": contentType, \"Cache-Control\": \"no-cache\" },\n });\n } catch (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, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { decodeAudioPeaks, buildWaveformCacheKey } from \"../helpers/waveform.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 = decodeURIComponent(\n c.req.path.replace(`/projects/${project.id}/waveform/`, \"\").split(\"?\")[0] ?? \"\",\n );\n const audioPath = join(project.dir, assetPath);\n if (!existsSync(audioPath)) return c.json({ error: \"file not found\" }, 404);\n\n const cacheDir = join(project.dir, \".waveform-cache\");\n const cachePath = join(cacheDir, buildWaveformCacheKey(assetPath));\n\n if (existsSync(cachePath)) {\n try {\n const peaks = JSON.parse(readFileSync(cachePath, \"utf-8\")) as number[];\n return c.json({ peaks });\n } catch {\n // corrupt cache — regenerate\n }\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 mkdirSync(cacheDir, { recursive: true });\n writeFileSync(cachePath, JSON.stringify(peaks));\n } catch {\n // cache write failure is non-fatal\n }\n\n return c.json({ peaks });\n });\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\";\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: \"Registry install not available\" }, 501);\n }\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"Project not found\" }, 404);\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 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, mkdirSync } from \"node:fs\";\nimport { basename, dirname, extname, join } from \"node:path\";\nimport type { MediaProcessingJobState, StudioApiAdapter } from \"../types.js\";\nimport { 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(projectDir: string, assetPath: string): string {\n const ext = extname(assetPath);\n const withoutExt = assetPath.slice(0, -ext.length);\n let candidate = assetPath;\n for (let index = 2; existsSync(join(projectDir, candidate)); index++) {\n candidate = `${withoutExt}-${index}${ext}`;\n }\n return candidate;\n}\n\nfunction defaultOutputPath(projectDir: string, inputPath: string): string {\n const ext = isImagePath(inputPath) ? \".png\" : \".webm\";\n return uniqueAssetPath(projectDir, `assets/cutouts/${slugFileBase(inputPath)}-cutout${ext}`);\n}\n\nfunction defaultPlatePath(projectDir: string, inputPath: string): string {\n return uniqueAssetPath(projectDir, `assets/cutouts/${slugFileBase(inputPath)}-plate.webm`);\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 ? normalizeProjectAssetPath(body.outputPath) : \"\";\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 outputAssetPath = requestedOutput\n ? uniqueAssetPath(project.dir, requestedOutput)\n : defaultOutputPath(project.dir, inputAssetPath);\n const outputPath = resolveWithinProject(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 backgroundOutputAssetPath = defaultPlatePath(project.dir, inputAssetPath);\n backgroundOutputPath =\n resolveWithinProject(project.dir, backgroundOutputAssetPath) ?? undefined;\n if (!backgroundOutputPath) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n }\n\n mkdirSync(dirname(outputPath), { recursive: true });\n if (backgroundOutputPath) mkdirSync(dirname(backgroundOutputPath), { recursive: true });\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 { 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":["join","readdirSync","join","readFileSync","readFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","unlinkSync","rmSync","readdirSync","resolve","dirname","join","existsSync","join","writeFileSync","join","mkdirSync","readdirSync","readFileSync","writeFileSync","Buffer","join","relative","Buffer","relative","readFileSync","join","mkdirSync","writeFileSync","readdirSync","createHash","parseHTML","existsSync","readFileSync","randomUUID","relative","resolve","existsSync","relative","resolve","readFileSync","randomUUID","existsSync","writeFileSync","readFileSync","dirname","mkdirSync","resolve","readdirSync","join","parseHTML","updateAnimationInScript","addAnimationToScript","removeAnimationFromScript","addKeyframeToScript","removeKeyframeFromScript","moveKeyframeInScript","resizeKeyframedTweenInScript","updateKeyframeInScript","removeAllKeyframesFromScript","unrollDynamicAnimations","setArcPathInScript","updateArcSegmentInScript","removeArcPathFromScript","addAnimationWithKeyframesToScript","splitAnimationsInScript","dedupePositionWritesInScript","shiftPositionsInScript","scalePositionsInScript","rmSync","unlinkSync","version","existsSync","readFileSync","statSync","join","createHash","stripEmbeddedRuntimeScripts","existsSync","readFileSync","join","parseHTML","ensureHfIds","closeSync","ftruncateSync","openSync","readFileSync","writeFileSync","writeSync","join","existsSync","readFileSync","createHash","stripEmbeddedRuntimeScripts","ensureHfIds","statSync","readFileSync","join","readFileSync","join","existsSync","readFileSync","mkdirSync","unlinkSync","readdirSync","statSync","join","existsSync","mkdirSync","join","readFileSync","unlinkSync","readdirSync","statSync","existsSync","readFileSync","writeFileSync","mkdirSync","statSync","join","createHash","join","existsSync","readFileSync","createHash","statSync","mkdirSync","writeFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","join","join","existsSync","peaks","readFileSync","mkdirSync","writeFileSync","closeSync","constants","fstatSync","openSync","isRecord","streamSSE","existsSync","mkdirSync","basename","dirname","extname","join","extname","basename","existsSync","join","mkdirSync","dirname","streamSSE","existsSync","readFileSync","join"]}
1
+ {"version":3,"sources":["../src/createStudioApi.ts","../src/routes/projects.ts","../src/helpers/safePath.ts","../src/helpers/projectSignature.ts","../src/routes/storyboard.ts","../src/routes/files.ts","../src/helpers/mime.ts","../src/helpers/waveform.ts","../src/helpers/mediaValidation.ts","../src/helpers/backupJournal.ts","../src/helpers/fileVersion.ts","../src/helpers/compositionInsertion.ts","../src/routes/gsapMutationCapabilities.ts","../src/routes/preview.ts","../src/helpers/subComposition.ts","../src/helpers/hfIdPersist.ts","../src/helpers/variablesPayload.ts","../src/routes/lint.ts","../src/routes/render.ts","../src/routes/thumbnail.ts","../src/routes/waveform.ts","../src/routes/fonts.ts","../src/routes/registry.ts","../src/routes/selection.ts","../src/routes/media.ts","../src/routes/globalAssets.ts","../src/helpers/backgroundRemovalJob.ts"],"sourcesContent":["import { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"./types.js\";\nimport { registerProjectRoutes } from \"./routes/projects.js\";\nimport { registerStoryboardRoutes } from \"./routes/storyboard.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 { registerThumbnailRoutes } from \"./routes/thumbnail.js\";\nimport { registerWaveformRoutes } from \"./routes/waveform.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\";\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\n registerProjectRoutes(api, adapter);\n registerStoryboardRoutes(api, adapter);\n registerFileRoutes(api, adapter);\n registerPreviewRoutes(api, adapter);\n registerLintRoutes(api, adapter);\n registerRenderRoutes(api, adapter);\n registerThumbnailRoutes(api, adapter);\n registerSelectionRoutes(api, adapter);\n registerMediaRoutes(api, adapter);\n registerWaveformRoutes(api, adapter);\n registerFontRoutes(api);\n registerRegistryRoutes(api, adapter);\n registerGlobalAssetRoutes(api);\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, walkDir } from \"../helpers/safePath.js\";\nimport { resolveProjectSignature } from \"../helpers/projectSignature.js\";\n\nconst COMPOSITION_ID_RE = /data-composition-id\\s*=/;\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 COMPOSITION_ID_RE.test(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\n // that refresh themselves when files change on disk (the storyboard board\n // re-fetches when this differs from the signature its data was loaded with).\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);\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","import { join } from \"node:path\";\nimport { readdirSync } from \"node:fs\";\n\n// `isSafePath` lives at the package root so non-studio-api layers (compiler,\n// CLI, engine) can share it without a backwards dependency on studio-api.\n// Re-exported here for back-compat with existing `../helpers/safePath.js` imports.\nexport { isSafePath, resolveWithinProject } from \"@hyperframes/core\";\n\nconst IGNORE_DIRS = new Set([\".thumbnails\", \"node_modules\", \".git\"]);\n\nfunction shouldIgnoreDir(rel: string): boolean {\n return rel === \".hyperframes/backup\";\n}\n\n/**\n * True when any directory segment of a relative path is a dot-directory or\n * node_modules. Projects that vendor tooling assets under dot-directories\n * (.hyperframes/, .cache/, …) ship example/preset HTML that must not surface\n * as project compositions or studio lint targets (#1384). The file tree is\n * deliberately not filtered — this only gates discovery.\n */\nexport function isInHiddenOrVendorDir(relPath: string): boolean {\n const segments = relPath.split(\"/\");\n return segments.slice(0, -1).some((seg) => seg.startsWith(\".\") || seg === \"node_modules\");\n}\n\n/** Recursively walk a directory and return relative file paths. */\nexport function walkDir(dir: string, prefix = \"\"): string[] {\n const files: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (IGNORE_DIRS.has(entry.name) || shouldIgnoreDir(rel)) continue;\n if (entry.isDirectory()) {\n files.push(...walkDir(join(dir, entry.name), rel));\n } else {\n files.push(rel);\n }\n }\n return files;\n}\n","import { createHash } from \"node:crypto\";\nimport { lstatSync, readFileSync, readdirSync } from \"node:fs\";\nimport { extname, isAbsolute, relative, resolve } from \"node:path\";\nimport type { ResolvedProject, StudioApiAdapter } from \"../types.js\";\n\nconst SIGNATURE_TEXT_EXTENSIONS = new Set([\n \".cjs\",\n \".css\",\n \".html\",\n \".js\",\n \".json\",\n \".jsx\",\n \".mjs\",\n \".svg\",\n \".ts\",\n \".tsx\",\n]);\nconst SIGNATURE_EXCLUDED_DIRS = new Set([\n \".cache\",\n \".git\",\n \".hyperframes\",\n \".next\",\n \".vite\",\n \"build\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n \"outputs\",\n \"renders\",\n]);\nconst MAX_SIGNATURE_TEXT_BYTES = 2_000_000;\nconst STUDIO_SIGNATURE_MANIFEST_PATHS = [\n \".hyperframes/studio-manual-edits.json\",\n \".hyperframes/studio-motion.json\",\n] as const;\n\ninterface ProjectSignatureFile {\n file: string;\n mtimeMs: number;\n size: number;\n textContentEligible: boolean;\n}\n\ninterface ProjectSignatureCacheEntry {\n fingerprint: string;\n signature: string;\n}\n\nconst projectSignatureCache = new Map<string, ProjectSignatureCacheEntry>();\n\nfunction isPathWithin(parentDir: string, childPath: string): boolean {\n const childRelativePath = relative(parentDir, childPath);\n return (\n childRelativePath === \"\" ||\n (!childRelativePath.startsWith(\"..\") && !isAbsolute(childRelativePath))\n );\n}\n\nfunction isTextContentEligible(file: string, size: number): boolean {\n return (\n SIGNATURE_TEXT_EXTENSIONS.has(extname(file).toLowerCase()) && size <= MAX_SIGNATURE_TEXT_BYTES\n );\n}\n\nfunction collectProjectSignatureFiles(\n projectDir: string,\n dir: string,\n files: ProjectSignatureFile[],\n): void {\n let entries: string[];\n try {\n entries = readdirSync(dir).sort();\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (SIGNATURE_EXCLUDED_DIRS.has(entry)) continue;\n const file = resolve(dir, entry);\n if (!isPathWithin(projectDir, file)) continue;\n let stat: ReturnType<typeof lstatSync>;\n try {\n stat = lstatSync(file);\n } catch {\n continue;\n }\n if (stat.isSymbolicLink()) continue;\n if (stat.isDirectory()) {\n collectProjectSignatureFiles(projectDir, file, files);\n } else if (stat.isFile()) {\n files.push({\n file,\n mtimeMs: stat.mtimeMs,\n size: stat.size,\n textContentEligible: isTextContentEligible(file, stat.size),\n });\n }\n }\n}\n\nfunction collectProjectSignatureManifestFiles(\n projectDir: string,\n files: ProjectSignatureFile[],\n): void {\n const seen = new Set(files.map((entry) => entry.file));\n for (const manifestPath of STUDIO_SIGNATURE_MANIFEST_PATHS) {\n const file = resolve(projectDir, manifestPath);\n if (seen.has(file) || !isPathWithin(projectDir, file)) continue;\n let stat: ReturnType<typeof lstatSync>;\n try {\n stat = lstatSync(file);\n } catch {\n continue;\n }\n if (stat.isSymbolicLink() || !stat.isFile()) continue;\n files.push({\n file,\n mtimeMs: stat.mtimeMs,\n size: stat.size,\n textContentEligible: isTextContentEligible(file, stat.size),\n });\n seen.add(file);\n }\n}\n\nfunction createProjectFingerprint(projectDir: string, files: ProjectSignatureFile[]): string {\n const hash = createHash(\"sha256\");\n for (const entry of files) {\n hash.update(relative(projectDir, entry.file));\n hash.update(\"\\0\");\n hash.update(String(entry.size));\n hash.update(\"\\0\");\n hash.update(String(entry.mtimeMs));\n hash.update(\"\\0\");\n hash.update(entry.textContentEligible ? \"text\" : \"binary\");\n hash.update(\"\\0\");\n }\n return hash.digest(\"hex\").slice(0, 24);\n}\n\n/**\n * Resolve the project signature through the adapter's cached path when the host\n * provides one (the CLI invalidates its cache from the file watcher), falling\n * back to a direct computation.\n */\nexport function resolveProjectSignature(adapter: StudioApiAdapter, projectDir: string): string {\n return adapter.getProjectSignature?.(projectDir) ?? createProjectSignature(projectDir);\n}\n\n/** The shared route opening: resolve the project (null → caller 404s) with its signature. */\nexport async function resolveProjectAndSignature(\n adapter: StudioApiAdapter,\n projectId: string,\n): Promise<{ project: ResolvedProject; signature: string } | null> {\n const project = await adapter.resolveProject(projectId);\n if (!project) return null;\n return { project, signature: resolveProjectSignature(adapter, project.dir) };\n}\n\n/**\n * Creates a stable preview cache-busting signature for project source plus Studio manifests.\n */\nexport function createProjectSignature(projectDir: string): string {\n const normalizedProjectDir = resolve(projectDir);\n const files: ProjectSignatureFile[] = [];\n collectProjectSignatureFiles(normalizedProjectDir, normalizedProjectDir, files);\n collectProjectSignatureManifestFiles(normalizedProjectDir, files);\n files.sort((a, b) => a.file.localeCompare(b.file));\n\n const fingerprint = createProjectFingerprint(normalizedProjectDir, files);\n const cached = projectSignatureCache.get(normalizedProjectDir);\n if (cached?.fingerprint === fingerprint) return cached.signature;\n\n const hash = createHash(\"sha256\");\n for (const entry of files) {\n const relativePath = relative(normalizedProjectDir, entry.file);\n hash.update(relativePath);\n hash.update(\"\\0\");\n hash.update(String(entry.size));\n hash.update(\"\\0\");\n if (entry.textContentEligible) {\n try {\n hash.update(readFileSync(entry.file));\n } catch {\n hash.update(String(entry.mtimeMs));\n }\n } else {\n hash.update(String(entry.mtimeMs));\n }\n hash.update(\"\\0\");\n }\n const signature = hash.digest(\"hex\").slice(0, 24);\n projectSignatureCache.set(normalizedProjectDir, { fingerprint, signature });\n return signature;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { resolveWithinProject } from \"../helpers/safePath.js\";\nimport { resolveProjectAndSignature } from \"../helpers/projectSignature.js\";\nimport {\n parseStoryboard,\n SCRIPT_FILENAME,\n STORYBOARD_FILENAME,\n type StoryboardFrame,\n} from \"@hyperframes/core/storyboard\";\n\n/** A frame enriched with disk-resolution info the Studio needs to render tiles. */\ninterface ResolvedStoryboardFrame extends StoryboardFrame {\n /** Whether `src` resolves to an existing file inside the project. */\n srcExists: boolean;\n}\n\nfunction resolveFrames(projectDir: string, frames: StoryboardFrame[]): ResolvedStoryboardFrame[] {\n return frames.map((frame) => {\n let srcExists = false;\n if (frame.src) {\n const abs = resolveWithinProject(projectDir, frame.src);\n srcExists = abs ? existsSync(abs) : false;\n }\n return { ...frame, srcExists };\n });\n}\n\n/** Read the companion SCRIPT.md narration doc if it exists alongside the storyboard. */\nfunction readScript(projectDir: string): { exists: boolean; path: string; content: string } {\n const abs = resolveWithinProject(projectDir, SCRIPT_FILENAME);\n if (abs && existsSync(abs)) {\n try {\n return { exists: true, path: SCRIPT_FILENAME, content: readFileSync(abs, \"utf-8\") };\n } catch {\n /* fall through to absent */\n }\n }\n return { exists: false, path: SCRIPT_FILENAME, content: \"\" };\n}\n\nexport function registerStoryboardRoutes(api: Hono, adapter: StudioApiAdapter): void {\n // Parsed storyboard manifest for a project. Markdown (STORYBOARD.md) stays\n // canonical on disk; this returns the derived, normalized structure. When the\n // file is absent we return `exists: false` with empty frames rather than 404,\n // so the Studio can render an opt-in empty state.\n api.get(\"/projects/:id/storyboard\", async (c) => {\n // The signature lets the board bust poster caches and lets the client tell\n // whether this payload is already current (see /projects/:id/signature).\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 const abs = resolveWithinProject(project.dir, STORYBOARD_FILENAME);\n if (!abs || !existsSync(abs)) {\n return c.json({\n exists: false,\n path: STORYBOARD_FILENAME,\n globals: { extra: {} },\n frames: [],\n warnings: [],\n script: readScript(project.dir),\n signature,\n });\n }\n\n let source: string;\n try {\n source = readFileSync(abs, \"utf-8\");\n } catch {\n return c.json({ error: \"failed to read storyboard\" }, 500);\n }\n\n const manifest = parseStoryboard(source);\n return c.json({\n exists: true,\n path: STORYBOARD_FILENAME,\n globals: manifest.globals,\n frames: resolveFrames(project.dir, manifest.frames),\n warnings: manifest.warnings,\n script: readScript(project.dir),\n signature,\n });\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 ftruncateSync,\n openSync,\n readFileSync,\n writeFileSync,\n writeSync,\n mkdirSync,\n unlinkSync,\n rmSync,\n statSync,\n renameSync,\n readdirSync,\n} from \"node:fs\";\nimport { resolve, dirname, join } from \"node:path\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isAudioFile } from \"../helpers/mime.js\";\nimport { generateWaveformCache } from \"../helpers/waveform.js\";\nimport { validateUploadedMediaBuffer } from \"../helpers/mediaValidation.js\";\nimport { isSafePath, resolveWithinProject } from \"../helpers/safePath.js\";\nimport { backupPathForResponse, snapshotBeforeWrite } from \"../helpers/backupJournal.js\";\nimport {\n createWriteToken,\n fileContentVersion,\n recordFileWriteReceipt,\n} from \"../helpers/fileVersion.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 { 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 splitAnimationsInScript,\n splitIntoPropertyGroupsFromScript,\n shiftPositionsInScript,\n scalePositionsInScript,\n dedupePositionWritesInScript,\n syncPositionHoldsBeforeKeyframes,\n} from \"@hyperframes/parsers/gsap-writer-acorn\";\nimport {\n removeElementFromHtml,\n patchElementInHtml,\n probeElementInSource,\n splitElementInHtml,\n wrapElementsInHtml,\n unwrapElementsFromHtml,\n isHTMLElement,\n type PatchOperation,\n type ElementRebase,\n} from \"../helpers/sourceMutation.js\";\nimport { parseHTML } from \"linkedom\";\nimport {\n CompositionInsertionError,\n insertCompositionIntoSource,\n} from \"../helpers/compositionInsertion.js\";\nimport { resolveGsapWriter } from \"./gsapMutationCapabilities.js\";\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 path: string;\n query: (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/** Resolve project + safe absolute path for any project-scoped route. */\nasync function resolveProjectPath(\n c: RouteContext,\n adapter: StudioApiAdapter,\n pathPrefix: (projectId: string) => string,\n opts?: { mustExist?: 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 const filePath = decodeURIComponent(c.req.path.replace(pathPrefix(project.id), \"\"));\n if (filePath.includes(\"\\0\")) {\n return { error: c.json({ error: \"forbidden\" }, 403) } as const;\n }\n\n const absPath = resolveWithinProject(project.dir, filePath);\n if (!absPath) {\n return { error: c.json({ error: \"forbidden\" }, 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 },\n) {\n return resolveProjectPath(c, adapter, (id) => `/projects/${id}/files/`, opts);\n}\n\nfunction resolveFileMutationContext(c: RouteContext, adapter: StudioApiAdapter, operation: string) {\n return resolveProjectPath(c, adapter, (id) => `/projects/${id}/file-mutations/${operation}/`);\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}\n\ninterface AtomicCutFileRequest {\n path: string;\n expectedVersion: string;\n targets: AtomicCutTarget[];\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 );\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\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. Studio Server is intentionally single-process; within that\n * process the final snapshots/writes are synchronous, so another route cannot\n * interleave once the commit section begins. A multi-process deployment must\n * replace this process-local guarantee with a shared per-project file lock.\n */\nexport function commitElementPatchBatches(\n projectDir: string,\n batches: ElementPatchBatchRequest[],\n writeFile: (path: string, content: string, encoding: \"utf-8\") => void = writeFileSync,\n):\n | { error: \"duplicate\" | \"forbidden\" | \"not-found\"; sourceFile: string }\n | { durable: boolean; files: ElementPatchBatchFileResult[] } {\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 = resolveWithinProject(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 files: ElementPatchBatchFileResult[] = [];\n const attemptedWrites: typeof prepared = [];\n try {\n for (const file of prepared) {\n if (file.after === file.before) {\n files.push({\n sourceFile: file.sourceFile,\n changed: false,\n matched: file.matched,\n before: file.before,\n after: file.before,\n });\n continue;\n }\n const backup = snapshotBeforeWrite(projectDir, file.absPath);\n if (backup.error) {\n throw new Error(`Failed to create backup for ${file.sourceFile}: ${backup.error}`);\n }\n attemptedWrites.push(file);\n writeFile(file.absPath, file.after, \"utf-8\");\n files.push({\n sourceFile: file.sourceFile,\n changed: true,\n matched: file.matched,\n before: file.before,\n after: file.after,\n backupPath: backupPathForResponse(projectDir, backup.backupPath),\n });\n }\n } catch (error) {\n const rollbackErrors: unknown[] = [];\n for (const file of attemptedWrites.reverse()) {\n try {\n writeFile(file.absPath, file.before, \"utf-8\");\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n }\n if (rollbackErrors.length > 0) {\n throw new AggregateError(\n [error, ...rollbackErrors],\n \"Element patch batch failed and rollback did not complete\",\n );\n }\n throw error;\n }\n return { durable: true, files };\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 backup = snapshotBeforeWrite(projectDir, absPath);\n if (backup.error) console.warn(`Failed to create backup for ${filePath}: ${backup.error}`);\n writeFileSync(absPath, next, \"utf-8\");\n return c.json({\n ok: true,\n changed: true,\n content: next,\n path: filePath,\n backupPath: backupPathForResponse(projectDir, backup.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: \"duplicate\" | \"forbidden\" | \"not-found\",\n sourceFile: string,\n): Response {\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. */\nfunction ensureDir(filePath: string) {\n const dir = dirname(filePath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\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 readdirSync(dir, { withFileTypes: true })) {\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\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 filename/path and replaces.\n */\nfunction updateReferences(projectDir: string, oldPath: string, newPath: string): 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 let updatedCount = 0;\n for (const file of textFiles) {\n const content = readFileSync(file, \"utf-8\");\n\n // Only replace full relative paths — never bare filenames, which can\n // corrupt unrelated content (e.g. \"logo.png\" inside \"my-logo.png\").\n if (!content.includes(oldPath)) continue;\n\n const updated = content.split(oldPath).join(newPath);\n if (updated !== content) {\n writeFileSync(file, updated, \"utf-8\");\n updatedCount++;\n }\n }\n return updatedCount;\n}\n\n// ── GSAP script extraction ──────────────────────────────────────────────────\n\n/**\n * Parse an HTML string with linkedom, locate the inline `<script>` that\n * contains GSAP timeline code, and return both its text content and a\n * function that replaces that script block and serialises back to HTML.\n */\nfunction extractGsapScriptBlock(html: string): {\n scriptText: string;\n document: Document;\n replaceScript: (newText: string) => string;\n} | null {\n const { document } = parseHTML(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 for (const script of scripts) {\n const content = script.textContent || \"\";\n if (\n content.includes(\"gsap.timeline\") ||\n content.includes(\".set(\") ||\n content.includes(\".to(\")\n ) {\n return {\n scriptText: content,\n document,\n replaceScript(newText: string): string {\n script.textContent = newText;\n return document.toString();\n },\n };\n }\n }\n return null;\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 }\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\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 that has keyframes whose first percentage 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 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\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 html = html.includes(\"</body>\")\n ? html.replace(\"</body>\", `${bootstrap}\\n</body>`)\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\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\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 for (const mutation of mutations) {\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 newScript =\n writer === \"acorn\"\n ? syncPositionHoldsBeforeKeyframes(newScript)\n : (await loadGsapParser()).syncPositionHoldsBeforeKeyframes(newScript);\n }\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 backup = snapshotBeforeWrite(res.project.dir, res.absPath);\n if (backup.error) console.warn(`Failed to create backup for ${res.filePath}: ${backup.error}`);\n backupPath = backupPathForResponse(res.project.dir, backup.backupPath);\n writeFileSync(res.absPath, newHtml, \"utf-8\");\n }\n\n const responsePayload: Record<string, unknown> = {\n ok: true,\n changed,\n mutated: changed,\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 const script = removeAnimationFromScript(block.scriptText, body.animationId);\n const added = addAnimationWithKeyframesToScript(\n script,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n );\n return added.script;\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\": {\n const { targetSelector, delta } = body;\n if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;\n return shiftPositionsInScript(block.scriptText, targetSelector, delta);\n }\n case \"shift-positions-batch\": {\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);\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 return scalePositionsInScript(\n block.scriptText,\n targetSelector,\n oldStart,\n oldDuration,\n newStart,\n newDuration,\n );\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 const script = removeAnimationFromScript(block.scriptText, body.animationId);\n const added = addAnimationWithKeyframesToScript(\n script,\n body.targetSelector,\n body.position,\n body.duration,\n body.keyframes,\n body.ease,\n );\n return added.script;\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);\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);\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 );\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 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 });\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\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)\n : (await loadGsapParser()).syncPositionHoldsBeforeKeyframes(script);\n after = block.replaceScript(script);\n }\n }\n\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\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}> {\n const MAX_UPLOAD_BYTES = 500 * 1024 * 1024; // 500 MB per file\n const uploaded: string[] = [];\n const skipped: string[] = [];\n const invalid: 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 if (existsSync(finalPath)) {\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 let n = 2;\n const MAX_COPY_INDEX = 10000;\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 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 writeFileSync(finalPath, buffer);\n const relativePath = subDir ? join(subDir, finalName) : finalName;\n uploaded.push(relativePath);\n if (isAudioFile(finalName)) {\n generateWaveformCache(projectDir, relativePath).catch(() => {});\n }\n }\n\n return { uploaded, skipped, invalid };\n}\n\n// ── Route registration ──────────────────────────────────────────────────────\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 if (!existsSync(res.absPath)) {\n if (c.req.query(\"optional\") === \"1\") {\n return c.json({ filename: res.filePath, content: \"\" });\n }\n return c.json({ error: \"not found\" }, 404);\n }\n\n const content = readFileSync(res.absPath, \"utf-8\");\n const version = fileContentVersion(content);\n c.header(\"ETag\", version);\n return c.json({ filename: res.filePath, content, version });\n });\n\n // ── Write (overwrite) ──\n\n api.put(\"/projects/:id/files/*\", async (c) => {\n const res = await resolveProjectFile(c, adapter);\n if (\"error\" in res) return res.error;\n\n const body = await c.req.text();\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: string | null = null;\n try {\n currentContent = readFileSync(res.absPath, \"utf-8\");\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,\n },\n 428,\n );\n }\n\n let backup: ReturnType<typeof snapshotBeforeWrite> = { backupPath: null };\n if (createOnly) {\n ensureDir(res.absPath);\n let fd: number;\n try {\n fd = openSync(res.absPath, \"wx\");\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, \"utf-8\");\n return c.json(\n {\n error: \"file conflict\",\n path: res.filePath,\n currentVersion: fileContentVersion(currentContent),\n currentContent,\n },\n 409,\n );\n }\n try {\n writeSync(fd, body, 0, \"utf-8\");\n } finally {\n closeSync(fd);\n }\n } else {\n let fd: number;\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, \"utf-8\");\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,\n },\n 409,\n );\n }\n backup = snapshotBeforeWrite(res.project.dir, res.absPath);\n if (backup.error)\n console.warn(`Failed to create backup for ${res.filePath}: ${backup.error}`);\n ftruncateSync(fd, 0);\n writeSync(fd, body, 0, \"utf-8\");\n } finally {\n 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 });\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 if (existsSync(res.absPath)) {\n return c.json({ error: \"already exists\" }, 409);\n }\n\n ensureDir(res.absPath);\n const body = await c.req.text().catch(() => \"\");\n writeFileSync(res.absPath, body, \"utf-8\");\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) console.warn(`Failed to create backup for ${res.filePath}: ${backup.error}`);\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 writeFileSync(ctx.absPath, insertion.html, \"utf-8\");\n const version = fileContentVersion(insertion.html);\n const writeToken = createWriteToken(c.req.header(\"X-Hyperframes-Write-Token\"));\n recordFileWriteReceipt(ctx.absPath, { path: ctx.filePath, version, writeToken });\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 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 = resolveWithinProject(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 writeFileSync(file.absPath, file.after, \"utf-8\");\n written.push(file);\n recordFileWriteReceipt(file.absPath, {\n path: file.path,\n version: fileContentVersion(file.after),\n writeToken,\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 writeFileSync(file.absPath, file.before, \"utf-8\");\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 backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);\n if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);\n writeFileSync(ctx.absPath, result.html, \"utf-8\");\n const version = fileContentVersion(result.html);\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: backupPathForResponse(ctx.project.dir, backup.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 }>(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 unsafeFields = findUnsafeDomPatchValues(parsed.body);\n if (unsafeFields.length > 0) {\n return rejectUnsafeMutationValues(c, unsafeFields);\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 { html: patched, matched } = patchElementInHtml(\n originalContent,\n parsed.target,\n parsed.body.operations,\n );\n if (patched === originalContent) {\n return c.json({\n ok: true,\n changed: false,\n matched,\n content: originalContent,\n path: ctx.filePath,\n });\n }\n const backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);\n if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);\n writeFileSync(ctx.absPath, patched, \"utf-8\");\n return c.json({\n ok: true,\n changed: true,\n matched,\n content: patched,\n path: ctx.filePath,\n backupPath: backupPathForResponse(ctx.project.dir, backup.backupPath),\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 = commitElementPatchBatches(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 = commitElementPatchBatches(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 );\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 backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);\n if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);\n writeFileSync(ctx.absPath, result.html, \"utf-8\");\n return c.json({\n ok: true,\n changed: true,\n groupId: result.groupId,\n content: result.html,\n path: ctx.filePath,\n backupPath: backupPathForResponse(ctx.project.dir, backup.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<{ target?: MutationTarget }>(c);\n if (\"error\" in parsed) return parsed.error;\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);\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 // ── 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 ensureDir(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);\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(destAbs);\n writeFileSync(destAbs, readFileSync(srcAbs));\n\n return c.json({ ok: true, path: copyPath }, 201);\n });\n\n // ── Upload (binary assets via multipart form) ──\n\n const MAX_UPLOAD_BYTES = 500 * 1024 * 1024; // 500 MB per file\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\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 if (subDir && !existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });\n\n const formData = await c.req.formData();\n const result = await processUploadedFiles(formData, targetDir, project.dir);\n\n return c.json(\n { ok: true, files: result.uploaded, skipped: result.skipped, invalid: result.invalid },\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, (id) => `/projects/${id}/gsap-animations/`, {\n mustExist: true,\n });\n if (\"error\" in res) return res.error;\n\n const html = readFileSync(res.absPath, \"utf-8\");\n const block = extractGsapScriptBlock(html);\n if (!block) {\n return c.json({\n animations: [],\n timelineVar: \"tl\",\n preamble: \"\",\n postamble: \"\",\n });\n }\n\n const parsed = parseGsapScriptAcorn(block.scriptText);\n return c.json(parsed);\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, (id) => `/projects/${id}/gsap-mutations/`, {\n mustExist: 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(\n c,\n adapter,\n (id) => `/projects/${id}/gsap-mutations-batch/`,\n { mustExist: 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(\n c,\n adapter,\n (id) => `/projects/${id}/gsap-mutation-rollback/`,\n { mustExist: 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 writeFileSync(res.absPath, body.restore, \"utf-8\");\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 { spawn } from \"node:child_process\";\nimport { existsSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { 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\nexport function buildWaveformCacheKey(assetPath: string): string {\n return `${WAVEFORM_CACHE_VERSION}_${assetPath.replace(/[/\\\\]/g, \"_\")}.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\"] },\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 cacheDir = join(projectDir, \".waveform-cache\");\n const cachePath = join(cacheDir, buildWaveformCacheKey(assetPath));\n if (existsSync(cachePath)) return;\n\n const peaks = await decodeAudioPeaks(audioPath);\n mkdirSync(cacheDir, { recursive: true });\n writeFileSync(cachePath, JSON.stringify(peaks));\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\";\n\nconst VIDEO_EXT = /\\.(mp4|webm|mov|mkv|avi|m4v|mxf|mts|m2ts|ts)$/i;\nconst AUDIO_EXT = /\\.(mp3|wav|ogg|m4a|aac)$/i;\n\ntype FfprobeRunner = (\n command: string,\n args: string[],\n) => {\n status: number | null;\n stdout: string | Buffer;\n stderr: string | Buffer;\n error?: NodeJS.ErrnoException;\n};\n\nexport function validateUploadedMedia(\n filePath: string,\n runner: FfprobeRunner = spawnSync as unknown as FfprobeRunner,\n): { ok: true } | { ok: false; reason: string } {\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 result = runner(\"ffprobe\", [\n \"-v\",\n \"error\",\n \"-show_entries\",\n \"stream=codec_type\",\n \"-of\",\n \"json\",\n filePath,\n ]);\n\n if (result.error?.code === \"ENOENT\") {\n return { ok: true };\n }\n if (result.status !== 0) {\n return { ok: false, reason: \"ffprobe failed to read the media file\" };\n }\n\n try {\n const parsed = JSON.parse(String(result.stdout || \"{}\")) as {\n streams?: Array<{ codec_type?: string }>;\n };\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 = spawnSync as unknown as FfprobeRunner,\n): { ok: true } | { ok: false; reason: string } {\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 { mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { Buffer } from \"node:buffer\";\nimport { join, relative } from \"node:path\";\nimport { isSafePath } 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 mkdirSync(backupDir, { recursive: true });\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 (\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 { createHash, randomUUID } from \"node:crypto\";\n\nexport interface FileWriteReceipt {\n path: string;\n version: string;\n writeToken: string;\n}\n\ninterface StoredReceipt extends FileWriteReceipt {\n recordedAt: number;\n}\n\nconst RECEIPT_TTL_MS = 10_000;\nconst receipts = new Map<string, StoredReceipt[]>();\n\n/** Strong content version used as both the JSON version and HTTP ETag. */\nexport function fileContentVersion(content: string): string {\n return `\"sha256:${createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\")}\"`;\n}\n\nexport function createWriteToken(requestToken?: string): string {\n const token = requestToken?.trim();\n return token && token.length <= 200 ? token : randomUUID();\n}\n\nexport function recordFileWriteReceipt(absPath: string, receipt: FileWriteReceipt): void {\n const now = Date.now();\n const current = (receipts.get(absPath) ?? []).filter(\n (entry) => now - entry.recordedAt < RECEIPT_TTL_MS,\n );\n current.push({ ...receipt, recordedAt: now });\n receipts.set(absPath, current);\n}\n\n/** Attach one API write's identity to the corresponding filesystem-watch echo. */\nexport function consumeFileWriteReceipt(absPath: string): FileWriteReceipt | null {\n const now = Date.now();\n const current = (receipts.get(absPath) ?? []).filter(\n (entry) => now - entry.recordedAt < RECEIPT_TTL_MS,\n );\n const receipt = current.shift() ?? null;\n if (current.length > 0) receipts.set(absPath, current);\n else receipts.delete(absPath);\n if (!receipt) return null;\n const { path, version, writeToken } = receipt;\n return { path, version, writeToken };\n}\n\nexport function resetFileWriteReceipts(): void {\n receipts.clear();\n}\n","import { existsSync, readFileSync, realpathSync } from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport { dirname, relative, resolve, sep } from \"node:path\";\nimport { parseHTML } from \"linkedom\";\nimport { isSafePath, 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\nfunction 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 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 = realpathSync(candidate);\n if (!isSafePath(realpathSync(projectDir), canonical)) {\n throw new CompositionInsertionError(\"Composition source escapes the project\", 400);\n }\n return canonical;\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 = readFileSync(file, \"utf-8\");\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 = readFileSync(sourceAbs, \"utf-8\");\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 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 \"Every operation has differential parity, the Acorn path imports no Recast runtime, and canary divergence is zero for the agreed soak window.\",\n});\n\nexport function resolveGsapWriter(env: { HYPERFRAMES_GSAP_WRITER?: string }): \"recast\" | \"acorn\" {\n const configured = env.HYPERFRAMES_GSAP_WRITER ?? \"recast\";\n if (configured === \"recast\" || configured === \"acorn\") return configured;\n throw new Error(`Invalid ${GSAP_WRITER_MIGRATION.flag}=${configured}; expected recast or acorn`);\n}\n\nexport function acornDefaultBlockers(): 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\\``,\n \"\",\n \"| Operation | Family | Acorn | Recast | Parity evidence |\",\n \"| --- | --- | --- | --- | --- |\",\n ...rows,\n \"\",\n `Default blockers: ${acornDefaultBlockers().join(\", \") || \"none\"}`,\n \"\",\n ].join(\"\\n\");\n}\n","import type { Hono } from \"hono\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { injectScriptsIntoHtml, stripEmbeddedRuntimeScripts } from \"@hyperframes/core/compiler\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { resolveWithinProject } from \"../helpers/safePath.js\";\nimport { getMimeType } from \"../helpers/mime.js\";\nimport { buildSubCompositionHtml } from \"../helpers/subComposition.js\";\nimport {\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 { persistHfIdsIfNeeded, stampFileHfIds } from \"../helpers/hfIdPersist.js\";\nimport { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from \"../helpers/variablesPayload.js\";\nimport {\n resolveProxy,\n ProxyCapacityError,\n ProxyTranscodeError,\n} from \"../helpers/proxyTranscoder.js\";\nimport {\n decideMediaProxyEligibility,\n isProxyVariantRequest,\n probeAssetCodec,\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\";\n\nconst PROJECT_SIGNATURE_META = \"hyperframes-project-signature\";\nconst GSAP_CDN_VERSION = \"3.15.0\";\nconst GSAP_CDN_SCRIPT = `<script src=\"https://cdn.jsdelivr.net/npm/gsap@${GSAP_CDN_VERSION}/dist/gsap.min.js\"></script>`;\nconst GSAP_CUSTOM_EASE_CDN_SCRIPT = `<script src=\"https://cdn.jsdelivr.net/npm/gsap@${GSAP_CDN_VERSION}/dist/CustomEase.min.js\"></script>`;\nconst GSAP_MOTION_PATH_CDN_SCRIPT = `<script src=\"https://cdn.jsdelivr.net/npm/gsap@${GSAP_CDN_VERSION}/dist/MotionPathPlugin.min.js\"></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 if (html.includes(\"</head>\")) return html.replace(\"</head>\", `${tag}\\n</head>`);\n return `${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\nfunction injectScriptTagIntoHead(html: string, scriptTag: string): string {\n if (html.includes(\"</head>\")) return html.replace(\"</head>\", `${scriptTag}\\n</head>`);\n return `${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 gsapScript = /<script\\b[^>]*\\bsrc=[\"'][^\"']*\\/gsap(\\.min)?\\.js[\"'][^>]*>\\s*<\\/script>/i;\n const match = html.match(gsapScript);\n if (match) {\n // Match the plugin version to the composition's own gsap so the plugin\n // registers cleanly (a minor-version skew triggers a GSAP compatibility warning).\n const version = match[0].match(/gsap@([\\d.]+)/)?.[1] ?? GSAP_CDN_VERSION;\n const pluginTag = `<script src=\"https://cdn.jsdelivr.net/npm/gsap@${version}/dist/MotionPathPlugin.min.js\"></script>`;\n const end = html.indexOf(match[0]) + match[0].length;\n return html.slice(0, end) + \"\\n\" + pluginTag + html.slice(end);\n }\n return injectScriptTagIntoHead(html, GSAP_MOTION_PATH_CDN_SCRIPT);\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 return injectScriptsIntoHtml(\n injectStudioMotionDependencies(html, manifestContent),\n [],\n [script],\n false,\n );\n}\n\nconst GSAP_CDN_FALLBACK_SCRIPT = `<script data-hf-gsap-fallback>\n(function(){\n var cdnBase=\"https://cdn.jsdelivr.net/npm/gsap@${GSAP_CDN_VERSION}/dist/\";\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.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)return;\n var m=t.src.match(/gsap[^/]*\\\\/dist\\\\/(.+\\\\.js)/);\n if(m)loadFallback(m[1]);\n },true);\n})();\n</script>`;\n\nfunction injectGsapCdnFallback(html: string): string {\n if (html.includes(\"data-hf-gsap-fallback\")) 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 * 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 */\nfunction 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 const at = match.index + match[0].length;\n return html.slice(0, at) + tag + html.slice(at);\n }\n }\n return tag + 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\nfunction injectStudioPreviewAugmentations(\n html: string,\n adapter: StudioApiAdapter,\n projectDir: string,\n activeCompositionPath: string,\n): string {\n return injectStudioMotionScript(\n injectMotionPathPluginIfNeeded(\n injectGsapCdnFallback(\n injectProjectSignature(html, 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 if (existsSync(indexPath)) {\n return {\n html: readFileSync(indexPath, \"utf-8\"),\n compositionPath: \"index.html\",\n };\n }\n const blockHtmlPath = join(projectDir, `${projectId}.html`);\n if (existsSync(blockHtmlPath)) {\n return {\n html: readFileSync(blockHtmlPath, \"utf-8\"),\n compositionPath: `${projectId}.html`,\n };\n }\n return null;\n}\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 // 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\n const etag = `\"preview:${signature}${variablesEtagSalt(vars.raw)}\"`;\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 // Normalize + persist data-hf-id to disk before bundle reads it. Idempotent.\n const diskMain = resolveProjectMainHtml(project.dir, project.id);\n const normalizedDisk = diskMain\n ? persistHfIdsIfNeeded(join(project.dir, diskMain.compositionPath), diskMain.html)\n : null;\n\n try {\n let bundled = await adapter.bundle(project.dir);\n let mainCompositionPath = \"index.html\";\n if (!bundled) {\n if (!diskMain) return c.text(\"not found\", 404);\n // Disk HTML may carry a baked inline runtime from a prior export; strip\n // it so the preview runtime injected below isn't double-loaded (the\n // bundled path already strips via htmlBundler). Idempotent if absent.\n bundled = stripEmbeddedRuntimeScripts(normalizedDisk ?? diskMain.html);\n mainCompositionPath = diskMain.compositionPath;\n }\n\n // Inject runtime if not already present (check URL pattern and bundler attribute)\n if (\n !bundled.includes(\"hyperframe.runtime\") &&\n !bundled.includes(\"hyperframes-preview-runtime\")\n ) {\n const runtimeTag = `<script src=\"${adapter.runtimeUrl}\"></script>`;\n bundled = bundled.includes(\"</body>\")\n ? bundled.replace(\"</body>\", `${runtimeTag}\\n</body>`)\n : bundled + `\\n${runtimeTag}`;\n }\n\n // Inject <base> for relative asset resolution\n const baseHref = `/api/projects/${project.id}/preview/`;\n if (!bundled.includes(\"<base\")) {\n bundled = bundled.replace(/<head>/i, `<head><base href=\"${baseHref}\">`);\n }\n\n // ensureHfIds runs after transformPreviewHtml in case the adapter injected\n // new elements. On the no-bundle path bundled=normalizedDisk (already tagged)\n // so this is idempotent. On the bundled path the bundler may return untagged\n // HTML (stale cache); because ids are content-keyed the minted ids will match\n // the ids already written to disk by persistHfIdsIfNeeded above.\n bundled = injectStudioPreviewAugmentations(\n ensureHfIds(await transformPreviewHtml(bundled, adapter, project, mainCompositionPath)),\n adapter,\n project.dir,\n mainCompositionPath,\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 return c.html(bundled, 200, previewCacheHeaders(etag));\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 = persistHfIdsIfNeeded(\n join(project.dir, fallback.compositionPath),\n fallback.html,\n );\n let fallbackAugmented = injectStudioPreviewAugmentations(\n await transformPreviewHtml(fallbackHtml, adapter, project, fallback.compositionPath),\n adapter,\n project.dir,\n fallback.compositionPath,\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 c.html(fallbackAugmented, 200, previewCacheHeaders(etag));\n }\n return c.text(\"not found\", 404);\n }\n });\n\n /**\n * Pin hf-ids to the RAW sub-comp file before the build pipeline mutates\n * attributes (rewriteRelativePaths etc.) — minting is content-keyed over\n * attrs, so stamping only AFTER the rewrite mints preview-only ids that\n * exist nowhere in the source. Pinned ids ride through the rewrite\n * unchanged, keeping the served DOM, the disk file, and the studio SDK\n * session in one id space. Mirrors the main-preview route's\n * persistHfIdsIfNeeded call.\n *\n * Gated to composition files: the wildcard route serves any project path,\n * and stamping a non-HTML file (SVG, etc.) would corrupt it on disk.\n *\n * Returns the stamped content to thread into the build (so served ids match\n * the mint even when the disk write is skipped — read-only fs), undefined\n * for non-HTML paths, or null when the file vanished after the caller's\n * stat. stampFileHfIds does its validation, read, and write through one\n * file descriptor, so there is no check/read/write path gap to race.\n */\n function pinSubCompHfIds(compFile: string, compPath: string): string | undefined | null {\n if (!/\\.html?$/i.test(compPath)) return undefined;\n return stampFileHfIds(compFile);\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 = decodeURIComponent(\n c.req.path.replace(`/projects/${project.id}/preview/comp/`, \"\").split(\"?\")[0] ?? \"\",\n );\n const compFile = resolveWithinProject(project.dir, compPath);\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 etag = `\"comp:v2:${compPath}:${signature}${variablesEtagSalt(vars.raw)}\"`;\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 = `/api/projects/${project.id}/preview/`;\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 html = ensureHfIds(await transformPreviewHtml(html, adapter, project, compPath));\n html = injectStudioPreviewAugmentations(html, adapter, project.dir, compPath);\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 = decodeURIComponent(\n c.req.path.replace(`/projects/${project.id}/preview/`, \"\").split(\"?\")[0] ?? \"\",\n );\n const file = resolveWithinProject(project.dir, subPath);\n if (!file) {\n return c.text(\"not found\", 404);\n }\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 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);\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 etag = `\"${stat.mtimeMs.toString(36)}-${stat.size.toString(36)}${proxyEtagSalt(proxyVariant)}\"`;\n const cacheHeaders: Record<string, string> = isText\n ? { \"Cache-Control\": \"no-store\" }\n : {\n \"Cache-Control\": \"private, max-age=3600, must-revalidate\",\n ETag: etag,\n };\n\n if (!isText) {\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 servedPath = await resolveProxy(project.dir, file, proxyVariant);\n } catch (err) {\n if (err instanceof ProxyCapacityError) {\n return c.text(err.message, 503, { \"Retry-After\": \"5\" });\n }\n const message = err instanceof ProxyTranscodeError ? err.message : \"proxy transcode failed\";\n return c.text(message, 502);\n }\n servedContentType = PROXY_VARIANT_CONFIG[proxyVariant].contentType;\n }\n\n const buffer: Buffer = isText\n ? Buffer.from(readFileSync(file, \"utf-8\"), \"utf-8\")\n : readFileSync(servedPath);\n const totalSize = buffer.length;\n\n // Support byte-range requests so browsers can seek audio/video elements.\n const rangeHeader = c.req.header(\"Range\");\n if (rangeHeader) {\n const match = /bytes=(\\d+)-(\\d*)/.exec(rangeHeader);\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 const chunkSize = safeEnd - start + 1;\n return new Response(new Uint8Array(buffer.slice(start, safeEnd + 1)), {\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(chunkSize),\n },\n });\n }\n }\n\n return new Response(new Uint8Array(buffer), {\n headers: {\n ...cacheHeaders,\n \"Content-Type\": servedContentType,\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": String(totalSize),\n },\n });\n });\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 { stripEmbeddedRuntimeScripts } from \"@hyperframes/core/compiler\";\n\n/**\n * Detect whether `html` is a full document (has `<html>`, `<head>`, or\n * `<!doctype`), as opposed to a `<template>`-wrapped fragment.\n * Anchored to start-of-string (ignoring leading whitespace) so stray\n * occurrences inside script/template content don't false-positive.\n */\nfunction isFullHtmlDocument(html: string): boolean {\n return /^\\s*(?:<!doctype\\s|<html[\\s>])/i.test(html);\n}\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 */\nfunction rewriteRelativePaths(root: ParentNode, compPath: string): void {\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 );\n rewriteInlineStyleAssetUrls(\n root.querySelectorAll(\"[style]\"),\n compPath,\n (el: Element) => el.getAttribute(\"style\"),\n (el: Element, value: string) => el.setAttribute(\"style\", value),\n );\n for (const styleEl of root.querySelectorAll(\"style\")) {\n styleEl.textContent = rewriteCssAssetUrls(styleEl.textContent || \"\", compPath);\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): {\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);\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, \"&amp;\").replace(/\"/g, \"&quot;\");\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\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 pinned ids even when the persist-to-disk write\n // was skipped (read-only fs, concurrent-save TOCTOU guard).\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);\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);\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);\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\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)) {\n const indexHtml = readFileSync(indexPath, \"utf-8\");\n const headMatch = indexHtml.match(/<head[^>]*>([\\s\\S]*?)<\\/head>/i);\n headContent = headMatch?.[1] ?? \"\";\n }\n\n // Inject <base> for relative asset resolution (before other tags)\n if (baseHref && !headContent.includes(\"<base\")) {\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 // Ensure runtime is present (might differ from the one in index.html)\n if (\n !headContent.includes(\"hyperframe.runtime\") &&\n !headContent.includes(\"hyperframes-preview-runtime\")\n ) {\n headContent += `\\n<script data-hyperframes-preview-runtime=\"1\" src=\"${runtimeUrl}\"></script>`;\n }\n\n // Fallback: if no index.html head was found, add minimal deps\n if (!headContent.includes(\"gsap\")) {\n headContent += `\\n<script src=\"https://cdn.jsdelivr.net/npm/gsap@3/dist/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","import { ensureHfIds } from \"@hyperframes/parsers/hf-ids\";\nimport {\n closeSync,\n constants,\n fstatSync,\n ftruncateSync,\n openSync,\n readFileSync,\n writeFileSync,\n writeSync,\n} from \"node:fs\";\n\n/**\n * Ensure `html` has `data-hf-id` attributes minted, and write the result back\n * to `filePath` if new ids were added.\n *\n * **Invariant:** `html` must be the raw file content read from `filePath` just\n * before this call. If `html` is constructed or transformed HTML the TOCTOU\n * guard (`current === html`) will never match and writes will silently be\n * skipped — no ids will reach disk.\n */\nexport function persistHfIdsIfNeeded(filePath: string, html: string): string {\n const normalized = ensureHfIds(html);\n // Use attribute count instead of string equality: linkedom serialization may\n // normalize quote style and whitespace even when no ids were actually minted,\n // which would cause spurious writes on every request.\n const idsBefore = (html.match(/\\bdata-hf-id=/g) ?? []).length;\n const idsAfter = (normalized.match(/\\bdata-hf-id=/g) ?? []).length;\n if (idsAfter > idsBefore) {\n try {\n // Re-read before writing to guard against concurrent user saves. If the\n // file changed since we read it, skip the write — serving with ids is\n // still correct; the next request will re-persist. Best-effort only: a\n // user save landing between readFileSync and writeFileSync below can\n // still be overwritten (microsecond window).\n const current = readFileSync(filePath, \"utf-8\");\n if (current === html) {\n writeFileSync(filePath, normalized, \"utf-8\");\n }\n } catch (err) {\n // Non-fatal — serve with ids even if the disk write fails (e.g. read-only\n // filesystem, sandboxed environment). Log so the failure is diagnosable.\n console.warn(\"[hyperframes] persistHfIdsIfNeeded: failed to write ids to disk:\", err);\n }\n }\n return normalized;\n}\n\nfunction openNoFollow(filePath: string, flags: number): number | null {\n // O_NOFOLLOW is undefined on Windows; opening without it is the platform norm there.\n const noFollow = constants.O_NOFOLLOW ?? 0;\n try {\n return openSync(filePath, flags | noFollow);\n } catch {\n return null;\n }\n}\n\n/**\n * Read `filePath`, mint any missing `data-hf-id`s, write the stamped content\n * back if new ids were added, and return the stamped content — all through ONE\n * file descriptor. Unlike the check-path / read-path / write-path sequence a\n * route handler would otherwise do, the validation (fstat), read, and write\n * all target the same open inode, so the path cannot be swapped (e.g. for a\n * symlink) between validation and write (CodeQL js/file-system-race).\n *\n * Falls back to read-only stamping when the file isn't writable (read-only\n * fs, sandbox) — serving stamped content without persisting is still correct;\n * ids are content-keyed so the SDK mints the same ones from the same bytes.\n *\n * Returns null when the file is missing, unreadable, or not a regular file.\n *\n * Best-effort on concurrent saves: a user save landing between the read and\n * the write below can still be overwritten (same microsecond window\n * persistHfIdsIfNeeded documents) — the next save simply re-persists.\n */\nexport function stampFileHfIds(filePath: string): string | null {\n let fd = openNoFollow(filePath, constants.O_RDWR);\n let writable = true;\n if (fd === null) {\n fd = openNoFollow(filePath, constants.O_RDONLY);\n writable = false;\n }\n if (fd === null) return null;\n try {\n if (!fstatSync(fd).isFile()) return null;\n const html = readFileSync(fd, \"utf-8\");\n const normalized = ensureHfIds(html);\n // Attribute count, not string equality — linkedom serialization normalizes\n // quote style/whitespace even when no ids were minted (see persistHfIdsIfNeeded).\n const idsBefore = (html.match(/\\bdata-hf-id=/g) ?? []).length;\n const idsAfter = (normalized.match(/\\bdata-hf-id=/g) ?? []).length;\n if (writable && idsAfter > idsBefore) {\n ftruncateSync(fd, 0);\n writeSync(fd, normalized, 0, \"utf-8\");\n }\n return normalized;\n } catch (err) {\n console.warn(\"[hyperframes] stampFileHfIds: failed to stamp ids:\", err);\n return null;\n } finally {\n closeSync(fd);\n }\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","import type { Hono } from \"hono\";\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { isInHiddenOrVendorDir, walkDir } from \"../helpers/safePath.js\";\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 allFindings: Array<{\n severity: string;\n message: string;\n file?: string;\n fixHint?: string;\n }> = [];\n for (const file of htmlFiles) {\n const content = readFileSync(join(project.dir, file), \"utf-8\");\n const result = await adapter.lint(content, { filePath: file });\n if (result?.findings) {\n for (const f of result.findings) {\n allFindings.push({ ...f, file });\n }\n }\n }\n return c.json({ findings: allFindings });\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, readFileSync, mkdirSync, 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 { resolveWithinProject } from \"../helpers/safePath.js\";\nimport { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from \"../helpers/variablesPayload.js\";\n\nconst VALID_RESOLUTIONS = new Set<string>(VALID_CANVAS_RESOLUTIONS);\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 // 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 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 if (!existsSync(rendersDir)) mkdirSync(rendersDir, { recursive: true });\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 });\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 }),\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 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 || !existsSync(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\": `inline; filename=\"${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 || !existsSync(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\": `attachment; filename=\"${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) 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\": `inline; filename=\"${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 .map((f) => {\n const fp = join(rendersDir, f);\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 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 } catch {\n /* ignore */\n }\n }\n return {\n id: rid,\n filename: f,\n size: stat.size,\n createdAt: stat.mtimeMs,\n status,\n durationMs,\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: join(rendersDir, file.filename),\n createdAt: file.createdAt,\n } as RenderJobState & { createdAt: number });\n }\n }\n return c.json({ renders: files });\n });\n}\n","import type { Hono } from \"hono\";\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { STUDIO_MANUAL_EDITS_PATH } from \"../helpers/manualEditsRenderScript.js\";\nimport { STUDIO_MOTION_PATH } from \"../helpers/studioMotionRenderScript.js\";\n\nconst THUMBNAIL_CACHE_VERSION = \"v4\";\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 project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"not found\" }, 404);\n\n let compPath = decodeURIComponent(\n c.req.path.replace(`/projects/${project.id}/thumbnail/`, \"\").split(\"?\")[0] ?? \"\",\n );\n if (compPath && !compPath.includes(\".\")) compPath += \".html\";\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 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 const htmlFile = join(project.dir, compPath);\n if (existsSync(htmlFile)) {\n const html = readFileSync(htmlFile, \"utf-8\");\n sourceKey = `_${createHash(\"sha1\").update(html).digest(\"hex\").slice(0, 16)}`;\n sourceMtime = Math.round(statSync(htmlFile).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 manualEditsFile = join(project.dir, STUDIO_MANUAL_EDITS_PATH);\n let manualEditsKey = \"\";\n if (existsSync(manualEditsFile)) {\n const manualEditsContent = readFileSync(manualEditsFile, \"utf-8\");\n manualEditsKey = `_${createHash(\"sha1\").update(manualEditsContent).digest(\"hex\").slice(0, 16)}`;\n sourceMtime = Math.max(sourceMtime, Math.round(statSync(manualEditsFile).mtimeMs));\n }\n const motionFile = join(project.dir, STUDIO_MOTION_PATH);\n let motionKey = \"\";\n if (existsSync(motionFile)) {\n const motionContent = readFileSync(motionFile, \"utf-8\");\n motionKey = `_${createHash(\"sha1\").update(motionContent).digest(\"hex\").slice(0, 16)}`;\n sourceMtime = Math.max(sourceMtime, Math.round(statSync(motionFile).mtimeMs));\n }\n\n const previewUrl =\n compPath === \"index.html\"\n ? `http://${c.req.header(\"host\")}/api/projects/${project.id}/preview`\n : `http://${c.req.header(\"host\")}/api/projects/${project.id}/preview/comp/${compPath}`;\n\n // Cache\n const cacheDir = join(project.dir, \".thumbnails\");\n const selectorKey = selector\n ? `_${selector.replace(/[^a-zA-Z0-9_-]+/g, \"_\").slice(0, 80)}_${selectorIndex ?? 0}`\n : \"\";\n const urlVersionKey = urlVersion\n ? `_${urlVersion.replace(/[^a-zA-Z0-9_-]+/g, \"_\").slice(0, 32)}`\n : \"\";\n const cacheKey = `${THUMBNAIL_CACHE_VERSION}${urlVersionKey}${manualEditsKey}${motionKey}${sourceKey}_${format}_${compPath.replace(/\\//g, \"_\")}_${compW}x${compH}_${sourceMtime}_${seekTime.toFixed(2)}${selectorKey}.${format === \"png\" ? \"png\" : \"jpg\"}`;\n const cachePath = join(cacheDir, cacheKey);\n if (existsSync(cachePath)) {\n return new Response(new Uint8Array(readFileSync(cachePath)), {\n headers: { \"Content-Type\": contentType, \"Cache-Control\": \"no-cache\" },\n });\n }\n\n try {\n const buffer = await adapter.generateThumbnail({\n project,\n compPath,\n seekTime,\n width: compW,\n height: compH,\n previewUrl,\n selector,\n format,\n selectorIndex,\n });\n if (!buffer) {\n return c.json(\n { error: \"Thumbnail generation failed — Chrome browser may not be available\" },\n 500,\n );\n }\n if (!existsSync(cacheDir)) mkdirSync(cacheDir, { recursive: true });\n writeFileSync(cachePath, buffer);\n return new Response(new Uint8Array(buffer), {\n headers: { \"Content-Type\": contentType, \"Cache-Control\": \"no-cache\" },\n });\n } catch (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, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Hono } from \"hono\";\nimport type { StudioApiAdapter } from \"../types.js\";\nimport { decodeAudioPeaks, buildWaveformCacheKey } from \"../helpers/waveform.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 = decodeURIComponent(\n c.req.path.replace(`/projects/${project.id}/waveform/`, \"\").split(\"?\")[0] ?? \"\",\n );\n const audioPath = join(project.dir, assetPath);\n if (!existsSync(audioPath)) return c.json({ error: \"file not found\" }, 404);\n\n const cacheDir = join(project.dir, \".waveform-cache\");\n const cachePath = join(cacheDir, buildWaveformCacheKey(assetPath));\n\n if (existsSync(cachePath)) {\n try {\n const peaks = JSON.parse(readFileSync(cachePath, \"utf-8\")) as number[];\n return c.json({ peaks });\n } catch {\n // corrupt cache — regenerate\n }\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 mkdirSync(cacheDir, { recursive: true });\n writeFileSync(cachePath, JSON.stringify(peaks));\n } catch {\n // cache write failure is non-fatal\n }\n\n return c.json({ peaks });\n });\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\";\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: \"Registry install not available\" }, 501);\n }\n const project = await adapter.resolveProject(c.req.param(\"id\"));\n if (!project) return c.json({ error: \"Project not found\" }, 404);\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 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, mkdirSync } from \"node:fs\";\nimport { basename, dirname, extname, join } from \"node:path\";\nimport type { MediaProcessingJobState, StudioApiAdapter } from \"../types.js\";\nimport { 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(projectDir: string, assetPath: string): string {\n const ext = extname(assetPath);\n const withoutExt = assetPath.slice(0, -ext.length);\n let candidate = assetPath;\n for (let index = 2; existsSync(join(projectDir, candidate)); index++) {\n candidate = `${withoutExt}-${index}${ext}`;\n }\n return candidate;\n}\n\nfunction defaultOutputPath(projectDir: string, inputPath: string): string {\n const ext = isImagePath(inputPath) ? \".png\" : \".webm\";\n return uniqueAssetPath(projectDir, `assets/cutouts/${slugFileBase(inputPath)}-cutout${ext}`);\n}\n\nfunction defaultPlatePath(projectDir: string, inputPath: string): string {\n return uniqueAssetPath(projectDir, `assets/cutouts/${slugFileBase(inputPath)}-plate.webm`);\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 ? normalizeProjectAssetPath(body.outputPath) : \"\";\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 outputAssetPath = requestedOutput\n ? uniqueAssetPath(project.dir, requestedOutput)\n : defaultOutputPath(project.dir, inputAssetPath);\n const outputPath = resolveWithinProject(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 backgroundOutputAssetPath = defaultPlatePath(project.dir, inputAssetPath);\n backgroundOutputPath =\n resolveWithinProject(project.dir, backgroundOutputAssetPath) ?? undefined;\n if (!backgroundOutputPath) {\n return c.json({ error: \"forbidden\" }, 403);\n }\n }\n\n mkdirSync(dirname(outputPath), { recursive: true });\n if (backgroundOutputPath) mkdirSync(dirname(backgroundOutputPath), { recursive: true });\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 { 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":["join","readdirSync","join","readFileSync","readFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","unlinkSync","rmSync","readdirSync","resolve","dirname","join","existsSync","join","writeFileSync","join","mkdirSync","readdirSync","readFileSync","writeFileSync","Buffer","join","relative","Buffer","relative","readFileSync","join","mkdirSync","writeFileSync","readdirSync","createHash","parseHTML","existsSync","readFileSync","randomUUID","relative","resolve","existsSync","relative","resolve","readFileSync","randomUUID","existsSync","writeFileSync","readFileSync","dirname","mkdirSync","resolve","readdirSync","join","parseHTML","updateAnimationInScript","addAnimationToScript","removeAnimationFromScript","addKeyframeToScript","removeKeyframeFromScript","moveKeyframeInScript","resizeKeyframedTweenInScript","updateKeyframeInScript","removeAllKeyframesFromScript","unrollDynamicAnimations","setArcPathInScript","updateArcSegmentInScript","updateMotionPathPointInScript","addMotionPathPointInScript","removeMotionPathPointInScript","addMotionPathToScript","removeArcPathFromScript","addAnimationWithKeyframesToScript","splitAnimationsInScript","dedupePositionWritesInScript","shiftPositionsInScript","scalePositionsInScript","rmSync","unlinkSync","version","existsSync","readFileSync","statSync","join","createHash","stripEmbeddedRuntimeScripts","existsSync","readFileSync","join","parseHTML","ensureHfIds","closeSync","ftruncateSync","openSync","readFileSync","writeFileSync","writeSync","join","existsSync","readFileSync","createHash","stripEmbeddedRuntimeScripts","ensureHfIds","statSync","readFileSync","join","readFileSync","join","existsSync","readFileSync","mkdirSync","unlinkSync","readdirSync","statSync","join","existsSync","mkdirSync","join","readFileSync","unlinkSync","readdirSync","statSync","existsSync","readFileSync","writeFileSync","mkdirSync","statSync","join","createHash","join","existsSync","readFileSync","createHash","statSync","mkdirSync","writeFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","join","join","existsSync","peaks","readFileSync","mkdirSync","writeFileSync","closeSync","constants","fstatSync","openSync","isRecord","streamSSE","existsSync","mkdirSync","basename","dirname","extname","join","extname","basename","existsSync","join","mkdirSync","dirname","streamSSE","existsSync","readFileSync","join"]}