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

@affectively/bun-isolated-runner

v5.0.0

Published

Run Bun tests in isolated subprocesses to prevent mock pollution and global state leakage.

Downloads

39

Readme

@affectively/bun-isolated-runner

Run Bun tests in isolated subprocesses to prevent mock pollution and global state leakage.

npm version License: MIT

The Problem

Bun's test runner is blazing fast because it reuses the same process for all tests. But this speed comes with a cost: mock pollution.

// test-a.test.ts
import { mock } from 'bun:test';
mock.module('firebase/firestore', () => ({ getDoc: mock(() => 'mocked') }));

// test-b.test.ts - THIS STILL SEES THE MOCK FROM TEST A! 
import { getDoc } from 'firebase/firestore';
// getDoc is still mocked, even though we didn't mock it here
```text

Unlike Jest, which runs each test file in isolation by default, Bun shares the module registry across all tests. This leads to:

- **Flaky tests** that pass individually but fail together
- **Mock leakage** where one test's mocks affect others
- **Global state pollution** from singletons

## The Solution

Run each test file in its own subprocess:

```bash
npx bun-isolated
# or
bun-isolated src/**/*.test.ts
```text

Each test file gets a **fresh Bun process** with clean module registry. No mock pollution. No shared state. Tests run deterministically.

## Installation

```bash
npm install -D @affectively/bun-isolated-runner
# or
bun add -D @affectively/bun-isolated-runner
```text

## Quick Start

### CLI Usage

```bash
# Run all tests in isolation
npx bun-isolated

# Run specific test files
npx bun-isolated src/my-test.test.ts src/other.test.ts

# Run with glob pattern
npx bun-isolated "src/**/*.test.ts"

# Parallel execution (default: CPU count)
npx bun-isolated --parallel=4

# Sequential (for debugging)
npx bun-isolated --parallel=1

# Preload script (overrides auto-detect of bun.preload.ts)
npx bun-isolated --preload ./bun.preload.ts

# Exclude paths (repeatable)
npx bun-isolated --exclude src/app --exclude e2e

# Run only paths matching expression (substring or regex)
npx bun-isolated --testPathPattern=shared-ui/services
npx bun-isolated --testPathPattern="^shared-utils/src/.*\\.test\\.ts$"

# Fail fast after first failed file
npx bun-isolated --bail

# Stop after 3 failed files
npx bun-isolated --max-failures=3

# Write telemetry to a custom JSONL path
npx bun-isolated --telemetry-log=.build-logs/isolated.jsonl

# Disable telemetry logging
npx bun-isolated --no-telemetry

# Enable sticky-pass cache
npx bun-isolated --sticky-pass

# Reset sticky-pass cache for a fresh run
npx bun-isolated --sticky-pass --sticky-pass-reset
```text

### package.json Integration

```json
{
 "scripts": {
 "test": "bun-isolated --sticky-pass",
 "test:changed": "bun-isolated --changed --sticky-pass",
 "test:ci": "bun-isolated --parallel=4 --bail"
 }
}
```text

### Programmatic API

```typescript
import { runIsolated, findTestFiles } from '@affectively/bun-isolated-runner';

// Find all test files
const files = await findTestFiles('src/**/*.test.ts');

// Run them in isolation
const results = await runIsolated(files, {
 parallel: 4,
 timeout: 30000,
 env: { NODE_ENV: 'test' }
});

console.log(`Passed: ${results.passed}, Failed: ${results.failed}`);
```text

## How It Works

1. **Discovery**: Find all test files matching the pattern
2. **Spawning**: Run each file with `bun test <file>` in a subprocess
3. **Isolation**: Each subprocess has a fresh module registry
4. **Aggregation**: Collect results and report

```text
┌─────────────────────────────────────┐
│ bun-isolated │
├─────────────────────────────────────┤
│ ┌─────────┐ ┌─────────┐ │
│ │ bun test│ │ bun test│ ... │
│ │ file1.ts│ │ file2.ts│ │
│ └─────────┘ └─────────┘ │
│ │ │ │
│ Clean VM Clean VM │
│ No leaks No leaks │
└─────────────────────────────────────┘
```text

## Configuration

### bun-isolated.config.ts

```typescript
import type { IsolatedConfig } from '@affectively/bun-isolated-runner';

export default {
 // Test file patterns
 include: ['src/**/*.test.ts', 'tests/**/*.test.ts'],
 exclude: ['**/node_modules/**'],
 
 // Execution
 parallel: 4, // Number of parallel workers
 timeout: 30000, // Per-test timeout (ms)
 retries: 0, // Retry failed tests
 testPathPatterns: ['shared-ui/services'], // Optional path filters
 bail: false, // Stop after first failed file
 maxFailures: Infinity, // Or set a number, e.g. 3
 telemetryEnabled: true, // Disable with false
 telemetryLogPath: '.build-logs/bun-isolated-runner.jsonl',
 stickyPassEnabled: true, // Or set with --sticky-pass / BUN_ISOLATED_STICKY=1
 stickyPassCachePath: '.build-logs/bun-isolated-sticky.json',
 stickyPassReset: false,
 
 // Environment
 env: {
 NODE_ENV: 'test',
 TZ: 'UTC'
 },
 
 // Reporting
 reporter: 'default', // 'default' | 'json' | 'junit'
 verbose: false,
} satisfies IsolatedConfig;

When to Use This

Use bun-isolated when:

  • Tests use mock.module() extensively
  • You have singleton services (Firebase, DB connections)
  • Tests are flaky when run together but pass individually
  • You need Jest-like isolation guarantees

Don't use when:

  • Tests are already fast and isolated
  • You don't use mocks
  • You need the absolute fastest test execution

Performance

| Approach | 100 test files | Isolation | |----------|---------------|-----------| | bun test | ~2s | Shared | | bun-isolated --parallel=8 | ~8s | Full | | bun-isolated --parallel=1 | ~30s | Full |

The overhead is ~3-5x, but deterministic tests are worth it.

New Normal Defaults

  • --bail and --max-failures=N let CI fail fast and avoid spending time on known-bad runs.
  • JSONL telemetry (--telemetry-log=<path>) captures p50/p95/file-throughput trends for real performance tuning.
  • --no-telemetry keeps local runs quiet when metrics are not needed.
  • --sticky-pass reuses passing results for unchanged files to speed repeated local runs.

API Reference

runIsolated(files, options)

Run test files in isolated subprocesses.

findTestFiles(pattern)

Find test files matching a glob pattern.

IsolatedConfig

Configuration type for the runner.

Related Packages

License

MIT License - see LICENSE for details.


Made with ️ by AFFECTIVELY