Skip to main content
Home

@fartlabs/rtx@0.0.16
Built and signed on GitHub Actions

Minimal HTTP router library based on the URLPattern API in JSX.

This package works with DenoIt is unknown whether this package works with Cloudflare Workers, Node.js, Bun, Browsers
It is unknown whether this package works with Cloudflare Workers
It is unknown whether this package works with Node.js
This package works with Deno
It is unknown whether this package works with Bun
It is unknown whether this package works with Browsers
JSR Score
94%
Published
2 weeks ago (0.0.16)

@fartlabs/rtx

JSR JSR score GitHub Actions

Library of @fartlabs/jsonx components for composing @fartlabs/rt routers in JSX.

API documentation

Generated API documentation is available at https://jsr.io/@fartlabs/rtx.

Getting started

Deno

Let's learn how to get started with rtx by creating a simple router in Deno.

1. Install Deno.

2. Start a new Deno project.

deno init

3. Add @fartlabs/rtx as a project dependency.

deno add jsr:@fartlabs/rtx

4. Add the following values to your deno.json(c) file.

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@fartlabs/rtx"
  }
}

5. Add a file ending in .[j|t]sx to your project. For example, main.tsx.

import { Get, Router } from "@fartlabs/rtx";

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

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

6. Spin up your HTTP server by running the .[j|t]sx file.

deno run --allow-net main.tsx

Examples

Multiple HTTP methods

import { Delete, Get, Post, Put, Router } from "@fartlabs/rtx";

const router = (
  <Router default={() => new Response("Not found", { status: 404 })}>
    <Get
      pattern="/"
      handle={() =>
        new Response("Home")}
    />
    <Post
      pattern="/items"
      handle={async (req) => {
        const body = await req.json();
        return Response.json({ created: body }, { status: 201 });
      }}
    />
    <Put
      pattern="/items/:id"
      handle={async (req, { params }) => {
        const body = await req.json();
        return Response.json({ updatedId: params.id, data: body });
      }}
    />
    <Delete
      pattern="/items/:id"
      handle={(_, { params }) =>
        new Response(`Deleted ${params.id}`, { status: 204 })}
    />
  </Router>
);

Route parameters and query parameters

import { Get, Router } from "@fartlabs/rtx";

const router = (
  <Router default={() => new Response("Not found", { status: 404 })}>
    <Get
      pattern="/users/:id"
      handle={(request, { params, url }) => {
        const page = Number(url.searchParams.get("page") ?? 1);
        return Response.json({ id: params.id, page });
      }}
    />
  </Router>
);

Middleware-like composition

You can wrap handlers to implement common behavior (auth, logging, headers).

import { Get, Router } from "@fartlabs/rtx";
import type { RequestHandler } from "@fartlabs/rt";

const withJson = (handler: RequestHandler): RequestHandler => async (ctx) => {
  try {
    const res = await handler(ctx);
    const headers = new Headers(res.headers);
    if (!headers.has("content-type")) {
      headers.set("content-type", "application/json; charset=utf-8");
    }
    return new Response(res.body, { status: res.status, headers });
  } catch (error) {
    return Response.json({ error: String(error) }, { status: 500 });
  }
};

const router = (
  <Router default={() => new Response("Not found", { status: 404 })}>
    <Get
      pattern="/health"
      handle={withJson(() =>
        Response.json({ ok: true })
      )}
    />
  </Router>
);

Nested routes

import { Get, Router } from "@fartlabs/rtx";

const Users = (
  <>
    <Get pattern="/users" handle={() => Response.json([{ id: "1" }])} />
    <Get
      pattern="/users/:id"
      handle={(_, { params }) => Response.json({ id: params.id })}
    />
  </>
);

const router = (
  <Router default={() => new Response("Not found", { status: 404 })}>
    {Users}
  </Router>
);

Error handling

import { Get, Router } from "@fartlabs/rtx";

const router = (
  <Router default={() => new Response("Not found", { status: 404 })}>
    <Get
      pattern="/boom"
      handle={() => {
        throw new Error("Something went wrong");
      }}
    />
  </Router>
);

// Wrap fetch to centralize error responses
const safeFetch = async (request: Request) => {
  try {
    return await router.fetch(request);
  } catch (error) {
    return Response.json({ error: String(error) }, { status: 500 });
  }
};

Deno.serve((request) => safeFetch(request));

Contribute

Style

Run deno fmt to format the code.

Run deno lint to lint the code.


Developed with ❤️ @FartLabs

Testing

This repo uses Deno tests.

deno test -A

Migration from rt to rtx

  • Replace imperative route registrations with JSX elements like Get, Post, etc.
  • Create a top-level Router and pass a default handler for unmatched routes.
  • Handlers receive Request and a context with url and params (for :param tokens).
  • Compose cross-cutting concerns by higher-order functions that wrap route handle.

License

This project is licensed under the MIT License — see LICENSE for details.

Built and signed on
GitHub Actions

New Ticket: Report package

Please provide a reason for reporting this package. We will review your report and take appropriate action.

Please review the JSR usage policy before submitting a report.

Add Package

deno add jsr:@fartlabs/rtx

Import symbol

import * as rtx from "@fartlabs/rtx";
or

Import directly with a jsr specifier

import * as rtx from "jsr:@fartlabs/rtx";

Add Package

pnpm i jsr:@fartlabs/rtx
or (using pnpm 10.8 or older)
pnpm dlx jsr add @fartlabs/rtx

Import symbol

import * as rtx from "@fartlabs/rtx";

Add Package

yarn add jsr:@fartlabs/rtx
or (using Yarn 4.8 or older)
yarn dlx jsr add @fartlabs/rtx

Import symbol

import * as rtx from "@fartlabs/rtx";

Add Package

vlt install jsr:@fartlabs/rtx

Import symbol

import * as rtx from "@fartlabs/rtx";

Add Package

npx jsr add @fartlabs/rtx

Import symbol

import * as rtx from "@fartlabs/rtx";

Add Package

bunx jsr add @fartlabs/rtx

Import symbol

import * as rtx from "@fartlabs/rtx";