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

@sejori/peko

v2.4.2

Published

Featherweight apps on the edge 🐣⚡

Downloads

47

Readme

npm i @sejori/peko

Routes and middleware are added to a Router instance with .use, .addRoute or .get/post/put/delete.

The router is then used with your web server of choice, e.g. Deno.serve or Bun.serve.

import * as Peko from "@sejori/peko"; // or https://deno.land/x/peko/mod.ts in Deno

const router = new Peko.Router();

router.use(Peko.logger(console.log));

router.get("/shorthand-route", () => new Response("Hello world!"));

router.post(
  "/shorthand-route-ext",
  async (ctx, next) => {
    await next();
    console.log(ctx.request.headers);
  },
  (req) => new Response(req.body)
);

router.addRoute({
  path: "/object-route",
  middleware: async (ctx, next) => {
    await next();
    console.log(ctx.request.headers);
  }, // can also be array of middleware
  handler: () => new Response("Hello world!"),
});

router.addRoutes([
  /* array of route objects */
]);

Deno.serve((req) => router.handle(req));
  • git clone https://github.com/sejori/peko && cd peko

Check example directory to see implementations of:

  • server-side rendering react to HTML
  • streaming server-sent events to web client
  • logging requests
  • caching responses
  • JWT authentication middleware

Deno Live Deploy

  • Process 1: deno task dev:build
  • Process 2: deno task dev:deno

Cloudflare Workers Live Deploy

  • npm i
  • Process 1: npm run dev:build
  • Process 2: npm run dev:wrangler

Bun: Bun is currently not deployed but it is profiled against Deno, check the GitHub actions to see results.

  • bun install
  • Process 1: bun dev:build
  • Process 2: bun dev:bun

Router

The main class/entrypoint of Peko.

The handle method generates a Response from a Request argument via configured routes and middleware.

Route

Routes are added to a Router and matched to a Request via their path property. Once matched, the route's middleware and handlers are invoked to process the Request (after global middleware on the Router).

Dynamic path parameters are supported in the /users/:userid syntax.

RequestContext

An object containing request data that is passed into middleware and handlers in the Request process lifecycle.

The state property is an object designed to transfer information between middleware/handlers.

Middleware

Functions that receive RequestContext and next. They are designed to:

  • Return a Response and end the Request processing lifecycle (e.g. returning a 401)
  • Call await next() to access the final response (e.g. logging)
  • Edit the context's state (e.g. rendering geolocation to HTML)

Handler

The final request handling function on a Route, receives RequestContext argument.

Must return/resolve to a Response (e.g. Render HTML or return JSON payload).

Error handling

If no matching route is found for a request an empty 404 response is sent. If an error occurs in handling a request an empty 500 response is sent. Both of these behaviours can be overwritten with the following middleware:

router.use(async (_, next) => {
  const response = await next();
  if (!response)
    return new Response("Would you look at that? Nothing's here!", {
      status: 404,
    });
});
router.use(async (_, next) => {
  try {
    await next();
  } catch (e) {
    console.log(e);
    return new Response("Oh no! An error occured :(", { status: 500 });
  }
});

Response Caching

In stateless computing, memory should only be used for source code and disposable cache data. Response caching ensures that we only store data that can be regenerated or refetched. The configurable cacher middleware provides drop in handler memoization and response caching for your routes.

router.addRoute(
  "/get-time",
  Peko.cacher({ itemLifetime: 5000 }),
  () => new Response(Date.now())
);

The cacher stores response items in memory by default, but it can be extended to use any key value storage by supplying the store options parameter (e.g. Cloudflare Workers KV).

import { Router, CacheItem, cacher } from "@sejori/peko";

const router = new Router();

const itemMap: Map<string, CacheItem> = new Map();

router.addRoute("/get-time", {
  middleware: cacher({
    itemLifetime: 5000,
    store: {
      get: (key) => itemMap.get(key),
      set: (key, value) => itemMap.set(key, value),
      delete: (key) => itemMap.delete(key),
    },
  }),
  handler: () => new Response(Date.now()),
});

PR to add your project 🙌

shineon.systems

  • Stack: React, Cloudflare Workers, KV and R2
  • Features: KV cache, R2 email list, Markdown rendering
  • source

thesebsite.deno.dev

  • Stack: HTML5
  • Features: UI TS scripts transpiled to JS and cached for browser
  • source

Note: lit-html and es6-string-css VS Code extensions recommended.

Apps on the edge

The modern JavaScript edge rocks because the client-server gap practically disappears. We can share modules across the client and cloud.

This eliminates much of the bloat in traditional JS server-side systems, increasing project simplicity while making our software faster and more efficient.

This is made possible by engines such as Cloudflare Workers, Deno and Bun that are built to the ECMAScript specification.

If you are interested in contributing please submit a PR or get in contact ^^

What does stateless mean?

Peko apps are designed to boot from scratch at request time and disappear once the request is served. Therefore, storing data in memory between requests (stateful logic) is not reliable. Instead we should use stateless logic and store data within the client or external services.

This paradigm is often referred to as "serverless" or "edge computing" on cloud platforms, which offer code execution on shared server hardware (a.k.a JavaScript isolates). This is much more resource efficient than traditional server provisioning.

Because stateless apps can "cold-start" it is important to keep their codebases small. The react demo app only imports Peko, react and Htm as dependencies and is very fast as a result - https://peko.deno.dev!

Note: In reality a single app instance will serve multiple requests, we just can't guarantee it. This is why caching is still an effective optimization strategy but in-memory user sessions are not an effective authentication strategy.

Credits:

Chick logo from Twemoji