FacadeProxyHandler unconditionally imports @athenna/test in non-test environments, activating nock and breaking real HTTP connections
- Dominant language
- TypeScript
- Stars
- 8
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Bug Description
`FacadeProxyHandler.js` performs a top-level `await Module.safeImport('@athenna/test')` at module load time, unconditionally — regardless of whether the application is running in a test environment. This causes `nock` (a dependency of `@athenna/test`) to activate its HTTP interceptors via `@mswjs/interceptors` on every application startup where `@athenna/test` is installed.
## Affected File
`src/facades/FacadeProxyHandler.ts` (compiled: `src/facades/FacadeProxyHandler.js`)
```js
// Line 12 — runs on every module load, in every environment
const athennaTest = await Module.safeImport('@athenna/test');
const Mock = athennaTest?.Mock;
```
## Root Cause Chain
1. Any facade (e.g. `Storage`, `Database`) is used in an artisan command
2. → `FacadeProxyHandler` module is loaded
3. → `Module.safeImport('@athenna/test')` runs unconditionally
4. → `@athenna/test/src/mocks/Mock.js` is loaded, which does `import nock from 'nock'`
5. → **nock v14 auto-activates `@mswjs/interceptors`** on import (by design — see nock's [own comment](https://github.com/nock/nock/blob/main/index.js): *"We always activate Nock on import"*)
6. → All subsequent HTTP/HTTPS connections go through `MockHttpSocket`
7. → Real TLS connections (e.g. AWS S3 SDK uploads) fail with `Error: read EINVAL`
## How to Reproduce
1. Have a project with `@athenna/test` as a **devDependency** (installed locally)
2. Use any Athenna facade (e.g. `Storage`) inside an artisan command
3. Run the command: `node artisan my:command`
4. Any real outbound HTTPS call made inside the command (e.g. AWS S3 SDK) fails with:
```
Error: read EINVAL
at tryReadStart (node:net:702:20)
at Socket._read (node:net:717:5)
at MockHttpSocket. (.../node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/MockHttpSocket.ts:165:12)
at TLSSocket. (.../node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/MockHttpSocket.ts:293:14)
```
The AWS SDK metadata confirms it's a real outbound call being intercepted:
```json
{ "$metadata": { "attempts": 1, "totalRetryDelay": 0 } }
```
## Verification
Confirmed with CJS require tracing that nock is loaded via:
```
nock/index.js
← Module.safeImport('@athenna/test') [at FacadeProxyHandler.js:12]
← FacadeProxyHandler module load
← any Facade usage in the application
```
And confirmed that `nock.isActive()` returns `true` immediately after `@athenna/test` is imported — even with no test setup, no `nock()` calls, no `disableNetConnect()`.
## Proposed Fix
Only import `@athenna/test` when the application is actually running in test mode:
```ts
// src/facades/FacadeProxyHandler.ts
const isTestEnv = process.argv[2] === 'test' || process.env.APP_ENV === 'test';
const athennaTest = isTestEnv ? await Module.safeImport('@athenna/test') : null;
const Mock = athennaTest?.Mock;
```
Alternatively, a more robust check could use a dedicated env variable or the Athenna RC configuration.
## Environment
- `@athenna/ioc`: checked on latest (the `FacadeProxyHandler.js` in the published package has this code)
- `@athenna/test`: `^5.8.0`
- `nock`: `14.0.15` (auto-activates interceptors on import — this is intentional nock v14 behavior)
- `@mswjs/interceptors`: `0.41.9` (used by nock v14 under the hood)
- Node.js: `v22.8.0`
Contributor guide
Research direction
Start with src/facades/FacadeProxyHandler.ts and trace the top-level Module.safeImport('@athenna/test') during facade loading. Reproduce the artisan command with @athenna/test installed and verify that non-test startup no longer activates nock or breaks real HTTPS connections, while test-mode mocking remains available.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100