mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
feat: cache shader transition preview frames (#634)
* feat: cache shader transition preview frames * fix: move shader transition loading to player
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { shouldWatchProjectFile } from "./fileWatcher.js";
|
||||
|
||||
describe("shouldWatchProjectFile", () => {
|
||||
it("watches files that can affect the project signature", () => {
|
||||
expect(shouldWatchProjectFile("index.html")).toBe(true);
|
||||
expect(shouldWatchProjectFile("src/scene.tsx")).toBe(true);
|
||||
expect(shouldWatchProjectFile("assets/hero.png")).toBe(true);
|
||||
expect(shouldWatchProjectFile("Dockerfile")).toBe(true);
|
||||
});
|
||||
|
||||
it("skips generated and dependency directories excluded from signatures", () => {
|
||||
expect(shouldWatchProjectFile("node_modules/pkg/index.js")).toBe(false);
|
||||
expect(shouldWatchProjectFile("renders/output.mp4")).toBe(false);
|
||||
expect(shouldWatchProjectFile("dist/index.html")).toBe(false);
|
||||
expect(shouldWatchProjectFile(".hyperframes/cache.json")).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -8,9 +8,27 @@ export interface ProjectWatcher {
|
||||
close(): void;
|
||||
}
|
||||
|
||||
const WATCHED_EXTENSIONS = new Set([".html", ".css", ".js", ".json"]);
|
||||
const WATCHER_EXCLUDED_DIRS = new Set([
|
||||
".cache",
|
||||
".git",
|
||||
".hyperframes",
|
||||
".next",
|
||||
".vite",
|
||||
"build",
|
||||
"coverage",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"outputs",
|
||||
"renders",
|
||||
]);
|
||||
const DEBOUNCE_MS = 300;
|
||||
|
||||
export function shouldWatchProjectFile(filename: string): boolean {
|
||||
if (!filename) return false;
|
||||
const parts = filename.split(/[\\/]+/);
|
||||
return !parts.some((part) => WATCHER_EXCLUDED_DIRS.has(part));
|
||||
}
|
||||
|
||||
export function createProjectWatcher(projectDir: string): ProjectWatcher {
|
||||
const listeners = new Set<FileChangeListener>();
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
@@ -19,13 +37,13 @@ export function createProjectWatcher(projectDir: string): ProjectWatcher {
|
||||
try {
|
||||
watcher = watch(projectDir, { recursive: true }, (_event, filename) => {
|
||||
if (!filename) return;
|
||||
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
||||
if (!WATCHED_EXTENSIONS.has(ext)) return;
|
||||
const relativePath = filename.toString();
|
||||
if (!shouldWatchProjectFile(relativePath)) return;
|
||||
|
||||
if (debounceTimer) clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(() => {
|
||||
for (const fn of listeners) {
|
||||
fn(filename);
|
||||
fn(relativePath);
|
||||
}
|
||||
}, DEBOUNCE_MS);
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ import { loadRuntimeSource } from "./runtimeSource.js";
|
||||
import { VERSION as version } from "../version.js";
|
||||
import {
|
||||
createStudioApi,
|
||||
createProjectSignature,
|
||||
getMimeType,
|
||||
type StudioApiAdapter,
|
||||
type ResolvedProject,
|
||||
@@ -144,6 +145,10 @@ export function createStudioServer(options: StudioServerOptions): StudioServer {
|
||||
// ── CLI adapter for the shared studio API ──────────────────────────────
|
||||
|
||||
const project: ResolvedProject = { id: projectId, dir: projectDir, title: projectId };
|
||||
let cachedProjectSignature: string | null = null;
|
||||
watcher.addListener(() => {
|
||||
cachedProjectSignature = null;
|
||||
});
|
||||
|
||||
const adapter: StudioApiAdapter = {
|
||||
listProjects: () => [project],
|
||||
@@ -169,6 +174,12 @@ export function createStudioServer(options: StudioServerOptions): StudioServer {
|
||||
}
|
||||
},
|
||||
|
||||
getProjectSignature(dir: string): string {
|
||||
if (resolve(dir) !== resolve(projectDir)) return createProjectSignature(dir);
|
||||
cachedProjectSignature ??= createProjectSignature(projectDir);
|
||||
return cachedProjectSignature;
|
||||
},
|
||||
|
||||
async lint(html: string, opts?: { filePath?: string }) {
|
||||
const { lintHyperframeHtml } = await import("@hyperframes/core/lint");
|
||||
return lintHyperframeHtml(html, opts);
|
||||
|
||||
Reference in New Issue
Block a user