export type StudioProjectFileWriter = (path: string, content: string) => Promise; // A writer is bound to one project (see useFileManager), so writer identity plus // path is the complete durable-file identity. Sharing this queue across SDK and // legacy mutation paths prevents independent read-modify-write transactions from // cloning the same stale bytes and overwriting one another. const mutationQueues = new WeakMap>>(); export function serializeStudioFileMutation( writer: StudioProjectFileWriter, targetPath: string, task: () => Promise, ): Promise { let queues = mutationQueues.get(writer); if (!queues) { queues = new Map(); mutationQueues.set(writer, queues); } const prior = queues.get(targetPath) ?? Promise.resolve(); const next = prior.then(task, task); queues.set(targetPath, next); void next.then( () => { if (queues?.get(targetPath) === next) queues.delete(targetPath); }, () => { if (queues?.get(targetPath) === next) queues.delete(targetPath); }, ); return next; } export function serializeStudioFileMutations( writer: StudioProjectFileWriter, targetPaths: readonly string[], task: () => Promise, ): Promise { const paths = [...new Set(targetPaths)].sort(); const acquire = (index: number): Promise => { const path = paths[index]; if (path === undefined) return task(); return serializeStudioFileMutation(writer, path, () => acquire(index + 1)); }; return acquire(0); }