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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@rescale/nemo

v1.4.0

Published

A middleware composition library for Next.js applications that allows you to organize and chain middleware functions based on URL patterns.

Downloads

5,679

Readme

@rescale/nemo

A middleware composition library for Next.js applications that allows you to organize and chain middleware functions based on URL patterns.

codecov

Installation

npm install @rescale/nemo
pnpm add @rescale/nemo
bun add @rescale/nemo

Key Features

  • Path-based middleware routing
  • Global middleware support (before/after)
  • Context sharing between middleware
  • Support for both legacy and modern middleware patterns
  • Request/Response header and cookie forwarding

API Reference

Types

MiddlewareFunction

Can be either a legacy Next.js middleware (NextMiddleware) or the new middleware format (NewMiddleware).

MiddlewareConfig

Record<string, MiddlewareFunction | MiddlewareFunction[]>

MiddlewareFunctionProps

interface MiddlewareFunctionProps {
  request: NextRequest;
  context: MiddlewareContext;
  event: NextFetchEvent;
  forward: (response: MiddlewareReturn) => void;
}

Main Functions

createMiddleware

function createMiddleware(
  pathMiddlewareMap: MiddlewareConfig,
  globalMiddleware?: {
    before?: MiddlewareFunction | MiddlewareFunction[];
    after?: MiddlewareFunction | MiddlewareFunction[];
  }
): NextMiddleware

Creates a composed middleware function that:

  • Executes global "before" middleware first
  • Matches URL patterns and executes corresponding middleware
  • Executes global "after" middleware last
  • Forwards headers and cookies between middleware functions

forward

function forward(response: MiddlewareReturn): void

Function that allows passing response from legacy middleware functions to the next middleware in the chain. This enables compatibility between legacy Next.js middleware and the new middleware format.

Matchers

To make it easier to understand, you can check the below examples:

Simple route

Matches /dashboard route and returns no params.

/dashboard

Prams

General structure of the params is :paramName where paramName is the name of the param that will be returned in the middleware function.

Single

Matches /dashboard/anything route and returns team param with anything value.

/dashboard/:team

You can also define segments in the middle of URL with is matching /team/anything/dashboard and returns team param with anything value.

/dashboard/:team/delete

Optional

Matches /dashboard and /dashboard/anything routes and returns team param with anything value if there is value provided in url.

/dashboard{/:team}
/dashboard{/*team}

Wildcard

Matches /dashboard and /dashboard/anything/test routes and returns team param with [anything, test] value if there is value provided in url.

/dashboard/*team

Debugging tool

To debug your matchers and params parsing you can use the following tool:

Rescale path-to-regexp debugger

Usage Examples

Basic Path-Based Middleware

import { createMiddleware } from '@rescale/nemo';

export default createMiddleware({
  '/api{/*path}': async ({ request }) => {
    // Handle API routes
  },
  '/protected{/*path}': async ({ request, context }) => {
    // Handle protected routes
  }
});

You can test your's matchers using this tool.

Using Global Middleware

import { createMiddleware } from '@rescale/nemo';

export default createMiddleware({
  '/api{/*path}': apiMiddleware,
},
{
  before: [loggerMiddleware, authMiddleware],
  after: cleanupMiddleware,
});

Context Sharing

import { createMiddleware } from '@rescale/nemo';

export default createMiddleware({
  '/*path': [
    async ({ context }) => {
      context.set('user', { id: 1 });
    },
    async ({ context }) => {
      const user = context.get('user');
      // Use the user data
    }
  ]
});

Notes

  • Middleware functions are executed in order until a Response is returned
  • The context Map is shared between all middleware functions in the chain
  • Headers and cookies are automatically forwarded between middleware functions
  • Supports both Next.js legacy middleware pattern and the new props-based pattern

Motivation

I'm working with Next.js project for a few years now, after Vercel moved multiple /**/_middleware.ts files to a single /middleware.ts file, there was a unfilled gap - but just for now. After a 2023 retro I had found that there is no good solution for that problem, so I took matters into my own hands. I wanted to share that motivation with everyone here, as I think that we all need to remember how it all started.

Hope it will save you some time and would make your project DX better!