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

named-patch

v2.0.1

Published

Higher order function for patching named export functions.

Downloads

1,134

Readme

named-patch

Higher-order function for patching named export functions in tests.

npm package License

Contents

Install

npm i named-patch

Example

// a.ts
import { patch } from 'named-patch';

export const randName = patch(<T extends string>(names: T[]) => names[Math.trunc(Math.random() * names.length)]);

// test.ts
import { patchKey } from 'named-patch';
import { randName } from './a.js';

randName(['foo', 'bar']); // 'foo' or 'bar'
// Still supports generics
randName<'abc' | 'xyz'>(['abc', 'xyz']); // 'abc' or 'xyz'

randName[patchKey] = () => '<custom>';
randName(['foo', 'bar']); // '<custom>'

Usage

named-patch is an ESM module. It must be imported. To load from a CJS module, use dynamic import: const { patch } = await import('named-patch').

The package exports two different implementations depending on the Node.js condition in use:

  • Default (no special condition): patch returns the function unchanged — zero overhead in production.
  • patchable condition: enables the wrapping behaviour along with patchKey and getPatched.

Enable the patchable condition in test environments:

node --conditions=patchable ./my-script.js
NODE_OPTIONS='--conditions=patchable' node ./my-script.js

Mocha users can set this via the node-option config key.

The key use case is replacing module mocking with runtime patching: wrap any function with patch() at the module level, then reassign fn[patchKey] in tests. Because patch() is idempotent and cached, any file that imports the same original function and passes it through patch() will receive the same patchable wrapper — making third-party functions patchable without re-exporting them.

API

patch(fn)

Returns a patchable wrapper around fn. By default the wrapper calls fn internally. Reassign wrapper[patchKey] to swap the implementation at runtime.

The wrapper preserves the full TypeScript type of fn, including generics, async, and this binding. Patching is idempotent: calling patch() on the same function or on an already-patched wrapper always returns the same wrapper object.

Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | fn | (...args: any[]) => any | — | Required. The function to make patchable. |

Returns PatchableInterface<T> — a wrapper with the same signature as fn plus a writable [patchKey] property. The wrapper also exposes fn's own properties (e.g. static helpers), reading and writing through to fn.

import { patch } from 'named-patch';

const original = (x: number, y: number) => x + y;
const patched = patch(original);

patch(original) === patched; // true
patch(patched) === patched;  // true

patchKey

A unique symbol written onto every wrapper returned by patch. Assign a new function to wrapper[patchKey] to replace the implementation.

Only exported when the patchable condition is active.

import { patch, patchKey } from 'named-patch';
import { stub } from 'sinon';

const fn = patch((x: number) => x * 2);
stub(fn, patchKey).returns(99);
fn(5); // 99

getPatched(fn)

Returns the already-cached patchable wrapper for fn without creating one. Use this in tests when you want to assert that patch() was called on a function rather than silently creating the wrapper for the first time.

Only exported when the patchable condition is active.

Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | fn | (...args: any[]) => any | — | Required. The original (unpatched) function to look up. |

Returns PatchableInterface<T> — the cached wrapper.

Throws Error — if fn has never been passed to patch(), or if fn is itself already a patched wrapper.