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

@ecosy/next

v2.0.0

Published

Ecosy Next.js bindings

Readme

@ecosy/next

Adapters for building a Next.js app on Route and Gateway: a request context shared across both, a cookie jar that works in a proxy, and the Next-shaped half of CSRF and identity checks. The package depends on nothing but Next — session and CSRF implementations stay in the app.

Documentation: docs.ecosy.io/next

Route, Gateway, Context, ContextValues, cookieJar, CookieJar, CookieJarOptions, CookieForwarding, csrfOrigin, csrfGuard, CsrfPort, CsrfPortClass, IdentityPort, CsrfGuardOptions, CsrfContext

Installation

yarn add @ecosy/next

Peer dependencies: next ^16.3.1 (required). jsonwebtoken ^9.0.3 is optional — only needed by @ecosy/next/jwt.

Entry points

| Entry | What it needs | |---|---| | @ecosy/next | Next only | | @ecosy/next/inject | Next only | | @ecosy/next/jwt | jsonwebtoken |

inject stays off the root export so pulling in dependency injection is an explicit choice. jwt stays off it so an app that never touches JWTs never pulls jsonwebtoken into its bundle.

Route

Route builds a Next route handler. ctx.get/ctx.set hand a value from one middleware to the next, or across a GatewayRoute boundary, for the rest of one request. Building a Context by hand instead of through Route takes its seed values typed as ContextValues.

Values a Gateway sets travel to the Route serving the same request through a bounded store (10,000 entries, 60 seconds), keyed by a signed request id the proxy issues on every request — a client-supplied id is never trusted, and an invalid one is rejected with a 400 before any middleware runs.

import { Route } from "@ecosy/next";

export const GET = Route().get((ctx) => {
  return { userId: ctx.get<string>("userId") };
});

cookieJar

cookieJar() reads and writes cookies over Next's cookies(). In a route handler or Server Component, call it with no argument. In a Gateway, pass its context — otherwise a cookie set there compiles fine but is never seen by the Route serving the same request, because the write never reaches the request headers the proxy forwards.

import { cookieJar } from "@ecosy/next";

export async function GET() {
  const jar = await cookieJar();
  await jar.set("theme", "dark", { path: "/" });
  return Response.json({ theme: jar.get("theme") });
}

CSRF

The package ships no CSRF or session implementation — csrfOrigin and csrfGuard are wiring only, over a CsrfPort and an IdentityPort the app supplies. csrfOrigin belongs in the proxy, ahead of everything, and needs no token or secret: it only checks that the request's origin says it came from this site. csrfGuard binds a token to the id an IdentityPort loads, under the identity key — or to a custom value via bind, when there is no identity to load from.

A csrfGuard whose Csrf.check() always answers true is a no-op: nothing in this package can tell, and no test here will say so. The guard is only as strong as the module passed in.

import { Route, Gateway, csrfOrigin, csrfGuard, type IdentityPort, type CsrfPort } from "@ecosy/next";

class AppCsrf implements CsrfPort {
  origin() { return true; }
  async check() { return true; }
}
class AppSession implements IdentityPort {
  async load() { return { id: "u1" }; }
}

export const proxy = Gateway({}).use(csrfOrigin(AppCsrf));
export const POST = Route()
  .use(csrfGuard(AppCsrf, { identity: AppSession }))
  .post(async () => Response.json({ ok: true }));

Upgrading

From 1.1.0, rename the session option and the SessionPort type to identity / IdentityPort — same class, same shape:

- import type { SessionPort } from "@ecosy/next";
+ import type { IdentityPort } from "@ecosy/next";

- csrfGuard(AppCsrf, { session: AppSession })
+ csrfGuard(AppCsrf, { identity: AppSession })

Remove the session key rather than leaving it beside identity. Written straight at the call site TypeScript rejects session (TS2353); the same object hoisted into a variable compiles clean, runs on identity alone and drops session with no signal. Full detail, including the 1.0.x upgrade path and the Instrument removal, is in CHANGELOG.md.

Documentation

Package docs: docs.ecosy.io/next. Everything else Ecosy ships: docs.ecosy.io.

License

MIT