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

@litejs/server

v26.7.0

Published

Server for LiteJS full-stack framework

Downloads

442

Readme

LiteJS Server – Coverage Size Buy Me A Tea

A small, zero-dependency HTTP application core that runs the same code across Bun, Cloudflare Workers, Deno, Node.js, and on browser Service Worker.

Usage

npm install @litejs/server

// app.mjs
import { App } from "@litejs/server"

const app = App()

// Middlewares runs only if any route matches
app.use((req, env) => {
	// return a response to stop further execution
})

// Only single, first matching route get executed!
app.get('hello/world', (req, env) => 'Hello MOON!')
app.get('hello/{name}', (req, env) => 'Hello ' + req.param.name)
app.get('bye/{name}', (req, env) => 'Bye ' + req.param.name)
app.get('bye/moon', (req, env) => { /* Never executed as previous handler matches */ })
app.get('teapot', (req) => (req.resStatus = 418, "no coffee"))
app.get('notFound', () => 404) // Return a number to send status code

// Group routes and mount under a prefix
const subApp = App()
.post("", (req, env) => {
    // GET /api -> req.path == '/' and req.fullPath == '/api'
    return { data: [] }
})
.post("echo", async (req, env) => {
    // POST /api/echo -> req.path == '/echo' and req.fullPath == '/api/echo'
    return await req.json()
})

app.mount("api", subApp)

export default app

Handlers receive (req, env, ctx) and may return a native Response, a number (status only), an object or array (serialized to JSON), or a body passed to new Response.

Set the status with req.resStatus = 409, extra headers with req.resHeaders.allow = 'GET, PUT'. Thrown errors map to err.code || 500; 5xx bodies are kept generic.

Requests include param, path, fullPath, query, searchParams, and header(name).

Routes

  • user/{username} matches one path segment (no /)
  • post/{id+} matches one or more digits
  • files/{rest*}.ext matches all chars, greedy
  • a/{dir/}{name} matches zero or more slash-terminated directories
  • pub/\{x} matches the literal path pub/{x}

Adapters

The same app runs on every runtime. @litejs/server exports the matching adapter through conditional export, so the one file below runs unchanged on Node.js, Bun, and Deno.

// run.mjs
import {
    DB, KV, listen, loadEnv, serveStatic, setupShutdown
} from "@litejs/server"
import app from "./app.mjs"

const db = new DB("db.sqlite")
const env = loadEnv(".env.json", {
    ASSETS: serveStatic("public"),
    // Inject Cloudflare style KV on top of sqlite
    DEVICE: KV(db, "device"),
})
const server = listen(app, env)
app.get("/{path*}", env.ASSETS.fetch)

// Attach SIGINT/SIGTERM/SIGHUP/uncaughtException
setupShutdown([ server ])

Run it with node run.mjs, bun run.mjs, or deno run -A run.mjs.

Runtimes

  • Node.js, Bun, Deno: import from @litejs/server; the runtime is detected automatically.
  • Cloudflare Workers: import { worker } from "@litejs/server", then export default { fetch: worker(app) }.
  • Service Workers: import { listen } from "@litejs/server".

On Node, Bun, and Deno @litejs/server also exports serveStatic, loadEnv, setupShutdown, and SQLite-backed DB (D1) and KV shims.

Runnable examples are in test/server/.

Copyright (c) 2026 Lauri Rooden <[email protected]>
MIT License | GitHub repo | npm package | Buy Me A Tea