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

@geektech/backone

v0.1.2

Published

BackOne 是基于 Bun 的轻量级纯 TypeScript 服务端框架,零运行时依赖,提供路由、中间件、上下文与静态文件服务

Readme

BackOne

English | 简体中文

A lightweight server-side framework written entirely in TypeScript, built on Bun. Zero runtime dependencies — routing, middleware, request context, and static file serving.

Features

  • TypeScript-first with zero runtime dependencies
  • Bun-native: built on Bun.serve, streaming responses, zero-copy static files
  • Segment radix-tree router with :param and * wildcard support
  • Typed routes: generic params give IDE autocompletion and type checking
  • Onion-model middleware chain with a typed per-request Context
  • Lazy query / body parsing with caching
  • Return a Response directly for zero-overhead passthrough
  • Built-in middleware: logger, cors, gzip, serveStatic, timeout, helmet
  • Static files with ETag, Last-Modified, If-None-Match 304 and Range 206
  • WebSocket support via app.ws(path, handler) on Bun native upgrade
  • Route groups with app.group(prefix, callback) for shared prefixes
  • Route prefix with app.usePrefix(prefix, callback?): persistent replacement or scoped stacking for later routes, composable with group
  • Graceful shutdown: wait for in-flight requests, force-close after timeout

Requirements

  • Bun >= 1.3

Quick Start

import { createServer } from '@geektech/backone';

const app = createServer({ port: 3000 });

app.useLogger();
app.get('/users/:id', (ctx) => ctx.json({ id: ctx.params.id }));
app.post('/echo', async (ctx) => ctx.json(await ctx.bodyJson()));
app.serveStatic('/public', './public');

await app.listen();

API

createServer(options)

Create a server application. Options: port (default 3000, 0 for a random port), hostname (default 0.0.0.0), development (log error details and expose messages in error responses), maxRequestBodySize, idleTimeout.

Routing

app.get / post / put / patch / delete / options / head / all(path, ...handlers) register handlers. Paths support static segments, :param, and * wildcards. Multiple handlers on one route run in order.

All route methods accept a generic type for typed params:

app.get<{ id: string }>('/users/:id', (ctx) => {
  // ctx.params.id is typed as string
  return ctx.json({ id: ctx.params.id });
});

Route groups register multiple routes under a shared prefix:

app.group('/api/v1', (api) => {
  api.get('/users', handler);
  api.post('/users', handler);
});

usePrefix adds a prefix to routes registered afterwards — persistent or scoped, composable with group:

app.usePrefix('/api');
app.get('/users', handler); // GET /api/users

app.usePrefix('/v2', (api) => {
  api.get('/users', handler); // GET /api/v2/users
}); // prefix restored to /api afterwards

app.usePrefix(); // reset: no prefix

Context

Each request gets a Context:

  • ctx.params, ctx.query — path / query parameters (query is lazily parsed)
  • ctx.bodyJson<T>(), ctx.bodyText() — lazily parsed and cached body
  • ctx.json / text / html / stream / redirect / noContent — response builders
  • ctx.status, ctx.set(name, value), ctx.headers
  • ctx.cookie(name), ctx.setCookie(name, value, options)

Handlers may return a Response directly (passthrough) or a primitive / object which the framework serializes.

Middleware

app.use(...handlers) installs middleware; the chain follows the onion model. Built-in: logger, cors, gzip, timeout, helmet, serveStatic (also available as app.useLogger(), app.useCors(), app.useGzip(), app.useTimeout(), app.useHelmet(), app.serveStatic()).

serveStatic serves files via Bun.file with zero-copy streaming. Responses carry ETag, Last-Modified and Accept-Ranges: bytes; If-None-Match / If-Modified-Since return 304, and Range requests return 206 partial content.

helmet sets common security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy, etc.), each overridable or disablable via options. timeout returns 504 when a handler exceeds the specified milliseconds.

WebSocket

Register a WebSocket handler on a path with app.ws(path, handler). Requests with Upgrade: websocket on a registered path are automatically upgraded via Bun native server.upgrade().

app.ws('/echo', {
  open(ws) { ws.send('connected'); },
  message(ws, message) { ws.send(`echo: ${message}`); },
  close(ws, code, reason) { console.log('closed', code, reason); },
});

Errors

Throw HttpError from @geektech/backone to control the status code; unknown errors become 500 Internal Server Error without leaking internals.

Development

bun test          # run tests
bun run build     # build dist (Bun.build + type declarations)
bun run lint      # eslint

Repository Structure

This package lives at packages/backone in the BackOne monorepo (@geektech/backone is the server-side framework; @geektech/backone-utils is its general-purpose toolkit; @geektech/backone-cli scaffolds server applications). Publish checks follow the same discipline: bun test && bunx tsc --noEmit && bun run build && bun pm pack --dry-run.

License

MIT