@hyperframes/studio-server 0.8.170 → 0.8.171
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-SZF3L5MT.js → chunk-GG4AS4RK.js} +32 -11
- package/dist/helpers/mediaProxyPreview.d.ts +2 -2
- package/dist/history/index.d.ts +4 -3
- package/dist/history/index.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +31 -2
- package/dist/{mediaProxyPreview-J8vlAvrx.d.ts → mediaProxyPreview-6bL5skob.d.ts} +1 -1
- package/dist/{projectHistory-C5dpCjPU.d.ts → projectHistory-ByC9sa3X.d.ts} +1 -0
- package/package.json +3 -3
|
@@ -107,15 +107,17 @@ import { replaceFileAtomically } from "@hyperframes/core/atomic-file";
|
|
|
107
107
|
|
|
108
108
|
// src/history/ownerLock.ts
|
|
109
109
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
110
|
-
import { linkSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
110
|
+
import { linkSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
|
|
111
111
|
import { join } from "path";
|
|
112
112
|
var HistoryBusyError = class extends Error {
|
|
113
|
-
constructor(pid) {
|
|
113
|
+
constructor(pid, url) {
|
|
114
114
|
super(`This project's history is open in another process (pid ${pid}).`);
|
|
115
115
|
this.pid = pid;
|
|
116
|
+
this.url = url;
|
|
116
117
|
this.name = "HistoryBusyError";
|
|
117
118
|
}
|
|
118
119
|
pid;
|
|
120
|
+
url;
|
|
119
121
|
};
|
|
120
122
|
function alive(pid) {
|
|
121
123
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -166,14 +168,32 @@ function evictDeadOwner(file) {
|
|
|
166
168
|
releaseOwn(evictor);
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
|
-
|
|
171
|
+
function advertise(urlFile, url) {
|
|
172
|
+
if (!url) return rmSync(urlFile, { force: true });
|
|
173
|
+
const draft = `${urlFile}-${process.pid}-${randomUUID2()}.tmp`;
|
|
174
|
+
writeFileSync(draft, JSON.stringify({ pid: process.pid, url }));
|
|
175
|
+
renameSync(draft, urlFile);
|
|
176
|
+
}
|
|
177
|
+
function servedBy(file, urlFile, pid) {
|
|
178
|
+
try {
|
|
179
|
+
const said = JSON.parse(readFileSync(urlFile, "utf-8"));
|
|
180
|
+
const live = said.pid === pid && alive(pid) && ownerOf(file) === pid;
|
|
181
|
+
return live && typeof said.url === "string" ? said.url : void 0;
|
|
182
|
+
} catch {
|
|
183
|
+
return void 0;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async function takeHistoryOwnership(home, waitMs, url) {
|
|
170
187
|
const file = join(home, "owner.pid");
|
|
188
|
+
const urlFile = join(home, "owner-url.json");
|
|
171
189
|
const deadline = Date.now() + waitMs;
|
|
172
190
|
mkdirSync(home, { recursive: true });
|
|
173
191
|
for (; ; ) {
|
|
174
192
|
if (claim(file)) {
|
|
193
|
+
advertise(urlFile, url);
|
|
175
194
|
let held = true;
|
|
176
195
|
return () => {
|
|
196
|
+
if (held && servedBy(file, urlFile, process.pid)) rmSync(urlFile, { force: true });
|
|
177
197
|
if (held) releaseOwn(file);
|
|
178
198
|
held = false;
|
|
179
199
|
};
|
|
@@ -181,7 +201,7 @@ async function takeHistoryOwnership(home, waitMs) {
|
|
|
181
201
|
const pid = ownerOf(file);
|
|
182
202
|
if (pid === null) continue;
|
|
183
203
|
if (!alive(pid) && evictDeadOwner(file)) continue;
|
|
184
|
-
if (Date.now() >= deadline) throw new HistoryBusyError(pid);
|
|
204
|
+
if (Date.now() >= deadline) throw new HistoryBusyError(pid, servedBy(file, urlFile, pid));
|
|
185
205
|
await new Promise((settle) => setTimeout(settle, 50));
|
|
186
206
|
}
|
|
187
207
|
}
|
|
@@ -411,7 +431,7 @@ function createProjectSignature(projectDir, excluding = /* @__PURE__ */ new Set(
|
|
|
411
431
|
|
|
412
432
|
// src/history/blobStore.ts
|
|
413
433
|
import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
|
|
414
|
-
import { constants, createReadStream, createWriteStream, renameSync } from "fs";
|
|
434
|
+
import { constants, createReadStream, createWriteStream, renameSync as renameSync2 } from "fs";
|
|
415
435
|
import { copyFile, mkdir, readdir, readFile, rename, rm, stat } from "fs/promises";
|
|
416
436
|
import { dirname, join as join2 } from "path";
|
|
417
437
|
import { pipeline } from "stream/promises";
|
|
@@ -441,7 +461,7 @@ async function cloneOrCopy(from, to, beforeReplace) {
|
|
|
441
461
|
try {
|
|
442
462
|
await copyFile(from, temp, constants.COPYFILE_FICLONE);
|
|
443
463
|
beforeReplace?.();
|
|
444
|
-
|
|
464
|
+
renameSync2(temp, to);
|
|
445
465
|
} catch (error) {
|
|
446
466
|
await rm(temp, { force: true });
|
|
447
467
|
throw error;
|
|
@@ -493,7 +513,7 @@ async function openBlobStore(dir) {
|
|
|
493
513
|
|
|
494
514
|
// src/history/pruneHistories.ts
|
|
495
515
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
496
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync5, renameSync as
|
|
516
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync5, renameSync as renameSync3, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
497
517
|
import { lstat, readdir as readdir2, rm as rm2 } from "fs/promises";
|
|
498
518
|
import { tmpdir } from "os";
|
|
499
519
|
import { dirname as dirname2, join as join4 } from "path";
|
|
@@ -657,7 +677,7 @@ function recheckAndMoveAway(historyRoot, id, { now, dryRun, tempDir }) {
|
|
|
657
677
|
if (projectDir === null) return null;
|
|
658
678
|
if (dryRun) return { projectDir, trash: null };
|
|
659
679
|
const trash = join4(historyRoot, `${PRUNED_PREFIX}${id}-${randomUUID5()}`);
|
|
660
|
-
|
|
680
|
+
renameSync3(home, trash);
|
|
661
681
|
return { projectDir, trash };
|
|
662
682
|
}
|
|
663
683
|
function abandonedProject(home, id, now, tempDir) {
|
|
@@ -716,7 +736,7 @@ function pruneGoneProjectHistoriesDaily(historyRoot, now, { onError, budgetMs }
|
|
|
716
736
|
|
|
717
737
|
// src/history/videoState.ts
|
|
718
738
|
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
719
|
-
import { createReadStream as createReadStream2, existsSync as existsSync2, readFileSync as readFileSync8, renameSync as
|
|
739
|
+
import { createReadStream as createReadStream2, existsSync as existsSync2, readFileSync as readFileSync8, renameSync as renameSync4, statSync as statSync3 } from "fs";
|
|
720
740
|
import { isAbsolute as isAbsolute4, join as join7, resolve as resolve6 } from "path";
|
|
721
741
|
import { replaceFileAtomically as replaceFileAtomically3 } from "@hyperframes/core/atomic-file";
|
|
722
742
|
|
|
@@ -1117,7 +1137,7 @@ async function updateState(dir, update) {
|
|
|
1117
1137
|
state = readState(dir);
|
|
1118
1138
|
} catch (error) {
|
|
1119
1139
|
if (!(error instanceof SyntaxError)) throw error;
|
|
1120
|
-
|
|
1140
|
+
renameSync4(statePath(dir), `${statePath(dir)}.invalid-${randomUUID6()}`);
|
|
1121
1141
|
state = emptyState();
|
|
1122
1142
|
}
|
|
1123
1143
|
update(state);
|
|
@@ -2406,7 +2426,8 @@ async function openProjectHistory(options) {
|
|
|
2406
2426
|
const projectId = projectHistoryId(options.projectDir, options.historyRoot);
|
|
2407
2427
|
const release = await takeHistoryOwnership(
|
|
2408
2428
|
join8(options.historyRoot, projectId),
|
|
2409
|
-
options.ownerWaitMs ?? 5e3
|
|
2429
|
+
options.ownerWaitMs ?? 5e3,
|
|
2430
|
+
options.ownerUrl
|
|
2410
2431
|
);
|
|
2411
2432
|
try {
|
|
2412
2433
|
const blobs = await openBlobStore(join8(options.historyRoot, projectId, "blobs"));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '@hyperframes/core';
|
|
2
|
-
export { a as PreviewApiAdapter, P as PreviewDocumentStore, i as injectMediaCodecMap, f as injectMediaCodecMapIntoHtml, g as isAutoProxyEnabled, p as proxyEtagSalt, r as resolvePreviewMediaCodecProbeCache } from '../mediaProxyPreview-
|
|
2
|
+
export { a as PreviewApiAdapter, P as PreviewDocumentStore, i as injectMediaCodecMap, f as injectMediaCodecMapIntoHtml, g as isAutoProxyEnabled, p as proxyEtagSalt, r as resolvePreviewMediaCodecProbeCache } from '../mediaProxyPreview-6bL5skob.js';
|
|
3
3
|
import './mediaCodecMap.js';
|
|
4
4
|
import '@hyperframes/parsers';
|
|
5
5
|
import '@hyperframes/core/compiler';
|
|
6
|
-
import '../projectHistory-
|
|
6
|
+
import '../projectHistory-ByC9sa3X.js';
|
package/dist/history/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { P as ProjectHistory, f as HistoryTarget, g as HistoryWho } from '../projectHistory-
|
|
2
|
-
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 HistoryResult, h as HistoryWindow, M as MAX_WINDOW_IDLE_MS, i as ProjectHistoryOptions, j as ProjectHistoryView, U as UNDO_MODES, k as UndoMode, o as openProjectHistory, r as readProjectHistory } from '../projectHistory-
|
|
1
|
+
import { P as ProjectHistory, f as HistoryTarget, g as HistoryWho } from '../projectHistory-ByC9sa3X.js';
|
|
2
|
+
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 HistoryResult, h as HistoryWindow, M as MAX_WINDOW_IDLE_MS, i as ProjectHistoryOptions, j as ProjectHistoryView, U as UNDO_MODES, k as UndoMode, o as openProjectHistory, r as readProjectHistory } from '../projectHistory-ByC9sa3X.js';
|
|
3
3
|
|
|
4
4
|
declare class HistoryBusyError extends Error {
|
|
5
5
|
readonly pid: number;
|
|
6
|
-
|
|
6
|
+
readonly url?: string | undefined;
|
|
7
|
+
constructor(pid: number, url?: string | undefined);
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
declare class HistoryIdError extends Error {
|
package/dist/history/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-
|
|
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-
|
|
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 HistoryResult, f as HistoryTarget, g as HistoryWho, h as HistoryWindow, M as MAX_WINDOW_IDLE_MS, P as ProjectHistory, i as ProjectHistoryOptions, j as ProjectHistoryView, U as UNDO_MODES, k as UndoMode, o as openProjectHistory, r as readProjectHistory } from './projectHistory-
|
|
2
|
+
import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-6bL5skob.js';
|
|
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-6bL5skob.js';
|
|
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 HistoryResult, f as HistoryTarget, g as HistoryWho, h as HistoryWindow, M as MAX_WINDOW_IDLE_MS, P as ProjectHistory, i as ProjectHistoryOptions, j as ProjectHistoryView, U as UNDO_MODES, k as UndoMode, o as openProjectHistory, r as readProjectHistory } from './projectHistory-ByC9sa3X.js';
|
|
5
5
|
export { ArtifactCapture, ArtifactInput, ArtifactRecord, HistoryBusyError, HistoryIdError, ProjectHistoryRecord, PrunedHistory, RenderRecord, VideoState, artifactDirectory, beginArtifactCapture, finishSnapshotRun, forgetRecordedArtifacts, historyCache, listProjectHistories, pruneGoneProjectHistories, 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';
|
package/dist/index.js
CHANGED
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
resolveProjectSignature,
|
|
61
61
|
retainSnapshotOutput,
|
|
62
62
|
settledFileTag
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-GG4AS4RK.js";
|
|
64
64
|
import {
|
|
65
65
|
clearElementScreenshotIsolation,
|
|
66
66
|
getElementScreenshotClip
|
|
@@ -6409,6 +6409,33 @@ function nextStep(history, direction) {
|
|
|
6409
6409
|
const paths = target.files.map((file) => file.path);
|
|
6410
6410
|
return { id: target.id, label: target.label, endedAt: target.endedAt, paths };
|
|
6411
6411
|
}
|
|
6412
|
+
var LOOPBACK = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
|
|
6413
|
+
var FORWARD_DEADLINE_MS = 5e3;
|
|
6414
|
+
function ownerRoute(c, error) {
|
|
6415
|
+
if (!(error instanceof HistoryBusyError) || !error.url || !URL.canParse(error.url)) return null;
|
|
6416
|
+
const owner = new URL(error.url);
|
|
6417
|
+
if (owner.protocol !== "http:" || !LOOPBACK.has(owner.hostname)) return null;
|
|
6418
|
+
const rest = c.req.path.replace(/^.*?\/projects\/[^/]+\/history/, "");
|
|
6419
|
+
return `${owner.href.replace(/\/$/, "")}${rest}${new URL(c.req.url).search}`;
|
|
6420
|
+
}
|
|
6421
|
+
async function forward(c, target) {
|
|
6422
|
+
const token = c.req.header("X-Hyperframes-Write-Token");
|
|
6423
|
+
const reads = c.req.method === "GET" || c.req.method === "HEAD";
|
|
6424
|
+
const reply = await fetch(target, {
|
|
6425
|
+
method: c.req.method,
|
|
6426
|
+
headers: {
|
|
6427
|
+
"content-type": c.req.header("content-type") ?? "application/json",
|
|
6428
|
+
...token && { "X-Hyperframes-Write-Token": token }
|
|
6429
|
+
},
|
|
6430
|
+
...!reads && { body: await c.req.arrayBuffer() },
|
|
6431
|
+
signal: AbortSignal.timeout(FORWARD_DEADLINE_MS)
|
|
6432
|
+
});
|
|
6433
|
+
const type = reply.headers.get("content-type") ?? "application/json";
|
|
6434
|
+
return new Response(await reply.arrayBuffer(), {
|
|
6435
|
+
status: reply.status,
|
|
6436
|
+
headers: { "content-type": type }
|
|
6437
|
+
});
|
|
6438
|
+
}
|
|
6412
6439
|
async function withHistory(adapter, c, task) {
|
|
6413
6440
|
try {
|
|
6414
6441
|
const history = await historyOf(adapter, c);
|
|
@@ -6416,7 +6443,9 @@ async function withHistory(adapter, c, task) {
|
|
|
6416
6443
|
const result = await task(history, await bodyOf(c));
|
|
6417
6444
|
return result instanceof Response ? result : c.json(result ?? null);
|
|
6418
6445
|
} catch (error) {
|
|
6419
|
-
|
|
6446
|
+
const target = ownerRoute(c, error);
|
|
6447
|
+
const forwarded = target && await forward(c, target).catch(() => null);
|
|
6448
|
+
return forwarded || c.json({ error: error instanceof Error ? error.message : String(error) }, 409);
|
|
6420
6449
|
}
|
|
6421
6450
|
}
|
|
6422
6451
|
function registerHistoryRoutes(api, adapter) {
|
|
@@ -2,7 +2,7 @@ import * as _hyperframes_core from '@hyperframes/core';
|
|
|
2
2
|
import { RegistryItem, PreviewProxyBox } from '@hyperframes/core';
|
|
3
3
|
import { CanvasResolution } from '@hyperframes/parsers';
|
|
4
4
|
import { BundleOptions } from '@hyperframes/core/compiler';
|
|
5
|
-
import { P as ProjectHistory } from './projectHistory-
|
|
5
|
+
import { P as ProjectHistory } from './projectHistory-ByC9sa3X.js';
|
|
6
6
|
import { MediaCodecProbeCache, HtmlSourceLike } from './helpers/mediaCodecMap.js';
|
|
7
7
|
|
|
8
8
|
/** Resolved info about a single project. */
|
|
@@ -50,6 +50,7 @@ interface ProjectHistoryOptions {
|
|
|
50
50
|
onError?: (error: unknown) => void;
|
|
51
51
|
/** How long an open waits for another process to close the same history (default 5 s). */
|
|
52
52
|
ownerWaitMs?: number;
|
|
53
|
+
ownerUrl?: string;
|
|
53
54
|
/** A CLI turn's window from an earlier open: writes since, within its idle limit, become the entry with its id. */
|
|
54
55
|
closedWindow?: ClosedWindow;
|
|
55
56
|
closedWindowAfterOwnership?: () => ClosedWindow | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio-server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.171",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/heygen-com/hyperframes",
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
"postcss": "^8.5.8",
|
|
86
86
|
"postcss-selector-parser": "^7.1.2",
|
|
87
87
|
"sharp": "^0.35.0",
|
|
88
|
-
"@hyperframes/core": "0.8.
|
|
89
|
-
"@hyperframes/parsers": "0.8.
|
|
88
|
+
"@hyperframes/core": "0.8.171",
|
|
89
|
+
"@hyperframes/parsers": "0.8.171"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
92
|
"@types/node": "^25.0.10",
|