diff --git a/middleware/01.redirect-to-custom-domain.ts b/middleware/01.redirect-to-custom-domain.ts new file mode 100644 index 0000000..bc3ad16 --- /dev/null +++ b/middleware/01.redirect-to-custom-domain.ts @@ -0,0 +1,16 @@ +import { defineMiddleware } from "void"; + +const LEGACY_HOST = "vp-setup.void.app"; +const CANONICAL_ORIGIN = "https://setup.viteplus.dev"; + +export function buildRedirectTarget(host: string | undefined, requestUrl: string): string | null { + if (host !== LEGACY_HOST) return null; + const url = new URL(requestUrl); + return `${CANONICAL_ORIGIN}${url.pathname}${url.search}`; +} + +export default defineMiddleware(async (c, next) => { + const target = buildRedirectTarget(c.req.header("host"), c.req.url); + if (target) return c.redirect(target, 301); + await next(); +}); diff --git a/tests/redirect.test.ts b/tests/redirect.test.ts new file mode 100644 index 0000000..a7f572a --- /dev/null +++ b/tests/redirect.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from "vite-plus/test"; +import { buildRedirectTarget } from "../middleware/01.redirect-to-custom-domain"; + +describe("buildRedirectTarget", () => { + it("redirects legacy host root to canonical origin", () => { + expect(buildRedirectTarget("vp-setup.void.app", "https://vp-setup.void.app/")).toBe( + "https://setup.viteplus.dev/", + ); + }); + + it("preserves path and query string", () => { + expect( + buildRedirectTarget("vp-setup.void.app", "https://vp-setup.void.app/?tag=v1.2.3&arch=arm64"), + ).toBe("https://setup.viteplus.dev/?tag=v1.2.3&arch=arm64"); + }); + + it("returns null for the custom domain (no redirect)", () => { + expect(buildRedirectTarget("setup.viteplus.dev", "https://setup.viteplus.dev/")).toBeNull(); + }); + + it("returns null for localhost during dev", () => { + expect(buildRedirectTarget("localhost:5173", "http://localhost:5173/")).toBeNull(); + }); + + it("returns null when host header is missing", () => { + expect(buildRedirectTarget(undefined, "https://vp-setup.void.app/")).toBeNull(); + }); + + it("does not match preview/staging subdomains", () => { + expect( + buildRedirectTarget("vp-setup-staging.void.app", "https://vp-setup-staging.void.app/"), + ).toBeNull(); + }); +});