@hyperframes/studio-server 0.8.98 → 0.8.99

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 CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  import {
18
18
  isCompositionSource,
19
19
  stampProjectHfIds
20
- } from "./chunk-WUHW3MWG.js";
20
+ } from "./chunk-7ON477WG.js";
21
21
  import {
22
22
  DEFAULT_HISTORY_ROOT,
23
23
  DELETED_VERSION,
@@ -43,10 +43,7 @@ import {
43
43
  resolveProjectAndSignature,
44
44
  resolveProjectSignature,
45
45
  settledFileTag
46
- } from "./chunk-EQULRR3G.js";
47
- import {
48
- replaceFileAtomically
49
- } from "./chunk-PMXUKOC3.js";
46
+ } from "./chunk-ZZCG4HGG.js";
50
47
  import {
51
48
  getElementScreenshotClip
52
49
  } from "./chunk-W2SBTCO2.js";
@@ -155,8 +152,6 @@ import {
155
152
  openSync,
156
153
  readFileSync as readFileSync3,
157
154
  readlinkSync,
158
- writeFileSync as writeFileSync4,
159
- writeSync,
160
155
  unlinkSync as unlinkSync2,
161
156
  rmSync as rmSync3,
162
157
  statSync as statSync3,
@@ -212,6 +207,9 @@ function isAudioFile(name) {
212
207
  return (getMimeType(name) ?? "").startsWith("audio/");
213
208
  }
214
209
 
210
+ // src/routes/files.ts
211
+ import { createFileAtomically, replaceFileAtomically as replaceFileAtomically2 } from "@hyperframes/core/atomic-file";
212
+
215
213
  // src/helpers/waveform.ts
216
214
  import { spawn } from "child_process";
217
215
  import {
@@ -471,6 +469,7 @@ function replaceWithProjectDirMissing(c, hostHeaders) {
471
469
 
472
470
  // src/helpers/applyFileMutations.ts
473
471
  import { readFileSync as readFileSync2, statSync as statSync2 } from "fs";
472
+ import { replaceFileAtomically } from "@hyperframes/core/atomic-file";
474
473
  function applyFileMutations(projectDir, mutations, requestToken, writeFile = (path, content) => replaceFileAtomically(path, content, statSync2(path).mode)) {
475
474
  const prepared = mutations.map((mutation) => ({
476
475
  ...mutation,
@@ -557,7 +556,7 @@ function assertExpectedVersion(mutation, current) {
557
556
 
558
557
  // src/routes/files.ts
559
558
  import { classifyPropertyGroup } from "@hyperframes/parsers/gsap-constants";
560
- import { parseGsapScriptAcorn } from "@hyperframes/parsers/gsap-parser-acorn";
559
+ import { findTimelineScript, parseGsapScriptAcorn } from "@hyperframes/parsers/gsap-parser-acorn";
561
560
  import { unrollComputedTimeline } from "@hyperframes/parsers";
562
561
  import {
563
562
  updateAnimationInScript,
@@ -585,7 +584,8 @@ import {
585
584
  shiftPositionsInScript,
586
585
  scalePositionsInScript,
587
586
  dedupePositionWritesInScript,
588
- syncPositionHoldsBeforeKeyframes
587
+ syncPositionHoldsBeforeKeyframes,
588
+ clipQueryRoot
589
589
  } from "@hyperframes/parsers/gsap-writer-acorn";
590
590
  import { parseHTML as parseHTML2 } from "linkedom";
591
591
  import { ensureHfIds } from "@hyperframes/parsers/hf-ids";
@@ -962,7 +962,7 @@ function foldElementPatches(originalContent, patches) {
962
962
  return { content, matched };
963
963
  }
964
964
  var PATCH_CONFLICT_ATTEMPTS = 3;
965
- function commitElementPatchBatches(projectDir, batches, writeFile = (path, content) => replaceFileAtomically(path, content, statSync3(path).mode), requestToken) {
965
+ function commitElementPatchBatches(projectDir, batches, writeFile = (path, content) => replaceFileAtomically2(path, content, statSync3(path).mode), requestToken) {
966
966
  for (let attempt = 1; ; attempt += 1) {
967
967
  try {
968
968
  return foldAndCommitElementPatchBatches(projectDir, batches, writeFile, requestToken);
@@ -1040,7 +1040,7 @@ function commitElementPatchBatchesWithReceipts(c, projectDir, batches) {
1040
1040
  }
1041
1041
  function writeFileWithReceipt(c, filePath, absPath, html) {
1042
1042
  const overwrote = readFileSync3(absPath);
1043
- replaceFileAtomically(absPath, html, statSync3(absPath).mode);
1043
+ replaceFileAtomically2(absPath, html, statSync3(absPath).mode);
1044
1044
  const version = fileContentVersion(html);
1045
1045
  const writeToken = createWriteToken(c.req.header("X-Hyperframes-Write-Token"));
1046
1046
  recordFileWriteReceipt(absPath, { path: filePath, version, writeToken, overwrote });
@@ -1136,7 +1136,7 @@ function updateReferences(projectDir, oldPath, newPath) {
1136
1136
  if (!content.includes(oldPath)) continue;
1137
1137
  const updated = content.split(oldPath).join(newPath);
1138
1138
  if (updated !== content) {
1139
- replaceFileAtomically(file, updated, statSync3(file).mode);
1139
+ replaceFileAtomically2(file, updated, statSync3(file).mode);
1140
1140
  updatedCount++;
1141
1141
  }
1142
1142
  }
@@ -1150,20 +1150,17 @@ function extractGsapScriptBlock(html) {
1150
1150
  (tmpl) => Array.from(tmpl.querySelectorAll("script:not([src])"))
1151
1151
  )
1152
1152
  ];
1153
- for (const script of scripts) {
1154
- const content = script.textContent || "";
1155
- if (content.includes("gsap.timeline") || content.includes(".set(") || content.includes(".to(")) {
1156
- return {
1157
- scriptText: content,
1158
- document,
1159
- replaceScript(newText) {
1160
- script.textContent = newText;
1161
- return document.toString();
1162
- }
1163
- };
1153
+ const script = findTimelineScript(scripts);
1154
+ if (!script) return null;
1155
+ return {
1156
+ scriptText: script.textContent || "",
1157
+ document,
1158
+ root: clipQueryRoot(script),
1159
+ replaceScript(newText) {
1160
+ script.textContent = newText;
1161
+ return document.toString();
1164
1162
  }
1165
- }
1166
- return null;
1163
+ };
1167
1164
  }
1168
1165
  function stripGsapAnimationsForSelector(html, selector) {
1169
1166
  const block = extractGsapScriptBlock(html);
@@ -1780,13 +1777,13 @@ function executeGsapMutationAcorn(body, block, respond) {
1780
1777
  case "shift-positions": {
1781
1778
  const { targetSelector, delta } = body;
1782
1779
  if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;
1783
- return shiftPositionsInScript(block.scriptText, targetSelector, delta);
1780
+ return shiftPositionsInScript(block.scriptText, targetSelector, delta, block.root);
1784
1781
  }
1785
1782
  case "shift-positions-batch": {
1786
1783
  let script = block.scriptText;
1787
1784
  for (const s of body.shifts) {
1788
1785
  if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;
1789
- script = shiftPositionsInScript(script, s.targetSelector, s.delta);
1786
+ script = shiftPositionsInScript(script, s.targetSelector, s.delta, block.root);
1790
1787
  }
1791
1788
  return script;
1792
1789
  }
@@ -1801,7 +1798,8 @@ function executeGsapMutationAcorn(body, block, respond) {
1801
1798
  oldStart,
1802
1799
  oldDuration,
1803
1800
  newStart,
1804
- newDuration
1801
+ newDuration,
1802
+ block.root
1805
1803
  );
1806
1804
  }
1807
1805
  default:
@@ -2112,14 +2110,14 @@ async function executeGsapMutationRecast(body, block, respond) {
2112
2110
  const { targetSelector, delta } = body;
2113
2111
  if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;
2114
2112
  const { shiftPositionsInScript: shiftPositionsInScript2 } = parser;
2115
- return shiftPositionsInScript2(block.scriptText, targetSelector, delta);
2113
+ return shiftPositionsInScript2(block.scriptText, targetSelector, delta, block.root);
2116
2114
  }
2117
2115
  case "shift-positions-batch": {
2118
2116
  const { shiftPositionsInScript: shiftPositionsInScript2 } = parser;
2119
2117
  let script = block.scriptText;
2120
2118
  for (const s of body.shifts) {
2121
2119
  if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;
2122
- script = shiftPositionsInScript2(script, s.targetSelector, s.delta);
2120
+ script = shiftPositionsInScript2(script, s.targetSelector, s.delta, block.root);
2123
2121
  }
2124
2122
  return script;
2125
2123
  }
@@ -2135,7 +2133,8 @@ async function executeGsapMutationRecast(body, block, respond) {
2135
2133
  oldStart,
2136
2134
  oldDuration,
2137
2135
  newStart,
2138
- newDuration
2136
+ newDuration,
2137
+ block.root
2139
2138
  );
2140
2139
  }
2141
2140
  default:
@@ -2256,12 +2255,7 @@ async function processUploadedFiles(formData, targetDir, projectDir) {
2256
2255
  let written = false;
2257
2256
  while (n < MAX_COPY_INDEX && isSafePath(projectDir, finalPath)) {
2258
2257
  try {
2259
- const fd = openSync(finalPath, "wx");
2260
- try {
2261
- writeFileSync4(fd, buffer);
2262
- } finally {
2263
- closeSync(fd);
2264
- }
2258
+ createFileAtomically(finalPath, buffer);
2265
2259
  written = true;
2266
2260
  break;
2267
2261
  } catch (error) {
@@ -2355,9 +2349,8 @@ function registerFileRoutes(api, adapter) {
2355
2349
  let overwrote;
2356
2350
  if (createOnly) {
2357
2351
  ensureDir(res.project.dir, res.absPath);
2358
- let fd;
2359
2352
  try {
2360
- fd = openSync(res.absPath, "wx");
2353
+ createFileAtomically(res.absPath, body);
2361
2354
  } catch (error) {
2362
2355
  if (!error || typeof error !== "object" || !("code" in error) || error.code !== "EEXIST") {
2363
2356
  throw error;
@@ -2373,11 +2366,6 @@ function registerFileRoutes(api, adapter) {
2373
2366
  409
2374
2367
  );
2375
2368
  }
2376
- try {
2377
- writeSync(fd, body, 0, body.length, 0);
2378
- } finally {
2379
- closeSync(fd);
2380
- }
2381
2369
  } else {
2382
2370
  let fd;
2383
2371
  try {
@@ -2416,7 +2404,7 @@ function registerFileRoutes(api, adapter) {
2416
2404
  const mode = fstatSync(fd).mode;
2417
2405
  closeSync(fd);
2418
2406
  fd = null;
2419
- replaceFileAtomically(res.absPath, body, mode);
2407
+ replaceFileAtomically2(res.absPath, body, mode);
2420
2408
  } finally {
2421
2409
  if (fd !== null) closeSync(fd);
2422
2410
  }
@@ -2439,7 +2427,7 @@ function registerFileRoutes(api, adapter) {
2439
2427
  ensureDir(res.project.dir, res.absPath);
2440
2428
  const body = Buffer.from(await c.req.arrayBuffer());
2441
2429
  try {
2442
- writeFileSync4(res.absPath, body, { flag: "wx" });
2430
+ createFileAtomically(res.absPath, body);
2443
2431
  } catch (error) {
2444
2432
  if (!error || typeof error !== "object" || !("code" in error) || error.code !== "EEXIST") {
2445
2433
  throw error;
@@ -2646,7 +2634,7 @@ function registerFileRoutes(api, adapter) {
2646
2634
  const written = [];
2647
2635
  try {
2648
2636
  for (const file of prepared) {
2649
- replaceFileAtomically(file.absPath, file.after, statSync3(file.absPath).mode);
2637
+ replaceFileAtomically2(file.absPath, file.after, statSync3(file.absPath).mode);
2650
2638
  written.push(file);
2651
2639
  recordFileWriteReceipt(file.absPath, {
2652
2640
  path: file.path,
@@ -2664,7 +2652,7 @@ function registerFileRoutes(api, adapter) {
2664
2652
  conflicts.push(file.path);
2665
2653
  continue;
2666
2654
  }
2667
- replaceFileAtomically(file.absPath, file.before, statSync3(file.absPath).mode);
2655
+ replaceFileAtomically2(file.absPath, file.before, statSync3(file.absPath).mode);
2668
2656
  recordFileWriteReceipt(file.absPath, {
2669
2657
  path: file.path,
2670
2658
  version: fileContentVersion(file.before),
@@ -3000,7 +2988,7 @@ function registerFileRoutes(api, adapter) {
3000
2988
  }
3001
2989
  ensureDir(project.dir, destAbs);
3002
2990
  try {
3003
- writeFileSync4(destAbs, readFileSync3(srcAbs), { flag: "wx" });
2991
+ createFileAtomically(destAbs, readFileSync3(srcAbs));
3004
2992
  } catch (error) {
3005
2993
  if (!error || typeof error !== "object" || !("code" in error) || error.code !== "EEXIST") {
3006
2994
  throw error;
@@ -3104,7 +3092,7 @@ function registerFileRoutes(api, adapter) {
3104
3092
  if (current !== body.expected) {
3105
3093
  return c.json({ ok: true, restored: false, conflict: true });
3106
3094
  }
3107
- replaceFileAtomically(res.absPath, body.restore, statSync3(res.absPath).mode);
3095
+ replaceFileAtomically2(res.absPath, body.restore, statSync3(res.absPath).mode);
3108
3096
  return c.json({ ok: true, restored: true, conflict: false });
3109
3097
  });
3110
3098
  }
@@ -4421,7 +4409,7 @@ import {
4421
4409
  rmSync as rmSync4,
4422
4410
  statSync as statSync6,
4423
4411
  unlinkSync as unlinkSync4,
4424
- writeFileSync as writeFileSync5
4412
+ writeFileSync as writeFileSync4
4425
4413
  } from "fs";
4426
4414
  import { join as join11 } from "path";
4427
4415
  import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
@@ -4530,7 +4518,7 @@ function pruneThumbnailCache(cacheDir, protectedPaths, now = Date.now()) {
4530
4518
  function writeThumbnailAtomically(path, buffer) {
4531
4519
  const temporaryPath = `${path}.${process.pid}.${randomUUID2()}.tmp`;
4532
4520
  try {
4533
- writeFileSync5(temporaryPath, buffer, { flag: "wx" });
4521
+ writeFileSync4(temporaryPath, buffer, { flag: "wx" });
4534
4522
  renameSync3(temporaryPath, path);
4535
4523
  } finally {
4536
4524
  rmSync4(temporaryPath, { force: true });
@@ -5463,6 +5451,7 @@ function numericAttribute(element, name) {
5463
5451
  import { createHash as createHash4 } from "crypto";
5464
5452
  import { readFileSync as readFileSync12, readdirSync as readdirSync5, rmSync as rmSync5 } from "fs";
5465
5453
  import { join as join15 } from "path";
5454
+ import { replaceFileAtomically as replaceFileAtomically3 } from "@hyperframes/core/atomic-file";
5466
5455
  function createPreviewDocumentStore(projectDir, salt) {
5467
5456
  const dir = join15(projectDir, ".hyperframes", "preview");
5468
5457
  const fileFor = (key) => join15(dir, `${createHash4("sha256").update(`${salt}
@@ -5479,7 +5468,7 @@ ${key}`).digest("hex").slice(0, 32)}.html`);
5479
5468
  try {
5480
5469
  mkdirWithinProject(projectDir, dir);
5481
5470
  const file = fileFor(key);
5482
- replaceFileAtomically(file, html, 420);
5471
+ replaceFileAtomically3(file, html, 420);
5483
5472
  for (const name of readdirSync5(dir)) {
5484
5473
  if (join15(dir, name) !== file) rmSync5(join15(dir, name), { force: true });
5485
5474
  }