@hyperframes/studio-server 0.8.209 → 0.8.211
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-2B5SR4RJ.js → chunk-KPCW4DQM.js} +2 -4
- package/dist/{chunk-BWZMWYB2.js → chunk-UMPRW7BV.js} +104 -42
- package/dist/{chunk-C3KTZ7G3.js → chunk-YOCRTHW3.js} +1 -1
- package/dist/helpers/mediaProxyPreview.js +2 -2
- package/dist/helpers/proxyTranscoder.js +1 -1
- package/dist/history/index.d.ts +5 -1
- package/dist/history/index.js +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +13 -5
- package/package.json +3 -3
|
@@ -407,9 +407,8 @@ var ProxyDroppedError = class extends ProxyTranscodeError {
|
|
|
407
407
|
var activeTranscodes = 0;
|
|
408
408
|
var waitQueue = [];
|
|
409
409
|
function enqueue(job) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
else waitQueue.splice(firstNormal, 0, job);
|
|
410
|
+
if (job.priority) waitQueue.unshift(job);
|
|
411
|
+
else waitQueue.push(job);
|
|
413
412
|
}
|
|
414
413
|
function dequeue(job) {
|
|
415
414
|
const index = waitQueue.indexOf(job);
|
|
@@ -445,7 +444,6 @@ function releaseSlot() {
|
|
|
445
444
|
waitQueue.shift()?.queued?.start();
|
|
446
445
|
}
|
|
447
446
|
function prioritize(job) {
|
|
448
|
-
if (job.priority) return;
|
|
449
447
|
job.priority = true;
|
|
450
448
|
if (!job.queued) return;
|
|
451
449
|
dequeue(job);
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
rmSync as rmSync3
|
|
20
20
|
} from "fs";
|
|
21
21
|
import { homedir } from "os";
|
|
22
|
-
import { dirname as dirname5, isAbsolute as isAbsolute5, join as join8, relative as relative5, resolve as
|
|
22
|
+
import { dirname as dirname5, isAbsolute as isAbsolute5, join as join8, relative as relative5, resolve as resolve8, sep as sep5 } from "path";
|
|
23
23
|
import { replaceFileAtomically as replaceFileAtomically6 } from "@hyperframes/core/atomic-file";
|
|
24
24
|
|
|
25
25
|
// src/helpers/fileVersion.ts
|
|
@@ -534,11 +534,44 @@ function createProjectSignature(projectDir, excluding = /* @__PURE__ */ new Set(
|
|
|
534
534
|
// src/history/blobStore.ts
|
|
535
535
|
import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
|
|
536
536
|
import { constants, createReadStream, createWriteStream } from "fs";
|
|
537
|
-
import { copyFile, mkdir, readdir, readFile, rm, stat } from "fs/promises";
|
|
537
|
+
import { copyFile, mkdir, open, readdir, readFile, rm, stat } from "fs/promises";
|
|
538
538
|
import { dirname, join as join2 } from "path";
|
|
539
539
|
import { pipeline } from "stream/promises";
|
|
540
540
|
import { atomicTempPath } from "@hyperframes/core/atomic-file";
|
|
541
|
-
import {
|
|
541
|
+
import {
|
|
542
|
+
isWindowsHold,
|
|
543
|
+
renameWithRetry,
|
|
544
|
+
renameWithRetryAsync
|
|
545
|
+
} from "@hyperframes/core/rename-retry";
|
|
546
|
+
|
|
547
|
+
// src/helpers/servedFiles.ts
|
|
548
|
+
import { resolve as resolve3 } from "path";
|
|
549
|
+
var serving = /* @__PURE__ */ new Map();
|
|
550
|
+
var keyOf = (path) => process.platform === "win32" ? resolve3(path).toLowerCase() : resolve3(path);
|
|
551
|
+
function serveWhileOpen(path, stream) {
|
|
552
|
+
const key = keyOf(path);
|
|
553
|
+
const reads = serving.get(key) ?? /* @__PURE__ */ new Set();
|
|
554
|
+
serving.set(key, reads.add(stream));
|
|
555
|
+
stream.once("close", () => {
|
|
556
|
+
reads.delete(stream);
|
|
557
|
+
if (reads.size === 0 && serving.get(key) === reads) serving.delete(key);
|
|
558
|
+
});
|
|
559
|
+
return stream;
|
|
560
|
+
}
|
|
561
|
+
async function stopServingAndClose(path) {
|
|
562
|
+
const reads = [...serving.get(keyOf(path)) ?? []];
|
|
563
|
+
await Promise.all(
|
|
564
|
+
reads.map(
|
|
565
|
+
(stream) => new Promise((done) => {
|
|
566
|
+
if (stream.closed) return done();
|
|
567
|
+
stream.once("close", () => done());
|
|
568
|
+
stream.destroy();
|
|
569
|
+
})
|
|
570
|
+
)
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// src/history/blobStore.ts
|
|
542
575
|
var BLOB_HASH = /^[0-9a-f]{64}$/;
|
|
543
576
|
function blobPath(dir, hash) {
|
|
544
577
|
if (!BLOB_HASH.test(hash)) throw new Error("That is not a history blob.");
|
|
@@ -558,18 +591,45 @@ async function cloneOrStream(from, to) {
|
|
|
558
591
|
await pipeline(createReadStream(from), createWriteStream(to, { mode }));
|
|
559
592
|
}
|
|
560
593
|
}
|
|
561
|
-
|
|
594
|
+
var inPlaceListeners = /* @__PURE__ */ new Set();
|
|
595
|
+
function onRestoredInPlace(listener) {
|
|
596
|
+
inPlaceListeners.add(listener);
|
|
597
|
+
return () => inPlaceListeners.delete(listener);
|
|
598
|
+
}
|
|
599
|
+
async function cloneOrCopy(from, to, hash, beforeReplace) {
|
|
562
600
|
await mkdir(dirname(to), { recursive: true });
|
|
563
601
|
const temp = atomicTempPath(to);
|
|
564
602
|
try {
|
|
565
603
|
await copyFile(from, temp, constants.COPYFILE_FICLONE);
|
|
604
|
+
await stopServingAndClose(to);
|
|
566
605
|
beforeReplace?.();
|
|
567
|
-
|
|
568
|
-
|
|
606
|
+
try {
|
|
607
|
+
renameWithRetry(temp, to);
|
|
608
|
+
} catch (error) {
|
|
609
|
+
if (!isWindowsHold(error)) throw error;
|
|
610
|
+
await writeInPlace(temp, to, hash);
|
|
611
|
+
}
|
|
612
|
+
} finally {
|
|
569
613
|
await rm(temp, { force: true });
|
|
570
|
-
throw error;
|
|
571
614
|
}
|
|
572
615
|
}
|
|
616
|
+
async function writeInPlace(temp, to, hash) {
|
|
617
|
+
let outcome = "failed";
|
|
618
|
+
try {
|
|
619
|
+
await copyFile(temp, to);
|
|
620
|
+
const handle = await open(to, "r+");
|
|
621
|
+
try {
|
|
622
|
+
await handle.sync();
|
|
623
|
+
} finally {
|
|
624
|
+
await handle.close();
|
|
625
|
+
}
|
|
626
|
+
outcome = await hashFile(to) === hash ? "restored" : "mismatch";
|
|
627
|
+
} finally {
|
|
628
|
+
for (const listener of inPlaceListeners) listener(to, outcome);
|
|
629
|
+
}
|
|
630
|
+
if (outcome === "mismatch")
|
|
631
|
+
throw new Error("The file was written in place, but it does not match the copy history kept.");
|
|
632
|
+
}
|
|
573
633
|
var listDir = (path) => readdir(path, { withFileTypes: true }).catch((error) => {
|
|
574
634
|
if (error.code === "ENOENT") return [];
|
|
575
635
|
throw error;
|
|
@@ -628,7 +688,7 @@ async function openBlobStore(dir) {
|
|
|
628
688
|
reference: (absPath) => hashFile(absPath),
|
|
629
689
|
has: (hash) => sizes.has(hash) || asideSizes.has(hash),
|
|
630
690
|
read: (hash) => readFile(pathOf(hash)),
|
|
631
|
-
writeTo: async (hash, absPath, beforeReplace) => cloneOrCopy(pathOf(hash), absPath, beforeReplace),
|
|
691
|
+
writeTo: async (hash, absPath, beforeReplace) => cloneOrCopy(pathOf(hash), absPath, hash, beforeReplace),
|
|
632
692
|
async release(held) {
|
|
633
693
|
for (const [hash, path] of held) {
|
|
634
694
|
holds.get(hash)?.delete(path);
|
|
@@ -717,7 +777,7 @@ import { dirname as dirname2, join as join4 } from "path";
|
|
|
717
777
|
// src/history/historyId.ts
|
|
718
778
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
719
779
|
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync4, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
720
|
-
import { basename, join as join3, resolve as
|
|
780
|
+
import { basename, join as join3, resolve as resolve4 } from "path";
|
|
721
781
|
import { replaceFileAtomically as replaceFileAtomically3 } from "@hyperframes/core/atomic-file";
|
|
722
782
|
var ID_PATH = join3(".hyperframes", "history-id");
|
|
723
783
|
var ID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
@@ -756,7 +816,7 @@ function isCopyOf0878Folder(recordedDir, id, folder) {
|
|
|
756
816
|
return !!there && !sameFolder(there, folder) && readId(recordedDir) === id;
|
|
757
817
|
}
|
|
758
818
|
function projectHistoryId(projectDir, historyRoot) {
|
|
759
|
-
const dir =
|
|
819
|
+
const dir = resolve4(projectDir);
|
|
760
820
|
const folder = statSync2(dir);
|
|
761
821
|
let id = readId(dir);
|
|
762
822
|
if (!id && existsSync(join3(dir, ID_PATH)))
|
|
@@ -933,7 +993,7 @@ function pruneGoneProjectHistoriesDaily(historyRoot, now, { onError, budgetMs }
|
|
|
933
993
|
// src/history/videoState.ts
|
|
934
994
|
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
935
995
|
import { createReadStream as createReadStream2, existsSync as existsSync2, readFileSync as readFileSync8, renameSync as renameSync2, statSync as statSync4 } from "fs";
|
|
936
|
-
import { isAbsolute as isAbsolute4, join as join7, resolve as
|
|
996
|
+
import { isAbsolute as isAbsolute4, join as join7, resolve as resolve7 } from "path";
|
|
937
997
|
import { replaceFileAtomically as replaceFileAtomically4 } from "@hyperframes/core/atomic-file";
|
|
938
998
|
|
|
939
999
|
// src/history/artifactCleanup.ts
|
|
@@ -947,7 +1007,7 @@ import {
|
|
|
947
1007
|
readFileSync as readFileSync6,
|
|
948
1008
|
unlinkSync
|
|
949
1009
|
} from "fs";
|
|
950
|
-
import { isAbsolute as isAbsolute3, join as join5, relative as relative3, resolve as
|
|
1010
|
+
import { isAbsolute as isAbsolute3, join as join5, relative as relative3, resolve as resolve5, sep as sep3 } from "path";
|
|
951
1011
|
var kinds = ["checks", "snapshots"];
|
|
952
1012
|
var records = (state, kind) => [
|
|
953
1013
|
...Object.values(state[kind].revisions).flat(),
|
|
@@ -955,7 +1015,7 @@ var records = (state, kind) => [
|
|
|
955
1015
|
];
|
|
956
1016
|
var protectedRevisions = (state) => /* @__PURE__ */ new Set([state.currentRevision, ...state.renders?.retainedRevisions ?? []]);
|
|
957
1017
|
function managedPath(projectDir, path, kind) {
|
|
958
|
-
const canonicalProject = realFilePath(
|
|
1018
|
+
const canonicalProject = realFilePath(resolve5(projectDir));
|
|
959
1019
|
const canonicalPath = realFilePath(path);
|
|
960
1020
|
const root = join5(canonicalProject, ".hyperframes", "artifacts", kind);
|
|
961
1021
|
const rel = relative3(root, canonicalPath);
|
|
@@ -1067,15 +1127,15 @@ import {
|
|
|
1067
1127
|
writeSync,
|
|
1068
1128
|
writeFileSync as writeFileSync4
|
|
1069
1129
|
} from "fs";
|
|
1070
|
-
import { dirname as dirname3, join as join6, relative as relative4, resolve as
|
|
1130
|
+
import { dirname as dirname3, join as join6, relative as relative4, resolve as resolve6, sep as sep4 } from "path";
|
|
1071
1131
|
var SNAPSHOT_RUNS_TO_KEEP = 10;
|
|
1072
1132
|
var SNAPSHOT_GRACE_MS = 24 * 60 * 60 * 1e3;
|
|
1073
1133
|
var OWNER = ".capture-owner.json";
|
|
1074
1134
|
var ownedMarkers = /* @__PURE__ */ new Map();
|
|
1075
1135
|
var UUID = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i;
|
|
1076
|
-
var rootOf = (project) => join6(
|
|
1136
|
+
var rootOf = (project) => join6(resolve6(project), ".hyperframes", "artifacts", "snapshots");
|
|
1077
1137
|
function ordinaryPath(project, path) {
|
|
1078
|
-
const root =
|
|
1138
|
+
const root = resolve6(project);
|
|
1079
1139
|
const rel = relative4(root, path);
|
|
1080
1140
|
if (rel === ".." || rel.startsWith(`..${sep4}`)) return false;
|
|
1081
1141
|
let current = root;
|
|
@@ -1090,7 +1150,7 @@ function ordinaryPath(project, path) {
|
|
|
1090
1150
|
return true;
|
|
1091
1151
|
}
|
|
1092
1152
|
function createSnapshotParents(project, path) {
|
|
1093
|
-
let parent =
|
|
1153
|
+
let parent = resolve6(project);
|
|
1094
1154
|
for (const part of relative4(parent, path).split(sep4).filter(Boolean)) {
|
|
1095
1155
|
parent = join6(parent, part);
|
|
1096
1156
|
try {
|
|
@@ -1186,7 +1246,7 @@ function recordsOf(state) {
|
|
|
1186
1246
|
}
|
|
1187
1247
|
function containingRun(root, path) {
|
|
1188
1248
|
if (!path) return null;
|
|
1189
|
-
const name = relative4(root,
|
|
1249
|
+
const name = relative4(root, resolve6(path)).split(sep4)[0];
|
|
1190
1250
|
return name && UUID.test(name) ? join6(root, name) : null;
|
|
1191
1251
|
}
|
|
1192
1252
|
function keepContainingRun(keep, root, path) {
|
|
@@ -1287,7 +1347,7 @@ function retainSnapshotOutput(project, path) {
|
|
|
1287
1347
|
const root = rootOf(project);
|
|
1288
1348
|
const run = containingRun(root, path);
|
|
1289
1349
|
if (!run) return;
|
|
1290
|
-
createSnapshotParents(project,
|
|
1350
|
+
createSnapshotParents(project, resolve6(path));
|
|
1291
1351
|
try {
|
|
1292
1352
|
writeFileSync4(
|
|
1293
1353
|
join6(run, ".user-output"),
|
|
@@ -1343,7 +1403,7 @@ async function updateState(dir, update) {
|
|
|
1343
1403
|
}
|
|
1344
1404
|
}
|
|
1345
1405
|
async function writeHistoryState(projectDir, historyId, historyDirectory, entries, currentFiles, committedFiles) {
|
|
1346
|
-
const blob = (hash) => hash === null ? null :
|
|
1406
|
+
const blob = (hash) => hash === null ? null : resolve7(historyDirectory, "blobs", hash.slice(0, 2), hash);
|
|
1347
1407
|
await updateState(projectDir, (state) => {
|
|
1348
1408
|
if (state.historyId && state.historyId !== historyId) {
|
|
1349
1409
|
state.checks = collection();
|
|
@@ -1474,7 +1534,7 @@ function listsOf(artifacts) {
|
|
|
1474
1534
|
return [...Object.values(artifacts.revisions), artifacts.unversioned];
|
|
1475
1535
|
}
|
|
1476
1536
|
async function forgetRecordedArtifacts(projectDir, paths) {
|
|
1477
|
-
const gone = new Set(paths.map((path) =>
|
|
1537
|
+
const gone = new Set(paths.map((path) => resolve7(path)));
|
|
1478
1538
|
if (gone.size === 0) return;
|
|
1479
1539
|
await updateState(projectDir, (state) => {
|
|
1480
1540
|
for (const artifacts of [state.checks, state.snapshots]) {
|
|
@@ -1482,7 +1542,7 @@ async function forgetRecordedArtifacts(projectDir, paths) {
|
|
|
1482
1542
|
for (let i = list.length - 1; i >= 0; i--) {
|
|
1483
1543
|
const record = list[i];
|
|
1484
1544
|
const path = record.image ?? record.report;
|
|
1485
|
-
if (path && gone.has(
|
|
1545
|
+
if (path && gone.has(resolve7(path))) list.splice(i, 1);
|
|
1486
1546
|
}
|
|
1487
1547
|
}
|
|
1488
1548
|
if (artifacts.latest && !listsOf(artifacts).some(
|
|
@@ -1494,7 +1554,7 @@ async function forgetRecordedArtifacts(projectDir, paths) {
|
|
|
1494
1554
|
});
|
|
1495
1555
|
}
|
|
1496
1556
|
function artifactDirectory(projectDir, kind) {
|
|
1497
|
-
const path = join7(
|
|
1557
|
+
const path = join7(resolve7(projectDir), ".hyperframes", "artifacts", kind, randomUUID6());
|
|
1498
1558
|
if (kind === "snapshots") ownSnapshotRun(projectDir, path);
|
|
1499
1559
|
return path;
|
|
1500
1560
|
}
|
|
@@ -1510,7 +1570,7 @@ async function recordRenderSuccess(projectDir, output, status = "completed", cap
|
|
|
1510
1570
|
const record = {
|
|
1511
1571
|
id: randomUUID6(),
|
|
1512
1572
|
completedAt: Date.now(),
|
|
1513
|
-
output:
|
|
1573
|
+
output: resolve7(output),
|
|
1514
1574
|
status
|
|
1515
1575
|
};
|
|
1516
1576
|
const unchanged = Boolean(capture && after?.fingerprint === capture.fingerprint);
|
|
@@ -1777,7 +1837,7 @@ var Engine = class {
|
|
|
1777
1837
|
this.options = options;
|
|
1778
1838
|
this.projectId = projectId;
|
|
1779
1839
|
this.blobs = blobs;
|
|
1780
|
-
this.dir =
|
|
1840
|
+
this.dir = resolve8(options.projectDir);
|
|
1781
1841
|
this.home = join8(options.historyRoot, projectId);
|
|
1782
1842
|
this.foldsCase = ignoresCase(this.dir);
|
|
1783
1843
|
const folder = statSync5(this.dir, { throwIfNoEntry: false });
|
|
@@ -2086,7 +2146,7 @@ var Engine = class {
|
|
|
2086
2146
|
return known.hash !== hash || known.stat !== stat4;
|
|
2087
2147
|
}
|
|
2088
2148
|
async record(path, before, after, at) {
|
|
2089
|
-
const endedBeforeThisWrite = this.windows.filter((
|
|
2149
|
+
const endedBeforeThisWrite = this.windows.filter((open2) => !takesWrite(open2, at));
|
|
2090
2150
|
if (endedBeforeThisWrite.length) await this.commitOutside();
|
|
2091
2151
|
for (const window2 of endedBeforeThisWrite) await this.endWindow(window2);
|
|
2092
2152
|
const window = this.windows.at(-1);
|
|
@@ -2128,7 +2188,7 @@ var Engine = class {
|
|
|
2128
2188
|
if (window.changes.size) await this.commitCut(window, [...window.changes.keys()]);
|
|
2129
2189
|
}
|
|
2130
2190
|
pendingElsewhere() {
|
|
2131
|
-
return Boolean(this.outside?.changes.size) || this.windows.some((
|
|
2191
|
+
return Boolean(this.outside?.changes.size) || this.windows.some((open2) => open2.changes.size > 0);
|
|
2132
2192
|
}
|
|
2133
2193
|
/** The held claim `taken` continues: same key, each file from its own last change, no held file changed since. */
|
|
2134
2194
|
heldFor(key, taken) {
|
|
@@ -2142,7 +2202,7 @@ var Engine = class {
|
|
|
2142
2202
|
return group && taken.every((change) => after(change.path, change.before) === change.before) && [...group.changes.values()].every(untouched) ? group : null;
|
|
2143
2203
|
}
|
|
2144
2204
|
logPath(path) {
|
|
2145
|
-
return relative5(this.dir,
|
|
2205
|
+
return relative5(this.dir, resolve8(this.dir, path)).split(sep5).join("/");
|
|
2146
2206
|
}
|
|
2147
2207
|
/** Takes `paths`' uncommitted changes from others, cut at what `who` overwrote. */
|
|
2148
2208
|
async takeClaimed(who, paths, overwrote) {
|
|
@@ -2153,7 +2213,7 @@ var Engine = class {
|
|
|
2153
2213
|
hashOfVersion(version)
|
|
2154
2214
|
])
|
|
2155
2215
|
);
|
|
2156
|
-
const others = this.windows.filter((
|
|
2216
|
+
const others = this.windows.filter((open2) => !sameWho(open2.who, who));
|
|
2157
2217
|
const groups = this.outside ? [this.outside, ...others] : others;
|
|
2158
2218
|
const hits = groups.flatMap(
|
|
2159
2219
|
(group) => [...group.changes.values()].filter((change) => wanted.has(change.path)).map((change) => ({ group, change }))
|
|
@@ -2303,7 +2363,7 @@ var Engine = class {
|
|
|
2303
2363
|
}
|
|
2304
2364
|
/** A watcher saw a write: one sweep per burst takes it in (a deleted folder is reported by its name alone). */
|
|
2305
2365
|
noteChange(path) {
|
|
2306
|
-
const absolute =
|
|
2366
|
+
const absolute = resolve8(this.dir, path);
|
|
2307
2367
|
if (this.notedTimer || !affectsProjectSignature(this.dir, absolute)) return;
|
|
2308
2368
|
if (!isHistoryPath(relative5(this.dir, absolute).split(sep5).join("/"))) return;
|
|
2309
2369
|
this.notedTimer = setTimeout(() => {
|
|
@@ -2323,12 +2383,12 @@ var Engine = class {
|
|
|
2323
2383
|
const at = this.now();
|
|
2324
2384
|
if (exclusive) {
|
|
2325
2385
|
const blocking = this.windows.find(
|
|
2326
|
-
(
|
|
2386
|
+
(open2) => !sameWho(open2.who, who) && takesWrite(open2, at)
|
|
2327
2387
|
);
|
|
2328
2388
|
if (blocking)
|
|
2329
2389
|
throw new Error(`${blocking.who.name}'s turn is open; it has to end before yours begins`);
|
|
2330
|
-
for (const
|
|
2331
|
-
if (!takesWrite(
|
|
2390
|
+
for (const open2 of [...this.windows])
|
|
2391
|
+
if (!takesWrite(open2, at) || sameWho(open2.who, who)) await this.endWindow(open2);
|
|
2332
2392
|
}
|
|
2333
2393
|
const window = { ...this.newGroup(who, label), idleMs };
|
|
2334
2394
|
this.windows.push(window);
|
|
@@ -2365,7 +2425,7 @@ var Engine = class {
|
|
|
2365
2425
|
if (!this.windows.includes(window)) return window.entry ?? null;
|
|
2366
2426
|
clearTimeout(window.idleTimer);
|
|
2367
2427
|
await this.commitClaim();
|
|
2368
|
-
this.windows = this.windows.filter((
|
|
2428
|
+
this.windows = this.windows.filter((open2) => open2 !== window);
|
|
2369
2429
|
window.entry = await this.commit(window) ?? window.entry ?? null;
|
|
2370
2430
|
return window.entry;
|
|
2371
2431
|
}
|
|
@@ -2424,7 +2484,7 @@ var Engine = class {
|
|
|
2424
2484
|
);
|
|
2425
2485
|
await this.sweep();
|
|
2426
2486
|
} finally {
|
|
2427
|
-
this.windows = this.windows.filter((
|
|
2487
|
+
this.windows = this.windows.filter((open2) => open2 !== group);
|
|
2428
2488
|
}
|
|
2429
2489
|
return this.commit(group, extra);
|
|
2430
2490
|
}
|
|
@@ -2491,7 +2551,7 @@ var Engine = class {
|
|
|
2491
2551
|
);
|
|
2492
2552
|
if (pending) return direction === "back" ? this.pendingEntry(pending) : void 0;
|
|
2493
2553
|
const everyone = this.options.undoScope === "everyone";
|
|
2494
|
-
const ofOpenTurn = (entry) => this.windows.some((
|
|
2554
|
+
const ofOpenTurn = (entry) => this.windows.some((open2) => open2.parts?.has(entry.id));
|
|
2495
2555
|
return stepTarget(
|
|
2496
2556
|
this.log.entries,
|
|
2497
2557
|
direction,
|
|
@@ -2590,7 +2650,7 @@ var Engine = class {
|
|
|
2590
2650
|
checkout: (entryId, side, emptyDir) => this.queue(async () => {
|
|
2591
2651
|
this.entry(entryId);
|
|
2592
2652
|
if (!existsSync3(this.dir)) throw new Error(`The project folder is gone: ${this.dir}`);
|
|
2593
|
-
const dest =
|
|
2653
|
+
const dest = resolve8(emptyDir);
|
|
2594
2654
|
if (isWithin(this.dir, dest))
|
|
2595
2655
|
throw new Error(`Checkout writes outside the project only: ${dest}`);
|
|
2596
2656
|
if ((await readdir3(dest).catch(missingIsEmpty)).length > 0)
|
|
@@ -2641,7 +2701,7 @@ var Engine = class {
|
|
|
2641
2701
|
}
|
|
2642
2702
|
};
|
|
2643
2703
|
function isWithin(dir, path) {
|
|
2644
|
-
let probe =
|
|
2704
|
+
let probe = resolve8(path);
|
|
2645
2705
|
while (!existsSync3(probe) && dirname5(probe) !== probe) probe = dirname5(probe);
|
|
2646
2706
|
const rel = relative5(realpathSync.native(dir), realpathSync.native(probe));
|
|
2647
2707
|
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep5}`) && !isAbsolute5(rel);
|
|
@@ -2694,7 +2754,7 @@ async function openProjectHistory(options) {
|
|
|
2694
2754
|
}
|
|
2695
2755
|
}
|
|
2696
2756
|
function readProjectHistory(options) {
|
|
2697
|
-
const dir =
|
|
2757
|
+
const dir = resolve8(options.projectDir);
|
|
2698
2758
|
const id = readId(dir);
|
|
2699
2759
|
const home = id && isRecordedFolder(join8(options.historyRoot, id), statSync5(dir)) ? join8(options.historyRoot, id) : null;
|
|
2700
2760
|
const read = home && readLog(logFileIn(home), () => {
|
|
@@ -2771,14 +2831,14 @@ async function reclaimUncopiedBlobs(historyRoot, { dryRun = false, onError } = {
|
|
|
2771
2831
|
}
|
|
2772
2832
|
|
|
2773
2833
|
// src/history/historyCache.ts
|
|
2774
|
-
function historyCache(
|
|
2834
|
+
function historyCache(open2) {
|
|
2775
2835
|
const histories = /* @__PURE__ */ new Map();
|
|
2776
2836
|
const get = async (projectDir) => {
|
|
2777
2837
|
let cached = histories.get(projectDir);
|
|
2778
|
-
if (!cached) histories.set(projectDir, cached =
|
|
2838
|
+
if (!cached) histories.set(projectDir, cached = open2(projectDir));
|
|
2779
2839
|
const opened = await cached;
|
|
2780
2840
|
if (!opened?.replacedAtPath()) return opened;
|
|
2781
|
-
const reopen = () =>
|
|
2841
|
+
const reopen = () => open2(projectDir);
|
|
2782
2842
|
if (histories.get(projectDir) === cached)
|
|
2783
2843
|
histories.set(projectDir, opened.close().then(reopen, reopen));
|
|
2784
2844
|
return get(projectDir);
|
|
@@ -2810,6 +2870,8 @@ export {
|
|
|
2810
2870
|
clearFileWriteReceipt,
|
|
2811
2871
|
identifyFileWrite,
|
|
2812
2872
|
consumeFileWriteReceipt,
|
|
2873
|
+
serveWhileOpen,
|
|
2874
|
+
onRestoredInPlace,
|
|
2813
2875
|
HistoryIdError,
|
|
2814
2876
|
listProjectHistories,
|
|
2815
2877
|
pruneGoneProjectHistories,
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
isAutoProxyEnabled,
|
|
5
5
|
proxyEtagSalt,
|
|
6
6
|
resolvePreviewMediaCodecProbeCache
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-YOCRTHW3.js";
|
|
8
|
+
import "../chunk-KPCW4DQM.js";
|
|
9
9
|
import "../chunk-FUTDRYQK.js";
|
|
10
10
|
import "../chunk-X73QTST2.js";
|
|
11
11
|
import "../chunk-QF7MFJJU.js";
|
package/dist/history/index.d.ts
CHANGED
|
@@ -17,6 +17,10 @@ declare class HistoryBusyError extends Error {
|
|
|
17
17
|
constructor(pid: number, url?: string | undefined);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
type InPlaceOutcome = "restored" | "mismatch" | "failed";
|
|
21
|
+
type InPlaceListener = (absPath: string, outcome: InPlaceOutcome) => void;
|
|
22
|
+
declare function onRestoredInPlace(listener: InPlaceListener): () => void;
|
|
23
|
+
|
|
20
24
|
declare class HistoryIdError extends Error {
|
|
21
25
|
constructor(message: string);
|
|
22
26
|
}
|
|
@@ -148,4 +152,4 @@ declare function registerRenderOutput(projectDir: string, output: string): Promi
|
|
|
148
152
|
/** Explicit outputs remain user evidence even when reusing a managed UUID folder. */
|
|
149
153
|
declare function retainSnapshotOutput(project: string, path: string): void;
|
|
150
154
|
|
|
151
|
-
export { type ArtifactCapture, type ArtifactInput, type ArtifactRecord, HistoryBusyError, HistoryIdError, HistoryTarget, HistoryWho, ProjectHistory, type ProjectHistoryRecord, type PrunedHistory, type ReclaimedHistory, type RenderRecord, type VideoState, artifactDirectory, beginArtifactCapture, finishSnapshotRun, forgetRecordedArtifacts, historyCache, listProjectHistories, pruneGoneProjectHistories, reclaimUncopiedBlobs, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput, retainSnapshotOutput };
|
|
155
|
+
export { type ArtifactCapture, type ArtifactInput, type ArtifactRecord, HistoryBusyError, HistoryIdError, HistoryTarget, HistoryWho, type InPlaceOutcome, ProjectHistory, type ProjectHistoryRecord, type PrunedHistory, type ReclaimedHistory, type RenderRecord, type VideoState, artifactDirectory, beginArtifactCapture, finishSnapshotRun, forgetRecordedArtifacts, historyCache, listProjectHistories, onRestoredInPlace, pruneGoneProjectHistories, reclaimUncopiedBlobs, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput, retainSnapshotOutput };
|
package/dist/history/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
forgetRecordedArtifacts,
|
|
14
14
|
historyCache,
|
|
15
15
|
listProjectHistories,
|
|
16
|
+
onRestoredInPlace,
|
|
16
17
|
openProjectHistory,
|
|
17
18
|
pruneGoneProjectHistories,
|
|
18
19
|
readProjectHistory,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
recordRenderSuccess,
|
|
23
24
|
registerRenderOutput,
|
|
24
25
|
retainSnapshotOutput
|
|
25
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-UMPRW7BV.js";
|
|
26
27
|
import "../chunk-QF7MFJJU.js";
|
|
27
28
|
import "../chunk-SVQFE44C.js";
|
|
28
29
|
import "../chunk-L3HJVTQE.js";
|
|
@@ -41,6 +42,7 @@ export {
|
|
|
41
42
|
forgetRecordedArtifacts,
|
|
42
43
|
historyCache,
|
|
43
44
|
listProjectHistories,
|
|
45
|
+
onRestoredInPlace,
|
|
44
46
|
openProjectHistory,
|
|
45
47
|
pruneGoneProjectHistories,
|
|
46
48
|
readProjectHistory,
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Hono } from 'hono';
|
|
|
2
2
|
import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-DIEtpLJo.js';
|
|
3
3
|
export { L as LintResult, a as PreviewApiAdapter, R as RenderJobState, b as ResolvedProject, c as StudioSelectionResponse, d as StudioSelectionSnapshot, e as StudioSelectionTextField } from './mediaProxyPreview-DIEtpLJo.js';
|
|
4
4
|
export { C as ClosedWindow, D as DEFAULT_HISTORY_ROOT, S as HISTORY_START, H as HistoryClosedError, a as HistoryEntry, b as HistoryEntrySide, c as HistoryFileChange, d as HistoryListItem, e as HistoryRefusedError, f as HistoryResult, g as HistoryTarget, h as HistoryWho, i as HistoryWindow, M as MAX_WINDOW_IDLE_MS, P as ProjectHistory, j as ProjectHistoryOptions, k as ProjectHistoryView, U as UNDO_MODES, l as UndoMode, o as openProjectHistory, r as readProjectHistory } from './projectHistory-C18HDvac.js';
|
|
5
|
-
export { ArtifactCapture, ArtifactInput, ArtifactRecord, HistoryBusyError, HistoryIdError, ProjectHistoryRecord, PrunedHistory, ReclaimedHistory, RenderRecord, VideoState, artifactDirectory, beginArtifactCapture, finishSnapshotRun, forgetRecordedArtifacts, historyCache, listProjectHistories, pruneGoneProjectHistories, reclaimUncopiedBlobs, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput, retainSnapshotOutput } from './history/index.js';
|
|
5
|
+
export { ArtifactCapture, ArtifactInput, ArtifactRecord, HistoryBusyError, HistoryIdError, InPlaceOutcome, ProjectHistoryRecord, PrunedHistory, ReclaimedHistory, RenderRecord, VideoState, artifactDirectory, beginArtifactCapture, finishSnapshotRun, forgetRecordedArtifacts, historyCache, listProjectHistories, onRestoredInPlace, pruneGoneProjectHistories, reclaimUncopiedBlobs, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput, retainSnapshotOutput } from './history/index.js';
|
|
6
6
|
export { CACHE_DIR_NAME as PROXY_CACHE_DIR_NAME } from './helpers/proxyTranscoder.js';
|
|
7
7
|
export { walkDir } from './helpers/safePath.js';
|
|
8
8
|
export { stampProjectHfIds } from './helpers/hfIdPersist.js';
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
historyCache,
|
|
50
50
|
identifyFileWrite,
|
|
51
51
|
listProjectHistories,
|
|
52
|
+
onRestoredInPlace,
|
|
52
53
|
openProjectHistory,
|
|
53
54
|
pruneGoneProjectHistories,
|
|
54
55
|
readProjectHistory,
|
|
@@ -61,8 +62,9 @@ import {
|
|
|
61
62
|
resolveProjectAndSignature,
|
|
62
63
|
resolveProjectSignature,
|
|
63
64
|
retainSnapshotOutput,
|
|
65
|
+
serveWhileOpen,
|
|
64
66
|
settledFileTag
|
|
65
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-UMPRW7BV.js";
|
|
66
68
|
import {
|
|
67
69
|
clearElementScreenshotIsolation,
|
|
68
70
|
getElementScreenshotClip
|
|
@@ -82,7 +84,7 @@ import {
|
|
|
82
84
|
isAutoProxyEnabled,
|
|
83
85
|
proxyEtagSalt,
|
|
84
86
|
resolvePreviewMediaCodecProbeCache
|
|
85
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-YOCRTHW3.js";
|
|
86
88
|
import {
|
|
87
89
|
CACHE_DIR_NAME,
|
|
88
90
|
PROXY_PENDING_RETRY_AFTER_SECONDS,
|
|
@@ -95,7 +97,7 @@ import {
|
|
|
95
97
|
resolveProxy,
|
|
96
98
|
retryProxyCopy,
|
|
97
99
|
waitForProxy
|
|
98
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-KPCW4DQM.js";
|
|
99
101
|
import {
|
|
100
102
|
PROXY_VARIANT_CONFIG,
|
|
101
103
|
decideMediaProxyEligibility,
|
|
@@ -3930,6 +3932,7 @@ import {
|
|
|
3930
3932
|
import {
|
|
3931
3933
|
PREVIEW_PROXY_BOX_PARAM,
|
|
3932
3934
|
PREVIEW_PROXY_LIGHT_PARAM,
|
|
3935
|
+
PREVIEW_PROXY_PRIORITY_HEADER,
|
|
3933
3936
|
PREVIEW_PROXY_PROGRESS_HEADER,
|
|
3934
3937
|
PREVIEW_PROXY_RETRY_PARAM,
|
|
3935
3938
|
parsePreviewProxyBox
|
|
@@ -4632,7 +4635,11 @@ ${etag}`;
|
|
|
4632
4635
|
if (c.req.query(PREVIEW_PROXY_RETRY_PARAM) !== void 0) {
|
|
4633
4636
|
retryProxyCopy(project.dir, file, proxyVariant, proxyBox);
|
|
4634
4637
|
}
|
|
4635
|
-
|
|
4638
|
+
const priority = c.req.header(PREVIEW_PROXY_PRIORITY_HEADER) === "1";
|
|
4639
|
+
servedPath = await waitForProxy(
|
|
4640
|
+
resolveProxy(project.dir, file, proxyVariant, proxyBox, { priority }),
|
|
4641
|
+
0
|
|
4642
|
+
);
|
|
4636
4643
|
} catch (err) {
|
|
4637
4644
|
if (err instanceof ProxyWaitTimeoutError) {
|
|
4638
4645
|
const progress = proxyCopyProgress(project.dir, file, proxyVariant, proxyBox);
|
|
@@ -4659,7 +4666,7 @@ ${etag}`;
|
|
|
4659
4666
|
// Node's web stream type and the DOM one do not overlap for tsc on
|
|
4660
4667
|
// every platform's lib set; the double cast is the documented bridge.
|
|
4661
4668
|
Readable.toWeb(
|
|
4662
|
-
createReadStream(servedPath, { start, end })
|
|
4669
|
+
serveWhileOpen(servedPath, createReadStream(servedPath, { start, end }))
|
|
4663
4670
|
)
|
|
4664
4671
|
);
|
|
4665
4672
|
const rangeHeader = c.req.header("Range");
|
|
@@ -7007,6 +7014,7 @@ export {
|
|
|
7007
7014
|
identifyFileWrite,
|
|
7008
7015
|
isSafePath,
|
|
7009
7016
|
listProjectHistories,
|
|
7017
|
+
onRestoredInPlace,
|
|
7010
7018
|
openProjectHistory,
|
|
7011
7019
|
parseSourceDocument,
|
|
7012
7020
|
patchElementInHtml,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio-server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.211",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/heygen-com/hyperframes",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"linkedom": "^0.18.12",
|
|
85
85
|
"postcss": "^8.5.8",
|
|
86
86
|
"postcss-selector-parser": "^7.1.2",
|
|
87
|
-
"@hyperframes/core": "0.8.
|
|
88
|
-
"@hyperframes/parsers": "0.8.
|
|
87
|
+
"@hyperframes/core": "0.8.211",
|
|
88
|
+
"@hyperframes/parsers": "0.8.211"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@types/node": "^25.0.10",
|