Files
pnpm/exec/commands/test/exec.ts
Maël Nison 0474a9c3b1 feat: add support for package maps (#12430)
Generate a Node.js package map at `node_modules/.package-map.json` on every
isolated or hoisted install, including under the global virtual store, so that
third-party tooling can start experimenting with package maps. The file is
serialized compactly.

Two settings control how the map is consumed:

- `node-experimental-package-map` (default: off): inject
  `--experimental-package-map` into `NODE_OPTIONS` for the Node.js scripts pnpm
  runs — dependency lifecycle scripts, `pnpm exec`, and `pnpm run` (including
  recursive runs).
- `node-package-map-type` (`standard` | `loose`): choose between a strict map
  and one that tolerates hoisting-like access.

Covered by both the pnpm CLI and the pacquet (Rust) implementation.

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-06-18 11:51:50 +02:00

86 lines
2.1 KiB
TypeScript

import fs from 'node:fs'
import path from 'node:path'
import { beforeEach, expect, jest, test } from '@jest/globals'
import { prepareEmpty } from '@pnpm/prepare'
import { DEFAULT_OPTS } from './utils/index.js'
jest.unstable_mockModule('execa', () => ({
safeExeca: jest.fn(),
sync: jest.fn(),
}))
const { safeExeca: execa } = await import('execa')
const { exec } = await import('@pnpm/exec.commands')
beforeEach(() => {
jest.mocked(execa).mockClear()
})
test('exec should set npm_config_user_agent', async () => {
prepareEmpty()
const userAgent = 'pnpm/0.0.0'
await exec.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
selectedProjectsGraph: {},
userAgent,
}, ['eslint'])
expect(execa).toHaveBeenCalledWith('eslint', [], expect.objectContaining({
env: expect.objectContaining({
npm_config_user_agent: userAgent,
}),
}))
})
test('exec should set the NODE_OPTIONS env var', async () => {
prepareEmpty()
await exec.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
selectedProjectsGraph: {},
nodeOptions: '--max-old-space-size=4096',
}, ['eslint'])
expect(execa).toHaveBeenCalledWith('eslint', [], expect.objectContaining({
env: expect.objectContaining({
NODE_OPTIONS: '--max-old-space-size=4096',
}),
}))
})
test('exec should merge node options with PnP require option', async () => {
prepareEmpty()
const pnpPath = path.join(process.cwd(), '.pnp.cjs')
fs.writeFileSync(pnpPath, '')
await exec.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
selectedProjectsGraph: {},
workspaceDir: undefined,
nodeOptions: '--max-old-space-size=4096',
}, ['eslint'])
expect(execa).toHaveBeenCalledWith('eslint', [], expect.objectContaining({
env: expect.objectContaining({
NODE_OPTIONS: `--max-old-space-size=4096 --require=${pnpPath}`,
}),
}))
})
test('exec should specify the command', async () => {
prepareEmpty()
await expect(exec.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
selectedProjectsGraph: {},
}, [])
).rejects.toThrow("'pnpm exec' requires a command to run")
})