diff --git a/packages/core/src/studio-api/helpers/safePath.test.ts b/packages/core/src/studio-api/helpers/safePath.test.ts index fbfce353f..4a431792d 100644 --- a/packages/core/src/studio-api/helpers/safePath.test.ts +++ b/packages/core/src/studio-api/helpers/safePath.test.ts @@ -19,7 +19,7 @@ function createProjectDir(): string { } describe("walkDir", () => { - it("hides internal HyperFrames files from project listings", () => { + it("hides only internal HyperFrames backups, not vendored dot-directory files", () => { const projectDir = createProjectDir(); mkdirSync(join(projectDir, ".hyperframes", "backup"), { recursive: true }); mkdirSync(join(projectDir, ".hyperframes", "examples"), { recursive: true }); @@ -31,9 +31,11 @@ describe("walkDir", () => { writeFileSync(join(projectDir, "compositions", "scene.html"), "scene"); const files = walkDir(projectDir); + // Vendored dot-dir files stay browsable in the file tree (#1366) — only + // Studio's own backup snapshots are hidden (shouldIgnoreDir). expect(files).toContain(".cache/examples/preset.html"); + expect(files).toContain(".hyperframes/examples/preset.html"); expect(files).toContain("compositions/scene.html"); expect(files).not.toContain(".hyperframes/backup/snapshot.html"); - expect(files).not.toContain(".hyperframes/examples/preset.html"); }); }); diff --git a/packages/core/src/studio-api/helpers/safePath.ts b/packages/core/src/studio-api/helpers/safePath.ts index 4da2a529d..2f9a18e56 100644 --- a/packages/core/src/studio-api/helpers/safePath.ts +++ b/packages/core/src/studio-api/helpers/safePath.ts @@ -6,7 +6,11 @@ import { readdirSync } from "node:fs"; // Re-exported here for back-compat with existing `../helpers/safePath.js` imports. export { isSafePath } from "../../safePath.js"; -const IGNORE_DIRS = new Set([".thumbnails", ".hyperframes", "node_modules", ".git"]); +const IGNORE_DIRS = new Set([".thumbnails", "node_modules", ".git"]); + +function shouldIgnoreDir(rel: string): boolean { + return rel === ".hyperframes/backup"; +} /** * True when any directory segment of a relative path is a dot-directory or @@ -25,7 +29,7 @@ export function walkDir(dir: string, prefix = ""): string[] { const files: string[] = []; for (const entry of readdirSync(dir, { withFileTypes: true })) { const rel = prefix ? `${prefix}/${entry.name}` : entry.name; - if (IGNORE_DIRS.has(entry.name)) continue; + if (IGNORE_DIRS.has(entry.name) || shouldIgnoreDir(rel)) continue; if (entry.isDirectory()) { files.push(...walkDir(join(dir, entry.name), rel)); } else {