From 68fa3eeaae28ec54dda4d61e50d1806080b3cb9c Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 14:56:35 +0200 Subject: [PATCH 01/52] deno stuff --- deno/.gitignore | 2 ++ deno/main.ts | 19 ++++++++++++++++--- deno/serve-ssl.ts | 25 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 deno/.gitignore create mode 100644 deno/serve-ssl.ts diff --git a/deno/.gitignore b/deno/.gitignore new file mode 100644 index 00000000..f933710b --- /dev/null +++ b/deno/.gitignore @@ -0,0 +1,2 @@ +cert.pem +key.pem diff --git a/deno/main.ts b/deno/main.ts index 1a1b0184..05cfe691 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -1,8 +1,21 @@ import { serveDir } from "jsr:@std/http/file-server"; +import * as fsrouter from "jsr:@pomdtr/fsrouter"; +import { route, type Route } from "jsr:@std/http/unstable-route"; -/** run `pnpm build --watch` */ -function handleFetch(req: Request): Promise { - return serveDir(req, { fsRoot: "build" }); +// watchexec --verbose -i deno/** pnpm build +// https://jsr.io/@http/route and https://github.com/jollytoad/deno_http_fns/tree/main/packages/examples has newer fancier stuff +async function handleFetch(req: Request): Promise { + const routes = fsrouter.discoverRoutes("./functions") as Route[]; + console.log(`${JSON.stringify(routes.map((x) => x.pattern.pathname))}`); + + return route(routes, async (req: Request) => { + console.log("fallback", req); + const ret = await serveDir(req, { fsRoot: "build" }); + console.log(ret); + return ret; + })(req); + + // return ; } export default { diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts new file mode 100644 index 00000000..26a1ea01 --- /dev/null +++ b/deno/serve-ssl.ts @@ -0,0 +1,25 @@ +import handler from "./main.ts"; +// deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts +let keys: string[]; +do { + try { + keys = await Promise.all(["cert", "key"].map((name) => Deno.readTextFile(`${name}.pem`))); + break; + } catch (error) { + if (error instanceof Deno.errors.NotFound) { + console.log("SSL certificates not found, generating new ones..."); + await new Deno.Command("sh", { + args: [ + "-c", + "openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'", + ], + }).output(); + continue; + } + throw error; + } +} while (true); + +const [cert, key] = keys; +Deno.chdir(".."); +Deno.serve({ cert, key, port: 4443, reusePort: true }, handler.fetch); From edbfa99dc2b73d439db76043c162b25c3234ae74 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 16:14:49 +0200 Subject: [PATCH 02/52] refactor: Replace fsrouter with new route discovery mechanism using @http/discovery --- deno/main.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 05cfe691..c73865af 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -1,12 +1,36 @@ import { serveDir } from "jsr:@std/http/file-server"; -import * as fsrouter from "jsr:@pomdtr/fsrouter"; import { route, type Route } from "jsr:@std/http/unstable-route"; +import freshPathMapper from "jsr:@http/discovery/fresh-path-mapper"; +import { discoverRoutes } from "jsr:@http/discovery/discover-routes"; +import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-pattern"; +import { byPattern } from "jsr:@http/route/by-pattern"; + +async function cfRoutes(fileRootUrl: string) { + const routes = await discoverRoutes({ + pattern: "/", + fileRootUrl: fileRootUrl, + pathMapper: freshPathMapper, + verbose: true, + }); + + + const handlers = []; + + for (const { pattern, module } of routes) { + console.log("\nPattern:", asSerializablePattern(pattern)); + console.log("Module:", module.toString()); + const routeModule = await import(module.toString()); + console.log("Default:", routeModule.default); + handlers.push(byPattern(pattern, routeModule.default)); + } + return handlers; +} // watchexec --verbose -i deno/** pnpm build // https://jsr.io/@http/route and https://github.com/jollytoad/deno_http_fns/tree/main/packages/examples has newer fancier stuff async function handleFetch(req: Request): Promise { - const routes = fsrouter.discoverRoutes("./functions") as Route[]; - console.log(`${JSON.stringify(routes.map((x) => x.pattern.pathname))}`); + const routes = await cfRoutes(import.meta.resolve("../functions")) as Route[]; + console.log(`${JSON.stringify(routes.map((x) => { p: x.pattern.pathname }))}`); return route(routes, async (req: Request) => { console.log("fallback", req); From c8166bdad3325fb5d9fd019a1a9feece78e614fe Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 16:14:51 +0200 Subject: [PATCH 03/52] feat: Skip test files when importing route modules --- deno/main.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deno/main.ts b/deno/main.ts index c73865af..b7989e52 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -17,6 +17,11 @@ async function cfRoutes(fileRootUrl: string) { const handlers = []; for (const { pattern, module } of routes) { + // Skip test files + if (module.toString().includes('.test')) { + continue; + } + console.log("\nPattern:", asSerializablePattern(pattern)); console.log("Module:", module.toString()); const routeModule = await import(module.toString()); From b73dd18463d84acf79d3ab73d0f2fd6e2c3cca9a Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 16:16:59 +0200 Subject: [PATCH 04/52] refactor: Modify route filtering to only include paths starting with '/api' --- deno/main.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index b7989e52..1f7e24e2 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -17,13 +17,14 @@ async function cfRoutes(fileRootUrl: string) { const handlers = []; for (const { pattern, module } of routes) { - // Skip test files - if (module.toString().includes('.test')) { + const modulePath = module.toString(); + // Only include routes that start with /api and aren't tests + if (!modulePath.startsWith('/api') || modulePath.includes('.test')) { continue; } console.log("\nPattern:", asSerializablePattern(pattern)); - console.log("Module:", module.toString()); + console.log("Module:", modulePath); const routeModule = await import(module.toString()); console.log("Default:", routeModule.default); handlers.push(byPattern(pattern, routeModule.default)); From 1f2694a11ea05c78480cc50c311c47bbe9020c5f Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 16:27:42 +0200 Subject: [PATCH 05/52] refactor: Improve route filtering and logging in Cloudflare route handler --- deno/main.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 1f7e24e2..8e168150 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -18,24 +18,29 @@ async function cfRoutes(fileRootUrl: string) { for (const { pattern, module } of routes) { const modulePath = module.toString(); + const modulePathShort = modulePath.substring(fileRootUrl.length) // Only include routes that start with /api and aren't tests - if (!modulePath.startsWith('/api') || modulePath.includes('.test')) { + const valid = modulePathShort.startsWith('/api') && !modulePathShort.includes('.test'); + if (!valid) { continue; } console.log("\nPattern:", asSerializablePattern(pattern)); console.log("Module:", modulePath); - const routeModule = await import(module.toString()); + const routeModule = await import(modulePath); console.log("Default:", routeModule.default); + console.log("onRequestGet:", routeModule.onRequestGet); handlers.push(byPattern(pattern, routeModule.default)); } return handlers; } +const routes = await cfRoutes(import.meta.resolve("../functions")) as Route[]; + + // watchexec --verbose -i deno/** pnpm build // https://jsr.io/@http/route and https://github.com/jollytoad/deno_http_fns/tree/main/packages/examples has newer fancier stuff async function handleFetch(req: Request): Promise { - const routes = await cfRoutes(import.meta.resolve("../functions")) as Route[]; console.log(`${JSON.stringify(routes.map((x) => { p: x.pattern.pathname }))}`); return route(routes, async (req: Request) => { From b623a2e52dd9974a7f368fdcb2a99319371d3d7c Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 16:27:44 +0200 Subject: [PATCH 06/52] feat: Add adapter for legacy Cloudflare Workers route handlers --- deno/main.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/deno/main.ts b/deno/main.ts index 8e168150..1f6619ee 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -5,6 +5,21 @@ import { discoverRoutes } from "jsr:@http/discovery/discover-routes"; import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-pattern"; import { byPattern } from "jsr:@http/route/by-pattern"; +function adaptLegacyCloudflareHandler(handler: Function) { + return async (request: Request) => { + // Create minimal CF-style context object + const env = {}; + const ctx = { + waitUntil: () => {}, + passThroughOnException: () => {}, + }; + + // Call the legacy handler with CF-style arguments + const response = await handler(request, env, ctx); + return response; + }; +} + async function cfRoutes(fileRootUrl: string) { const routes = await discoverRoutes({ pattern: "/", @@ -30,7 +45,12 @@ async function cfRoutes(fileRootUrl: string) { const routeModule = await import(modulePath); console.log("Default:", routeModule.default); console.log("onRequestGet:", routeModule.onRequestGet); - handlers.push(byPattern(pattern, routeModule.default)); + + if (routeModule.onRequestGet) { + handlers.push(byPattern(pattern, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); + } else if (routeModule.default) { + handlers.push(byPattern(pattern, routeModule.default)); + } } return handlers; } From 8f5438b40a4b0083f1cb41502a0cf91602cd2c5d Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 16:28:23 +0200 Subject: [PATCH 07/52] feat: Add type annotation for `cfRoutes` return value and remove type assertion --- deno/main.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 1f6619ee..6028835a 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -20,7 +20,7 @@ function adaptLegacyCloudflareHandler(handler: Function) { }; } -async function cfRoutes(fileRootUrl: string) { +async function cfRoutes(fileRootUrl: string): Promise { const routes = await discoverRoutes({ pattern: "/", fileRootUrl: fileRootUrl, @@ -28,8 +28,7 @@ async function cfRoutes(fileRootUrl: string) { verbose: true, }); - - const handlers = []; + const handlers: Route[] = []; for (const { pattern, module } of routes) { const modulePath = module.toString(); @@ -55,7 +54,7 @@ async function cfRoutes(fileRootUrl: string) { return handlers; } -const routes = await cfRoutes(import.meta.resolve("../functions")) as Route[]; +const routes = await cfRoutes(import.meta.resolve("../functions")); // watchexec --verbose -i deno/** pnpm build From fded73cea8b639c92de12b4542bc61e227fa65cd Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:03:37 +0200 Subject: [PATCH 08/52] refactor: Simplify Cloudflare route handling and improve environment configuration --- deno/main.ts | 49 +++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 6028835a..2a9bf31d 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -4,14 +4,18 @@ import freshPathMapper from "jsr:@http/discovery/fresh-path-mapper"; import { discoverRoutes } from "jsr:@http/discovery/discover-routes"; import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-pattern"; import { byPattern } from "jsr:@http/route/by-pattern"; +import { handle } from "jsr:@http/route/handle"; +const env = {...process.env}; +if (!env.ENVIRONMENT) { + env.ENVIRONMENT = 'development'; +} function adaptLegacyCloudflareHandler(handler: Function) { - return async (request: Request) => { + return async (request: Request, _match: URLPatternResult) => { // Create minimal CF-style context object - const env = {}; const ctx = { - waitUntil: () => {}, - passThroughOnException: () => {}, + waitUntil: () => { }, + passThroughOnException: () => { }, }; // Call the legacy handler with CF-style arguments @@ -20,7 +24,7 @@ function adaptLegacyCloudflareHandler(handler: Function) { }; } -async function cfRoutes(fileRootUrl: string): Promise { +async function cfRoutes(fileRootUrl: string) { const routes = await discoverRoutes({ pattern: "/", fileRootUrl: fileRootUrl, @@ -28,7 +32,7 @@ async function cfRoutes(fileRootUrl: string): Promise { verbose: true, }); - const handlers: Route[] = []; + const handlers = []; for (const { pattern, module } of routes) { const modulePath = module.toString(); @@ -36,42 +40,31 @@ async function cfRoutes(fileRootUrl: string): Promise { // Only include routes that start with /api and aren't tests const valid = modulePathShort.startsWith('/api') && !modulePathShort.includes('.test'); if (!valid) { - continue; + continue; } - - console.log("\nPattern:", asSerializablePattern(pattern)); - console.log("Module:", modulePath); + const routeModule = await import(modulePath); - console.log("Default:", routeModule.default); - console.log("onRequestGet:", routeModule.onRequestGet); - + // console.log("Default:", routeModule.default); if (routeModule.onRequestGet) { + console.log("\nPattern:", asSerializablePattern(pattern)); + console.log("Module:", modulePath); + console.log("onRequestGet:", routeModule.onRequestGet); handlers.push(byPattern(pattern, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); - } else if (routeModule.default) { - handlers.push(byPattern(pattern, routeModule.default)); } } return handlers; } -const routes = await cfRoutes(import.meta.resolve("../functions")); +const cfHandlers = await cfRoutes(import.meta.resolve("../functions")); // watchexec --verbose -i deno/** pnpm build -// https://jsr.io/@http/route and https://github.com/jollytoad/deno_http_fns/tree/main/packages/examples has newer fancier stuff -async function handleFetch(req: Request): Promise { - console.log(`${JSON.stringify(routes.map((x) => { p: x.pattern.pathname }))}`); - - return route(routes, async (req: Request) => { +// deno run --unstable-net --unstable-sloppy-imports --unstable-node-globals --watch -A serve-ssl.ts +export default { + fetch: handle(cfHandlers, async (req: Request) => { console.log("fallback", req); const ret = await serveDir(req, { fsRoot: "build" }); console.log(ret); return ret; - })(req); - - // return ; -} - -export default { - fetch: handleFetch, + }), }; From 18e2c70f0299450725e03161952009c0792a0885 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 17:03:38 +0200 Subject: [PATCH 09/52] refactor: Extract common serveDir options and add fallback to index.html --- deno/main.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/deno/main.ts b/deno/main.ts index 2a9bf31d..1d602bd6 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -60,10 +60,18 @@ const cfHandlers = await cfRoutes(import.meta.resolve("../functions")); // watchexec --verbose -i deno/** pnpm build // deno run --unstable-net --unstable-sloppy-imports --unstable-node-globals --watch -A serve-ssl.ts +const commonOpts = { fsRoot: "build" }; + export default { fetch: handle(cfHandlers, async (req: Request) => { console.log("fallback", req); - const ret = await serveDir(req, { fsRoot: "build" }); + let ret = await serveDir(req, commonOpts); + if (ret.status === 404) { + // Try again with /index.html appended + const url = new URL(req.url); + url.pathname = '/index.html'; + ret = await serveDir(new Request(url, req), commonOpts); + } console.log(ret); return ret; }), From 3e20e4dee3e8c0da92fa8acef530c5d979c9cb3e Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:07:19 +0200 Subject: [PATCH 10/52] fix: Update fallback route to serve index.html correctly --- deno/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 1d602bd6..db1ebb5f 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -60,17 +60,17 @@ const cfHandlers = await cfRoutes(import.meta.resolve("../functions")); // watchexec --verbose -i deno/** pnpm build // deno run --unstable-net --unstable-sloppy-imports --unstable-node-globals --watch -A serve-ssl.ts -const commonOpts = { fsRoot: "build" }; +const serveOpts = { fsRoot: "build" }; export default { fetch: handle(cfHandlers, async (req: Request) => { console.log("fallback", req); - let ret = await serveDir(req, commonOpts); + let ret = await serveDir(req, serveOpts); if (ret.status === 404) { // Try again with /index.html appended const url = new URL(req.url); - url.pathname = '/index.html'; - ret = await serveDir(new Request(url, req), commonOpts); + url.pathname = '/'; + ret = await serveDir(new Request(url, req), serveOpts); } console.log(ret); return ret; From f49b41e28740e1c43d6df960cf1d4c9733d12163 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 17:07:21 +0200 Subject: [PATCH 11/52] feat: Add logging for 404 status in Deno server --- deno/main.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/deno/main.ts b/deno/main.ts index db1ebb5f..79e58248 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -67,6 +67,7 @@ export default { console.log("fallback", req); let ret = await serveDir(req, serveOpts); if (ret.status === 404) { + console.log("Got 404, trying with root path:", req.url); // Add this line // Try again with /index.html appended const url = new URL(req.url); url.pathname = '/'; From 8c2b3f4bf714006d9a7d1e81b16ec84156fcc9d3 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:12:08 +0200 Subject: [PATCH 12/52] feat: Add logging and default export for login API function --- functions/api/login.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/functions/api/login.ts b/functions/api/login.ts index 56d3c7ac..dc999ba5 100644 --- a/functions/api/login.ts +++ b/functions/api/login.ts @@ -19,6 +19,7 @@ export const onRequestGet: PagesFunction = async ({ request, env }) => { GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OUATH_CLIENT_SECRET, } = env; + console.log({ request, env }); const reqUrl = new URL(request.url); // Determine the login provider @@ -72,3 +73,7 @@ export const onRequestGet: PagesFunction = async ({ request, env }) => { }); } }; + +export default { + fetch: (request: Request, env: Env) => onRequestGet({ request, env: env ? env : {} }), +}; From 040396abf866dbd0172af39306ae330a8126acbb Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:15:49 +0200 Subject: [PATCH 13/52] misc --- deno/main.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 79e58248..6b684e77 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -6,20 +6,20 @@ import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-patte import { byPattern } from "jsr:@http/route/by-pattern"; import { handle } from "jsr:@http/route/handle"; -const env = {...process.env}; +const env = { ...process.env }; if (!env.ENVIRONMENT) { - env.ENVIRONMENT = 'development'; + env.ENVIRONMENT = "development"; } function adaptLegacyCloudflareHandler(handler: Function) { return async (request: Request, _match: URLPatternResult) => { // Create minimal CF-style context object const ctx = { - waitUntil: () => { }, - passThroughOnException: () => { }, + waitUntil: () => {}, + passThroughOnException: () => {}, }; // Call the legacy handler with CF-style arguments - const response = await handler(request, env, ctx); + const response = await handler({ request, env, ctx }); return response; }; } @@ -36,9 +36,9 @@ async function cfRoutes(fileRootUrl: string) { for (const { pattern, module } of routes) { const modulePath = module.toString(); - const modulePathShort = modulePath.substring(fileRootUrl.length) + const modulePathShort = modulePath.substring(fileRootUrl.length); // Only include routes that start with /api and aren't tests - const valid = modulePathShort.startsWith('/api') && !modulePathShort.includes('.test'); + const valid = modulePathShort.startsWith("/api") && !modulePathShort.includes(".test"); if (!valid) { continue; } @@ -57,20 +57,18 @@ async function cfRoutes(fileRootUrl: string) { const cfHandlers = await cfRoutes(import.meta.resolve("../functions")); - // watchexec --verbose -i deno/** pnpm build // deno run --unstable-net --unstable-sloppy-imports --unstable-node-globals --watch -A serve-ssl.ts const serveOpts = { fsRoot: "build" }; export default { fetch: handle(cfHandlers, async (req: Request) => { - console.log("fallback", req); let ret = await serveDir(req, serveOpts); if (ret.status === 404) { - console.log("Got 404, trying with root path:", req.url); // Add this line - // Try again with /index.html appended + console.log("Got 404 from serveDir, trying with /:", req.url); // Add this line + // Try again with / const url = new URL(req.url); - url.pathname = '/'; + url.pathname = "/"; ret = await serveDir(new Request(url, req), serveOpts); } console.log(ret); From d565915187db09083d7268727773e55c59d09b3b Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 17:20:58 +0200 Subject: [PATCH 14/52] feat: Add fallback values for environment variables in Deno main --- deno/main.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/deno/main.ts b/deno/main.ts index 6b684e77..2637a316 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -10,6 +10,15 @@ const env = { ...process.env }; if (!env.ENVIRONMENT) { env.ENVIRONMENT = "development"; } +if (!env.CLIENT_ID) { + env.CLIENT_ID = "client_id"; +} +if (!env.CLIENT_SECRET) { + env.CLIENT_SECRET = "client_secret"; +} +if (!env.JWT_SECRET) { + env.JWT_SECRET = "jwt_secret"; +} function adaptLegacyCloudflareHandler(handler: Function) { return async (request: Request, _match: URLPatternResult) => { // Create minimal CF-style context object From 22c92124c213379c637f7d7910e95e170bef2be6 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:21:47 +0200 Subject: [PATCH 15/52] dummy login/logout works on deno now --- functions/api/login.ts | 1 - functions/github.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/functions/api/login.ts b/functions/api/login.ts index dc999ba5..f3adbec2 100644 --- a/functions/api/login.ts +++ b/functions/api/login.ts @@ -19,7 +19,6 @@ export const onRequestGet: PagesFunction = async ({ request, env }) => { GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OUATH_CLIENT_SECRET, } = env; - console.log({ request, env }); const reqUrl = new URL(request.url); // Determine the login provider diff --git a/functions/github.ts b/functions/github.ts index e6785801..bcb10c10 100644 --- a/functions/github.ts +++ b/functions/github.ts @@ -183,7 +183,7 @@ export async function handleGithubDevLogin({ ]), }); } catch (err) { - console.error(err); + console.error(err.stack); return Response.redirect(`/?github_login_error`, 302); } } From 797952d3d4c81e041384fab103bae9e51471003a Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 17:27:02 +0200 Subject: [PATCH 16/52] refactor: Replace process.env with Deno.env.toObject() for Deno compatibility --- deno/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno/main.ts b/deno/main.ts index 2637a316..87a592c2 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -6,7 +6,7 @@ import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-patte import { byPattern } from "jsr:@http/route/by-pattern"; import { handle } from "jsr:@http/route/handle"; -const env = { ...process.env }; +const env = { ...Deno.env.toObject() }; if (!env.ENVIRONMENT) { env.ENVIRONMENT = "development"; } From c0626b65da66f721244503e63c8baab02aff3270 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:29:25 +0200 Subject: [PATCH 17/52] refactor: Remove unused imports and simplify route logging --- deno/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 87a592c2..9536aa7e 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -1,5 +1,4 @@ import { serveDir } from "jsr:@std/http/file-server"; -import { route, type Route } from "jsr:@std/http/unstable-route"; import freshPathMapper from "jsr:@http/discovery/fresh-path-mapper"; import { discoverRoutes } from "jsr:@http/discovery/discover-routes"; import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-pattern"; @@ -19,6 +18,7 @@ if (!env.CLIENT_SECRET) { if (!env.JWT_SECRET) { env.JWT_SECRET = "jwt_secret"; } + function adaptLegacyCloudflareHandler(handler: Function) { return async (request: Request, _match: URLPatternResult) => { // Create minimal CF-style context object @@ -57,7 +57,7 @@ async function cfRoutes(fileRootUrl: string) { if (routeModule.onRequestGet) { console.log("\nPattern:", asSerializablePattern(pattern)); console.log("Module:", modulePath); - console.log("onRequestGet:", routeModule.onRequestGet); + // console.log("onRequestGet:", routeModule.onRequestGet); handlers.push(byPattern(pattern, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); } } From 152d240187f0709a3adf7c73b172ebbc4b88320c Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 17:29:27 +0200 Subject: [PATCH 18/52] refactor: Consolidate route logging into a single, concise console.log statement --- deno/main.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 9536aa7e..1b624ec4 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -55,8 +55,7 @@ async function cfRoutes(fileRootUrl: string) { const routeModule = await import(modulePath); // console.log("Default:", routeModule.default); if (routeModule.onRequestGet) { - console.log("\nPattern:", asSerializablePattern(pattern)); - console.log("Module:", modulePath); + console.log("\nRoute:", asSerializablePattern(pattern), "->", modulePath); // console.log("onRequestGet:", routeModule.onRequestGet); handlers.push(byPattern(pattern, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); } From bbefc91ee7c0f9341feba61eb7f98cb7197b7827 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:30:39 +0200 Subject: [PATCH 19/52] misc --- deno/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno/main.ts b/deno/main.ts index 1b624ec4..da0411a0 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -55,7 +55,7 @@ async function cfRoutes(fileRootUrl: string) { const routeModule = await import(modulePath); // console.log("Default:", routeModule.default); if (routeModule.onRequestGet) { - console.log("\nRoute:", asSerializablePattern(pattern), "->", modulePath); + console.log("Route:", asSerializablePattern(pattern), "->", modulePathShort); // console.log("onRequestGet:", routeModule.onRequestGet); handlers.push(byPattern(pattern, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); } From 6f70660d07e50796a219599108d8b4714e8c72a6 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:31:50 +0200 Subject: [PATCH 20/52] misc --- deno/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index da0411a0..6ad06040 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -1,3 +1,5 @@ +// watchexec --verbose -i deno/** pnpm build +// deno run --unstable-net --unstable-sloppy-imports --watch -A serve-ssl.ts import { serveDir } from "jsr:@std/http/file-server"; import freshPathMapper from "jsr:@http/discovery/fresh-path-mapper"; import { discoverRoutes } from "jsr:@http/discovery/discover-routes"; @@ -65,8 +67,6 @@ async function cfRoutes(fileRootUrl: string) { const cfHandlers = await cfRoutes(import.meta.resolve("../functions")); -// watchexec --verbose -i deno/** pnpm build -// deno run --unstable-net --unstable-sloppy-imports --unstable-node-globals --watch -A serve-ssl.ts const serveOpts = { fsRoot: "build" }; export default { From f6f6651907455269729644a27d8266dd1107227a Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:38:58 +0200 Subject: [PATCH 21/52] fix: Adjust SSL certificate loading and linting in Deno server --- deno/main.ts | 1 + deno/serve-ssl.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/deno/main.ts b/deno/main.ts index 6ad06040..3e256424 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -21,6 +21,7 @@ if (!env.JWT_SECRET) { env.JWT_SECRET = "jwt_secret"; } +// deno-lint-ignore ban-types function adaptLegacyCloudflareHandler(handler: Function) { return async (request: Request, _match: URLPatternResult) => { // Create minimal CF-style context object diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts index 26a1ea01..762857db 100644 --- a/deno/serve-ssl.ts +++ b/deno/serve-ssl.ts @@ -4,7 +4,6 @@ let keys: string[]; do { try { keys = await Promise.all(["cert", "key"].map((name) => Deno.readTextFile(`${name}.pem`))); - break; } catch (error) { if (error instanceof Deno.errors.NotFound) { console.log("SSL certificates not found, generating new ones..."); @@ -18,6 +17,7 @@ do { } throw error; } + break; } while (true); const [cert, key] = keys; From 04a9923c5e0b11e3bf9e9e940d65f6e8b51a45e2 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 17:39:00 +0200 Subject: [PATCH 22/52] chore: Add eslint-disable comments to silence specific lint warnings --- deno/main.ts | 1 + deno/serve-ssl.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/deno/main.ts b/deno/main.ts index 3e256424..a30270f7 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -21,6 +21,7 @@ if (!env.JWT_SECRET) { env.JWT_SECRET = "jwt_secret"; } +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // deno-lint-ignore ban-types function adaptLegacyCloudflareHandler(handler: Function) { return async (request: Request, _match: URLPatternResult) => { diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts index 762857db..ed075298 100644 --- a/deno/serve-ssl.ts +++ b/deno/serve-ssl.ts @@ -1,6 +1,7 @@ import handler from "./main.ts"; // deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts let keys: string[]; +// eslint-disable-next-line no-constant-condition do { try { keys = await Promise.all(["cert", "key"].map((name) => Deno.readTextFile(`${name}.pem`))); From fe7f6cb21ec53d0494863d3de6297c8c2c1fcd84 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:40:39 +0200 Subject: [PATCH 23/52] lint --- deno/main.ts | 1 - deno/serve-ssl.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index a30270f7..f463e732 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -22,7 +22,6 @@ if (!env.JWT_SECRET) { } // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type -// deno-lint-ignore ban-types function adaptLegacyCloudflareHandler(handler: Function) { return async (request: Request, _match: URLPatternResult) => { // Create minimal CF-style context object diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts index ed075298..8143a827 100644 --- a/deno/serve-ssl.ts +++ b/deno/serve-ssl.ts @@ -1,7 +1,6 @@ import handler from "./main.ts"; // deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts let keys: string[]; -// eslint-disable-next-line no-constant-condition do { try { keys = await Promise.all(["cert", "key"].map((name) => Deno.readTextFile(`${name}.pem`))); @@ -19,6 +18,7 @@ do { throw error; } break; + // eslint-disable-next-line no-constant-condition } while (true); const [cert, key] = keys; From 6273e537323a856ea0f16beb7a6a78c1f8c5b662 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:41:40 +0200 Subject: [PATCH 24/52] misc --- functions/api/login.ts | 4 ---- functions/github.ts | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/functions/api/login.ts b/functions/api/login.ts index f3adbec2..56d3c7ac 100644 --- a/functions/api/login.ts +++ b/functions/api/login.ts @@ -72,7 +72,3 @@ export const onRequestGet: PagesFunction = async ({ request, env }) => { }); } }; - -export default { - fetch: (request: Request, env: Env) => onRequestGet({ request, env: env ? env : {} }), -}; diff --git a/functions/github.ts b/functions/github.ts index bcb10c10..e6785801 100644 --- a/functions/github.ts +++ b/functions/github.ts @@ -183,7 +183,7 @@ export async function handleGithubDevLogin({ ]), }); } catch (err) { - console.error(err.stack); + console.error(err); return Response.redirect(`/?github_login_error`, 302); } } From 2d5c55a11802c4697c8df8f8cd24a1ee8aa53fe8 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Wed, 8 Jan 2025 17:44:02 +0200 Subject: [PATCH 25/52] refactor: Simplify environment variable initialization with defaults --- deno/main.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index f463e732..1963892d 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -7,19 +7,13 @@ import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-patte import { byPattern } from "jsr:@http/route/by-pattern"; import { handle } from "jsr:@http/route/handle"; -const env = { ...Deno.env.toObject() }; -if (!env.ENVIRONMENT) { - env.ENVIRONMENT = "development"; -} -if (!env.CLIENT_ID) { - env.CLIENT_ID = "client_id"; -} -if (!env.CLIENT_SECRET) { - env.CLIENT_SECRET = "client_secret"; -} -if (!env.JWT_SECRET) { - env.JWT_SECRET = "jwt_secret"; -} +const env = { + ENVIRONMENT: "development", + CLIENT_ID: "client_id", + CLIENT_SECRET: "client_secret", + JWT_SECRET: "jwt_secret", + ...Deno.env.toObject() +}; // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type function adaptLegacyCloudflareHandler(handler: Function) { From f06ab4e6dffd3d644127c2bce3c95abeea5acda4 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Wed, 8 Jan 2025 17:55:51 +0200 Subject: [PATCH 26/52] lint --- deno/main.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 1963892d..080f642e 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -7,12 +7,17 @@ import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-patte import { byPattern } from "jsr:@http/route/by-pattern"; import { handle } from "jsr:@http/route/handle"; -const env = { +// we can probably share these with vite by factoring them into a common JSON +const defaults = { ENVIRONMENT: "development", CLIENT_ID: "client_id", - CLIENT_SECRET: "client_secret", + CLIENT_SECRET: "client_secret", JWT_SECRET: "jwt_secret", - ...Deno.env.toObject() +}; + +const env = { + ...defaults, + ...Deno.env.toObject(), }; // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type From 3ad59557a688ddf76bf1e69f6e0cf3b9f0f73438 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 08:13:10 +0200 Subject: [PATCH 27/52] works in smallweb again --- smallweb.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/smallweb.json b/smallweb.json index e99602a1..f65a5f05 100644 --- a/smallweb.json +++ b/smallweb.json @@ -1,3 +1,4 @@ { - "entrypoint": "deno/main.ts" + "entrypoint": "deno/main.ts", + "denoArgs": ["--unstable-sloppy-imports"] } From c24f87d167edf96b5dca196b3f10c01ed2409877 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 08:19:48 +0200 Subject: [PATCH 28/52] feat: Add command-line argument parsing for serve-ssl.ts --- deno/serve-ssl.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts index 8143a827..87871d1f 100644 --- a/deno/serve-ssl.ts +++ b/deno/serve-ssl.ts @@ -1,5 +1,18 @@ -import handler from "./main.ts"; -// deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts +import { parseArgs } from "@std/cli/parse_args.ts"; + +// Parse command line arguments +const args = parseArgs(Deno.args, { + default: { + port: 443, + handler: "./main.ts" + }, + string: ["handler"], + number: ["port"] +}); + +// Dynamically import the handler +const handlerModule = await import(args.handler); +const handler = handlerModule.default; let keys: string[]; do { try { @@ -23,4 +36,4 @@ do { const [cert, key] = keys; Deno.chdir(".."); -Deno.serve({ cert, key, port: 4443, reusePort: true }, handler.fetch); +Deno.serve({ cert, key, port: args.port, reusePort: true }, handler.fetch); From 5b34c3dd833f0974ba4e84111cb67520f9b24d85 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 08:22:57 +0200 Subject: [PATCH 29/52] refactor: Update import for parseArgs from @std/cli to jsr namespace --- deno/serve-ssl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts index 87871d1f..cb0fa573 100644 --- a/deno/serve-ssl.ts +++ b/deno/serve-ssl.ts @@ -1,4 +1,4 @@ -import { parseArgs } from "@std/cli/parse_args.ts"; +import { parseArgs } from "jsr:@std/cli/parse-args"; // Parse command line arguments const args = parseArgs(Deno.args, { From c692187de3fb1b1005257c95053b57f86220e238 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 08:23:00 +0200 Subject: [PATCH 30/52] feat: Improve error handling for port binding with dynamic script name --- deno/serve-ssl.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts index cb0fa573..ef604b59 100644 --- a/deno/serve-ssl.ts +++ b/deno/serve-ssl.ts @@ -36,4 +36,19 @@ do { const [cert, key] = keys; Deno.chdir(".."); -Deno.serve({ cert, key, port: args.port, reusePort: true }, handler.fetch); + +try { + console.log(`Starting server on port ${args.port}...`); + await Deno.serve({ cert, key, port: args.port, reusePort: true }, handler.fetch); +} catch (error) { + if (error instanceof Deno.errors.PermissionDenied) { + const scriptName = Deno.mainModule.split('/').pop() || 'serve-ssl.ts'; + console.error(`\nError: Cannot bind to port ${args.port}. This port requires elevated privileges.`); + console.error(`Try one of these solutions:`); + console.error(` - Run with sudo: sudo deno run ... ${scriptName}`); + console.error(` - Use a port number above 1024: --port 8443\n`); + Deno.exit(1); + } + // Re-throw other errors + throw error; +} From 64cbd231daf6f707ce0ca64dae01b5abcbe3e8d9 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 08:26:12 +0200 Subject: [PATCH 31/52] feat: Add help text and -h/--help support for serve-ssl.ts --- deno/serve-ssl.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts index ef604b59..fb189bc0 100644 --- a/deno/serve-ssl.ts +++ b/deno/serve-ssl.ts @@ -1,5 +1,24 @@ import { parseArgs } from "jsr:@std/cli/parse-args"; +const helpText = ` +Secure HTTPS development server with auto-generated SSL certificates + +USAGE: + deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts [OPTIONS] + +OPTIONS: + -h, --help Show this help message + --port Port to listen on (default: 443) + --handler Path to handler module (default: "./main.ts") + +EXAMPLES: + # Run with defaults (port 443, main.ts handler) + deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts + + # Run on port 8443 with custom handler + deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts --port 8443 --handler "./custom.ts" +`; + // Parse command line arguments const args = parseArgs(Deno.args, { default: { @@ -7,9 +26,17 @@ const args = parseArgs(Deno.args, { handler: "./main.ts" }, string: ["handler"], - number: ["port"] + number: ["port"], + boolean: ["help", "h"], + alias: { h: "help" } }); +// Show help and exit if requested +if (args.help) { + console.log(helpText); + Deno.exit(0); +} + // Dynamically import the handler const handlerModule = await import(args.handler); const handler = handlerModule.default; From 5f143f4f02a01f492c488182a4643819b8a1d743 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 11:06:11 +0200 Subject: [PATCH 32/52] removed ssl hack --- deno/.gitignore | 2 -- deno/serve-ssl.ts | 81 ----------------------------------------------- 2 files changed, 83 deletions(-) delete mode 100644 deno/.gitignore delete mode 100644 deno/serve-ssl.ts diff --git a/deno/.gitignore b/deno/.gitignore deleted file mode 100644 index f933710b..00000000 --- a/deno/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -cert.pem -key.pem diff --git a/deno/serve-ssl.ts b/deno/serve-ssl.ts deleted file mode 100644 index fb189bc0..00000000 --- a/deno/serve-ssl.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { parseArgs } from "jsr:@std/cli/parse-args"; - -const helpText = ` -Secure HTTPS development server with auto-generated SSL certificates - -USAGE: - deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts [OPTIONS] - -OPTIONS: - -h, --help Show this help message - --port Port to listen on (default: 443) - --handler Path to handler module (default: "./main.ts") - -EXAMPLES: - # Run with defaults (port 443, main.ts handler) - deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts - - # Run on port 8443 with custom handler - deno run --unstable-sloppy-imports --unstable-net --watch -A serve-ssl.ts --port 8443 --handler "./custom.ts" -`; - -// Parse command line arguments -const args = parseArgs(Deno.args, { - default: { - port: 443, - handler: "./main.ts" - }, - string: ["handler"], - number: ["port"], - boolean: ["help", "h"], - alias: { h: "help" } -}); - -// Show help and exit if requested -if (args.help) { - console.log(helpText); - Deno.exit(0); -} - -// Dynamically import the handler -const handlerModule = await import(args.handler); -const handler = handlerModule.default; -let keys: string[]; -do { - try { - keys = await Promise.all(["cert", "key"].map((name) => Deno.readTextFile(`${name}.pem`))); - } catch (error) { - if (error instanceof Deno.errors.NotFound) { - console.log("SSL certificates not found, generating new ones..."); - await new Deno.Command("sh", { - args: [ - "-c", - "openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'", - ], - }).output(); - continue; - } - throw error; - } - break; - // eslint-disable-next-line no-constant-condition -} while (true); - -const [cert, key] = keys; -Deno.chdir(".."); - -try { - console.log(`Starting server on port ${args.port}...`); - await Deno.serve({ cert, key, port: args.port, reusePort: true }, handler.fetch); -} catch (error) { - if (error instanceof Deno.errors.PermissionDenied) { - const scriptName = Deno.mainModule.split('/').pop() || 'serve-ssl.ts'; - console.error(`\nError: Cannot bind to port ${args.port}. This port requires elevated privileges.`); - console.error(`Try one of these solutions:`); - console.error(` - Run with sudo: sudo deno run ... ${scriptName}`); - console.error(` - Use a port number above 1024: --port 8443\n`); - Deno.exit(1); - } - // Re-throw other errors - throw error; -} From 3a4b81f5e7b832dcaee5599e141ecee4958a8046 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 11:16:37 +0200 Subject: [PATCH 33/52] refactor: make API prefix configurable in cfRoutes function --- deno/main.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 080f642e..fbc2d33e 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -35,7 +35,7 @@ function adaptLegacyCloudflareHandler(handler: Function) { }; } -async function cfRoutes(fileRootUrl: string) { +async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { const routes = await discoverRoutes({ pattern: "/", fileRootUrl: fileRootUrl, @@ -49,7 +49,7 @@ async function cfRoutes(fileRootUrl: string) { const modulePath = module.toString(); const modulePathShort = modulePath.substring(fileRootUrl.length); // Only include routes that start with /api and aren't tests - const valid = modulePathShort.startsWith("/api") && !modulePathShort.includes(".test"); + const valid = modulePathShort.startsWith(prefix) && !modulePathShort.includes(".test"); if (!valid) { continue; } @@ -65,7 +65,7 @@ async function cfRoutes(fileRootUrl: string) { return handlers; } -const cfHandlers = await cfRoutes(import.meta.resolve("../functions")); +const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api"); const serveOpts = { fsRoot: "build" }; From 3851122590809054605eb122ba1d25723f4bd19e Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 13:01:55 +0200 Subject: [PATCH 34/52] refactor: update cfRoutes to handle URLPattern with prefix correctly --- deno/main.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index fbc2d33e..f92240a1 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -35,10 +35,10 @@ function adaptLegacyCloudflareHandler(handler: Function) { }; } -async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { +async function cfRoutes(fileRootUrl: string, prefix: string) { const routes = await discoverRoutes({ pattern: "/", - fileRootUrl: fileRootUrl, + fileRootUrl: fileRootUrl + prefix, pathMapper: freshPathMapper, verbose: true, }); @@ -46,6 +46,12 @@ async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { const handlers = []; for (const { pattern, module } of routes) { + let patternWithPrefix: URLPattern; + if (pattern instanceof URLPattern) { + patternWithPrefix = new URLPattern(pattern); + } else { + throw new Error("Only expect URLPatterns"); + } const modulePath = module.toString(); const modulePathShort = modulePath.substring(fileRootUrl.length); // Only include routes that start with /api and aren't tests @@ -57,9 +63,9 @@ async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { const routeModule = await import(modulePath); // console.log("Default:", routeModule.default); if (routeModule.onRequestGet) { - console.log("Route:", asSerializablePattern(pattern), "->", modulePathShort); + console.log("Route:", asSerializablePattern(patternWithPrefix), "->", modulePathShort); // console.log("onRequestGet:", routeModule.onRequestGet); - handlers.push(byPattern(pattern, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); + handlers.push(byPattern(patternWithPrefix, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); } } return handlers; From e527fafc9ce36a368a8ec144093b9e0a1ec2c6a8 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:01:57 +0200 Subject: [PATCH 35/52] refactor: simplify URL handling and destructure URLPattern properties inline --- deno/main.ts | 65 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index f92240a1..33243098 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -35,10 +35,13 @@ function adaptLegacyCloudflareHandler(handler: Function) { }; } -async function cfRoutes(fileRootUrl: string, prefix: string) { +async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { + // Proper URL joining using URL constructor + const fullFileRootUrl = new URL(prefix, fileRootUrl).toString(); + const routes = await discoverRoutes({ pattern: "/", - fileRootUrl: fileRootUrl + prefix, + fileRootUrl: fullFileRootUrl, pathMapper: freshPathMapper, verbose: true, }); @@ -46,32 +49,54 @@ async function cfRoutes(fileRootUrl: string, prefix: string) { const handlers = []; for (const { pattern, module } of routes) { - let patternWithPrefix: URLPattern; if (pattern instanceof URLPattern) { - patternWithPrefix = new URLPattern(pattern); + // Destructure pattern properties inline + const { + protocol, + username, + password, + hostname, + port, + pathname, + search, + hash, + } = pattern; + + // Add prefix to pathname using URL constructor for proper joining + const prefixedPath = new URL(prefix + pathname, 'http://localhost').pathname; + + // Create new pattern with prefixed path + const patternWithPrefix = new URLPattern({ + protocol, + username, + password, + hostname, + port, + pathname: prefixedPath, + search, + hash, + }); + + const modulePath = module.toString(); + const modulePathShort = modulePath.substring(fileRootUrl.length); + const valid = modulePathShort.startsWith(prefix) && !modulePathShort.includes(".test"); + if (!valid) { + continue; + } + + const routeModule = await import(modulePath); + if (routeModule.onRequestGet) { + console.log("Route:", asSerializablePattern(patternWithPrefix), "->", modulePathShort); + handlers.push(byPattern(patternWithPrefix, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); + } } else { throw new Error("Only expect URLPatterns"); } - const modulePath = module.toString(); - const modulePathShort = modulePath.substring(fileRootUrl.length); - // Only include routes that start with /api and aren't tests - const valid = modulePathShort.startsWith(prefix) && !modulePathShort.includes(".test"); - if (!valid) { - continue; - } - - const routeModule = await import(modulePath); - // console.log("Default:", routeModule.default); - if (routeModule.onRequestGet) { - console.log("Route:", asSerializablePattern(patternWithPrefix), "->", modulePathShort); - // console.log("onRequestGet:", routeModule.onRequestGet); - handlers.push(byPattern(patternWithPrefix, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); - } } return handlers; } -const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api"); +const cfHandlers = await cfRoutes(import.meta.resolve("../functions")); const serveOpts = { fsRoot: "build" }; From 109620de0c5bb88d49b5ab5681880a82d7897ab9 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 13:07:35 +0200 Subject: [PATCH 36/52] refactor: Add path module import to main.ts --- deno/main.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/deno/main.ts b/deno/main.ts index 33243098..a6e673fb 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -6,6 +6,7 @@ import { discoverRoutes } from "jsr:@http/discovery/discover-routes"; import { asSerializablePattern } from "jsr:@http/discovery/as-serializable-pattern"; import { byPattern } from "jsr:@http/route/by-pattern"; import { handle } from "jsr:@http/route/handle"; +import * as path from "jsr:@std/path"; // we can probably share these with vite by factoring them into a common JSON const defaults = { From 66a130e9975d2322109b42510ea4cf60c02daf65 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:07:37 +0200 Subject: [PATCH 37/52] refactor: Use `path.join` for proper path joining in cfRoutes --- deno/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index a6e673fb..af49e884 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -37,8 +37,8 @@ function adaptLegacyCloudflareHandler(handler: Function) { } async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { - // Proper URL joining using URL constructor - const fullFileRootUrl = new URL(prefix, fileRootUrl).toString(); + // Use path.join for proper path joining + const fullFileRootUrl = path.join(fileRootUrl, prefix); const routes = await discoverRoutes({ pattern: "/", @@ -63,8 +63,8 @@ async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { hash, } = pattern; - // Add prefix to pathname using URL constructor for proper joining - const prefixedPath = new URL(prefix + pathname, 'http://localhost').pathname; + // Use path.join for prefixing the path + const prefixedPath = path.join(prefix, pathname); // Create new pattern with prefixed path const patternWithPrefix = new URLPattern({ From 04b5ec41db77de58587584d69053c0653c651447 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:08:40 +0200 Subject: [PATCH 38/52] refactor: make prefix parameter required in cfRoutes function --- deno/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index af49e884..1e755978 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -36,7 +36,7 @@ function adaptLegacyCloudflareHandler(handler: Function) { }; } -async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { +async function cfRoutes(fileRootUrl: string, prefix: string) { // Use path.join for proper path joining const fullFileRootUrl = path.join(fileRootUrl, prefix); @@ -97,7 +97,7 @@ async function cfRoutes(fileRootUrl: string, prefix: string = "/api") { return handlers; } -const cfHandlers = await cfRoutes(import.meta.resolve("../functions")); +const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api"); const serveOpts = { fsRoot: "build" }; From 7d6585692f767f30f730f09aab6a058f64284d92 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:14:18 +0200 Subject: [PATCH 39/52] refactor: simplify URLPattern destructuring in cfRoutes function --- deno/main.ts | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 1e755978..2a55518f 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -51,31 +51,22 @@ async function cfRoutes(fileRootUrl: string, prefix: string) { for (const { pattern, module } of routes) { if (pattern instanceof URLPattern) { - // Destructure pattern properties inline - const { - protocol, - username, - password, - hostname, - port, - pathname, - search, - hash, - } = pattern; + // Only destructure pathname + const { pathname } = pattern; // Use path.join for prefixing the path const prefixedPath = path.join(prefix, pathname); - // Create new pattern with prefixed path + // Create new pattern using original pattern's properties with new pathname const patternWithPrefix = new URLPattern({ - protocol, - username, - password, - hostname, - port, + protocol: pattern.protocol, + username: pattern.username, + password: pattern.password, + hostname: pattern.hostname, + port: pattern.port, pathname: prefixedPath, - search, - hash, + search: pattern.search, + hash: pattern.hash, }); const modulePath = module.toString(); From e0c813b1f0bf888ac0f53bf32793cb35e26a99d7 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 13:19:17 +0200 Subject: [PATCH 40/52] refactor: optimize route filtering by removing redundant prefix check --- deno/main.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 2a55518f..85650bcb 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -36,8 +36,13 @@ function adaptLegacyCloudflareHandler(handler: Function) { }; } +/** + * Can reduce amount of scanning by filtering for prefix within fileRootUrl + * @param fileRootUrl + * @param prefix + * @returns + */ async function cfRoutes(fileRootUrl: string, prefix: string) { - // Use path.join for proper path joining const fullFileRootUrl = path.join(fileRootUrl, prefix); const routes = await discoverRoutes({ @@ -71,8 +76,7 @@ async function cfRoutes(fileRootUrl: string, prefix: string) { const modulePath = module.toString(); const modulePathShort = modulePath.substring(fileRootUrl.length); - const valid = modulePathShort.startsWith(prefix) && !modulePathShort.includes(".test"); - if (!valid) { + if (modulePathShort.includes(".test")) { continue; } From ea1071325b2289f7113296c4c5b96d980d639563 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:19:19 +0200 Subject: [PATCH 41/52] feat: add verbose parameter to control route logging in cfRoutes --- deno/main.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 85650bcb..409872e2 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -42,14 +42,14 @@ function adaptLegacyCloudflareHandler(handler: Function) { * @param prefix * @returns */ -async function cfRoutes(fileRootUrl: string, prefix: string) { +async function cfRoutes(fileRootUrl: string, prefix: string, verbose = false) { const fullFileRootUrl = path.join(fileRootUrl, prefix); const routes = await discoverRoutes({ pattern: "/", fileRootUrl: fullFileRootUrl, pathMapper: freshPathMapper, - verbose: true, + verbose, }); const handlers = []; @@ -82,7 +82,9 @@ async function cfRoutes(fileRootUrl: string, prefix: string) { const routeModule = await import(modulePath); if (routeModule.onRequestGet) { - console.log("Route:", asSerializablePattern(patternWithPrefix), "->", modulePathShort); + if (verbose) { + console.log("Route:", asSerializablePattern(patternWithPrefix), "->", modulePathShort); + } handlers.push(byPattern(patternWithPrefix, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); } } else { @@ -92,7 +94,7 @@ async function cfRoutes(fileRootUrl: string, prefix: string) { return handlers; } -const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api"); +const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api", false); const serveOpts = { fsRoot: "build" }; From 467e1e1e966fa69ac01fb5709736e882c6e93d96 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 13:20:52 +0200 Subject: [PATCH 42/52] refactor: Extract verbose flag into a variable in main.ts --- deno/main.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deno/main.ts b/deno/main.ts index 409872e2..d5d55062 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -94,7 +94,8 @@ async function cfRoutes(fileRootUrl: string, prefix: string, verbose = false) { return handlers; } -const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api", false); +const verbose = false; +const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api", verbose); const serveOpts = { fsRoot: "build" }; From bfca6d06a9d56513fd86cb25d317e21eb2923aae Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:20:54 +0200 Subject: [PATCH 43/52] refactor: gate logging on verbose parameter in main.ts --- deno/main.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index d5d55062..0ee5ece7 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -103,13 +103,17 @@ export default { fetch: handle(cfHandlers, async (req: Request) => { let ret = await serveDir(req, serveOpts); if (ret.status === 404) { - console.log("Got 404 from serveDir, trying with /:", req.url); // Add this line + if (verbose) { + console.log("Got 404 from serveDir, trying with /:", req.url); + } // Try again with / const url = new URL(req.url); url.pathname = "/"; ret = await serveDir(new Request(url, req), serveOpts); } - console.log(ret); + if (verbose) { + console.log(ret); + } return ret; }), }; From ac0b1621e824cef6def958fe2f2f531f22c3de64 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 13:22:51 +0200 Subject: [PATCH 44/52] comments --- deno/main.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 0ee5ece7..428f060c 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -37,10 +37,11 @@ function adaptLegacyCloudflareHandler(handler: Function) { } /** + * Scans CF path handlers * Can reduce amount of scanning by filtering for prefix within fileRootUrl - * @param fileRootUrl - * @param prefix - * @returns + * @param fileRootUrl + * @param prefix + * @returns */ async function cfRoutes(fileRootUrl: string, prefix: string, verbose = false) { const fullFileRootUrl = path.join(fileRootUrl, prefix); @@ -85,7 +86,9 @@ async function cfRoutes(fileRootUrl: string, prefix: string, verbose = false) { if (verbose) { console.log("Route:", asSerializablePattern(patternWithPrefix), "->", modulePathShort); } - handlers.push(byPattern(patternWithPrefix, adaptLegacyCloudflareHandler(routeModule.onRequestGet))); + handlers.push( + byPattern(patternWithPrefix, adaptLegacyCloudflareHandler(routeModule.onRequestGet)) + ); } } else { throw new Error("Only expect URLPatterns"); @@ -100,6 +103,7 @@ const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api", v const serveOpts = { fsRoot: "build" }; export default { + // Serve any pattern matches in cfHandlers, otherwise serve static files fetch: handle(cfHandlers, async (req: Request) => { let ret = await serveDir(req, serveOpts); if (ret.status === 404) { From 5196a8bc30dc4a355a0c0770286cbec0d5e3bd9a Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:27:01 +0200 Subject: [PATCH 45/52] refactor: consolidate module handling logic in adaptLegacyCloudflareHandler --- deno/main.ts | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 428f060c..2867981d 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -21,9 +21,25 @@ const env = { ...Deno.env.toObject(), }; -// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type -function adaptLegacyCloudflareHandler(handler: Function) { +function adaptLegacyCloudflareHandler(modulePath: string, verbose = false) { + const modulePathShort = modulePath.substring(modulePath.indexOf("/functions") + "/functions".length); + + // Skip test files + if (modulePathShort.includes(".test")) { + return null; + } + return async (request: Request, _match: URLPatternResult) => { + const routeModule = await import(modulePath); + + if (!routeModule.onRequestGet) { + return null; + } + + if (verbose) { + console.log("Route:", modulePathShort); + } + // Create minimal CF-style context object const ctx = { waitUntil: () => {}, @@ -31,8 +47,7 @@ function adaptLegacyCloudflareHandler(handler: Function) { }; // Call the legacy handler with CF-style arguments - const response = await handler({ request, env, ctx }); - return response; + return routeModule.onRequestGet({ request, env, ctx }); }; } @@ -75,20 +90,12 @@ async function cfRoutes(fileRootUrl: string, prefix: string, verbose = false) { hash: pattern.hash, }); - const modulePath = module.toString(); - const modulePathShort = modulePath.substring(fileRootUrl.length); - if (modulePathShort.includes(".test")) { - continue; - } - - const routeModule = await import(modulePath); - if (routeModule.onRequestGet) { + const handler = adaptLegacyCloudflareHandler(module.toString(), verbose); + if (handler) { if (verbose) { - console.log("Route:", asSerializablePattern(patternWithPrefix), "->", modulePathShort); + console.log("Route:", asSerializablePattern(patternWithPrefix), "->", module.toString()); } - handlers.push( - byPattern(patternWithPrefix, adaptLegacyCloudflareHandler(routeModule.onRequestGet)) - ); + handlers.push(byPattern(patternWithPrefix, handler)); } } else { throw new Error("Only expect URLPatterns"); From 3e9805099b751bce7b195fff7d74b5467c73d0fd Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:29:43 +0200 Subject: [PATCH 46/52] docs: Add JSDoc for `adaptLegacyCloudflareHandler` function --- deno/main.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/deno/main.ts b/deno/main.ts index 2867981d..5d6f1095 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -21,6 +21,19 @@ const env = { ...Deno.env.toObject(), }; +/** + * Adapts a legacy Cloudflare Workers-style module to a modern request handler. + * + * @param {string} modulePath - The full path to the module to import + * @param {boolean} [verbose=false] - Whether to enable verbose logging + * @returns {Function|null} - A request handler function or null if the module is invalid + * + * @example + * const handler = adaptLegacyCloudflareHandler('/path/to/module.ts'); + * if (handler) { + * app.get('/route', handler); + * } + */ function adaptLegacyCloudflareHandler(modulePath: string, verbose = false) { const modulePathShort = modulePath.substring(modulePath.indexOf("/functions") + "/functions".length); From b773b28f06c97948f0f471a298676697d0bc96f3 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:30:30 +0200 Subject: [PATCH 47/52] docs: update JSDoc to use modern fetch handler terminology --- deno/main.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 5d6f1095..572cd247 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -22,11 +22,11 @@ const env = { }; /** - * Adapts a legacy Cloudflare Workers-style module to a modern request handler. + * Adapts a Cloudflare Workers-style module to a modern fetch handler. * * @param {string} modulePath - The full path to the module to import * @param {boolean} [verbose=false] - Whether to enable verbose logging - * @returns {Function|null} - A request handler function or null if the module is invalid + * @returns {Function|null} - A fetch handler function or null if the module is invalid * * @example * const handler = adaptLegacyCloudflareHandler('/path/to/module.ts'); @@ -59,7 +59,7 @@ function adaptLegacyCloudflareHandler(modulePath: string, verbose = false) { passThroughOnException: () => {}, }; - // Call the legacy handler with CF-style arguments + // Call the handler with CF-style arguments return routeModule.onRequestGet({ request, env, ctx }); }; } From 1d82d5b57e7b92981dabe74ac9799c92896c6292 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:31:14 +0200 Subject: [PATCH 48/52] refactor: rename adaptLegacyCloudflareHandler to adaptCloudflareHandler --- deno/main.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 572cd247..345f4f22 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -29,12 +29,12 @@ const env = { * @returns {Function|null} - A fetch handler function or null if the module is invalid * * @example - * const handler = adaptLegacyCloudflareHandler('/path/to/module.ts'); + * const handler = adaptCloudflareHandler('/path/to/module.ts'); * if (handler) { * app.get('/route', handler); * } */ -function adaptLegacyCloudflareHandler(modulePath: string, verbose = false) { +function adaptCloudflareHandler(modulePath: string, verbose = false) { const modulePathShort = modulePath.substring(modulePath.indexOf("/functions") + "/functions".length); // Skip test files @@ -103,7 +103,7 @@ async function cfRoutes(fileRootUrl: string, prefix: string, verbose = false) { hash: pattern.hash, }); - const handler = adaptLegacyCloudflareHandler(module.toString(), verbose); + const handler = adaptCloudflareHandler(module.toString(), verbose); if (handler) { if (verbose) { console.log("Route:", asSerializablePattern(patternWithPrefix), "->", module.toString()); From f8d6e6a6ec624c8e0cee1f0499f348de1d8d38c8 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:36:33 +0200 Subject: [PATCH 49/52] style: format code to match Prettier standards --- deno/main.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deno/main.ts b/deno/main.ts index 345f4f22..2145547e 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -35,7 +35,9 @@ const env = { * } */ function adaptCloudflareHandler(modulePath: string, verbose = false) { - const modulePathShort = modulePath.substring(modulePath.indexOf("/functions") + "/functions".length); + const modulePathShort = modulePath.substring( + modulePath.indexOf("/functions") + "/functions".length + ); // Skip test files if (modulePathShort.includes(".test")) { From f50c1a7a9dfe37a30755950490b6687d7dd5b737 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:36:51 +0200 Subject: [PATCH 50/52] style: Format adaptCloudflareHandler function with Prettier --- deno/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno/main.ts b/deno/main.ts index 2145547e..20e84af6 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -38,7 +38,7 @@ function adaptCloudflareHandler(modulePath: string, verbose = false) { const modulePathShort = modulePath.substring( modulePath.indexOf("/functions") + "/functions".length ); - + // Skip test files if (modulePathShort.includes(".test")) { return null; From 258f8b4adada564938e5416d2b058b3a41b3cbd5 Mon Sep 17 00:00:00 2001 From: "Taras Glek (aider)" Date: Thu, 9 Jan 2025 13:37:51 +0200 Subject: [PATCH 51/52] style: Fix Prettier formatting in main.ts --- deno/main.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 20e84af6..826a7f82 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -36,8 +36,7 @@ const env = { */ function adaptCloudflareHandler(modulePath: string, verbose = false) { const modulePathShort = modulePath.substring( - modulePath.indexOf("/functions") + "/functions".length - ); + modulePath.indexOf("/functions") + "/functions".length); // Skip test files if (modulePathShort.includes(".test")) { From a0b43134e91645eaf9d6b6ec22201a04e3de7ab8 Mon Sep 17 00:00:00 2001 From: Taras Glek Date: Thu, 9 Jan 2025 13:38:51 +0200 Subject: [PATCH 52/52] lint --- deno/main.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/deno/main.ts b/deno/main.ts index 826a7f82..aff92c76 100644 --- a/deno/main.ts +++ b/deno/main.ts @@ -23,11 +23,11 @@ const env = { /** * Adapts a Cloudflare Workers-style module to a modern fetch handler. - * + * * @param {string} modulePath - The full path to the module to import * @param {boolean} [verbose=false] - Whether to enable verbose logging * @returns {Function|null} - A fetch handler function or null if the module is invalid - * + * * @example * const handler = adaptCloudflareHandler('/path/to/module.ts'); * if (handler) { @@ -36,7 +36,8 @@ const env = { */ function adaptCloudflareHandler(modulePath: string, verbose = false) { const modulePathShort = modulePath.substring( - modulePath.indexOf("/functions") + "/functions".length); + modulePath.indexOf("/functions") + "/functions".length + ); // Skip test files if (modulePathShort.includes(".test")) { @@ -45,7 +46,7 @@ function adaptCloudflareHandler(modulePath: string, verbose = false) { return async (request: Request, _match: URLPatternResult) => { const routeModule = await import(modulePath); - + if (!routeModule.onRequestGet) { return null; }