From cd7dc31de804e60c0ed4659d8f0337a9260aaf7a Mon Sep 17 00:00:00 2001 From: Francesco_Pepe Date: Mon, 13 Apr 2026 16:36:47 +0200 Subject: [PATCH] fix: support Verdaccio 6.5.0 ui-options external script Verdaccio 6.5.0 (verdaccio/verdaccio@df612faef, #5792) moved __VERDACCIO_BASENAME_UI_OPTIONS from an inline script in the HTML to an external ui-options.js file. The PatchHtml guard checked for that string in the response body, so the plugin script was never injected - causing the login button to show the default username/password modal instead of redirecting to GitHub OAuth. Check for both the legacy inline marker and the new external script filename so the plugin works with Verdaccio <=6.4 and >=6.5. --- src/server/plugin/PatchHtml.ts | 5 +- .../plugin/PatchHtml/insertTags.test.ts | 51 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 test/server/plugin/PatchHtml/insertTags.test.ts diff --git a/src/server/plugin/PatchHtml.ts b/src/server/plugin/PatchHtml.ts index 93e2351..fc21434 100644 --- a/src/server/plugin/PatchHtml.ts +++ b/src/server/plugin/PatchHtml.ts @@ -34,7 +34,10 @@ export class PatchHtml implements IPluginMiddleware { private insertTags = (req: Request, html: string | Buffer): string => { html = String(html) - if (!html.includes("__VERDACCIO_BASENAME_UI_OPTIONS")) { + if ( + !html.includes("__VERDACCIO_BASENAME_UI_OPTIONS") && + !html.includes("ui-options.js") + ) { return html } diff --git a/test/server/plugin/PatchHtml/insertTags.test.ts b/test/server/plugin/PatchHtml/insertTags.test.ts new file mode 100644 index 0000000..7769307 --- /dev/null +++ b/test/server/plugin/PatchHtml/insertTags.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, it } from "vitest" +import { PatchHtml } from "src/server/plugin/PatchHtml" + +const scriptPattern = /verdaccio-6\.js/ + +function createPatchHtml() { + const config = { url_prefix: "" } as any + return new PatchHtml(config) +} + +function callInsertTags(html: string) { + const patchHtml = createPatchHtml() + const req = { headers: { host: "localhost:4873" }, protocol: "http" } as any + // Access the private method via bracket notation + return (patchHtml as any).insertTags(req, html) +} + +// Verdaccio <=6.4 inlines the options in a +
+` + +// Verdaccio >=6.5 loads options from an external script +const modernHtml = ` + + + +
+` + +const jsonResponse = JSON.stringify({ name: "some-package", version: "1.0.0" }) + +describe("PatchHtml - insertTags", () => { + it("injects the client script into legacy Verdaccio HTML (<=6.4)", () => { + const result = callInsertTags(legacyHtml) + expect(result).toMatch(scriptPattern) + }) + + it("injects the client script into modern Verdaccio HTML (>=6.5)", () => { + const result = callInsertTags(modernHtml) + expect(result).toMatch(scriptPattern) + }) + + it("does not modify non-HTML responses", () => { + const result = callInsertTags(jsonResponse) + expect(result).toBe(jsonResponse) + }) +})