Skip to content

FartLabs/rt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub Actions JSR JSR score

Minimal HTTP router library based on the URLPattern API.

Usage

import { Router } from "@fartlabs/rt";

const router = new Router()
  .get("/", () => new Response("Hello, World!"))
  .default(() => new Response("Not found", { status: 404 }));

Deno.serve((request) => router.fetch(request));

Examples

Multiple methods

Handle common HTTP verbs (GET, POST, PUT, DELETE) on resourceful routes.

import { Router } from "@fartlabs/rt";

const router = new Router()
  .get("/users", () => new Response("List users"))
  .post("/users", async ({ request }) => {
    const body = await request.json();
    return Response.json({ created: true, user: body });
  })
  .put("/users/:id", async ({ params, request }) => {
    const id = params?.pathname.groups?.id;
    const body = await request.json();
    return Response.json({ updated: id, user: body });
  })
  .delete("/users/:id", ({ params }) => {
    const id = params?.pathname.groups?.id;
    return new Response(`Deleted ${id}`, { status: 204 });
  })
  .default(() => new Response("Not found", { status: 404 }));

Deno.serve((req) => router.fetch(req));

Route params and wildcards

Use URLPattern named parameters and a catch‑all wildcard for flexible matching.

const router = new Router()
  // Named params are available via URLPattern groups
  .get("/hello/:name", ({ params }) => {
    const name = params?.pathname.groups?.name ?? "World";
    return new Response(`Hello, ${name}!`);
  })
  // Wildcard catch-all
  .get("/*", () => new Response("Catch-all"));

Query parameters

Access query string values via new URL(request.url).searchParams.

const router = new Router().get("/search", ({ request }) => {
  const { searchParams } = new URL(request.url);
  const q = searchParams.get("q") ?? "";
  return new Response(`You searched for: ${q}`);
});

Middleware via next() and shared state

Add middleware that enriches a shared state object and delegates with next().

interface State {
  user?: { name: string };
}

const router = new Router<State>()
  // auth-like middleware that enriches state, then calls next()
  .get("/*", async ({ state, next }) => {
    state.user = { name: "Wazoo" };
    return await next();
  })
  .get("/:name", ({ params, state }) => {
    const name = params?.pathname.groups?.name;
    if (state.user?.name !== name) {
      return new Response("Forbidden", { status: 403 });
    }
    return new Response(`Hello, ${name}!`);
  });

Custom default and error handlers

Provide a custom 404 response and a centralized error handler for thrown errors.

const router = new Router()
  .get("/boom", () => {
    throw new Error("Kaboom");
  })
  .default(() => new Response("Custom 404", { status: 404 }))
  .error((err) => new Response(`Oops: ${err.message}`, { status: 500 }));

Nesting or composing routers

Compose routers by mounting one router's routes into another.

const api = new Router().get("/v1/ping", () => new Response("pong"));
const router = new Router().use(api);

Deno

1. Install Deno.

2. Start a new Deno project.

deno init

3. Add rt as a project dependency.

deno add jsr:@fartlabs/rt

Testing

Run tests:

deno test

Type-check the project:

deno task check

RTX

If you prefer composing routers in JSX, check out RTX: a library of JSX components that build @fartlabs/rt routers.

Contribute

We appreciate your help!

Style

Run deno fmt to format the code.

Run deno lint to lint the code.

License

This project is licensed under the WTFPL. See LICENSE for details.


Developed with ❤️ @FartLabs

About

Minimal HTTP router library based on the URLPattern API.

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published