{"_id":"@affectively/bun-isolated-runner","_rev":"6-7932e03e2b256fa3736f3b72b36e4c15","name":"@affectively/bun-isolated-runner","dist-tags":{"latest":"5.0.0"},"versions":{"1.0.0":{"name":"@affectively/bun-isolated-runner","version":"1.0.0","keywords":["bun","test","testing","isolated","subprocess","mock","cleanup","jest","vitest"],"author":{"name":"AFFECTIVELY","email":"opensource@affectively.app"},"license":"MIT","_id":"@affectively/bun-isolated-runner@1.0.0","maintainers":[{"name":"buley","email":"buley@outlook.com"}],"homepage":"https://github.com/affectively-ai/bun-isolated-runner#readme","bugs":{"url":"https://github.com/affectively-ai/bun-isolated-runner/issues"},"bin":{"bun-isolated":"dist/cli.js"},"dist":{"shasum":"c01a482fc994b74a5f501311b7c1ac2cc8a25407","tarball":"https://registry.npmjs.org/@affectively/bun-isolated-runner/-/bun-isolated-runner-1.0.0.tgz","fileCount":12,"integrity":"sha512-niaQ6z/tBZy7VYw63wleaTxGXsYL2AaKRTWcPwHl/uIfhh0MiC8uW2GYyS1O0r0jhbfE0aswJ0YEW3MplklCgw==","signatures":[{"sig":"MEYCIQClBfMoPzwmR9pzsb9uw6XtVsiInOrWE5KkhVxqRMdvgAIhAMfj6LyJBsCWwaC132sI9IEcUj88KWQ7AwHhKP68KtTq","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49420},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"b55b35819a15484fbb04f75246a154ee5bc28a60","scripts":{"test":"bun test","build":"tsup src/index.ts src/cli.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"buley","email":"buley@outlook.com"},"repository":{"url":"git+https://github.com/affectively-ai/bun-isolated-runner.git","type":"git"},"_npmVersion":"11.6.2","description":"Run Bun tests in isolated subprocesses to prevent mock pollution and global state leakage.","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.9.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/bun-isolated-runner_1.0.0_1768339427737_0.9208841653494932","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is deprecated and no longer supported. Do not use."},"1.0.1":{"name":"@affectively/bun-isolated-runner","version":"1.0.1","keywords":["bun","test","testing","isolated","subprocess","mock","cleanup","jest","vitest"],"author":{"name":"AFFECTIVELY","email":"opensource@affectively.ai"},"license":"MIT","_id":"@affectively/bun-isolated-runner@1.0.1","maintainers":[{"name":"buley","email":"buley@outlook.com"}],"homepage":"https://github.com/affectively-ai/bun-isolated-runner#readme","bugs":{"url":"https://github.com/affectively-ai/bun-isolated-runner/issues"},"bin":{"bun-isolated":"dist/cli.js"},"dist":{"shasum":"191cec4cdaf216105b71ea04bb369e8b81fb5737","tarball":"https://registry.npmjs.org/@affectively/bun-isolated-runner/-/bun-isolated-runner-1.0.1.tgz","fileCount":12,"integrity":"sha512-GORQohscfx3U4p86h+/oZEsbls2f5g/oeKtV/sSkrH2MbnNuSKj0FevlfbtFufoj2z6/JhyZ98Pj1xd3LYTs3Q==","signatures":[{"sig":"MEUCIQCekflvJmBV/HTGDyVI5ZmNfUxSXqrYtfQIO4qFFQEQKAIgM1QsaOa35Cr6Ftt4CTdGMAJs8KAoMs0DP2jIRwSTkOk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49194},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"f52d3052c061644ce33b23dd4a1aee7b15a807f1","scripts":{"test":"bun test","build":"tsup src/index.ts src/cli.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"buley","email":"buley@outlook.com"},"repository":{"url":"git+https://github.com/affectively-ai/bun-isolated-runner.git","type":"git"},"_npmVersion":"11.6.2","description":"Run Bun tests in isolated subprocesses to prevent mock pollution and global state leakage.","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.9.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/bun-isolated-runner_1.0.1_1768341351194_0.26185190476051545","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is deprecated and no longer supported. Do not use."},"1.2.0":{"name":"@affectively/bun-isolated-runner","version":"1.2.0","keywords":["bun","test","testing","isolated","subprocess","mock","cleanup","jest","vitest"],"author":{"name":"AFFECTIVELY","email":"opensource@affectively.ai"},"license":"MIT","_id":"@affectively/bun-isolated-runner@1.2.0","maintainers":[{"name":"buley","email":"buley@outlook.com"}],"homepage":"https://github.com/affectively-ai/bun-isolated-runner#readme","bugs":{"url":"https://github.com/affectively-ai/bun-isolated-runner/issues"},"bin":{"bun-isolated":"dist/cli.js"},"dist":{"shasum":"7ba3ebe0a2c408fefa960ceb81710b3ad8e14d6f","tarball":"https://registry.npmjs.org/@affectively/bun-isolated-runner/-/bun-isolated-runner-1.2.0.tgz","fileCount":13,"integrity":"sha512-lMzrx87aO3HBp21PdSdeOcQmhsB07iS+B7ZT5QEJBNZ05hQTLrAIUw2biOFq8yurQTx9uPvuTYt3JRXzVOhuKA==","signatures":[{"sig":"MEYCIQCs5DOqS7YwUNjFnfKh5in5OI+adN/jnuu2zSZWC7RLqQIhAN2IkuscMfTxAM1Vz8tIqxtDA6uSO/H0h3UDpJJ5aEDd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67944},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"test":"bun test","build":"tsup src/index.ts src/cli.ts --format cjs,esm --dts","publish":"npm publish --access public","prepublishOnly":"npm run build"},"_npmUser":{"name":"buley","email":"buley@outlook.com"},"repository":{"url":"git+https://github.com/affectively-ai/bun-isolated-runner.git","type":"git"},"_npmVersion":"11.8.0","description":"Run Bun tests in isolated subprocesses to prevent mock pollution and global state leakage.","directories":{},"_nodeVersion":"25.5.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.9.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/bun-isolated-runner_1.2.0_1770963862691_0.4553930311629397","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is deprecated and no longer supported. Do not use."},"1.2.1":{"name":"@affectively/bun-isolated-runner","version":"1.2.1","keywords":["bun","test","testing","isolated","subprocess","mock","cleanup","jest","vitest"],"author":{"name":"AFFECTIVELY","email":"opensource@affectively.ai"},"license":"MIT","_id":"@affectively/bun-isolated-runner@1.2.1","maintainers":[{"name":"buley","email":"buley@outlook.com"}],"homepage":"https://github.com/affectively-ai/bun-isolated-runner#readme","bugs":{"url":"https://github.com/affectively-ai/bun-isolated-runner/issues"},"bin":{"bun-isolated":"dist/cli.js"},"dist":{"shasum":"dcfce1c00579aa077a373ab2800239bb84b92a84","tarball":"https://registry.npmjs.org/@affectively/bun-isolated-runner/-/bun-isolated-runner-1.2.1.tgz","fileCount":13,"integrity":"sha512-tsW3iemKn/ydY8+5R5n+MHCNx6AOA2WmnWbh9zNKtzPDxR4wY0T61zcyM1YGZwTWwEXtgzmFvbbPTVznAX42Hg==","signatures":[{"sig":"MEYCIQCYRRot6V2coXKVx49PlWkOm3Wpy1+KVQapOWazvXEd4AIhAIatX4+O78L5P2fsNJZ0uIVO8A/4nHpkDjHfg5hQhkeH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68231},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"test":"bun test","build":"tsup src/index.ts src/cli.ts --format cjs,esm --dts","prepublishOnly":"npm run build","release:publish":"npm publish --access public"},"_npmUser":{"name":"buley","email":"buley@outlook.com"},"repository":{"url":"git+https://github.com/affectively-ai/bun-isolated-runner.git","type":"git"},"_npmVersion":"11.8.0","description":"Run Bun tests in isolated subprocesses to prevent mock pollution and global state leakage.","directories":{},"_nodeVersion":"25.5.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.9.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/bun-isolated-runner_1.2.1_1770964298617_0.8411301089292171","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is deprecated and no longer supported. Do not use."},"5.0.0":{"name":"@affectively/bun-isolated-runner","version":"5.0.0","keywords":["bun","test","testing","isolated","subprocess","mock","cleanup","jest","vitest"],"author":{"name":"AFFECTIVELY","email":"opensource@affectively.ai"},"license":"UNLICENSED","_id":"@affectively/bun-isolated-runner@5.0.0","maintainers":[{"name":"buley","email":"buley@outlook.com"}],"homepage":"https://github.com/affectively-ai/bun-isolated-runner#readme","bugs":{"url":"https://github.com/affectively-ai/bun-isolated-runner/issues"},"bin":{"bun-isolated":"dist/cli.js"},"dist":{"shasum":"b7674b6e0b6aac59f4d4395506422fd18c66a850","tarball":"https://registry.npmjs.org/@affectively/bun-isolated-runner/-/bun-isolated-runner-5.0.0.tgz","fileCount":13,"integrity":"sha512-g0Q/MllYthv1i5kziYjDGxSlZxK/SqxVBd15KnLo2pLDrEkX6FrQ9jEfSjd8hAObICnYn37lfGZGh/5R4Ml1gA==","signatures":[{"sig":"MEQCIAQuaeI1Etv3+WYN8r5r++z1tgkpbzHCeThJfoA/mgB8AiBLCQUs48JU7hstEzmAv22brf0JNkILiN/kwmAycJhoTQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":106024},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"test":"bun test","build":"tsup src/index.ts src/cli.ts --format cjs,esm --dts","prepublishOnly":"npm run build","release:publish":"npm publish --access public"},"_npmUser":{"name":"buley","email":"buley@outlook.com"},"repository":{"url":"git+https://github.com/affectively-ai/bun-isolated-runner.git","type":"git"},"_npmVersion":"11.8.0","description":"Run Bun tests in isolated subprocesses to prevent mock pollution and global state leakage.","directories":{},"_nodeVersion":"25.5.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.9.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/bun-isolated-runner_5.0.0_1773156215412_0.9793616558276341","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is deprecated and no longer supported. Do not use."}},"time":{"created":"2026-01-13T21:23:47.618Z","modified":"2026-03-27T20:03:14.902Z","1.0.0":"2026-01-13T21:23:47.900Z","1.0.1":"2026-01-13T21:55:51.351Z","1.2.0":"2026-02-13T06:24:22.859Z","1.2.1":"2026-02-13T06:31:38.760Z","5.0.0":"2026-03-10T15:23:35.550Z"},"bugs":{"url":"https://github.com/affectively-ai/bun-isolated-runner/issues"},"author":{"name":"AFFECTIVELY","email":"opensource@affectively.ai"},"license":"UNLICENSED","homepage":"https://github.com/affectively-ai/bun-isolated-runner#readme","keywords":["bun","test","testing","isolated","subprocess","mock","cleanup","jest","vitest"],"repository":{"url":"git+https://github.com/affectively-ai/bun-isolated-runner.git","type":"git"},"description":"Run Bun tests in isolated subprocesses to prevent mock pollution and global state leakage.","maintainers":[{"name":"buley","email":"buley@outlook.com"}],"readme":"# @affectively/bun-isolated-runner\r\n\r\nRun Bun tests in **isolated subprocesses** to prevent mock pollution and global state leakage.\r\n\r\n[![npm version](https://img.shields.io/npm/v/@affectively/bun-isolated-runner.svg)](https://www.npmjs.com/package/@affectively/bun-isolated-runner)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n\r\n## The Problem\r\n\r\nBun's test runner is **blazing fast** because it reuses the same process for all tests. But this speed comes with a cost: **mock pollution**.\r\n\r\n```typescript\r\n// test-a.test.ts\r\nimport { mock } from 'bun:test';\r\nmock.module('firebase/firestore', () => ({ getDoc: mock(() => 'mocked') }));\r\n\r\n// test-b.test.ts - THIS STILL SEES THE MOCK FROM TEST A! \r\nimport { getDoc } from 'firebase/firestore';\r\n// getDoc is still mocked, even though we didn't mock it here\r\n```text\n\r\nUnlike Jest, which runs each test file in isolation by default, Bun shares the module registry across all tests. This leads to:\r\n\r\n- **Flaky tests** that pass individually but fail together\r\n- **Mock leakage** where one test's mocks affect others\r\n- **Global state pollution** from singletons\r\n\r\n## The Solution\r\n\r\nRun each test file in its own subprocess:\r\n\r\n```bash\r\nnpx bun-isolated\r\n# or\r\nbun-isolated src/**/*.test.ts\r\n```text\n\r\nEach test file gets a **fresh Bun process** with clean module registry. No mock pollution. No shared state. Tests run deterministically.\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install -D @affectively/bun-isolated-runner\r\n# or\r\nbun add -D @affectively/bun-isolated-runner\r\n```text\n\r\n## Quick Start\r\n\r\n### CLI Usage\r\n\r\n```bash\r\n# Run all tests in isolation\r\nnpx bun-isolated\r\n\r\n# Run specific test files\r\nnpx bun-isolated src/my-test.test.ts src/other.test.ts\r\n\r\n# Run with glob pattern\r\nnpx bun-isolated \"src/**/*.test.ts\"\r\n\r\n# Parallel execution (default: CPU count)\r\nnpx bun-isolated --parallel=4\r\n\r\n# Sequential (for debugging)\r\nnpx bun-isolated --parallel=1\r\n\r\n# Preload script (overrides auto-detect of bun.preload.ts)\r\nnpx bun-isolated --preload ./bun.preload.ts\r\n\r\n# Exclude paths (repeatable)\nnpx bun-isolated --exclude src/app --exclude e2e\n\n# Run only paths matching expression (substring or regex)\nnpx bun-isolated --testPathPattern=shared-ui/services\nnpx bun-isolated --testPathPattern=\"^shared-utils/src/.*\\\\.test\\\\.ts$\"\n\n# Fail fast after first failed file\nnpx bun-isolated --bail\n\n# Stop after 3 failed files\nnpx bun-isolated --max-failures=3\n\n# Write telemetry to a custom JSONL path\nnpx bun-isolated --telemetry-log=.build-logs/isolated.jsonl\n\n# Disable telemetry logging\nnpx bun-isolated --no-telemetry\n\n# Enable sticky-pass cache\nnpx bun-isolated --sticky-pass\n\n# Reset sticky-pass cache for a fresh run\nnpx bun-isolated --sticky-pass --sticky-pass-reset\n```text\n\r\n### package.json Integration\r\n\r\n```json\r\n{\n \"scripts\": {\n \"test\": \"bun-isolated --sticky-pass\",\n \"test:changed\": \"bun-isolated --changed --sticky-pass\",\n \"test:ci\": \"bun-isolated --parallel=4 --bail\"\n }\n}\n```text\n\r\n### Programmatic API\r\n\r\n```typescript\r\nimport { runIsolated, findTestFiles } from '@affectively/bun-isolated-runner';\r\n\r\n// Find all test files\r\nconst files = await findTestFiles('src/**/*.test.ts');\r\n\r\n// Run them in isolation\r\nconst results = await runIsolated(files, {\r\n parallel: 4,\r\n timeout: 30000,\r\n env: { NODE_ENV: 'test' }\r\n});\r\n\r\nconsole.log(`Passed: ${results.passed}, Failed: ${results.failed}`);\r\n```text\n\r\n## How It Works\r\n\r\n1. **Discovery**: Find all test files matching the pattern\r\n2. **Spawning**: Run each file with `bun test <file>` in a subprocess\r\n3. **Isolation**: Each subprocess has a fresh module registry\r\n4. **Aggregation**: Collect results and report\r\n\r\n```text\n┌─────────────────────────────────────┐\r\n│ bun-isolated │\r\n├─────────────────────────────────────┤\r\n│ ┌─────────┐ ┌─────────┐ │\r\n│ │ bun test│ │ bun test│ ... │\r\n│ │ file1.ts│ │ file2.ts│ │\r\n│ └─────────┘ └─────────┘ │\r\n│ │ │ │\r\n│ Clean VM Clean VM │\r\n│ No leaks No leaks │\r\n└─────────────────────────────────────┘\r\n```text\n\r\n## Configuration\r\n\r\n### bun-isolated.config.ts\r\n\r\n```typescript\r\nimport type { IsolatedConfig } from '@affectively/bun-isolated-runner';\r\n\r\nexport default {\r\n // Test file patterns\r\n include: ['src/**/*.test.ts', 'tests/**/*.test.ts'],\r\n exclude: ['**/node_modules/**'],\r\n \r\n // Execution\n parallel: 4, // Number of parallel workers\n timeout: 30000, // Per-test timeout (ms)\n retries: 0, // Retry failed tests\n testPathPatterns: ['shared-ui/services'], // Optional path filters\n bail: false, // Stop after first failed file\n maxFailures: Infinity, // Or set a number, e.g. 3\n telemetryEnabled: true, // Disable with false\n telemetryLogPath: '.build-logs/bun-isolated-runner.jsonl',\n stickyPassEnabled: true, // Or set with --sticky-pass / BUN_ISOLATED_STICKY=1\n stickyPassCachePath: '.build-logs/bun-isolated-sticky.json',\n stickyPassReset: false,\n \r\n // Environment\r\n env: {\r\n NODE_ENV: 'test',\r\n TZ: 'UTC'\r\n },\r\n \r\n // Reporting\r\n reporter: 'default', // 'default' | 'json' | 'junit'\r\n verbose: false,\r\n} satisfies IsolatedConfig;\r\n```\r\n\r\n## When to Use This\r\n\r\n **Use bun-isolated when:**\r\n- Tests use `mock.module()` extensively\r\n- You have singleton services (Firebase, DB connections)\r\n- Tests are flaky when run together but pass individually\r\n- You need Jest-like isolation guarantees\r\n\r\n **Don't use when:**\r\n- Tests are already fast and isolated\r\n- You don't use mocks\r\n- You need the absolute fastest test execution\r\n\r\n## Performance\r\n\r\n| Approach | 100 test files | Isolation |\r\n|----------|---------------|-----------|\r\n| `bun test` | ~2s | Shared |\r\n| `bun-isolated --parallel=8` | ~8s | Full |\r\n| `bun-isolated --parallel=1` | ~30s | Full |\r\n\r\nThe overhead is ~3-5x, but **deterministic tests are worth it**.\n\n## New Normal Defaults\n\n- `--bail` and `--max-failures=N` let CI fail fast and avoid spending time on known-bad runs.\n- JSONL telemetry (`--telemetry-log=<path>`) captures p50/p95/file-throughput trends for real performance tuning.\n- `--no-telemetry` keeps local runs quiet when metrics are not needed.\n- `--sticky-pass` reuses passing results for unchanged files to speed repeated local runs.\n\r\n## API Reference\r\n\r\n### `runIsolated(files, options)`\r\n\r\nRun test files in isolated subprocesses.\r\n\r\n### `findTestFiles(pattern)`\r\n\r\nFind test files matching a glob pattern.\r\n\r\n### `IsolatedConfig`\r\n\r\nConfiguration type for the runner.\r\n\r\n## Related Packages\r\n\r\n- [`@affectively/devops-scripts`](https://www.npmjs.com/package/@affectively/devops-scripts) - Changed-file testing\r\n- [`@affectively/utils`](https://www.npmjs.com/package/@affectively/utils) - Utility functions\r\n\r\n## License\r\n\r\nMIT License - see [LICENSE](./LICENSE) for details.\r\n\r\n---\r\n\r\nMade with ️ by [AFFECTIVELY](https://affectively.ai)\r\n","readmeFilename":"README.md"}