Files
pnpm/pnpm11/exec/npm-lifecycle/test/extendPath.ts
Zoltan Kochan 4edeef9176 style(ts): port the perfectionist lint rules to ESLint (#16415)
Add TypeScript ports of the perfectionist rules that the Rust workspace
enforces through dylint.toml to @pnpm/eslint-config, with the same limits,
and fix every finding that needs no refactor.

The size and shape rules (function length, cognitive complexity, nesting,
local bindings, file length) are enforced for packages that already meet
them. The packages that do not are listed in PENDING_SIZE_AND_SHAPE_REFACTOR
in eslint.config.mjs and are refactored in follow-up changes.

The custom rules mirror perfectionist's semantics rather than reusing
sonarjs or max-lines-per-function, so that one limit means the same thing
in both codebases: a closure is a level of the body that contains it, a
nested function declaration is measured on its own, and a test-framework
callback plays the role of a #[test] function.

Bugs found and fixed along the way:
- a registry error body cut at exactly 64 KiB lost its truncation marker
- removing a dependency could leave dangling .bin shims
- constructor/__proto__ names crashed the projects graph, were skipped by
  the injected-deps syncer, and were dropped from writeWantedLockfile's
  returned lockfile

The CI chunk runner learns to run the node:test suite of the ESLint
config package.
2026-09-30 15:10:08 +02:00

78 lines
2.9 KiB
TypeScript

import path from 'node:path'
import { expect, test } from '@jest/globals'
import { extendPath } from '../src/extendPath.js'
const separator = process.platform === 'win32' ? ';' : ':'
test('the path to node-gyp should be added after the path to node_modules/.bin', () => {
const searchPath = extendPath(process.cwd(), '', { nodeGypBinDir: 'node_gyp', extraBinPaths: [] })
expect(searchPath.indexOf('.bin')).toBeLessThan(searchPath.indexOf('node_gyp'))
})
test('every node_modules above a nested package contributes its .bin, nearest first', () => {
const root = path.resolve('project')
const wd = path.join(root, 'node_modules', 'dep', 'node_modules', 'nested')
const searchPath = extendPath(wd, 'original', { nodeGypBinDir: 'node_gyp', extraBinPaths: ['extra'] })
expect(searchPath.split(separator)).toStrictEqual([
path.join(wd, 'node_modules', '.bin'),
path.join(root, 'node_modules', 'dep', 'node_modules', '.bin'),
path.join(root, 'node_modules', '.bin'),
'node_gyp',
'extra',
'original',
])
})
const testOnWindows = process.platform === 'win32' ? test : test.skip
testOnWindows('a drive-qualified path is split at its node_modules directories', () => {
const searchPath = extendPath('C:\\project\\node_modules\\dep', undefined, { nodeGypBinDir: 'node_gyp' })
expect(searchPath.split(separator)).toStrictEqual([
'C:\\project\\node_modules\\dep\\node_modules\\.bin',
'C:\\project\\node_modules\\.bin',
'node_gyp',
])
})
test('wdBinDir replaces the working directory\'s own .bin, leaving the packages above it on node_modules', () => {
const root = path.resolve('project')
const wd = path.join(root, 'node_modules', 'dep')
const searchPath = extendPath(wd, 'original', {
nodeGypBinDir: 'node_gyp',
wdBinDir: path.join(wd, 'vendor', '.bin'),
extraBinPaths: ['extra'],
})
expect(searchPath.split(separator)).toStrictEqual([
path.join(wd, 'vendor', '.bin'),
path.join(root, 'node_modules', '.bin'),
'node_gyp',
'extra',
'original',
])
})
test('a nested script does not add the entries of its parent script to PATH again', () => {
const wd = path.resolve('project')
const opts = { nodeGypBinDir: 'node_gyp', extraBinPaths: ['extra'] }
const original = ['user', 'user', 'system'].join(separator)
const outer = extendPath(wd, original, opts)
expect(extendPath(wd, outer, opts)).toBe(outer)
expect(outer.split(separator)).toStrictEqual([
path.join(wd, 'node_modules', '.bin'),
'node_gyp',
'extra',
'user',
'user',
'system',
])
})
test('an inherited PATH entry that pnpm adds keeps the position pnpm gives it', () => {
const wd = path.resolve('project')
const bin = path.join(wd, 'node_modules', '.bin')
const searchPath = extendPath(wd, ['system', bin].join(separator), { nodeGypBinDir: 'node_gyp' })
expect(searchPath.split(separator)).toStrictEqual([bin, 'node_gyp', 'system'])
})