npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tsonic/express

v10.0.39

Published

TypeScript type definitions for Express.js style API on ASP.NET Core

Readme

@tsonic/express

Express-style HTTP server APIs for Tsonic.

This package is part of Tsonic: https://tsonic.org.

Use this package to write Express-like apps in TypeScript and compile them to native binaries with tsonic.

The project surface should be @tsonic/js. @tsonic/express remains a normal imported package, but its public API is JS-facing:

  • Date, Uint8Array, number
  • Record<string, ...> and arrays
  • no CLR collection/runtime types in the TS-facing contract

Prerequisites

  • Install the .NET 10 SDK (required by Tsonic): https://dotnet.microsoft.com/download
  • Verify: dotnet --version

Quick Start (new project)

mkdir my-api && cd my-api
npx --yes tsonic@latest init --surface @tsonic/js

# Install Express runtime + bindings (installs required ASP.NET Core deps too)
npx --yes tsonic@latest add npm @tsonic/express

# Replace the default App.ts with a minimal API
cat > packages/my-api/src/App.ts <<'EOF'
import { express } from "@tsonic/express/index.js";

export function main(): void {
  const app = express.create();

  app.get("/", async (_req, res, _next) => {
    res.json({ ok: true });
  });

  app.listen(3000);
}
EOF

npm run dev

Then open http://localhost:3000/.

Hello World

// packages/my-api/src/App.ts
import { express } from "@tsonic/express/index.js";

export function main(): void {
  const app = express.create();

  app.get("/", async (_req, res, _next) => {
    res.send("hello");
  });

  app.listen(3000);
}

Basic API Surface

Handler model (important)

This package is Task-first (like ASP.NET): route handlers and middleware should be written as async functions (even if you don't await anything).

This avoids “async-void” behavior and keeps execution/exception semantics deterministic.

Also, handlers use the 3-argument signature: (req, res, next) (even for routes). If you don't need next, name it _next.

Create an app / router

import { express } from "@tsonic/express/index.js";

const app = express.create();
const router = express.Router();

router.get("/ping", async (_req, res, _next) => {
  res.send("pong");
});

app.use("/api", router);

Routing

Common verbs:

app.get("/health", async (_req, res, _next) => {
  res.send("ok");
});
app.post("/items", async (req, res, _next) => {
  res.json(req.body);
});
app.put("/items/:id", async (req, res, _next) => {
  res.send(req.params["id"] ?? "");
});
app.delete("/items/:id", async (_req, res, _next) => {
  res.sendStatus(204);
});
app.patch("/items/:id", async (_req, res, _next) => {
  res.sendStatus(204);
});
app.all("/anything", async (_req, res, _next) => {
  res.send("matched");
});

Middleware

app.use(async (req, _res, next) => {
  // Do something with req
  await next();
});

CORS

app.use(express.cors());

Cookies

app.get("/set-cookie", async (_req, res, _next) => {
  res.cookie("sid", "abc");
  res.send("ok");
});

app.get("/read-cookie", async (req, res, _next) => {
  res.json({ sid: req.cookies["sid"] });
});

Error middleware:

app.useError(async (err, _req, res, _next) => {
  res.status(500).json({ error: `${err}` });
});

Request / Response

Request highlights:

  • req.method, req.path, req.originalUrl
  • req.query, req.params, req.cookies, req.signedCookies
  • req.body (when using body parsers)
  • req.get(name) / req.header(name)

Response highlights:

  • res.status(code)
  • res.send(body), res.json(body), res.sendStatus(code)
  • res.redirect(path) / res.redirect(status, path)
  • res.set(name, value) / res.header(name, value)
  • res.cookie(name, value, options) / res.clearCookie(name, options)

Body parsing

app.use(express.json());
app.use(express.urlencoded());
app.use(express.text());
app.use(express.raw());

Multipart / file uploads

const upload = express.multipart();

app.post("/upload", upload.single("avatar"), async (req, res, _next) => {
  res.json({
    filename: req.file?.originalname,
    fields: req.body,
  });
});

Static files

app.use(express.static("./public"));

Listen / close

const server = app.listen(3000);
server.close();

Advanced docs

Versioning Model

This repo is versioned by runtime major:

License

MIT