@hyperframes/studio-server 0.8.143 → 0.8.144
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-6EFY2WPN.js → chunk-AZBGTB3N.js} +97 -29
- package/dist/chunk-AZBGTB3N.js.map +1 -0
- package/dist/{chunk-AYKLBPP2.js → chunk-VE2AOX4K.js} +2 -2
- package/dist/helpers/mediaProxyPreview.d.ts +1 -1
- package/dist/helpers/mediaProxyPreview.js +2 -2
- package/dist/helpers/proxyTranscoder.d.ts +12 -12
- package/dist/helpers/proxyTranscoder.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/{mediaProxyPreview-CJ4lbPcF.d.ts → mediaProxyPreview-ozy7FkMP.d.ts} +1 -0
- package/package.json +3 -3
- package/dist/chunk-6EFY2WPN.js.map +0 -1
- /package/dist/{chunk-AYKLBPP2.js.map → chunk-VE2AOX4K.js.map} +0 -0
|
@@ -235,31 +235,67 @@ function getProxyCachePath(projectDir, absoluteSourcePath, variant = "h264") {
|
|
|
235
235
|
variant
|
|
236
236
|
);
|
|
237
237
|
}
|
|
238
|
+
var ProxyDroppedError = class extends ProxyTranscodeError {
|
|
239
|
+
constructor() {
|
|
240
|
+
super("media proxy copy dropped: every caller left before it started", null, "");
|
|
241
|
+
this.name = "ProxyDroppedError";
|
|
242
|
+
}
|
|
243
|
+
};
|
|
238
244
|
var activeTranscodes = 0;
|
|
239
245
|
var waitQueue = [];
|
|
240
|
-
function
|
|
246
|
+
function enqueue(job) {
|
|
247
|
+
const firstNormal = job.priority ? waitQueue.findIndex((queued) => !queued.priority) : -1;
|
|
248
|
+
if (firstNormal === -1) waitQueue.push(job);
|
|
249
|
+
else waitQueue.splice(firstNormal, 0, job);
|
|
250
|
+
}
|
|
251
|
+
function dequeue(job) {
|
|
252
|
+
const index = waitQueue.indexOf(job);
|
|
253
|
+
if (index !== -1) waitQueue.splice(index, 1);
|
|
254
|
+
}
|
|
255
|
+
function acquireSlot(job) {
|
|
256
|
+
if (activeTranscodes < MAX_CONCURRENT_TRANSCODES) {
|
|
257
|
+
activeTranscodes++;
|
|
258
|
+
return Promise.resolve();
|
|
259
|
+
}
|
|
241
260
|
return new Promise((resolveSlot, reject) => {
|
|
242
|
-
|
|
243
|
-
|
|
261
|
+
job.queued = {
|
|
262
|
+
start: () => {
|
|
263
|
+
job.queued = void 0;
|
|
244
264
|
activeTranscodes++;
|
|
245
265
|
resolveSlot();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
266
|
+
},
|
|
267
|
+
drop: () => {
|
|
268
|
+
job.queued = void 0;
|
|
269
|
+
dequeue(job);
|
|
270
|
+
forget(job);
|
|
271
|
+
reject(new ProxyDroppedError());
|
|
252
272
|
}
|
|
253
273
|
};
|
|
254
|
-
|
|
274
|
+
enqueue(job);
|
|
255
275
|
});
|
|
256
276
|
}
|
|
277
|
+
function queueIsFull() {
|
|
278
|
+
return activeTranscodes >= MAX_CONCURRENT_TRANSCODES && waitQueue.length >= MAX_QUEUED_TRANSCODES;
|
|
279
|
+
}
|
|
257
280
|
function releaseSlot() {
|
|
258
281
|
activeTranscodes--;
|
|
259
|
-
|
|
260
|
-
|
|
282
|
+
waitQueue.shift()?.queued?.start();
|
|
283
|
+
}
|
|
284
|
+
function prioritize(job) {
|
|
285
|
+
if (job.priority) return;
|
|
286
|
+
job.priority = true;
|
|
287
|
+
if (!job.queued) return;
|
|
288
|
+
dequeue(job);
|
|
289
|
+
enqueue(job);
|
|
290
|
+
}
|
|
291
|
+
function leave(job) {
|
|
292
|
+
job.callers--;
|
|
293
|
+
if (job.callers === 0) job.queued?.drop();
|
|
261
294
|
}
|
|
262
295
|
var inFlight = /* @__PURE__ */ new Map();
|
|
296
|
+
function forget(job) {
|
|
297
|
+
if (inFlight.get(job.cachePath)?.job === job) inFlight.delete(job.cachePath);
|
|
298
|
+
}
|
|
263
299
|
function maintainProxyCache(cacheDir) {
|
|
264
300
|
try {
|
|
265
301
|
cleanupProxyCache(cacheDir, { protectedPaths: new Set(inFlight.keys()) });
|
|
@@ -421,8 +457,8 @@ async function runFfmpeg(sourcePath, outputPath, variant, box) {
|
|
|
421
457
|
});
|
|
422
458
|
});
|
|
423
459
|
}
|
|
424
|
-
async function transcodeToCache(projectDir, absoluteSourcePath, cachePath, variant, box) {
|
|
425
|
-
await acquireSlot();
|
|
460
|
+
async function transcodeToCache(job, projectDir, absoluteSourcePath, cachePath, variant, box) {
|
|
461
|
+
await acquireSlot(job);
|
|
426
462
|
try {
|
|
427
463
|
if (existsSync2(cachePath)) return cachePath;
|
|
428
464
|
const cacheDir = dirname(cachePath);
|
|
@@ -440,14 +476,15 @@ async function transcodeToCache(projectDir, absoluteSourcePath, cachePath, varia
|
|
|
440
476
|
releaseSlot();
|
|
441
477
|
}
|
|
442
478
|
}
|
|
443
|
-
var
|
|
479
|
+
var proxyActivity = 0;
|
|
444
480
|
function proxyActivityMark(projectDir) {
|
|
445
|
-
if (!existsSync2(projectDir)) return String(
|
|
481
|
+
if (!existsSync2(projectDir)) return String(proxyActivity);
|
|
446
482
|
const cacheDir = join2(realpath(projectDir), CACHE_DIR_NAME) + sep;
|
|
447
483
|
for (const cachePath of inFlight.keys()) if (cachePath.startsWith(cacheDir)) return null;
|
|
448
|
-
return String(
|
|
484
|
+
return String(proxyActivity);
|
|
449
485
|
}
|
|
450
|
-
async function resolveProxy(projectDir, absoluteSourcePath, variant = "h264", box) {
|
|
486
|
+
async function resolveProxy(projectDir, absoluteSourcePath, variant = "h264", box, options = {}) {
|
|
487
|
+
options.signal?.throwIfAborted();
|
|
451
488
|
const source = canonicalizeProxySource(projectDir, absoluteSourcePath);
|
|
452
489
|
const cachePath = getCanonicalProxyCachePath(source, variant, box);
|
|
453
490
|
if (existsSync2(cachePath)) {
|
|
@@ -460,17 +497,48 @@ async function resolveProxy(projectDir, absoluteSourcePath, variant = "h264", bo
|
|
|
460
497
|
if (rememberedFailure.expiresAt > Date.now()) throw rememberedFailure.error;
|
|
461
498
|
failedTranscodes.delete(cachePath);
|
|
462
499
|
}
|
|
463
|
-
|
|
464
|
-
if (
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
500
|
+
let entry = inFlight.get(cachePath);
|
|
501
|
+
if (!entry) {
|
|
502
|
+
if (!options.priority && queueIsFull()) {
|
|
503
|
+
proxyActivity += 1;
|
|
504
|
+
throw new ProxyCapacityError();
|
|
505
|
+
}
|
|
506
|
+
const job = {
|
|
507
|
+
cachePath,
|
|
508
|
+
priority: options.priority === true,
|
|
509
|
+
callers: 0
|
|
510
|
+
};
|
|
511
|
+
const promise = transcodeToCache(
|
|
512
|
+
job,
|
|
513
|
+
source.projectDir,
|
|
514
|
+
source.sourcePath,
|
|
515
|
+
cachePath,
|
|
516
|
+
variant,
|
|
517
|
+
box
|
|
518
|
+
).catch((err) => {
|
|
519
|
+
if (!(err instanceof ProxyDroppedError)) rememberFailure(cachePath, err);
|
|
520
|
+
throw err;
|
|
521
|
+
}).finally(() => {
|
|
522
|
+
forget(job);
|
|
523
|
+
proxyActivity += 1;
|
|
524
|
+
});
|
|
525
|
+
entry = { promise, job };
|
|
526
|
+
inFlight.set(cachePath, entry);
|
|
527
|
+
}
|
|
528
|
+
if (options.priority) prioritize(entry.job);
|
|
529
|
+
return joinJob(entry.promise, entry.job, options.signal);
|
|
530
|
+
}
|
|
531
|
+
function joinJob(promise, job, signal) {
|
|
532
|
+
job.callers++;
|
|
533
|
+
if (!signal) return promise;
|
|
534
|
+
return new Promise((resolveJoin, rejectJoin) => {
|
|
535
|
+
const onAbort = () => {
|
|
536
|
+
leave(job);
|
|
537
|
+
rejectJoin(signal.reason);
|
|
538
|
+
};
|
|
539
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
540
|
+
promise.finally(() => signal.removeEventListener("abort", onAbort)).then(resolveJoin, rejectJoin);
|
|
471
541
|
});
|
|
472
|
-
inFlight.set(cachePath, promise);
|
|
473
|
-
return promise;
|
|
474
542
|
}
|
|
475
543
|
|
|
476
544
|
export {
|
|
@@ -491,4 +559,4 @@ export {
|
|
|
491
559
|
proxyActivityMark,
|
|
492
560
|
resolveProxy
|
|
493
561
|
};
|
|
494
|
-
//# sourceMappingURL=chunk-
|
|
562
|
+
//# sourceMappingURL=chunk-AZBGTB3N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/helpers/proxyTranscoder.ts","../src/helpers/proxyCache.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, renameSync, statSync, unlinkSync, utimesSync } from \"node:fs\";\nimport { basename, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport {\n formatPreviewProxyBox,\n hdrToSdrToneMapFilter,\n type PreviewProxyBox,\n} from \"@hyperframes/core\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\nimport { probeFirstFrameColour, probeMediaMetadata } from \"./mediaMetadata.js\";\nimport { cleanupProxyCache } from \"./proxyCache.js\";\nimport { PROXY_VARIANT_CONFIG, type ProxyVariant } from \"./mediaCodecMap.js\";\nimport { mkdirWithinProject, realpath, realProjectRoot } from \"./safePath.js\";\n\n/**\n * Transcodes browser-hostile local video sources (HEVC, ProRes, ...) into a\n * cached, seekable authoring proxy. Consumed by the preview/play/static\n * project routes (U3/U4) to serve a `?hf-proxy=` request; never used on\n * the render path (render always sees the original file).\n *\n * A started ffmpeg child is never killed for one caller: every caller of a cache\n * key shares it (in-flight dedupe below). A caller's `signal` only detaches that\n * caller, and drops the copy while it is still queued with no caller left.\n */\n\nexport const PROXY_PARAMS_VERSION = \"v5\";\n\nexport const CACHE_DIR_NAME = \".transcode-cache\";\n\nfunction boundedEnvInteger(name: string, fallback: number, min: number, max: number): number {\n const raw = process.env[name]?.trim();\n if (!raw) return fallback;\n const parsed = Number(raw);\n return Number.isSafeInteger(parsed) && parsed >= min && parsed <= max ? parsed : fallback;\n}\n\n// ffmpeg is internally multithreaded, so two concurrent proxy encodes already\n// saturate a typical laptop. Operators of shared/large machines may tune the\n// bounded values without patching the package; invalid values fail safe.\nconst MAX_CONCURRENT_TRANSCODES = boundedEnvInteger(\"HYPERFRAMES_PROXY_MAX_CONCURRENCY\", 2, 1, 16);\nconst MAX_QUEUED_TRANSCODES = boundedEnvInteger(\"HYPERFRAMES_PROXY_MAX_QUEUE\", 8, 0, 256);\n\nconst STDERR_TAIL_MAX_CHARS = 4000;\nexport const TRANSCODE_TIMEOUT_MS = 15 * 60 * 1000;\nconst FAILURE_CACHE_TTL_MS = 60 * 1000;\nexport const PROXY_PENDING_RETRY_AFTER_SECONDS = 2;\nconst ENVIRONMENT_FAILURE_TTL_MS = 5 * PROXY_PENDING_RETRY_AFTER_SECONDS * 1000;\nconst MAX_FAILURE_CACHE_ENTRIES = 128;\nexport const DEFAULT_PROXY_WAIT_TIMEOUT_MS = 2 * 60 * 1000;\n\nexport class ProxyTranscodeError extends Error {\n readonly exitCode: number | null;\n readonly stderrTail: string;\n\n constructor(message: string, exitCode: number | null, stderrTail: string) {\n super(message);\n this.name = \"ProxyTranscodeError\";\n this.exitCode = exitCode;\n this.stderrTail = stderrTail;\n }\n}\n\n/** \"ffmpeg isn't installed\" — an environment condition, not a per-source\n * failure, so the negative cache below keeps it only briefly\n * (installing ffmpeg mid-session must recover without a server restart). */\nclass FfmpegUnavailableError extends ProxyTranscodeError {\n constructor() {\n super(\"ffmpeg binary not found\", null, \"\");\n }\n}\n\nexport class FfmpegMissingFilterError extends ProxyTranscodeError {\n constructor() {\n super(\n \"HDR proxying requires ffmpeg zscale/tonemap filters (libzimg); install an ffmpeg build with libzimg support\",\n null,\n \"\",\n );\n this.name = \"FfmpegMissingFilterError\";\n }\n}\n\nexport class ProxyCapacityError extends ProxyTranscodeError {\n constructor() {\n super(\"media proxy queue is full; retry shortly\", null, \"\");\n this.name = \"ProxyCapacityError\";\n }\n}\n\nexport class ProxySourceOutsideProjectError extends ProxyTranscodeError {\n constructor() {\n super(\"media proxy source must be addressed through the project\", null, \"\");\n this.name = \"ProxySourceOutsideProjectError\";\n }\n}\n\nexport class ProxyWaitTimeoutError extends ProxyTranscodeError {\n constructor(timeoutMs: number) {\n super(`media proxy did not become ready within ${timeoutMs}ms`, null, \"\");\n this.name = \"ProxyWaitTimeoutError\";\n }\n}\n\n/** Bounds one caller's wait without cancelling the shared in-flight ffmpeg\n * job. Other preview/publish callers still receive the completed cache entry. */\nexport async function waitForProxy<T>(\n promise: Promise<T>,\n timeoutMs = DEFAULT_PROXY_WAIT_TIMEOUT_MS,\n): Promise<T> {\n let timer: NodeJS.Timeout | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => reject(new ProxyWaitTimeoutError(timeoutMs)), timeoutMs);\n timer.unref();\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\n/**\n * Cache key inputs per the plan: project-relative source path (portable across\n * checkouts), canonical source identity (so retargeted external symlinks do\n * not reuse a proxy), mtime and file size (mtime alone can collide on\n * same-second re-exports on coarse-timestamp filesystems; size catches nearly\n * all such cases at zero cost), and a params version token so changing the\n * ffmpeg recipe below invalidates every cached proxy cleanly.\n */\ntype CanonicalProxySource = {\n projectDir: string;\n sourcePath: string;\n relativePath: string;\n cacheIdentity: string;\n};\n\nfunction canonicalizeProxySource(\n projectDir: string,\n absoluteSourcePath: string,\n): CanonicalProxySource {\n const requestedProjectDir = resolve(projectDir);\n const requestedSourcePath = resolve(absoluteSourcePath);\n const requestedRelativePath = relative(requestedProjectDir, requestedSourcePath);\n if (\n requestedRelativePath === \"..\" ||\n requestedRelativePath.startsWith(`..${sep}`) ||\n isAbsolute(requestedRelativePath)\n ) {\n throw new ProxySourceOutsideProjectError();\n }\n\n const canonicalProjectDir = realProjectRoot(projectDir);\n const canonicalSourcePath = realpath(absoluteSourcePath);\n const canonicalRelativePath = relative(canonicalProjectDir, canonicalSourcePath);\n const sourceIsInsideCanonicalProject =\n canonicalRelativePath !== \"..\" &&\n !canonicalRelativePath.startsWith(`..${sep}`) &&\n !isAbsolute(canonicalRelativePath);\n return {\n projectDir: canonicalProjectDir,\n sourcePath: canonicalSourcePath,\n relativePath: requestedRelativePath.normalize(\"NFC\"),\n // An external target needs a stable identity in addition to its project-local\n // symlink path, otherwise retargeting the link can reuse an unrelated proxy.\n cacheIdentity: (sourceIsInsideCanonicalProject\n ? canonicalRelativePath\n : canonicalSourcePath\n ).normalize(\"NFC\"),\n };\n}\n\nfunction buildProxyCacheKey(\n source: CanonicalProxySource,\n variant: ProxyVariant,\n box: PreviewProxyBox | undefined,\n): string {\n const stat = statSync(source.sourcePath);\n const size = box ? `\\0${formatPreviewProxyBox(box)}` : \"\";\n return createHash(\"sha256\")\n .update(\n `${source.relativePath}\\0${source.cacheIdentity}\\0${stat.mtimeMs}\\0${stat.size}\\0${PROXY_PARAMS_VERSION}\\0${variant}${size}`,\n )\n .digest(\"hex\");\n}\n\nfunction getCanonicalProxyCachePath(\n source: CanonicalProxySource,\n variant: ProxyVariant,\n box?: PreviewProxyBox,\n): string {\n const key = buildProxyCacheKey(source, variant, box);\n return join(\n source.projectDir,\n CACHE_DIR_NAME,\n `${key}${PROXY_VARIANT_CONFIG[variant].extension}`,\n );\n}\n\n/**\n * Computes the absolute path a proxy for this source would live at, without\n * transcoding anything. Route handlers use this to check cache state (e.g.\n * for ETag/If-None-Match) before deciding whether to await a transcode.\n */\nexport function getProxyCachePath(\n projectDir: string,\n absoluteSourcePath: string,\n variant: ProxyVariant = \"h264\",\n): string {\n return getCanonicalProxyCachePath(\n canonicalizeProxySource(projectDir, absoluteSourcePath),\n variant,\n );\n}\n\n// --- global concurrency limiter -------------------------------------------\n// ponytail: a counter + one wait queue is the whole semaphore. Priority copies\n// queue ahead of the rest and are never refused for a full queue, so a few\n// priority asks (the copy a viewer is waiting on) can exceed the cap.\n\n/** One copy per cache key, shared by every caller asking for it. */\ninterface ProxyJob {\n cachePath: string;\n priority: boolean;\n /** Callers still waiting; one without a signal never leaves, so its copy is always made. */\n callers: number;\n /** Set while the job waits for a slot. */\n queued?: { start: () => void; drop: () => void };\n}\n\nclass ProxyDroppedError extends ProxyTranscodeError {\n constructor() {\n super(\"media proxy copy dropped: every caller left before it started\", null, \"\");\n this.name = \"ProxyDroppedError\";\n }\n}\n\nlet activeTranscodes = 0;\nconst waitQueue: ProxyJob[] = [];\n\nfunction enqueue(job: ProxyJob): void {\n const firstNormal = job.priority ? waitQueue.findIndex((queued) => !queued.priority) : -1;\n if (firstNormal === -1) waitQueue.push(job);\n else waitQueue.splice(firstNormal, 0, job);\n}\n\nfunction dequeue(job: ProxyJob): void {\n const index = waitQueue.indexOf(job);\n if (index !== -1) waitQueue.splice(index, 1);\n}\n\nfunction acquireSlot(job: ProxyJob): Promise<void> {\n if (activeTranscodes < MAX_CONCURRENT_TRANSCODES) {\n activeTranscodes++;\n return Promise.resolve();\n }\n return new Promise((resolveSlot, reject) => {\n job.queued = {\n start: () => {\n job.queued = undefined;\n activeTranscodes++;\n resolveSlot();\n },\n drop: () => {\n job.queued = undefined;\n dequeue(job);\n forget(job);\n reject(new ProxyDroppedError());\n },\n };\n enqueue(job);\n });\n}\n\nfunction queueIsFull(): boolean {\n return activeTranscodes >= MAX_CONCURRENT_TRANSCODES && waitQueue.length >= MAX_QUEUED_TRANSCODES;\n}\n\nfunction releaseSlot(): void {\n activeTranscodes--;\n waitQueue.shift()?.queued?.start();\n}\n\nfunction prioritize(job: ProxyJob): void {\n if (job.priority) return;\n job.priority = true;\n if (!job.queued) return;\n dequeue(job);\n enqueue(job);\n}\n\nfunction leave(job: ProxyJob): void {\n job.callers--;\n if (job.callers === 0) job.queued?.drop();\n}\n\n// --- per-key in-flight dedupe ----------------------------------------------\n\nconst inFlight = new Map<string, { promise: Promise<string>; job: ProxyJob }>();\n\nfunction forget(job: ProxyJob): void {\n if (inFlight.get(job.cachePath)?.job === job) inFlight.delete(job.cachePath);\n}\n\nfunction maintainProxyCache(cacheDir: string): void {\n try {\n cleanupProxyCache(cacheDir, { protectedPaths: new Set(inFlight.keys()) });\n } catch (error) {\n // Cache maintenance must never turn a playable preview into an error.\n console.warn(\n `[media-proxy] cache cleanup failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\nfunction markCacheEntryUsed(cachePath: string): void {\n try {\n const now = new Date();\n utimesSync(cachePath, now, now);\n } catch {\n // A concurrent cleanup may have removed a stale entry after existsSync;\n // the normal miss path below will recreate it on the next request.\n }\n}\n\n// --- negative cache ---------------------------------------------------------\n// A source that failed to transcode fails again identically until the file\n// changes (the cache key embeds mtime+size, so a re-export invalidates this\n// naturally). Remembering the failure per key means repeated `?hf-proxy=`\n// requests for a broken asset rethrow instantly instead of respawning ffmpeg\n// on every retry the browser makes.\ninterface RememberedFailure {\n error: unknown;\n expiresAt: number;\n}\n\nconst failedTranscodes = new Map<string, RememberedFailure>();\n\nlet hdrFilterCheck: { ffmpegPath: string; promise: Promise<void> } | undefined;\n\nfunction ensureHdrFilters(ffmpegPath: string): Promise<void> {\n if (hdrFilterCheck?.ffmpegPath === ffmpegPath) return hdrFilterCheck.promise;\n const promise = new Promise<void>((resolveCheck, rejectCheck) => {\n const proc = spawn(ffmpegPath, [\"-hide_banner\", \"-filters\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n });\n let stdout = \"\";\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n proc.on(\"error\", () => rejectCheck(new FfmpegMissingFilterError()));\n proc.on(\"close\", (code) => {\n if (code !== 0 || !/\\bzscale\\b/.test(stdout) || !/\\btonemap\\b/.test(stdout)) {\n rejectCheck(new FfmpegMissingFilterError());\n } else {\n resolveCheck();\n }\n });\n });\n hdrFilterCheck = { ffmpegPath, promise };\n return promise;\n}\n\nfunction rememberFailure(cachePath: string, error: unknown): void {\n const ttlMs =\n error instanceof FfmpegUnavailableError || error instanceof FfmpegMissingFilterError\n ? ENVIRONMENT_FAILURE_TTL_MS\n : FAILURE_CACHE_TTL_MS;\n failedTranscodes.delete(cachePath);\n failedTranscodes.set(cachePath, { error, expiresAt: Date.now() + ttlMs });\n while (failedTranscodes.size > MAX_FAILURE_CACHE_ENTRIES) {\n const oldest = failedTranscodes.keys().next().value;\n if (oldest === undefined) break;\n failedTranscodes.delete(oldest);\n }\n}\n\n/** Test hook: forget remembered transcode failures (module state persists\n * across tests that don't reload the module). */\nexport function clearFailedTranscodesForTest(): void {\n failedTranscodes.clear();\n}\n\n/** Even dimensions; with a box, the source shrinks until its tighter side fills the box, never grows. */\nfunction proxyScaleFilter(box?: PreviewProxyBox): string {\n if (!box) return \"scale=trunc(iw/2)*2:trunc(ih/2)*2\";\n const factor = `min(1\\\\,max(${box.width}/iw\\\\,${box.height}/ih))`;\n const side = (d: string) => `min(trunc(${d}/2)*2\\\\,ceil(${d}*${factor}/2)*2)`;\n return `scale=${side(\"iw\")}:${side(\"ih\")}`;\n}\n\nasync function runFfmpeg(\n sourcePath: string,\n outputPath: string,\n variant: ProxyVariant,\n box: PreviewProxyBox | undefined,\n): Promise<void> {\n const metadata = await probeMediaMetadata(sourcePath);\n const ffmpegPath = findFfBinary(\"ffmpeg\", { configuredMustExist: true });\n if (!ffmpegPath) {\n throw new FfmpegUnavailableError();\n }\n const keepsAlpha = variant === \"vp8\";\n const { hdrTransfer } = metadata.color;\n const toneMap = (hdrTransfer === \"pq\" || hdrTransfer === \"hlg\") && !keepsAlpha;\n if (toneMap) await ensureHdrFilters(ffmpegPath);\n const firstFrame = toneMap ? await probeFirstFrameColour(sourcePath) : {};\n const evenScale = proxyScaleFilter(box);\n const pixelFormat = keepsAlpha ? \"yuva420p\" : \"yuv420p\";\n // The tone map ends in RGB; older ffmpeg (seen on 5.1) converts it with BT.601 unless the matrix is named.\n const videoFilter = toneMap\n ? [\n hdrToSdrToneMapFilter(metadata.color, firstFrame),\n `${evenScale}:out_color_matrix=bt709:out_range=tv`,\n `format=${pixelFormat}`,\n ].join(\",\")\n : [evenScale, `format=${pixelFormat}`].join(\",\");\n\n return new Promise((resolvePromise, reject) => {\n const commonArgs = [\"-y\", \"-i\", sourcePath, \"-vf\", videoFilter];\n const h264Args = [\n \"-c:v\",\n \"libx264\",\n \"-profile:v\",\n \"high\",\n \"-pix_fmt\",\n \"yuv420p\",\n \"-colorspace\",\n \"bt709\",\n \"-color_primaries\",\n \"bt709\",\n \"-color_trc\",\n \"bt709\",\n \"-crf\",\n \"18\",\n \"-preset\",\n \"veryfast\",\n \"-c:a\",\n \"aac\",\n \"-movflags\",\n \"+faststart\",\n ];\n const vp8Args = [\n \"-c:v\",\n \"libvpx\",\n \"-b:v\",\n \"0\",\n \"-crf\",\n \"23\",\n \"-deadline\",\n \"good\",\n \"-pix_fmt\",\n \"yuva420p\",\n \"-colorspace\",\n \"bt709\",\n \"-color_primaries\",\n \"bt709\",\n \"-color_trc\",\n \"bt709\",\n \"-cpu-used\",\n \"4\",\n \"-auto-alt-ref\",\n \"0\",\n \"-metadata:s:v:0\",\n \"alpha_mode=1\",\n \"-ac\",\n \"2\",\n \"-c:a\",\n \"libopus\",\n ];\n const args = [...commonArgs, ...(variant === \"vp8\" ? vp8Args : h264Args), outputPath];\n\n // Hard ceiling so a hung ffmpeg can never permanently occupy one of the\n // global transcode slots: the child is killed and the slot released via\n // the caller's finally. Generous because long assets transcode at\n // roughly real time; a healthy encode of any authoring asset fits.\n const proc = spawn(ffmpegPath, args, {\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n timeout: TRANSCODE_TIMEOUT_MS,\n killSignal: \"SIGKILL\",\n windowsHide: true,\n });\n let stderrTail = \"\";\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n stderrTail = (stderrTail + chunk.toString()).slice(-STDERR_TAIL_MAX_CHARS);\n });\n proc.on(\"error\", (err) => {\n reject(new ProxyTranscodeError(`failed to spawn ffmpeg: ${err.message}`, null, stderrTail));\n });\n proc.on(\"close\", (code, signal) => {\n if (code === 0) {\n resolvePromise();\n } else if (signal) {\n reject(\n new ProxyTranscodeError(\n `ffmpeg killed by ${signal} (timeout ${TRANSCODE_TIMEOUT_MS}ms or external kill)`,\n null,\n stderrTail,\n ),\n );\n } else {\n reject(new ProxyTranscodeError(`ffmpeg exited with code ${code}`, code, stderrTail));\n }\n });\n });\n}\n\nasync function transcodeToCache(\n job: ProxyJob,\n projectDir: string,\n absoluteSourcePath: string,\n cachePath: string,\n variant: ProxyVariant,\n box: PreviewProxyBox | undefined,\n): Promise<string> {\n await acquireSlot(job);\n try {\n // Another caller may have finished (or a pre-warm beat us) while queued.\n if (existsSync(cachePath)) return cachePath;\n\n const cacheDir = dirname(cachePath);\n mkdirWithinProject(projectDir, cacheDir);\n const tempPath = join(cacheDir, `.tmp-${randomUUID()}-${basename(cachePath)}`);\n try {\n await runFfmpeg(absoluteSourcePath, tempPath, variant, box);\n renameSync(tempPath, cachePath);\n maintainProxyCache(cacheDir);\n return cachePath;\n } finally {\n // No partial files: if anything above threw, remove whatever ffmpeg\n // may have partially written under the temp name.\n if (existsSync(tempPath)) unlinkSync(tempPath);\n }\n } finally {\n releaseSlot();\n }\n}\n\nlet proxyActivity = 0;\n\n/** Null while this project has a copy in progress; otherwise a mark that moves when any copy finishes or is refused. */\nexport function proxyActivityMark(projectDir: string): string | null {\n if (!existsSync(projectDir)) return String(proxyActivity);\n const cacheDir = join(realpath(projectDir), CACHE_DIR_NAME) + sep;\n for (const cachePath of inFlight.keys()) if (cachePath.startsWith(cacheDir)) return null;\n return String(proxyActivity);\n}\n\n/**\n * Resolves the cached proxy variant for `absoluteSourcePath`, transcoding it at\n * most once per cache key. Concurrent calls for the same key (including a\n * pre-warm call racing an element-triggered one) share one ffmpeg child and\n * one promise; calls for different keys queue through the global concurrency\n * limiter above. Throws `ProxyTranscodeError` on failure (missing ffmpeg or a\n * nonzero exit) — callers (route handlers) decide how to surface that (502).\n * A `box` makes a smaller preview-only copy with its own cache entry; without\n * one the copy keeps the source size (CLI play, static servers, publish).\n * `priority` moves the copy ahead of every normal queued copy; a `signal`\n * lets this caller leave (see the detachment note at the top of this file).\n */\nexport async function resolveProxy(\n projectDir: string,\n absoluteSourcePath: string,\n variant: ProxyVariant = \"h264\",\n box?: PreviewProxyBox,\n options: ResolveProxyOptions = {},\n): Promise<string> {\n options.signal?.throwIfAborted();\n const source = canonicalizeProxySource(projectDir, absoluteSourcePath);\n const cachePath = getCanonicalProxyCachePath(source, variant, box);\n if (existsSync(cachePath)) {\n markCacheEntryUsed(cachePath);\n maintainProxyCache(dirname(cachePath));\n return cachePath;\n }\n\n const rememberedFailure = failedTranscodes.get(cachePath);\n if (rememberedFailure) {\n if (rememberedFailure.expiresAt > Date.now()) throw rememberedFailure.error;\n failedTranscodes.delete(cachePath);\n }\n\n let entry = inFlight.get(cachePath);\n if (!entry) {\n if (!options.priority && queueIsFull()) {\n proxyActivity += 1;\n throw new ProxyCapacityError();\n }\n const job: ProxyJob = {\n cachePath,\n priority: options.priority === true,\n callers: 0,\n };\n const promise = transcodeToCache(\n job,\n source.projectDir,\n source.sourcePath,\n cachePath,\n variant,\n box,\n )\n .catch((err: unknown) => {\n if (!(err instanceof ProxyDroppedError)) rememberFailure(cachePath, err);\n throw err;\n })\n .finally(() => {\n forget(job);\n proxyActivity += 1;\n });\n entry = { promise, job };\n inFlight.set(cachePath, entry);\n }\n if (options.priority) prioritize(entry.job);\n return joinJob(entry.promise, entry.job, options.signal);\n}\n\nexport interface ResolveProxyOptions {\n priority?: boolean;\n signal?: AbortSignal;\n}\n\nfunction joinJob(promise: Promise<string>, job: ProxyJob, signal?: AbortSignal): Promise<string> {\n job.callers++;\n if (!signal) return promise;\n return new Promise((resolveJoin, rejectJoin) => {\n const onAbort = (): void => {\n leave(job);\n rejectJoin(signal.reason);\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n promise\n .finally(() => signal.removeEventListener(\"abort\", onAbort))\n .then(resolveJoin, rejectJoin);\n });\n}\n","import { existsSync, readdirSync, statSync, unlinkSync } from \"node:fs\";\nimport { extname, join } from \"node:path\";\nimport { PROXY_VARIANT_CONFIG } from \"./mediaCodecMap.js\";\n\nconst DEFAULT_MAX_BYTES = 10 * 1024 * 1024 * 1024;\nconst DEFAULT_STALE_TEMP_MS = 60 * 60 * 1000;\nconst DEFAULT_MIN_SWEEP_INTERVAL_MS = 5 * 60 * 1000;\nconst PROXY_EXTENSIONS: ReadonlySet<string> = new Set(\n Object.values(PROXY_VARIANT_CONFIG).map(({ extension }) => extension),\n);\nconst TRANSCODER_PROXY_NAME = /^[0-9a-f]{64}\\.\\w+$/;\nconst TRANSCODER_TEMP_NAME = /^\\.tmp-[0-9a-f-]{36}-[0-9a-f]{64}\\.\\w+$/;\n\nexport interface ProxyCacheCleanupOptions {\n maxBytes?: number;\n maxIdleMs?: number;\n staleTempMs?: number;\n minSweepIntervalMs?: number;\n protectedPaths?: ReadonlySet<string>;\n now?: number;\n dryRun?: boolean;\n}\n\nexport interface ProxyCacheCleanupResult {\n removed: string[];\n bytesBefore: number;\n bytesAfter: number;\n skipped: boolean;\n}\n\ninterface CacheEntry {\n path: string;\n size: number;\n modifiedAt: number;\n protected: boolean;\n}\n\nconst lastSweepAt = new Map<string, number>();\n\nfunction positiveEnvNumber(name: string, fallback: number): number {\n const parsed = Number(process.env[name]);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n}\n\nfunction proxyCacheCleanupDefaults(): Required<\n Pick<ProxyCacheCleanupOptions, \"maxBytes\" | \"maxIdleMs\" | \"staleTempMs\" | \"minSweepIntervalMs\">\n> {\n return {\n maxBytes: positiveEnvNumber(\"HYPERFRAMES_PROXY_CACHE_MAX_BYTES\", DEFAULT_MAX_BYTES),\n maxIdleMs: positiveEnvNumber(\"HYPERFRAMES_PROXY_CACHE_MAX_IDLE_DAYS\", 30) * 24 * 60 * 60 * 1000,\n staleTempMs: positiveEnvNumber(\"HYPERFRAMES_PROXY_CACHE_STALE_TEMP_MS\", DEFAULT_STALE_TEMP_MS),\n minSweepIntervalMs: positiveEnvNumber(\n \"HYPERFRAMES_PROXY_CACHE_SWEEP_INTERVAL_MS\",\n DEFAULT_MIN_SWEEP_INTERVAL_MS,\n ),\n };\n}\n\nfunction shouldSkipSweep(cacheDir: string, now: number, minSweepIntervalMs: number): boolean {\n const previousSweep = lastSweepAt.get(cacheDir);\n if (previousSweep !== undefined && now - previousSweep < minSweepIntervalMs) return true;\n lastSweepAt.set(cacheDir, now);\n return false;\n}\n\nfunction readCacheInventory(\n cacheDir: string,\n protectedPaths: ReadonlySet<string>,\n now: number,\n staleTempMs: number,\n): { entries: CacheEntry[]; staleTemps: CacheEntry[] } {\n const entries: CacheEntry[] = [];\n const staleTemps: CacheEntry[] = [];\n for (const dirent of readdirSync(cacheDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n const path = join(cacheDir, dirent.name);\n const stat = statSync(path);\n const entry = {\n path,\n size: stat.size,\n modifiedAt: stat.mtimeMs,\n protected: protectedPaths.has(path),\n };\n if (TRANSCODER_TEMP_NAME.test(dirent.name)) {\n if (now - stat.mtimeMs >= staleTempMs) staleTemps.push(entry);\n } else if (\n TRANSCODER_PROXY_NAME.test(dirent.name) &&\n PROXY_EXTENSIONS.has(extname(dirent.name))\n ) {\n entries.push(entry);\n }\n }\n const oldestFirst = (a: CacheEntry, b: CacheEntry): number =>\n a.modifiedAt - b.modifiedAt || a.path.localeCompare(b.path);\n entries.sort(oldestFirst);\n staleTemps.sort(oldestFirst);\n return { entries, staleTemps };\n}\n\nfunction evictCacheEntries(\n entries: CacheEntry[],\n staleTemps: CacheEntry[],\n now: number,\n maxIdleMs: number,\n maxBytes: number,\n dryRun: boolean,\n): Omit<ProxyCacheCleanupResult, \"skipped\"> {\n const bytesBefore = entries.reduce((total, entry) => total + entry.size, 0);\n let bytesAfter = bytesBefore;\n const removed: string[] = [];\n const remove = (entry: CacheEntry, countsTowardBudget: boolean): void => {\n if (!dryRun) unlinkSync(entry.path);\n removed.push(entry.path);\n if (countsTowardBudget) bytesAfter -= entry.size;\n };\n\n for (const entry of staleTemps) remove(entry, false);\n const kept: CacheEntry[] = [];\n for (const entry of entries) {\n if (!entry.protected && now - entry.modifiedAt >= maxIdleMs) remove(entry, true);\n else kept.push(entry);\n }\n for (const entry of kept) {\n if (bytesAfter <= maxBytes) break;\n if (!entry.protected && existsSync(entry.path)) remove(entry, true);\n }\n return { removed, bytesBefore, bytesAfter };\n}\n\n/**\n * Opportunistically bounds a project's transparent-proxy cache. Cleanup is\n * synchronous because callers already perform filesystem bookkeeping on the\n * preview request path, but rate limiting keeps the directory scan off the\n * hot path. Errors intentionally bubble so callers can warn without turning\n * a cache-maintenance failure into a preview failure.\n */\nexport function cleanupProxyCache(\n cacheDir: string,\n options: ProxyCacheCleanupOptions = {},\n): ProxyCacheCleanupResult {\n const defaults = proxyCacheCleanupDefaults();\n const now = options.now ?? Date.now();\n const minSweepIntervalMs = options.minSweepIntervalMs ?? defaults.minSweepIntervalMs;\n if (shouldSkipSweep(cacheDir, now, minSweepIntervalMs)) {\n return { removed: [], bytesBefore: 0, bytesAfter: 0, skipped: true };\n }\n if (!existsSync(cacheDir)) {\n return { removed: [], bytesBefore: 0, bytesAfter: 0, skipped: false };\n }\n\n const maxBytes = options.maxBytes ?? defaults.maxBytes;\n const maxIdleMs = options.maxIdleMs ?? defaults.maxIdleMs;\n const staleTempMs = options.staleTempMs ?? defaults.staleTempMs;\n const protectedPaths = options.protectedPaths ?? new Set<string>();\n const { entries, staleTemps } = readCacheInventory(cacheDir, protectedPaths, now, staleTempMs);\n return {\n ...evictCacheEntries(entries, staleTemps, now, maxIdleMs, maxBytes, options.dryRun ?? false),\n skipped: false,\n };\n}\n"],"mappings":"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","names":["existsSync","statSync","unlinkSync","join","statSync","join","existsSync","unlinkSync"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PROXY_PARAMS_VERSION,
|
|
3
3
|
resolveProxy
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AZBGTB3N.js";
|
|
5
5
|
import {
|
|
6
6
|
createMediaCodecProbeCache,
|
|
7
7
|
proxyVariantFor,
|
|
@@ -64,4 +64,4 @@ export {
|
|
|
64
64
|
injectMediaCodecMapIntoHtml,
|
|
65
65
|
injectMediaCodecMap
|
|
66
66
|
};
|
|
67
|
-
//# sourceMappingURL=chunk-
|
|
67
|
+
//# sourceMappingURL=chunk-VE2AOX4K.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
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-ozy7FkMP.js';
|
|
3
3
|
import './mediaCodecMap.js';
|
|
4
4
|
import '@hyperframes/parsers';
|
|
5
5
|
import '@hyperframes/core/compiler';
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
isAutoProxyEnabled,
|
|
5
5
|
proxyEtagSalt,
|
|
6
6
|
resolvePreviewMediaCodecProbeCache
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-VE2AOX4K.js";
|
|
8
|
+
import "../chunk-AZBGTB3N.js";
|
|
9
9
|
import "../chunk-RN33UALN.js";
|
|
10
10
|
import "../chunk-DTKK7TKL.js";
|
|
11
11
|
import "../chunk-6XMC64FJ.js";
|
|
@@ -7,15 +7,9 @@ import { ProxyVariant } from './mediaCodecMap.js';
|
|
|
7
7
|
* project routes (U3/U4) to serve a `?hf-proxy=` request; never used on
|
|
8
8
|
* the render path (render always sees the original file).
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* caller
|
|
13
|
-
* killed the ffmpeg child on client abort (page reload, HMR), every other
|
|
14
|
-
* caller waiting on that same promise would fail too, and the next request
|
|
15
|
-
* would restart a transcode that may have been minutes into a long asset.
|
|
16
|
-
* Callers MUST let the child run to completion regardless of request
|
|
17
|
-
* cancellation and simply let the held response also abort — the cache
|
|
18
|
-
* entry still lands for the next request.
|
|
10
|
+
* A started ffmpeg child is never killed for one caller: every caller of a cache
|
|
11
|
+
* key shares it (in-flight dedupe below). A caller's `signal` only detaches that
|
|
12
|
+
* caller, and drops the copy while it is still queued with no caller left.
|
|
19
13
|
*/
|
|
20
14
|
declare const PROXY_PARAMS_VERSION = "v5";
|
|
21
15
|
declare const CACHE_DIR_NAME = ".transcode-cache";
|
|
@@ -51,7 +45,7 @@ declare function getProxyCachePath(projectDir: string, absoluteSourcePath: strin
|
|
|
51
45
|
/** Test hook: forget remembered transcode failures (module state persists
|
|
52
46
|
* across tests that don't reload the module). */
|
|
53
47
|
declare function clearFailedTranscodesForTest(): void;
|
|
54
|
-
/** Null while
|
|
48
|
+
/** Null while this project has a copy in progress; otherwise a mark that moves when any copy finishes or is refused. */
|
|
55
49
|
declare function proxyActivityMark(projectDir: string): string | null;
|
|
56
50
|
/**
|
|
57
51
|
* Resolves the cached proxy variant for `absoluteSourcePath`, transcoding it at
|
|
@@ -62,7 +56,13 @@ declare function proxyActivityMark(projectDir: string): string | null;
|
|
|
62
56
|
* nonzero exit) — callers (route handlers) decide how to surface that (502).
|
|
63
57
|
* A `box` makes a smaller preview-only copy with its own cache entry; without
|
|
64
58
|
* one the copy keeps the source size (CLI play, static servers, publish).
|
|
59
|
+
* `priority` moves the copy ahead of every normal queued copy; a `signal`
|
|
60
|
+
* lets this caller leave (see the detachment note at the top of this file).
|
|
65
61
|
*/
|
|
66
|
-
declare function resolveProxy(projectDir: string, absoluteSourcePath: string, variant?: ProxyVariant, box?: PreviewProxyBox): Promise<string>;
|
|
62
|
+
declare function resolveProxy(projectDir: string, absoluteSourcePath: string, variant?: ProxyVariant, box?: PreviewProxyBox, options?: ResolveProxyOptions): Promise<string>;
|
|
63
|
+
interface ResolveProxyOptions {
|
|
64
|
+
priority?: boolean;
|
|
65
|
+
signal?: AbortSignal;
|
|
66
|
+
}
|
|
67
67
|
|
|
68
|
-
export { CACHE_DIR_NAME, DEFAULT_PROXY_WAIT_TIMEOUT_MS, FfmpegMissingFilterError, PROXY_PARAMS_VERSION, PROXY_PENDING_RETRY_AFTER_SECONDS, ProxyCapacityError, ProxySourceOutsideProjectError, ProxyTranscodeError, ProxyWaitTimeoutError, TRANSCODE_TIMEOUT_MS, clearFailedTranscodesForTest, getProxyCachePath, proxyActivityMark, resolveProxy, waitForProxy };
|
|
68
|
+
export { CACHE_DIR_NAME, DEFAULT_PROXY_WAIT_TIMEOUT_MS, FfmpegMissingFilterError, PROXY_PARAMS_VERSION, PROXY_PENDING_RETRY_AFTER_SECONDS, ProxyCapacityError, ProxySourceOutsideProjectError, ProxyTranscodeError, ProxyWaitTimeoutError, type ResolveProxyOptions, TRANSCODE_TIMEOUT_MS, clearFailedTranscodesForTest, getProxyCachePath, proxyActivityMark, resolveProxy, waitForProxy };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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-
|
|
2
|
+
import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-ozy7FkMP.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-ozy7FkMP.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 HistoryResult, f as HistoryWho, g as HistoryWindow, M as MAX_WINDOW_IDLE_MS, P as ProjectHistory, h as ProjectHistoryOptions, U as UNDO_MODES, i as UndoMode, o as openProjectHistory } from './projectHistory-Cm8Mdmmv.js';
|
|
5
5
|
export { HistoryBusyError, HistoryIdError, ProjectHistoryRecord, PrunedHistory, historyCache, listProjectHistories, pruneGoneProjectHistories } from './history/index.js';
|
|
6
6
|
export { CACHE_DIR_NAME as PROXY_CACHE_DIR_NAME } from './helpers/proxyTranscoder.js';
|
package/dist/index.js
CHANGED
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
isAutoProxyEnabled,
|
|
68
68
|
proxyEtagSalt,
|
|
69
69
|
resolvePreviewMediaCodecProbeCache
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-VE2AOX4K.js";
|
|
71
71
|
import {
|
|
72
72
|
CACHE_DIR_NAME,
|
|
73
73
|
PROXY_PENDING_RETRY_AFTER_SECONDS,
|
|
@@ -78,7 +78,7 @@ import {
|
|
|
78
78
|
proxyActivityMark,
|
|
79
79
|
resolveProxy,
|
|
80
80
|
waitForProxy
|
|
81
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-AZBGTB3N.js";
|
|
82
82
|
import {
|
|
83
83
|
PROXY_VARIANT_CONFIG,
|
|
84
84
|
decideMediaProxyEligibility,
|
|
@@ -4506,7 +4506,11 @@ async function lintUncoveredHtml(adapter, projectDir, htmlFiles, coveredFiles) {
|
|
|
4506
4506
|
for (const file of htmlFiles) {
|
|
4507
4507
|
if (coveredFiles.has(file)) continue;
|
|
4508
4508
|
const content = readFileSync7(join9(projectDir, file), "utf-8");
|
|
4509
|
-
const result = await adapter.lint(content, {
|
|
4509
|
+
const result = await adapter.lint(content, {
|
|
4510
|
+
filePath: file,
|
|
4511
|
+
isSubComposition: true,
|
|
4512
|
+
compSrcPath: file
|
|
4513
|
+
});
|
|
4510
4514
|
for (const finding of result?.findings ?? []) {
|
|
4511
4515
|
findings.push({ ...finding, file });
|
|
4512
4516
|
}
|