@hyperframes/studio-server 0.8.169 → 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 +43 -18
- 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
|
|
@@ -5857,7 +5857,6 @@ import { closeSync as closeSync3, constants, fstatSync as fstatSync3, openSync a
|
|
|
5857
5857
|
import {
|
|
5858
5858
|
collectFontFileEntries,
|
|
5859
5859
|
fontDirectories,
|
|
5860
|
-
getSystemProfilerFamilies,
|
|
5861
5860
|
locateSystemFont,
|
|
5862
5861
|
SYSTEM_FONT_SIZE_LIMIT
|
|
5863
5862
|
} from "@hyperframes/core/fonts/system-locator";
|
|
@@ -5897,10 +5896,6 @@ function collectFontsFromDir(dir) {
|
|
|
5897
5896
|
function listInstalledFontFamilies() {
|
|
5898
5897
|
if (cachedFonts) return cachedFonts;
|
|
5899
5898
|
const families = /* @__PURE__ */ new Set();
|
|
5900
|
-
for (const family of getSystemProfilerFamilies()) {
|
|
5901
|
-
families.add(family);
|
|
5902
|
-
if (families.size >= MAX_FONT_RESULTS) break;
|
|
5903
|
-
}
|
|
5904
5899
|
for (const dir of fontDirectories()) {
|
|
5905
5900
|
for (const family of collectFontsFromDir(dir)) {
|
|
5906
5901
|
families.add(family);
|
|
@@ -6414,13 +6409,43 @@ function nextStep(history, direction) {
|
|
|
6414
6409
|
const paths = target.files.map((file) => file.path);
|
|
6415
6410
|
return { id: target.id, label: target.label, endedAt: target.endedAt, paths };
|
|
6416
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
|
+
}
|
|
6417
6439
|
async function withHistory(adapter, c, task) {
|
|
6418
|
-
const history = await historyOf(adapter, c);
|
|
6419
|
-
if (!history) return c.json({ error: "This project has no history here." }, 404);
|
|
6420
6440
|
try {
|
|
6421
|
-
|
|
6441
|
+
const history = await historyOf(adapter, c);
|
|
6442
|
+
if (!history) return c.json({ error: "This project has no history here." }, 404);
|
|
6443
|
+
const result = await task(history, await bodyOf(c));
|
|
6444
|
+
return result instanceof Response ? result : c.json(result ?? null);
|
|
6422
6445
|
} catch (error) {
|
|
6423
|
-
|
|
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);
|
|
6424
6449
|
}
|
|
6425
6450
|
}
|
|
6426
6451
|
function registerHistoryRoutes(api, adapter) {
|
|
@@ -6474,14 +6499,14 @@ function registerHistoryRoutes(api, adapter) {
|
|
|
6474
6499
|
return { ok: true };
|
|
6475
6500
|
})
|
|
6476
6501
|
);
|
|
6477
|
-
api.get(
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6502
|
+
api.get(
|
|
6503
|
+
`${base}/blob/:hash`,
|
|
6504
|
+
(c) => withHistory(adapter, c, async (history) => {
|
|
6505
|
+
const hash = c.req.param("hash") ?? "";
|
|
6506
|
+
const bytes = /^[0-9a-f]{64}$/.test(hash) ? await history.readBlob(hash).catch(() => null) : null;
|
|
6507
|
+
return bytes ? c.body(new Uint8Array(bytes)) : c.json({ error: "That file is not kept in this project's history." }, 404);
|
|
6508
|
+
})
|
|
6509
|
+
);
|
|
6485
6510
|
api.post(
|
|
6486
6511
|
`${base}/claim`,
|
|
6487
6512
|
(c) => withHistory(adapter, c, async (history, body) => {
|
|
@@ -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",
|