mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-30 21:49:18 +01:00
Fix stale static SPA fallback html
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
4ad8727c42
commit
678ba3335e
3 files changed
+58
-2
No files matched your search
@@ -0,0 +1,49 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import express from "express";
|
||||
import request from "supertest";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { readBrandedStaticIndexHtml } from "../static-index-html.js";
|
||||
|
||||
describe("static SPA fallback HTML", () => {
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
afterEach(() => {
|
||||
for (const dir of tempDirs.splice(0)) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("serves the current index.html instead of reusing stale asset hashes", async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-static-index-"));
|
||||
tempDirs.push(tempDir);
|
||||
const indexPath = path.join(tempDir, "index.html");
|
||||
const app = express();
|
||||
app.get(/.*/, (_req, res) => {
|
||||
res
|
||||
.status(200)
|
||||
.set("Content-Type", "text/html")
|
||||
.set("Cache-Control", "no-cache")
|
||||
.end(readBrandedStaticIndexHtml(tempDir));
|
||||
});
|
||||
|
||||
fs.writeFileSync(
|
||||
indexPath,
|
||||
'<html><body><script type="module" src="/assets/index-old.js"></script></body></html>',
|
||||
"utf8",
|
||||
);
|
||||
await expect(request(app).get("/PAP/issues/PAP-9939")).resolves.toMatchObject({
|
||||
text: expect.stringContaining("/assets/index-old.js"),
|
||||
});
|
||||
|
||||
fs.writeFileSync(
|
||||
indexPath,
|
||||
'<html><body><script type="module" src="/assets/index-new.js"></script></body></html>',
|
||||
"utf8",
|
||||
);
|
||||
const res = await request(app).get("/PAP/issues/PAP-9939");
|
||||
expect(res.text).toContain("/assets/index-new.js");
|
||||
expect(res.text).not.toContain("/assets/index-old.js");
|
||||
});
|
||||
});
|
||||
+2
-2
@@ -41,6 +41,7 @@ import { accessRoutes } from "./routes/access.js";
|
||||
import { pluginRoutes } from "./routes/plugins.js";
|
||||
import { adapterRoutes } from "./routes/adapters.js";
|
||||
import { pluginUiStaticRoutes } from "./routes/plugin-ui-static.js";
|
||||
import { readBrandedStaticIndexHtml } from "./static-index-html.js";
|
||||
import { applyUiBranding } from "./ui-branding.js";
|
||||
import { logger } from "./middleware/logger.js";
|
||||
import { DEFAULT_LOCAL_PLUGIN_DIR, pluginLoader } from "./services/plugin-loader.js";
|
||||
@@ -328,7 +329,6 @@ export async function createApp(
|
||||
];
|
||||
const uiDist = candidates.find((p) => fs.existsSync(path.join(p, "index.html")));
|
||||
if (uiDist) {
|
||||
const indexHtml = applyUiBranding(fs.readFileSync(path.join(uiDist, "index.html"), "utf-8"));
|
||||
// Hashed asset files (Vite emits them under /assets/<name>.<hash>.<ext>)
|
||||
// never change once built, so they can be cached aggressively.
|
||||
app.use(
|
||||
@@ -368,7 +368,7 @@ export async function createApp(
|
||||
.status(200)
|
||||
.set("Content-Type", "text/html")
|
||||
.set("Cache-Control", "no-cache")
|
||||
.end(indexHtml);
|
||||
.end(readBrandedStaticIndexHtml(uiDist));
|
||||
});
|
||||
} else {
|
||||
console.warn("[paperclip] UI dist not found; running in API-only mode");
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { applyUiBranding } from "./ui-branding.js";
|
||||
|
||||
export function readBrandedStaticIndexHtml(uiDist: string): string {
|
||||
return applyUiBranding(fs.readFileSync(path.join(uiDist, "index.html"), "utf-8"));
|
||||
}
|
||||
Reference in new issue
Block a user