Skip to content

Commit 6c06a6c

Browse files
Merge pull request #252 from GenerationSoftware/fix/gen-2361-project-deep-links
fix: serve project deep links through the SPA
2 parents ff7b9b7 + 26d459d commit 6c06a6c

2 files changed

Lines changed: 4 additions & 4 deletions

File tree

‎packages/api/src/static-app.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { Env } from "./types";
22

33
export const STATIC_CSP = "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'self'";
4-
const pages = new Set(["/", "/jobs", "/jobs/new", "/job-runs", "/settings", "/settings/integrations", "/settings/api-keys", "/settings/authorized-clients", "/settings/password", "/auth/login", "/auth/signup", "/auth/password-reset", "/auth/verify", "/auth/verify/request", "/authorize", "/device"]);
4+
const pages = new Set(["/", "/jobs", "/jobs/new", "/projects", "/projects/new", "/job-runs", "/settings", "/settings/integrations", "/settings/api-keys", "/settings/authorized-clients", "/settings/password", "/auth/login", "/auth/signup", "/auth/password-reset", "/auth/verify", "/auth/verify/request", "/authorize", "/device"]);
55
export function isStaticPage(path: string) {
6-
return pages.has(path) || /^\/jobs\/[^/]+(?:\/(?:edit|settings))?$/.test(path) || /^\/job-runs\/[^/]+$/.test(path);
6+
return pages.has(path) || /^\/jobs\/[^/]+(?:\/(?:edit|settings))?$/.test(path) || /^\/projects\/[^/]+$/.test(path) || /^\/job-runs\/[^/]+$/.test(path);
77
}
88
export function isStaticAsset(path: string) {
99
return /^\/assets\/[A-Za-z0-9_.-]+$/.test(path) || path === "/styles.css";

‎packages/api/test/static-routing.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ describe("same-origin static ownership", () => {
66
it("serves explicit deep links with an external-bundle policy and revalidated entry HTML", async () => {
77
const fetch = vi.fn(async (request: Request) => new Response(request.method === "HEAD" ? null : "entry", { headers: { "Content-Type": "text/html" } }));
88
const env = { ASSETS: { fetch } } as unknown as Env;
9-
for (const path of ["/", "/jobs", "/jobs/new", "/jobs/id/edit", "/jobs/id/settings", "/job-runs", "/job-runs/id", "/settings/authorized-clients", "/auth/verify?token=one-time", "/authorize?client_id=test", "/device?user_code=ABCD-2345"]) {
9+
for (const path of ["/", "/jobs", "/jobs/new", "/jobs/id/edit", "/jobs/id/settings", "/projects", "/projects/new", "/projects/id", "/job-runs", "/job-runs/id", "/settings/authorized-clients", "/auth/verify?token=one-time", "/authorize?client_id=test", "/device?user_code=ABCD-2345"]) {
1010
const response = await staticApp(new Request(`https://app.factorize.sh${path}`), env);
1111
expect(response?.status).toBe(200);
1212
expect(response?.headers.get("content-security-policy")).toBe(STATIC_CSP);
@@ -21,7 +21,7 @@ describe("same-origin static ownership", () => {
2121
});
2222
it("never forwards backend namespaces, unknown routes or mutations to static hosting", async () => {
2323
const fetch = vi.fn(); const env = { ASSETS: { fetch } } as unknown as Env;
24-
for (const path of ["/api/v1", "/api/v1/unknown", "/api/v1/jobs", "/oauth/token", "/auth/linear", "/auth/github/setup", "/webhooks/github", "/internal/missing", "/mcp", "/healthz", "/.well-known/oauth-authorization-server", "/unknown", "/assets/subdir/file.js", "/index.html", "/jobs/id/edit/extra", "/jobs/id/settings/extra", "/jobs/id/unknown"]) {
24+
for (const path of ["/api/v1", "/api/v1/unknown", "/api/v1/jobs", "/oauth/token", "/auth/linear", "/auth/github/setup", "/webhooks/github", "/internal/missing", "/mcp", "/healthz", "/.well-known/oauth-authorization-server", "/unknown", "/assets/subdir/file.js", "/index.html", "/jobs/id/edit/extra", "/jobs/id/settings/extra", "/jobs/id/unknown", "/projects/id/unknown"]) {
2525
expect(await staticApp(new Request(`https://app.factorize.sh${path}`), env)).toBeNull();
2626
}
2727
for (const method of ["POST", "PUT", "DELETE", "OPTIONS"]) for (const path of ["/jobs", "/authorize", "/device", "/assets/index-hash.js", "/auth/login"]) expect(await staticApp(new Request(`https://app.factorize.sh${path}`, { method }), env)).toBeNull();

0 commit comments

Comments
 (0)