Alexandro.Net

Download README · GitHub release

@stackline/proxyquire

Compatibility-first CommonJS dependency injection with bounded cache cleanup, caller anchoring, and first-party types.

npm version license GitHub repository Docs Reddit community

Documentation | npm | Issues | Repository

Current package version: 1.0.5


Why this package?

Compatibility-first dependency stubbing for CommonJS tests. It preserves the established proxyquire@2.1.3 API while adding a caller-anchored factory for tests authored as native ES modules or TypeScript, first-party declarations, safer loader restoration, and a dependency-free runtime.

Compatibility

Item Value
Package @stackline/proxyquire@1.0.5
Node.js runtime >=12
CommonJS / primary entry ./index.js
ES module entry ./index.mjs
Type declarations ./index.d.ts

See the migration guide and full compatibility contract. Interactive documentation is available at alexandro.net.

Dependency and release choices are recorded in DEPENDENCY_DECISIONS.md and PUBLISHING.md.

Installation

Install

npm install --save-dev @stackline/proxyquire

Keep an existing require('proxyquire') unchanged with an npm alias:

npm install --save-dev proxyquire@npm:@stackline/proxyquire

Usage

CommonJS usage

Given a CommonJS subject:

// notifications.js
const mailer = require('./mailer')

exports.welcome = (address) => mailer.send(address, 'Welcome')

replace its dependency only while loading the subject:

const assert = require('assert').strict
const proxyquire = require('@stackline/proxyquire')

const notifications = proxyquire('./notifications', {
  './mailer': {
    send: (address, subject) => ({ address, subject })
  }
})

assert.deepEqual(notifications.welcome('dev@example.test'), {
  address: 'dev@example.test',
  subject: 'Welcome'
})

Stub keys match the request strings used by the subject. Relative subjects are resolved from the test module that created the Proxyquire instance.

Features and Integrations

Native ESM and TypeScript test files

An ES module has no CommonJS module.parent. Anchor resolution explicitly:

import { createProxyquire } from '@stackline/proxyquire'

const proxyquire = createProxyquire(import.meta.url)
const notifications = proxyquire('./notifications.cjs', {
  './mailer.cjs': { send: () => 'stubbed' }
})

createProxyquire(import.meta.url) lets an ESM or native-TypeScript test load and stub a CommonJS subject relative to that test. The factory accepts the same absolute path or file: URL anchors as module.createRequire(), and each call has independent call-through and cache settings.

It does not intercept static or dynamic imports inside a native ESM module. Use an ESM-aware test loader for native ESM dependency replacement.

Security

Proxyquire temporarily changes process-wide CommonJS cache and extension state. Use it only with trusted test code and stubs; it is not a sandbox or an access control. Report vulnerabilities privately as described in SECURITY.md.

API Surface

API

proxyquire(request, stubs) / proxyquire.load(request, stubs)

Loads a fresh CommonJS subject while replacing the requested dependencies. The callable form and .load are equivalent.

createProxyquire(from)

Returns a caller-anchored Proxyquire function with the same callable API and configuration methods. Pass an absolute filename or a file: URL, normally import.meta.url from an ESM or native-TypeScript test module. A CommonJS module object is also accepted for tooling integrations. proxyquire.from() is an alias of this factory.

Call-through controls

Missing properties call through to the original dependency by default.

const strictProxyquire = proxyquire.noCallThru()
strictProxyquire('./subject', {
  './dependency': { method: () => 'stubbed' }
})

proxyquire.callThru()

Set stub['@noCallThru'] to true or false to override the instance setting for one dependency. A null stub simulates MODULE_NOT_FOUND. Functions, arrays, primitives, and other non-object exports remain supported.

Cache controls

These controls do not recursively evict unrelated, unstubbed transitive dependencies. See the compatibility contract for the exact boundary.

Global controls

@global applies a stub through the CommonJS graph during initialization. @runtimeGlobal also applies it to later runtime require() calls. Both modes bypass more of Node's cache and may re-run module initialization; prefer direct stubs whenever possible.

Historical compatibility method

compat() remains present and throws the upstream message explaining that the removed Proxyquire 0.3 compatibility mode requires an older pinned release.

Local Development

git clone https://github.com/alexandroit/stackline-proxyquire.git
cd stackline-proxyquire
npm ci
npm run verify

Release tooling uses Node.js 24.20.0 and npm 11.19.0. The consumer runtime contract remains the one documented above.

Consumer Smoke Test

Run the repository's existing consumer/package check after installing development dependencies:

npm run test:smoke

Release Checklist

Run npm run verify and inspect the package contents before release. Publish a new version through the GitHub Actions publishing workflow, using the SHA-512 digest of the reviewed tarball. Verify the exact published version, tarball integrity, and npm provenance after the run.

License

License and attribution

MIT. Thorsten Lorenz's original copyright and license are preserved in LICENSE. This independent continuation is not affiliated with or endorsed by the original maintainer. See NOTICE and THIRD_PARTY_LICENSES.md.

Credits and original authors

Original copyright, license notices and contributor acknowledgements remain part of this distribution. Stackline maintenance does not replace authorship of the original work.

Community and Links

Use this repository's issue tracker for reproducible bugs and feature requests. Join r/Stackline for examples, usage questions and release discussions.