Skip to content

Commit cffada0

Browse files
vanceingallsclaude
andcommitted
fix(studio): watch external project dirs so preview ETag invalidates
Project dirs are symlinked into data/projects from anywhere on disk, but the preview signature cache was only invalidated by Vite's watcher, whose roots don't cover external paths. Edits hit disk while the cached ETag kept serving 304s — the browser showed a stale preview after refresh and edits looked lost. Register each project dir with the watcher when its signature is first cached. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 70d5fe8 commit cffada0

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

packages/studio/vite.adapter.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export function createViteAdapter(dataDir: string, server: ViteDevServer): Studi
9292
};
9393

9494
return {
95+
// fallow-ignore-next-line complexity
9596
listProjects() {
9697
if (!existsSync(dataDir)) return [];
9798
const sessionsDir = resolve(dataDir, "../sessions");
@@ -130,6 +131,7 @@ export function createViteAdapter(dataDir: string, server: ViteDevServer): Studi
130131
.sort((a, b) => (a.title ?? "").localeCompare(b.title ?? ""));
131132
},
132133

134+
// fallow-ignore-next-line complexity
133135
resolveProject(id: string) {
134136
let projectDir = join(dataDir, id);
135137
if (!existsSync(projectDir)) {
@@ -177,6 +179,11 @@ export function createViteAdapter(dataDir: string, server: ViteDevServer): Studi
177179
const cacheKey = resolve(projectDir);
178180
const cached = projectSignatureCache.get(cacheKey);
179181
if (cached) return cached;
182+
// Project dirs are symlinked from anywhere on disk (often outside the
183+
// studio package), so Vite's default watch roots don't cover them.
184+
// Without this, the signature cache never invalidates for external
185+
// projects and the preview ETag serves stale 304s after edits.
186+
server.watcher.add(cacheKey);
180187
const signature = createProjectSignature(cacheKey);
181188
projectSignatureCache.set(cacheKey, signature);
182189
return signature;
@@ -200,6 +207,7 @@ export function createViteAdapter(dataDir: string, server: ViteDevServer): Studi
200207
};
201208

202209
const startTime = Date.now();
210+
// fallow-ignore-next-line complexity
203211
(async () => {
204212
try {
205213
if (!process.env.PRODUCER_HEADLESS_SHELL_PATH) {
@@ -260,6 +268,7 @@ export function createViteAdapter(dataDir: string, server: ViteDevServer): Studi
260268
return null;
261269
},
262270

271+
// fallow-ignore-next-line complexity
263272
async listRegistryCatalog(): Promise<RegistryItem[]> {
264273
const registryRoot = resolve(__dirname, "../../registry");
265274
const items: RegistryItem[] = [];

0 commit comments

Comments
 (0)