Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deno routing to try to make existing cloudflare code run #773

Merged
merged 52 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
68fa3ee
deno stuff
tarasglek Jan 8, 2025
edbfa99
refactor: Replace fsrouter with new route discovery mechanism using @…
tarasglek Jan 8, 2025
c8166bd
feat: Skip test files when importing route modules
tarasglek Jan 8, 2025
b73dd18
refactor: Modify route filtering to only include paths starting with …
tarasglek Jan 8, 2025
1f2694a
refactor: Improve route filtering and logging in Cloudflare route han…
tarasglek Jan 8, 2025
b623a2e
feat: Add adapter for legacy Cloudflare Workers route handlers
tarasglek Jan 8, 2025
8f5438b
feat: Add type annotation for `cfRoutes` return value and remove type…
tarasglek Jan 8, 2025
fded73c
refactor: Simplify Cloudflare route handling and improve environment …
tarasglek Jan 8, 2025
18e2c70
refactor: Extract common serveDir options and add fallback to index.html
tarasglek Jan 8, 2025
3e20e4d
fix: Update fallback route to serve index.html correctly
tarasglek Jan 8, 2025
f49b41e
feat: Add logging for 404 status in Deno server
tarasglek Jan 8, 2025
8c2b3f4
feat: Add logging and default export for login API function
tarasglek Jan 8, 2025
040396a
misc
tarasglek Jan 8, 2025
d565915
feat: Add fallback values for environment variables in Deno main
tarasglek Jan 8, 2025
22c9212
dummy login/logout works on deno now
tarasglek Jan 8, 2025
797952d
refactor: Replace process.env with Deno.env.toObject() for Deno compa…
tarasglek Jan 8, 2025
c0626b6
refactor: Remove unused imports and simplify route logging
tarasglek Jan 8, 2025
152d240
refactor: Consolidate route logging into a single, concise console.lo…
tarasglek Jan 8, 2025
bbefc91
misc
tarasglek Jan 8, 2025
6f70660
misc
tarasglek Jan 8, 2025
f6f6651
fix: Adjust SSL certificate loading and linting in Deno server
tarasglek Jan 8, 2025
04a9923
chore: Add eslint-disable comments to silence specific lint warnings
tarasglek Jan 8, 2025
fe7f6cb
lint
tarasglek Jan 8, 2025
6273e53
misc
tarasglek Jan 8, 2025
2d5c55a
refactor: Simplify environment variable initialization with defaults
tarasglek Jan 8, 2025
f06ab4e
lint
tarasglek Jan 8, 2025
3ad5955
works in smallweb again
tarasglek Jan 9, 2025
c24f87d
feat: Add command-line argument parsing for serve-ssl.ts
tarasglek Jan 9, 2025
5b34c3d
refactor: Update import for parseArgs from @std/cli to jsr namespace
tarasglek Jan 9, 2025
c692187
feat: Improve error handling for port binding with dynamic script name
tarasglek Jan 9, 2025
64cbd23
feat: Add help text and -h/--help support for serve-ssl.ts
tarasglek Jan 9, 2025
5f143f4
removed ssl hack
tarasglek Jan 9, 2025
3a4b81f
refactor: make API prefix configurable in cfRoutes function
tarasglek Jan 9, 2025
3851122
refactor: update cfRoutes to handle URLPattern with prefix correctly
tarasglek Jan 9, 2025
e527faf
refactor: simplify URL handling and destructure URLPattern properties…
tarasglek Jan 9, 2025
109620d
refactor: Add path module import to main.ts
tarasglek Jan 9, 2025
66a130e
refactor: Use `path.join` for proper path joining in cfRoutes
tarasglek Jan 9, 2025
04b5ec4
refactor: make prefix parameter required in cfRoutes function
tarasglek Jan 9, 2025
7d65856
refactor: simplify URLPattern destructuring in cfRoutes function
tarasglek Jan 9, 2025
e0c813b
refactor: optimize route filtering by removing redundant prefix check
tarasglek Jan 9, 2025
ea10713
feat: add verbose parameter to control route logging in cfRoutes
tarasglek Jan 9, 2025
467e1e1
refactor: Extract verbose flag into a variable in main.ts
tarasglek Jan 9, 2025
bfca6d0
refactor: gate logging on verbose parameter in main.ts
tarasglek Jan 9, 2025
ac0b162
comments
tarasglek Jan 9, 2025
5196a8b
refactor: consolidate module handling logic in adaptLegacyCloudflareH…
tarasglek Jan 9, 2025
3e98050
docs: Add JSDoc for `adaptLegacyCloudflareHandler` function
tarasglek Jan 9, 2025
b773b28
docs: update JSDoc to use modern fetch handler terminology
tarasglek Jan 9, 2025
1d82d5b
refactor: rename adaptLegacyCloudflareHandler to adaptCloudflareHandler
tarasglek Jan 9, 2025
f8d6e6a
style: format code to match Prettier standards
tarasglek Jan 9, 2025
f50c1a7
style: Format adaptCloudflareHandler function with Prettier
tarasglek Jan 9, 2025
258f8b4
style: Fix Prettier formatting in main.ts
tarasglek Jan 9, 2025
a0b4313
lint
tarasglek Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 139 additions & 4 deletions deno/main.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,145 @@
// 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";
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";

/** run `pnpm build --watch` */
function handleFetch(req: Request): Promise<Response> {
return serveDir(req, { fsRoot: "build" });
// 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",
JWT_SECRET: "jwt_secret",
};

const env = {
...defaults,
...Deno.env.toObject(),
};

/**
* 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) {
* app.get('/route', handler);
* }
*/
function adaptCloudflareHandler(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: () => {},
passThroughOnException: () => {},
};

// Call the handler with CF-style arguments
return routeModule.onRequestGet({ request, env, ctx });
};
}

/**
* Scans CF path handlers
* Can reduce amount of scanning by filtering for prefix within fileRootUrl
* @param fileRootUrl
* @param prefix
* @returns
*/
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,
});

const handlers = [];

for (const { pattern, module } of routes) {
if (pattern instanceof URLPattern) {
// Only destructure pathname
const { pathname } = pattern;

// Use path.join for prefixing the path
const prefixedPath = path.join(prefix, pathname);

// Create new pattern using original pattern's properties with new pathname
const patternWithPrefix = new URLPattern({
protocol: pattern.protocol,
username: pattern.username,
password: pattern.password,
hostname: pattern.hostname,
port: pattern.port,
pathname: prefixedPath,
search: pattern.search,
hash: pattern.hash,
});

const handler = adaptCloudflareHandler(module.toString(), verbose);
if (handler) {
if (verbose) {
console.log("Route:", asSerializablePattern(patternWithPrefix), "->", module.toString());
}
handlers.push(byPattern(patternWithPrefix, handler));
}
} else {
throw new Error("Only expect URLPatterns");
}
}
return handlers;
}

const verbose = false;
const cfHandlers = await cfRoutes(import.meta.resolve("../functions"), "/api", verbose);

const serveOpts = { fsRoot: "build" };

export default {
fetch: handleFetch,
// 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) {
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);
}
if (verbose) {
console.log(ret);
}
return ret;
}),
};
3 changes: 2 additions & 1 deletion smallweb.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"entrypoint": "deno/main.ts"
"entrypoint": "deno/main.ts",
"denoArgs": ["--unstable-sloppy-imports"]
}
Loading