fix: remove `suppressImplicitAnyIndexErrors` from typescript settings (#5991)

This commit is contained in:
Zoltan Kochan 2023-01-28 18:19:26 +02:00 committed by GitHub
parent 4e0bed9a13
commit 583e3954be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
256 changed files with 952 additions and 692 deletions

View File

@ -13,7 +13,7 @@ const NEXT_TAG = 'next-7'
const CLI_PKG_NAME = 'pnpm' const CLI_PKG_NAME = 'pnpm'
export default async (workspaceDir: string) => { export default async (workspaceDir: string) => {
const pnpmManifest = loadJsonFile.sync(path.join(workspaceDir, 'pnpm/package.json')) const pnpmManifest = loadJsonFile.sync<any>(path.join(workspaceDir, 'pnpm/package.json'))
const pnpmVersion = pnpmManifest!['version'] // eslint-disable-line const pnpmVersion = pnpmManifest!['version'] // eslint-disable-line
const pnpmMajorKeyword = `pnpm${pnpmVersion.split('.')[0]}` const pnpmMajorKeyword = `pnpm${pnpmVersion.split('.')[0]}`
const utilsDir = path.join(workspaceDir, '__utils__') const utilsDir = path.join(workspaceDir, '__utils__')
@ -108,8 +108,10 @@ async function updateTSConfig (
}, { indent: 2 }) }, { indent: 2 })
return { return {
...tsConfig, ...tsConfig,
extends: '@pnpm/tsconfig',
composite: true,
compilerOptions: { compilerOptions: {
...tsConfig['compilerOptions'], ...(tsConfig as any)['compilerOptions'],
rootDir: 'src', rootDir: 'src',
}, },
references: references.sort((r1, r2) => r1.path.localeCompare(r2.path)), references: references.sort((r1, r2) => r1.path.localeCompare(r2.path)),

View File

@ -13,5 +13,6 @@
{ {
"path": "../lockfile/lockfile-file" "path": "../lockfile/lockfile-file"
} }
] ],
"composite": true
} }

1
.npmrc
View File

@ -12,3 +12,4 @@ save-workspace-protocol=rolling
save-prefix= save-prefix=
resolution-mode=time-based resolution-mode=time-based
auto-install-peers=true auto-install-peers=true
resolve-peers-from-workspace-root=true

View File

@ -32,7 +32,7 @@
}, },
"repository": "https://github.com/pnpm/pnpm/blob/master/privatePackages/assert-project", "repository": "https://github.com/pnpm/pnpm/blob/master/privatePackages/assert-project",
"scripts": { "scripts": {
"lint": "tslint -c ../../tslint.json --project .", "lint": "eslint src/**/*.ts test/**/*.ts",
"lint-test": "tslint -c tslint.json --project test", "lint-test": "tslint -c tslint.json --project test",
"compile": "rimraf tsconfig.tsbuildinfo lib && tsc --build", "compile": "rimraf tsconfig.tsbuildinfo lib && tsc --build",
"prepublishOnly": "pnpm run compile", "prepublishOnly": "pnpm run compile",

View File

@ -24,5 +24,6 @@
{ {
"path": "../assert-store" "path": "../assert-store"
} }
] ],
"composite": true
} }

View File

@ -34,7 +34,7 @@
"repository": "https://github.com/pnpm/pnpm/blob/master/privatePackages/assert-store", "repository": "https://github.com/pnpm/pnpm/blob/master/privatePackages/assert-store",
"scripts": { "scripts": {
"compile": "tsc --build", "compile": "tsc --build",
"lint": "tslint -c ../../tslint.json src/**/*.ts test/**/*.ts", "lint": "eslint src/**/*.ts test/**/*.ts",
"prepublishOnly": "pnpm run compile", "prepublishOnly": "pnpm run compile",
"pretest": "pnpm install -C test/fixture/project --force --no-shared-workspace-lockfile", "pretest": "pnpm install -C test/fixture/project --force --no-shared-workspace-lockfile",
"test": "pnpm pretest && pnpm run compile && jest" "test": "pnpm pretest && pnpm run compile && jest"

View File

@ -12,5 +12,6 @@
{ {
"path": "../../store/cafs" "path": "../../store/cafs"
} }
] ],
"composite": true
} }

View File

@ -29,6 +29,7 @@
} }
], ],
"@typescript-eslint/consistent-indexed-object-style": "off", "@typescript-eslint/consistent-indexed-object-style": "off",
"@typescript-eslint/prefer-reduce-type-parameter": "off",
"@typescript-eslint/naming-convention": "error", "@typescript-eslint/naming-convention": "error",
"@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-explicit-any": "error",

View File

@ -25,7 +25,7 @@
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "^5.48.1", "@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1", "@typescript-eslint/parser": "^5.48.1",
"eslint": "^8.31.0", "eslint": "^8.32.0",
"eslint-config-standard-with-typescript": "^26.0.0", "eslint-config-standard-with-typescript": "^26.0.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.6.0", "eslint-plugin-n": "^15.6.0",

View File

@ -9,5 +9,6 @@
"src/**/*.ts", "src/**/*.ts",
"../../__typings__/**/*.d.ts" "../../__typings__/**/*.d.ts"
], ],
"references": [] "references": [],
"composite": true
} }

View File

@ -16,7 +16,7 @@
"@types/node": "^14.18.36" "@types/node": "^14.18.36"
}, },
"scripts": { "scripts": {
"lint": "tslint -c ../../tslint.json --project .", "lint": "eslint src/**/*.ts",
"prepublishOnly": "pnpm run compile", "prepublishOnly": "pnpm run compile",
"test": "pnpm run compile", "test": "pnpm run compile",
"compile": "rimraf tsconfig.tsbuildinfo lib && tsc --build" "compile": "rimraf tsconfig.tsbuildinfo lib && tsc --build"

View File

@ -27,8 +27,13 @@ export function tempDir (chdir: boolean = true) {
return tmpDir return tmpDir
} }
interface LocationAndManifest {
location: string
package: ProjectManifest
}
export function preparePackages ( export function preparePackages (
pkgs: Array<{ location: string, package: ProjectManifest } | ProjectManifest>, pkgs: Array<LocationAndManifest | ProjectManifest>,
opts?: { opts?: {
manifestFormat?: ManifestFormat manifestFormat?: ManifestFormat
tempDir?: string tempDir?: string
@ -40,15 +45,15 @@ export function preparePackages (
const dirname = path.dirname(pkgTmpPath) const dirname = path.dirname(pkgTmpPath)
const result: { [name: string]: Project } = {} const result: { [name: string]: Project } = {}
for (const aPkg of pkgs) { for (const aPkg of pkgs) {
if (typeof aPkg['location'] === 'string') { if (typeof (aPkg as LocationAndManifest).location === 'string') {
result[aPkg['package']['name']] = prepare(aPkg['package'], { result[(aPkg as LocationAndManifest).package.name!] = prepare((aPkg as LocationAndManifest).package, {
manifestFormat, manifestFormat,
tempDir: path.join(dirname, aPkg['location']), tempDir: path.join(dirname, (aPkg as LocationAndManifest).location),
}) })
} else { } else {
result[aPkg['name']] = prepare(aPkg as ProjectManifest, { result[(aPkg as ProjectManifest).name!] = prepare(aPkg as ProjectManifest, {
manifestFormat, manifestFormat,
tempDir: path.join(dirname, aPkg['name']), tempDir: path.join(dirname, (aPkg as ProjectManifest).name!),
}) })
} }
} }

View File

@ -15,5 +15,6 @@
{ {
"path": "../assert-project" "path": "../assert-project"
} }
] ],
"composite": true
} }

View File

@ -27,7 +27,7 @@
}, },
"repository": "https://github.com/pnpm/pnpm/blob/master/privatePackages/test-fixtures", "repository": "https://github.com/pnpm/pnpm/blob/master/privatePackages/test-fixtures",
"scripts": { "scripts": {
"lint": "tslint -c ../../tslint.json --project .", "lint": "eslint src/**/*.ts",
"compile": "rimraf tsconfig.tsbuildinfo lib && tsc --build", "compile": "rimraf tsconfig.tsbuildinfo lib && tsc --build",
"test": "pnpm run compile" "test": "pnpm run compile"
}, },

View File

@ -12,5 +12,6 @@
{ {
"path": "../prepare" "path": "../prepare"
} }
] ],
"composite": true
} }

View File

@ -12,7 +12,6 @@
"removeComments": false, "removeComments": false,
"sourceMap": true, "sourceMap": true,
"strict": true, "strict": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es2020" "target": "es2020"
}, },
"atom": { "atom": {

View File

@ -12,5 +12,6 @@
{ {
"path": "../../packages/types" "path": "../../packages/types"
} }
] ],
"composite": true
} }

View File

@ -25,5 +25,6 @@ export const TABLE_OPTIONS = {
} }
for (const [key, value] of Object.entries(TABLE_OPTIONS.border)) { for (const [key, value] of Object.entries(TABLE_OPTIONS.border)) {
// @ts-expect-error
TABLE_OPTIONS.border[key] = chalk.grey(value) TABLE_OPTIONS.border[key] = chalk.grey(value)
} }

View File

@ -33,5 +33,6 @@
{ {
"path": "../default-reporter" "path": "../default-reporter"
} }
] ],
"composite": true
} }

View File

@ -8,5 +8,6 @@
"src/**/*.ts", "src/**/*.ts",
"../../__typings__/**/*.d.ts" "../../__typings__/**/*.d.ts"
], ],
"references": [] "references": [],
"composite": true
} }

View File

@ -8,5 +8,6 @@
"src/**/*.ts", "src/**/*.ts",
"../../__typings__/**/*.d.ts" "../../__typings__/**/*.d.ts"
], ],
"references": [] "references": [],
"composite": true
} }

View File

@ -101,7 +101,7 @@ export function reporterForClient (
outputs.push(reportContext(log$, { cwd })) outputs.push(reportContext(log$, { cwd }))
} }
if (PRINT_EXECUTION_TIME_IN_COMMANDS[opts.cmd]) { if (opts.cmd in PRINT_EXECUTION_TIME_IN_COMMANDS) {
outputs.push(reportExecutionTime(log$.executionTime)) outputs.push(reportExecutionTime(log$.executionTime))
} }

View File

@ -58,16 +58,16 @@ export function getPkgsDiff (
const deprecationSet = args[1] as Set<string> const deprecationSet = args[1] as Set<string>
let action: '-' | '+' | undefined let action: '-' | '+' | undefined
let log!: any // eslint-disable-line let log!: any // eslint-disable-line
if (rootLog['added']) { if ('added' in rootLog) {
action = '+' action = '+'
log = rootLog['added'] log = rootLog['added']
} else if (rootLog['removed']) { } else if ('removed' in rootLog) {
action = '-' action = '-'
log = rootLog['removed'] log = rootLog['removed']
} else { } else {
return pkgsDiff return pkgsDiff
} }
const depType = log.dependencyType || 'nodeModulesOnly' const depType = (log.dependencyType || 'nodeModulesOnly') as keyof typeof pkgsDiff
const oppositeKey = `${action === '-' ? '+' : '-'}${log.name as string}` const oppositeKey = `${action === '-' ? '+' : '-'}${log.name as string}`
const previous = pkgsDiff[depType][oppositeKey] const previous = pkgsDiff[depType][oppositeKey]
if (previous && previous.version === log.version) { if (previous && previous.version === log.version) {
@ -126,7 +126,7 @@ export function getPkgsDiff (
const initialPackageManifest = removeOptionalFromProdDeps(packageManifests['initial']) const initialPackageManifest = removeOptionalFromProdDeps(packageManifests['initial'])
const updatedPackageManifest = removeOptionalFromProdDeps(packageManifests['updated']) const updatedPackageManifest = removeOptionalFromProdDeps(packageManifests['updated'])
for (const depType of ['peer', 'prod', 'optional', 'dev']) { for (const depType of ['peer', 'prod', 'optional', 'dev'] as const) {
const prop = propertyByDependencyType[depType] const prop = propertyByDependencyType[depType]
const initialDeps = Object.keys(initialPackageManifest[prop] || {}) const initialDeps = Object.keys(initialPackageManifest[prop] || {})
const updatedDeps = Object.keys(updatedPackageManifest[prop] || {}) const updatedDeps = Object.keys(updatedPackageManifest[prop] || {})

View File

@ -52,8 +52,8 @@ export function reportSummary (
take(1), take(1),
map(([pkgsDiff]) => { map(([pkgsDiff]) => {
let msg = '' let msg = ''
for (const depType of ['prod', 'optional', 'peer', 'dev', 'nodeModulesOnly']) { for (const depType of ['prod', 'optional', 'peer', 'dev', 'nodeModulesOnly'] as const) {
const diffs: PackageDiff[] = Object.values(pkgsDiff[depType]) const diffs: PackageDiff[] = Object.values(pkgsDiff[depType as keyof typeof pkgsDiff])
if (diffs.length > 0) { if (diffs.length > 0) {
msg += EOL msg += EOL
if (opts.pnpmConfig?.global) { if (opts.pnpmConfig?.global) {

View File

@ -181,9 +181,10 @@ test('prints test error', (done) => {
}, },
}) })
const err = new Error('Tests failed') const err = Object.assign(new Error('Tests failed'), {
err['stage'] = 'test' code: 'ELIFECYCLE',
err['code'] = 'ELIFECYCLE' stage: 'test',
})
logger.error(err, err) logger.error(err, err)
}) })

View File

@ -2,7 +2,8 @@
"extends": "@pnpm/tsconfig", "extends": "@pnpm/tsconfig",
"compilerOptions": { "compilerOptions": {
"outDir": "lib", "outDir": "lib",
"rootDir": "src" "rootDir": "src",
"suppressImplicitAnyIndexErrors": true
}, },
"include": [ "include": [
"src/**/*.ts", "src/**/*.ts",
@ -24,5 +25,6 @@
{ {
"path": "../../packages/types" "path": "../../packages/types"
} }
] ],
"composite": true
} }

View File

@ -187,7 +187,7 @@ const CUSTOM_OPTION_PREFIX = 'config.'
function normalizeOptions (options: Record<string, unknown>, knownOptions: Set<string>) { function normalizeOptions (options: Record<string, unknown>, knownOptions: Set<string>) {
const standardOptionNames = [] const standardOptionNames = []
const normalizedOptions = {} const normalizedOptions: Record<string, unknown> = {}
for (const [optionName, optionValue] of Object.entries(options)) { for (const [optionName, optionValue] of Object.entries(options)) {
if (optionName.startsWith(CUSTOM_OPTION_PREFIX)) { if (optionName.startsWith(CUSTOM_OPTION_PREFIX)) {
normalizedOptions[optionName.substring(CUSTOM_OPTION_PREFIX.length)] = optionValue normalizedOptions[optionName.substring(CUSTOM_OPTION_PREFIX.length)] = optionValue

View File

@ -15,5 +15,6 @@
{ {
"path": "../../workspace/find-workspace-dir" "path": "../../workspace/find-workspace-dir"
} }
] ],
"composite": true
} }

View File

@ -1,10 +1,10 @@
import normalizeRegistryUrl from 'normalize-registry-url' import normalizeRegistryUrl from 'normalize-registry-url'
export function getScopeRegistries (rawConfig: Object) { export function getScopeRegistries (rawConfig: Record<string, object>) {
const registries = {} const registries: Record<string, string> = {}
for (const configKey of Object.keys(rawConfig)) { for (const configKey of Object.keys(rawConfig)) {
if (configKey[0] === '@' && configKey.endsWith(':registry')) { if (configKey[0] === '@' && configKey.endsWith(':registry')) {
registries[configKey.slice(0, configKey.indexOf(':'))] = normalizeRegistryUrl(rawConfig[configKey]) registries[configKey.slice(0, configKey.indexOf(':'))] = normalizeRegistryUrl(rawConfig[configKey] as unknown as string)
} }
} }
return registries return registries

View File

@ -262,6 +262,7 @@ export async function getConfig (
const cwd = (cliOptions.dir && path.resolve(cliOptions.dir)) ?? npmConfig.localPrefix const cwd = (cliOptions.dir && path.resolve(cliOptions.dir)) ?? npmConfig.localPrefix
pnpmConfig.maxSockets = npmConfig.maxsockets pnpmConfig.maxSockets = npmConfig.maxsockets
// @ts-expect-error
delete pnpmConfig['maxsockets'] delete pnpmConfig['maxsockets']
pnpmConfig.configDir = configDir pnpmConfig.configDir = configDir
@ -286,11 +287,14 @@ export async function getConfig (
...getScopeRegistries(pnpmConfig.rawConfig), ...getScopeRegistries(pnpmConfig.rawConfig),
} }
pnpmConfig.useLockfile = (() => { pnpmConfig.useLockfile = (() => {
// @ts-expect-error
if (typeof pnpmConfig['lockfile'] === 'boolean') return pnpmConfig['lockfile'] if (typeof pnpmConfig['lockfile'] === 'boolean') return pnpmConfig['lockfile']
// @ts-expect-error
if (typeof pnpmConfig['packageLock'] === 'boolean') return pnpmConfig['packageLock'] if (typeof pnpmConfig['packageLock'] === 'boolean') return pnpmConfig['packageLock']
return false return false
})() })()
pnpmConfig.useGitBranchLockfile = (() => { pnpmConfig.useGitBranchLockfile = (() => {
// @ts-expect-error
if (typeof pnpmConfig['gitBranchLockfile'] === 'boolean') return pnpmConfig['gitBranchLockfile'] if (typeof pnpmConfig['gitBranchLockfile'] === 'boolean') return pnpmConfig['gitBranchLockfile']
return false return false
})() })()
@ -309,7 +313,9 @@ export async function getConfig (
if (cliOptions['global']) { if (cliOptions['global']) {
let globalDirRoot let globalDirRoot
// @ts-expect-error
if (pnpmConfig['globalDir']) { if (pnpmConfig['globalDir']) {
// @ts-expect-error
globalDirRoot = pnpmConfig['globalDir'] globalDirRoot = pnpmConfig['globalDir']
} else { } else {
globalDirRoot = path.join(pnpmConfig.pnpmHomeDir, 'global') globalDirRoot = path.join(pnpmConfig.pnpmHomeDir, 'global')
@ -427,6 +433,7 @@ export async function getConfig (
} }
} }
// @ts-expect-error
if (pnpmConfig['shamefullyFlatten']) { if (pnpmConfig['shamefullyFlatten']) {
warnings.push('The "shamefully-flatten" setting has been renamed to "shamefully-hoist". Also, in most cases you won\'t need "shamefully-hoist". Since v4, a semistrict node_modules structure is on by default (via hoist-pattern=[*]).') warnings.push('The "shamefully-flatten" setting has been renamed to "shamefully-hoist". Also, in most cases you won\'t need "shamefully-hoist". Since v4, a semistrict node_modules structure is on by default (via hoist-pattern=[*]).')
pnpmConfig.shamefullyHoist = true pnpmConfig.shamefullyHoist = true
@ -437,6 +444,7 @@ export async function getConfig (
if (!pnpmConfig.stateDir) { if (!pnpmConfig.stateDir) {
pnpmConfig.stateDir = getStateDir(process) pnpmConfig.stateDir = getStateDir(process)
} }
// @ts-expect-error
if (pnpmConfig['hoist'] === false) { if (pnpmConfig['hoist'] === false) {
delete pnpmConfig.hoistPattern delete pnpmConfig.hoistPattern
} }
@ -486,6 +494,7 @@ export async function getConfig (
pnpmConfig.httpProxy = pnpmConfig.httpsProxy ?? getProcessEnv('http_proxy') ?? getProcessEnv('proxy') pnpmConfig.httpProxy = pnpmConfig.httpsProxy ?? getProcessEnv('http_proxy') ?? getProcessEnv('proxy')
} }
if (!pnpmConfig.noProxy) { if (!pnpmConfig.noProxy) {
// @ts-expect-error
pnpmConfig.noProxy = pnpmConfig['noproxy'] ?? getProcessEnv('no_proxy') pnpmConfig.noProxy = pnpmConfig['noproxy'] ?? getProcessEnv('no_proxy')
} }
switch (pnpmConfig.nodeLinker) { switch (pnpmConfig.nodeLinker) {
@ -526,7 +535,7 @@ export async function getConfig (
pnpmConfig.hooks = requireHooks(pnpmConfig.lockfileDir ?? pnpmConfig.dir, pnpmConfig) pnpmConfig.hooks = requireHooks(pnpmConfig.lockfileDir ?? pnpmConfig.dir, pnpmConfig)
} }
pnpmConfig.rootProjectManifest = await safeReadProjectManifestOnly(pnpmConfig.lockfileDir ?? pnpmConfig.workspaceDir ?? pnpmConfig.dir) ?? undefined pnpmConfig.rootProjectManifest = await safeReadProjectManifestOnly(pnpmConfig.lockfileDir ?? pnpmConfig.workspaceDir ?? pnpmConfig.dir) ?? undefined
if (pnpmConfig.rootProjectManifest?.['workspaces']?.length && !pnpmConfig.workspaceDir) { if (pnpmConfig.rootProjectManifest?.workspaces?.length && !pnpmConfig.workspaceDir) {
warnings.push('The "workspaces" field in package.json is not supported by pnpm. Create a "pnpm-workspace.yaml" file instead.') warnings.push('The "workspaces" field in package.json is not supported by pnpm. Create a "pnpm-workspace.yaml" file instead.')
} }

View File

@ -588,6 +588,7 @@ test('read only supported settings from config', async () => {
}) })
expect(config.storeDir).toEqual('__store__') expect(config.storeDir).toEqual('__store__')
// @ts-expect-error
expect(config['foo']).toBeUndefined() expect(config['foo']).toBeUndefined()
expect(config.rawConfig['foo']).toEqual('bar') expect(config.rawConfig['foo']).toEqual('bar')
}) })
@ -603,6 +604,7 @@ test('all CLI options are added to the config', async () => {
}, },
}) })
// @ts-expect-error
expect(config['fooBar']).toEqual('qar') expect(config['fooBar']).toEqual('qar')
}) })
@ -858,7 +860,7 @@ test('getConfig() sets merge-git-branch-lockfiles when branch matches merge-git-
await fs.writeFile('.npmrc', npmrc, 'utf8') await fs.writeFile('.npmrc', npmrc, 'utf8')
getCurrentBranch['mockReturnValue']('develop') ;(getCurrentBranch as jest.Mock).mockReturnValue('develop')
const { config } = await getConfig({ const { config } = await getConfig({
cliOptions: { cliOptions: {
global: false, global: false,
@ -873,7 +875,7 @@ test('getConfig() sets merge-git-branch-lockfiles when branch matches merge-git-
expect(config.mergeGitBranchLockfiles).toBe(false) expect(config.mergeGitBranchLockfiles).toBe(false)
} }
{ {
getCurrentBranch['mockReturnValue']('main') (getCurrentBranch as jest.Mock).mockReturnValue('main')
const { config } = await getConfig({ const { config } = await getConfig({
cliOptions: { cliOptions: {
global: false, global: false,
@ -886,7 +888,7 @@ test('getConfig() sets merge-git-branch-lockfiles when branch matches merge-git-
expect(config.mergeGitBranchLockfiles).toBe(true) expect(config.mergeGitBranchLockfiles).toBe(true)
} }
{ {
getCurrentBranch['mockReturnValue']('release/1.0.0') (getCurrentBranch as jest.Mock).mockReturnValue('release/1.0.0')
const { config } = await getConfig({ const { config } = await getConfig({
cliOptions: { cliOptions: {
global: false, global: false,

View File

@ -36,5 +36,6 @@
{ {
"path": "../matcher" "path": "../matcher"
} }
] ],
"composite": true
} }

View File

@ -8,5 +8,6 @@
"src/**/*.ts", "src/**/*.ts",
"../../__typings__/**/*.d.ts" "../../__typings__/**/*.d.ts"
], ],
"references": [] "references": [],
"composite": true
} }

View File

@ -12,5 +12,6 @@
{ {
"path": "../../packages/types" "path": "../../packages/types"
} }
] ],
"composite": true
} }

View File

@ -2,6 +2,7 @@ import mem from 'mem'
import * as execa from 'execa' import * as execa from 'execa'
export function getSystemNodeVersionNonCached () { export function getSystemNodeVersionNonCached () {
// @ts-expect-error
if (process['pkg'] != null) { if (process['pkg'] != null) {
return execa.sync('node', ['--version']).stdout.toString() return execa.sync('node', ['--version']).stdout.toString()
} }

View File

@ -8,12 +8,14 @@ jest.mock('execa', () => ({
})) }))
test('getSystemNodeVersion() executed from an executable pnpm CLI', () => { test('getSystemNodeVersion() executed from an executable pnpm CLI', () => {
// @ts-expect-error
process['pkg'] = {} process['pkg'] = {}
expect(getSystemNodeVersionNonCached()).toBe('v10.0.0') expect(getSystemNodeVersionNonCached()).toBe('v10.0.0')
expect(execa.sync).toHaveBeenCalledWith('node', ['--version']) expect(execa.sync).toHaveBeenCalledWith('node', ['--version'])
}) })
test('getSystemNodeVersion() from a non-executable pnpm CLI', () => { test('getSystemNodeVersion() from a non-executable pnpm CLI', () => {
// @ts-expect-error
delete process['pkg'] delete process['pkg']
expect(getSystemNodeVersionNonCached()).toBe(process.version) expect(getSystemNodeVersionNonCached()).toBe(process.version)
}) })

View File

@ -18,5 +18,6 @@
{ {
"path": "../../packages/types" "path": "../../packages/types"
} }
] ],
"composite": true
} }

View File

@ -15,5 +15,6 @@
{ {
"path": "../../packages/parse-wanted-dependency" "path": "../../packages/parse-wanted-dependency"
} }
] ],
"composite": true
} }

View File

@ -12,5 +12,6 @@
{ {
"path": "../../packages/types" "path": "../../packages/types"
} }
] ],
"composite": true
} }

View File

@ -15,9 +15,9 @@ export async function configSet (opts: ConfigCommandOptions, key: string, value:
await writeIniFile(configPath, settings) await writeIniFile(configPath, settings)
} }
async function safeReadIniFile (configPath: string) { async function safeReadIniFile (configPath: string): Promise<Record<string, unknown>> {
try { try {
return await readIniFile(configPath) return await readIniFile(configPath) as Record<string, unknown>
} catch (err: any) { // eslint-disable-line @typescript-eslint/no-explicit-any } catch (err: any) { // eslint-disable-line @typescript-eslint/no-explicit-any
if (err.code === 'ENOENT') return {} if (err.code === 'ENOENT') return {}
throw err throw err

View File

@ -21,5 +21,6 @@
{ {
"path": "../config" "path": "../config"
} }
] ],
"composite": true
} }

View File

@ -42,7 +42,7 @@ export async function fetchNode (fetch: FetchFromRegistry, version: string, targ
}) })
const cafs = createCafsStore(opts.cafsDir) const cafs = createCafsStore(opts.cafsDir)
const fetchTarball = pickFetcher(fetchers, { tarball }) const fetchTarball = pickFetcher(fetchers, { tarball })
const { filesIndex } = await fetchTarball(cafs, { tarball }, { const { filesIndex } = await fetchTarball(cafs, { tarball } as any, { // eslint-disable-line @typescript-eslint/no-explicit-any
lockfileDir: process.cwd(), lockfileDir: process.cwd(),
}) })
await cafs.importPackage(targetDir, { await cafs.importPackage(targetDir, {

View File

@ -25,7 +25,7 @@ const fetchMock = jest.fn(async (url: string) => {
}) })
beforeEach(() => { beforeEach(() => {
isNonGlibcLinux['mockReturnValue'](Promise.resolve(false)) (isNonGlibcLinux as jest.Mock).mockReturnValue(Promise.resolve(false))
fetchMock.mockClear() fetchMock.mockClear()
}) })
@ -60,7 +60,7 @@ test('install Node using the default node mirror', async () => {
}) })
test('install Node using a custom node mirror', async () => { test('install Node using a custom node mirror', async () => {
isNonGlibcLinux['mockReturnValue'](Promise.resolve(true)) (isNonGlibcLinux as jest.Mock).mockReturnValue(Promise.resolve(true))
tempDir() tempDir()
const opts: FetchNodeOptions = { const opts: FetchNodeOptions = {

View File

@ -33,5 +33,6 @@
{ {
"path": "../../store/create-cafs-store" "path": "../../store/create-cafs-store"
} }
] ],
"composite": true
} }

View File

@ -18,5 +18,6 @@
{ {
"path": "../node.fetcher" "path": "../node.fetcher"
} }
] ],
"composite": true
} }

View File

@ -36,5 +36,6 @@
{ {
"path": "../node.resolver" "path": "../node.resolver"
} }
] ],
"composite": true
} }

View File

@ -47,9 +47,10 @@ export async function buildModules (
} }
// postinstall hooks // postinstall hooks
const buildDepOpts = { ...opts, warn } const buildDepOpts = {
if (opts.hoistedLocations) { ...opts,
buildDepOpts['builtHoistedDeps'] = {} builtHoistedDeps: opts.hoistedLocations ? {} : undefined,
warn,
} }
const chunks = buildSequence(depGraph, rootDepPaths) const chunks = buildSequence(depGraph, rootDepPaths)
const groups = chunks.map((chunk) => { const groups = chunks.map((chunk) => {

View File

@ -36,5 +36,6 @@
{ {
"path": "../lifecycle" "path": "../lifecycle"
} }
] ],
"composite": true
} }

View File

@ -3,6 +3,7 @@ import { safeReadPackageJsonFromDir } from '@pnpm/read-package-json'
import exists from 'path-exists' import exists from 'path-exists'
import { runLifecycleHook, RunLifecycleHookOptions } from './runLifecycleHook' import { runLifecycleHook, RunLifecycleHookOptions } from './runLifecycleHook'
import { runLifecycleHooksConcurrently, RunLifecycleHooksConcurrentlyOptions } from './runLifecycleHooksConcurrently' import { runLifecycleHooksConcurrently, RunLifecycleHooksConcurrentlyOptions } from './runLifecycleHooksConcurrently'
import { PackageScripts } from '@pnpm/types'
export function makeNodeRequireOption (modulePath: string) { export function makeNodeRequireOption (modulePath: string) {
let { NODE_OPTIONS } = process.env let { NODE_OPTIONS } = process.env
@ -51,9 +52,9 @@ export async function runPostinstallHooks (
*/ */
async function checkBindingGyp ( async function checkBindingGyp (
root: string, root: string,
scripts: {} scripts: PackageScripts
) { ) {
if (await exists(path.join(root, 'binding.gyp'))) { if (await exists(path.join(root, 'binding.gyp'))) {
scripts['install'] = 'node-gyp rebuild' scripts.install = 'node-gyp rebuild'
} }
} }

View File

@ -30,5 +30,6 @@
{ {
"path": "../../store/store-controller-types" "path": "../../store/store-controller-types"
} }
] ],
"composite": true
} }

View File

@ -82,8 +82,8 @@ export async function extendRebuildOptions (
): Promise<StrictRebuildOptions> { ): Promise<StrictRebuildOptions> {
if (opts) { if (opts) {
for (const key in opts) { for (const key in opts) {
if (opts[key] === undefined) { if (opts[key as keyof RebuildOptions] === undefined) {
delete opts[key] delete opts[key as keyof RebuildOptions]
} }
} }
} }

View File

@ -81,5 +81,6 @@
{ {
"path": "../lifecycle" "path": "../lifecycle"
} }
] ],
"composite": true
} }

View File

@ -436,7 +436,7 @@ test('pnpm exec on single project should return non-zero exit code when the proc
selectedProjectsGraph: {}, selectedProjectsGraph: {},
}, ['node']) }, ['node'])
expect(runResult['exitCode']).toBe(1) expect(runResult).toHaveProperty(['exitCode'], 1)
} }
}) })

View File

@ -54,5 +54,6 @@
{ {
"path": "../lifecycle" "path": "../lifecycle"
} }
] ],
"composite": true
} }

View File

@ -24,5 +24,6 @@
{ {
"path": "../lifecycle" "path": "../lifecycle"
} }
] ],
"composite": true
} }

View File

@ -8,5 +8,6 @@
"src/**/*.ts", "src/**/*.ts",
"../../__typings__/**/*.d.ts" "../../__typings__/**/*.d.ts"
], ],
"references": [] "references": [],
"composite": true
} }

View File

@ -21,5 +21,6 @@
{ {
"path": "../fetcher-base" "path": "../fetcher-base"
} }
] ],
"composite": true
} }

View File

@ -18,5 +18,6 @@
{ {
"path": "../../store/cafs-types" "path": "../../store/cafs-types"
} }
] ],
"composite": true
} }

View File

@ -24,5 +24,6 @@
{ {
"path": "../fetcher-base" "path": "../fetcher-base"
} }
] ],
"composite": true
} }

View File

@ -14,7 +14,7 @@ export function pickFetcher (fetcherByHostingType: Partial<Fetchers>, resolution
} }
} }
const fetch = fetcherByHostingType[fetcherType!] const fetch = fetcherByHostingType[fetcherType! as keyof Fetchers]
if (!fetch) { if (!fetch) {
throw new Error(`Fetching for dependency type "${resolution.type ?? 'undefined'}" is not supported`) throw new Error(`Fetching for dependency type "${resolution.type ?? 'undefined'}" is not supported`)

View File

@ -15,5 +15,6 @@
{ {
"path": "../fetcher-base" "path": "../fetcher-base"
} }
] ],
"composite": true
} }

View File

@ -57,6 +57,7 @@ async function fetchFromLocalTarball (
sri: err['sri'], sri: err['sri'],
url: tarball, url: tarball,
}) })
// @ts-expect-error
error['resource'] = tarball error['resource'] = tarball
throw error throw error
} }

View File

@ -39,5 +39,6 @@
{ {
"path": "../fetcher-base" "path": "../fetcher-base"
} }
] ],
"composite": true
} }

View File

@ -15,5 +15,6 @@
{ {
"path": "../../pkg-manifest/read-project-manifest" "path": "../../pkg-manifest/read-project-manifest"
} }
] ],
"composite": true
} }

View File

@ -8,5 +8,6 @@
"src/**/*.ts", "src/**/*.ts",
"../../__typings__/**/*.d.ts" "../../__typings__/**/*.d.ts"
], ],
"references": [] "references": [],
"composite": true
} }

View File

@ -12,5 +12,6 @@
{ {
"path": "../../__utils__/prepare" "path": "../../__utils__/prepare"
} }
] ],
"composite": true
} }

View File

@ -99,12 +99,12 @@ async function tryImportIndexedDir (importFile: ImportFile, newDir: string, file
function getUniqueFileMap (fileMap: Record<string, string>) { function getUniqueFileMap (fileMap: Record<string, string>) {
const lowercaseFiles = new Map<string, string>() const lowercaseFiles = new Map<string, string>()
const conflictingFileNames = {} const conflictingFileNames: Record<string, string> = {}
const uniqueFileMap = {} const uniqueFileMap: Record<string, string> = {}
for (const filename of Object.keys(fileMap).sort()) { for (const filename of Object.keys(fileMap).sort()) {
const lowercaseFilename = filename.toLowerCase() const lowercaseFilename = filename.toLowerCase()
if (lowercaseFiles.has(lowercaseFilename)) { if (lowercaseFiles.has(lowercaseFilename)) {
conflictingFileNames[filename] = lowercaseFiles.get(lowercaseFilename) conflictingFileNames[filename] = lowercaseFiles.get(lowercaseFilename)!
continue continue
} }
lowercaseFiles.set(lowercaseFilename, filename) lowercaseFiles.set(lowercaseFilename, filename)

View File

@ -128,9 +128,7 @@ test('packageImportMethod=hardlink: fall back to copying if hardlinking fails',
const importPackage = createIndexedPkgImporter('hardlink') const importPackage = createIndexedPkgImporter('hardlink')
fsMock.promises.link = jest.fn((src: string, dest: string) => { fsMock.promises.link = jest.fn((src: string, dest: string) => {
if (dest.endsWith('license')) { if (dest.endsWith('license')) {
const err = new Error('') throw Object.assign(new Error(''), { code: 'EEXIST' })
err['code'] = 'EEXIST'
throw err
} }
throw new Error('This file system does not support hard linking') throw new Error('This file system does not support hard linking')
}) })
@ -207,9 +205,7 @@ test('packageImportMethod=hardlink links packages when they are not found', asyn
fsMock.promises.rename = jest.fn() fsMock.promises.rename = jest.fn()
fsMock.promises.stat = jest.fn((file) => { fsMock.promises.stat = jest.fn((file) => {
if (file === path.join('project/package', 'package.json')) { if (file === path.join('project/package', 'package.json')) {
const err = new Error() throw Object.assign(new Error(), { code: 'ENOENT' })
err['code'] = 'ENOENT'
throw err
} }
return { ino: 0 } return { ino: 0 }
}) })

View File

@ -18,5 +18,6 @@
{ {
"path": "../../store/store-controller-types" "path": "../../store/store-controller-types"
} }
] ],
"composite": true
} }

View File

@ -8,5 +8,6 @@
"src/**/*.ts", "src/**/*.ts",
"../../__typings__/**/*.d.ts" "../../__typings__/**/*.d.ts"
], ],
"references": [] "references": [],
"composite": true
} }

View File

@ -18,5 +18,6 @@
{ {
"path": "../../packages/types" "path": "../../packages/types"
} }
] ],
"composite": true
} }

View File

@ -60,16 +60,16 @@ export function requireHooks (
filterLog: [], filterLog: [],
readPackage: [], readPackage: [],
} }
for (const hookName of ['readPackage', 'afterAllResolved']) { for (const hookName of ['readPackage', 'afterAllResolved'] as const) {
if (globalHooks[hookName]) { if (globalHooks[hookName]) {
const globalHook = globalHooks[hookName] const globalHook = globalHooks[hookName]
const context = createReadPackageHookContext(globalPnpmfile.filename, prefix, hookName) const context = createReadPackageHookContext(globalPnpmfile.filename, prefix, hookName)
cookedHooks[hookName].push((pkg: object) => globalHook(pkg, context)) cookedHooks[hookName]!.push((pkg: object) => globalHook!(pkg as any, context)) // eslint-disable-line @typescript-eslint/no-explicit-any
} }
if (hooks[hookName]) { if (hooks[hookName]) {
const hook = hooks[hookName] const hook = hooks[hookName]
const context = createReadPackageHookContext(pnpmFile.filename, prefix, hookName) const context = createReadPackageHookContext(pnpmFile.filename, prefix, hookName)
cookedHooks[hookName].push((pkg: object) => hook(pkg, context)) cookedHooks[hookName]!.push((pkg: object) => hook!(pkg as any, context)) // eslint-disable-line @typescript-eslint/no-explicit-any
} }
} }
if (globalHooks.filterLog != null) { if (globalHooks.filterLog != null) {

View File

@ -30,5 +30,6 @@
{ {
"path": "../../store/store-controller-types" "path": "../../store/store-controller-types"
} }
] ],
"composite": true
} }

View File

@ -32,12 +32,12 @@ function extendPkgHook (extensionsByPkgName: Record<string, PackageExtensionMatc
function extendPkg (manifest: PackageManifest, extensions: PackageExtensionMatch[]) { function extendPkg (manifest: PackageManifest, extensions: PackageExtensionMatch[]) {
for (const { range, packageExtension } of extensions) { for (const { range, packageExtension } of extensions) {
if (range != null && !semver.satisfies(manifest.version, range)) continue if (range != null && !semver.satisfies(manifest.version, range)) continue
for (const field of ['dependencies', 'optionalDependencies', 'peerDependencies', 'peerDependenciesMeta']) { for (const field of ['dependencies', 'optionalDependencies', 'peerDependencies', 'peerDependenciesMeta'] as const) {
if (!packageExtension[field]) continue if (!packageExtension[field]) continue
manifest[field] = { manifest[field] = {
...packageExtension[field], ...packageExtension[field],
...manifest[field], ...manifest[field],
} } as any // eslint-disable-line @typescript-eslint/no-explicit-any
} }
} }
} }

View File

@ -1,3 +1,4 @@
import { ProjectManifest } from '@pnpm/types'
import { createPeerDependencyPatcher } from '../lib/createPeerDependencyPatcher' import { createPeerDependencyPatcher } from '../lib/createPeerDependencyPatcher'
test('createPeerDependencyPatcher() ignores missing', () => { test('createPeerDependencyPatcher() ignores missing', () => {
@ -9,8 +10,8 @@ test('createPeerDependencyPatcher() ignores missing', () => {
foo: '*', foo: '*',
bar: '*', bar: '*',
}, },
}) }) as ProjectManifest
expect(patchedPkg['peerDependenciesMeta']).toStrictEqual({ expect(patchedPkg.peerDependenciesMeta).toStrictEqual({
foo: { foo: {
optional: true, optional: true,
}, },
@ -26,8 +27,8 @@ test('createPeerDependencyPatcher() pattern matches to ignore missing', () => {
foobar: '*', foobar: '*',
bar: '*', bar: '*',
}, },
}) }) as ProjectManifest
expect(patchedPkg['peerDependenciesMeta']).toStrictEqual({ expect(patchedPkg.peerDependenciesMeta).toStrictEqual({
foobar: { foobar: {
optional: true, optional: true,
}, },
@ -49,8 +50,8 @@ test('createPeerDependencyPatcher() extends peer ranges', () => {
qar: '*', qar: '*',
baz: '1', baz: '1',
}, },
}) }) as ProjectManifest
expect(patchedPkg['peerDependencies']).toStrictEqual({ expect(patchedPkg.peerDependencies).toStrictEqual({
foo: '0 || 1', foo: '0 || 1',
bar: '0', bar: '0',
qar: '*', qar: '*',
@ -69,8 +70,8 @@ test('createPeerDependencyPatcher() ignores peer versions from allowAny', () =>
qar: '2', qar: '2',
baz: '2', baz: '2',
}, },
}) }) as ProjectManifest
expect(patchedPkg['peerDependencies']).toStrictEqual({ expect(patchedPkg.peerDependencies).toStrictEqual({
foo: '*', foo: '*',
bar: '*', bar: '*',
qar: '2', qar: '2',
@ -102,8 +103,8 @@ test('createPeerDependencyPatcher() does not create duplicate extended ranges',
// double apply the same patch to the same package // double apply the same patch to the same package
// this can occur in a monorepo when several packages // this can occur in a monorepo when several packages
// all try to apply the same patch // all try to apply the same patch
const patchedAgainPkg = patcher(await patchedPkg) const patchedAgainPkg = patcher(await patchedPkg) as ProjectManifest
expect(patchedAgainPkg['peerDependencies']).toStrictEqual({ expect(patchedAgainPkg.peerDependencies).toStrictEqual({
// the patch is applied only once (not 0 || 1 || 1) // the patch is applied only once (not 0 || 1 || 1)
foo: '0 || 1', foo: '0 || 1',
same: '12', same: '12',

View File

@ -21,5 +21,6 @@
{ {
"path": "../../packages/types" "path": "../../packages/types"
} }
] ],
"composite": true
} }

View File

@ -1,5 +1,5 @@
import path from 'path' import path from 'path'
import { Lockfile } from '@pnpm/lockfile-types' import { Lockfile, TarballResolution } from '@pnpm/lockfile-types'
import { nameVerFromPkgSnapshot } from '@pnpm/lockfile-utils' import { nameVerFromPkgSnapshot } from '@pnpm/lockfile-utils'
import { lockfileWalkerGroupImporterSteps, LockfileWalkerStep } from '@pnpm/lockfile-walker' import { lockfileWalkerGroupImporterSteps, LockfileWalkerStep } from '@pnpm/lockfile-walker'
import { DependenciesField } from '@pnpm/types' import { DependenciesField } from '@pnpm/types'
@ -29,7 +29,7 @@ export async function lockfileToAuditTree (
} }
): Promise<AuditTree> { ): Promise<AuditTree> {
const importerWalkers = lockfileWalkerGroupImporterSteps(lockfile, Object.keys(lockfile.importers), { include: opts?.include }) const importerWalkers = lockfileWalkerGroupImporterSteps(lockfile, Object.keys(lockfile.importers), { include: opts?.include })
const dependencies = {} const dependencies: Record<string, AuditNode> = {}
await Promise.all( await Promise.all(
importerWalkers.map(async (importerWalker) => { importerWalkers.map(async (importerWalker) => {
const importerDeps = lockfileToAuditNode(importerWalker.step) const importerDeps = lockfileToAuditNode(importerWalker.step)
@ -39,6 +39,7 @@ export async function lockfileToAuditTree (
const { manifest } = await readProjectManifest(path.join(opts.lockfileDir, importerWalker.importerId)) const { manifest } = await readProjectManifest(path.join(opts.lockfileDir, importerWalker.importerId))
dependencies[depName] = { dependencies[depName] = {
dependencies: importerDeps, dependencies: importerDeps,
dev: false,
requires: toRequires(importerDeps), requires: toRequires(importerDeps),
version: manifest.version ?? '0.0.0', version: manifest.version ?? '0.0.0',
} }
@ -59,14 +60,14 @@ export async function lockfileToAuditTree (
return auditTree return auditTree
} }
function lockfileToAuditNode (step: LockfileWalkerStep) { function lockfileToAuditNode (step: LockfileWalkerStep): Record<string, AuditNode> {
const dependencies = {} const dependencies: Record<string, AuditNode> = {}
for (const { depPath, pkgSnapshot, next } of step.dependencies) { for (const { depPath, pkgSnapshot, next } of step.dependencies) {
const { name, version } = nameVerFromPkgSnapshot(depPath, pkgSnapshot) const { name, version } = nameVerFromPkgSnapshot(depPath, pkgSnapshot)
const subdeps = lockfileToAuditNode(next()) const subdeps = lockfileToAuditNode(next())
const dep: AuditNode = { const dep: AuditNode = {
dev: pkgSnapshot.dev === true, dev: pkgSnapshot.dev === true,
integrity: pkgSnapshot.resolution['integrity'], integrity: (pkgSnapshot.resolution as TarballResolution).integrity,
version, version,
} }
if (Object.keys(subdeps).length > 0) { if (Object.keys(subdeps).length > 0) {

View File

@ -59,6 +59,7 @@ describe('audit', () => {
version: '1.0.0', version: '1.0.0',
}, },
}, },
dev: false,
requires: { requires: {
foo: '1.0.0', foo: '1.0.0',
}, },
@ -125,6 +126,7 @@ describe('audit', () => {
version: '1.0.0', version: '1.0.0',
}, },
}, },
dev: false,
requires: { requires: {
foo: '1.0.0', foo: '1.0.0',
}, },

View File

@ -45,5 +45,6 @@
{ {
"path": "../lockfile-walker" "path": "../lockfile-walker"
} }
] ],
"composite": true
} }

View File

@ -33,5 +33,6 @@
{ {
"path": "../lockfile-walker" "path": "../lockfile-walker"
} }
] ],
"composite": true
} }

View File

@ -239,7 +239,7 @@ function revertProjectSnapshot (from: InlineSpecifiersProjectSnapshot): ProjectS
} }
function mapValues<T, U> (obj: Record<string, T>, mapper: (val: T, key: string) => U): Record<string, U> { function mapValues<T, U> (obj: Record<string, T>, mapper: (val: T, key: string) => U): Record<string, U> {
const result = {} const result: Record<string, U> = {}
for (const [key, value] of Object.entries(obj)) { for (const [key, value] of Object.entries(obj)) {
result[key] = mapper(value, key) result[key] = mapper(value, key)
} }

View File

@ -145,7 +145,7 @@ export function createLockfileObject (
specifiers: {}, specifiers: {},
} }
return acc return acc
}, {}) }, {} as Lockfile['importers'])
return { return {
importers, importers,
lockfileVersion: opts.lockfileVersion || LOCKFILE_VERSION, lockfileVersion: opts.lockfileVersion || LOCKFILE_VERSION,

View File

@ -77,9 +77,9 @@ export function sortLockfileKeys (lockfile: LockfileFile) {
}) })
} }
} }
for (const key of ['specifiers', 'dependencies', 'devDependencies', 'optionalDependencies', 'time']) { for (const key of ['specifiers', 'dependencies', 'devDependencies', 'optionalDependencies', 'time'] as const) {
if (!lockfile[key]) continue if (!lockfile[key]) continue
lockfile[key] = sortKeys(lockfile[key]) lockfile[key] = sortKeys(lockfile[key]!)
} }
return sortKeys(lockfile, { compare: compareRootKeys }) return sortKeys(lockfile, { compare: compareRootKeys })
} }

View File

@ -177,9 +177,8 @@ function pruneTimeInLockfileV6 (time: Record<string, string>, importers: Record<
for (const importer of Object.values(importers)) { for (const importer of Object.values(importers)) {
for (const depType of DEPENDENCIES_FIELDS) { for (const depType of DEPENDENCIES_FIELDS) {
for (let [depName, ref] of Object.entries(importer[depType] ?? {})) { for (let [depName, ref] of Object.entries(importer[depType] ?? {})) {
if (ref['version']) { // @ts-expect-error
ref = ref['version'] if (ref['version']) ref = ref['version']
}
const suffixStart = ref.indexOf('(') const suffixStart = ref.indexOf('(')
const refWithoutPeerSuffix = suffixStart === -1 ? ref : ref.slice(0, suffixStart) const refWithoutPeerSuffix = suffixStart === -1 ? ref : ref.slice(0, suffixStart)
const depPath = refToRelative(refWithoutPeerSuffix, depName) const depPath = refToRelative(refWithoutPeerSuffix, depName)
@ -212,9 +211,8 @@ function pruneTime (time: Record<string, string>, importers: Record<string, Proj
for (const importer of Object.values(importers)) { for (const importer of Object.values(importers)) {
for (const depType of DEPENDENCIES_FIELDS) { for (const depType of DEPENDENCIES_FIELDS) {
for (let [depName, ref] of Object.entries(importer[depType] ?? {})) { for (let [depName, ref] of Object.entries(importer[depType] ?? {})) {
if (ref['version']) { // @ts-expect-error
ref = ref['version'] if (ref['version']) ref = ref['version']
}
const suffixStart = ref.indexOf('_') const suffixStart = ref.indexOf('_')
const refWithoutPeerSuffix = suffixStart === -1 ? ref : ref.slice(0, suffixStart) const refWithoutPeerSuffix = suffixStart === -1 ? ref : ref.slice(0, suffixStart)
const depPath = dp.refToRelative(refWithoutPeerSuffix, depName) const depPath = dp.refToRelative(refWithoutPeerSuffix, depName)

View File

@ -6,7 +6,7 @@ jest.mock('@pnpm/git-utils', () => ({ getCurrentBranch: jest.fn() }))
describe('lockfileName', () => { describe('lockfileName', () => {
afterEach(() => { afterEach(() => {
getCurrentBranch['mockReset']() (getCurrentBranch as jest.Mock).mockReset()
}) })
test('returns default lockfile name if useGitBranchLockfile is off', async () => { test('returns default lockfile name if useGitBranchLockfile is off', async () => {
@ -14,17 +14,17 @@ describe('lockfileName', () => {
}) })
test('returns git branch lockfile name', async () => { test('returns git branch lockfile name', async () => {
getCurrentBranch['mockReturnValue']('main') (getCurrentBranch as jest.Mock).mockReturnValue('main')
await expect(getWantedLockfileName({ useGitBranchLockfile: true })).resolves.toBe('pnpm-lock.main.yaml') await expect(getWantedLockfileName({ useGitBranchLockfile: true })).resolves.toBe('pnpm-lock.main.yaml')
}) })
test('returns git branch lockfile name when git branch contains clashes', async () => { test('returns git branch lockfile name when git branch contains clashes', async () => {
getCurrentBranch['mockReturnValue']('a/b/c') (getCurrentBranch as jest.Mock).mockReturnValue('a/b/c')
await expect(getWantedLockfileName({ useGitBranchLockfile: true })).resolves.toBe('pnpm-lock.a!b!c.yaml') await expect(getWantedLockfileName({ useGitBranchLockfile: true })).resolves.toBe('pnpm-lock.a!b!c.yaml')
}) })
test('returns git branch lockfile name when git branch contains uppercase', async () => { test('returns git branch lockfile name when git branch contains uppercase', async () => {
getCurrentBranch['mockReturnValue']('aBc') (getCurrentBranch as jest.Mock).mockReturnValue('aBc')
await expect(getWantedLockfileName({ useGitBranchLockfile: true })).resolves.toBe('pnpm-lock.abc.yaml') await expect(getWantedLockfileName({ useGitBranchLockfile: true })).resolves.toBe('pnpm-lock.abc.yaml')
}) })
}) })

View File

@ -196,7 +196,7 @@ test('existsWantedLockfile()', async () => {
}) })
test('readWantedLockfile() when useGitBranchLockfile', async () => { test('readWantedLockfile() when useGitBranchLockfile', async () => {
getCurrentBranch['mockReturnValue']('branch') (getCurrentBranch as jest.Mock).mockReturnValue('branch')
const lockfile = await readWantedLockfile(path.join('fixtures', '6'), { const lockfile = await readWantedLockfile(path.join('fixtures', '6'), {
ignoreIncompatible: false, ignoreIncompatible: false,
}) })
@ -236,7 +236,7 @@ test('readWantedLockfile() when useGitBranchLockfile', async () => {
}) })
test('readWantedLockfile() when useGitBranchLockfile and mergeGitBranchLockfiles', async () => { test('readWantedLockfile() when useGitBranchLockfile and mergeGitBranchLockfiles', async () => {
getCurrentBranch['mockReturnValue']('branch') (getCurrentBranch as jest.Mock).mockReturnValue('branch')
const lockfile = await readWantedLockfile(path.join('fixtures', '6'), { const lockfile = await readWantedLockfile(path.join('fixtures', '6'), {
ignoreIncompatible: false, ignoreIncompatible: false,
useGitBranchLockfile: true, useGitBranchLockfile: true,

View File

@ -198,7 +198,7 @@ test('writeLockfiles() does not fail if the lockfile has undefined properties',
test('writeLockfiles() when useGitBranchLockfile', async () => { test('writeLockfiles() when useGitBranchLockfile', async () => {
const branchName: string = 'branch' const branchName: string = 'branch'
getCurrentBranch['mockReturnValue'](branchName) ;(getCurrentBranch as jest.Mock).mockReturnValue(branchName)
const projectPath = tempy.directory() const projectPath = tempy.directory()
const wantedLockfile = { const wantedLockfile = {
importers: { importers: {

View File

@ -30,5 +30,6 @@
{ {
"path": "../merge-lockfile-changes" "path": "../merge-lockfile-changes"
} }
] ],
"composite": true
} }

View File

@ -21,5 +21,6 @@
{ {
"path": "../lockfile-utils" "path": "../lockfile-utils"
} }
] ],
"composite": true
} }

View File

@ -91,7 +91,7 @@ export interface PackageSnapshot {
} }
transitivePeerDependencies?: string[] transitivePeerDependencies?: string[]
bundledDependencies?: string[] bundledDependencies?: string[]
engines?: { engines?: Record<string, string> & {
node: string node: string
} }
os?: string[] os?: string[]

View File

@ -1,5 +1,6 @@
{ {
"extends": "@pnpm/tsconfig", "extends": "@pnpm/tsconfig",
"composite": true,
"compilerOptions": { "compilerOptions": {
"outDir": "lib", "outDir": "lib",
"rootDir": "src" "rootDir": "src"

View File

@ -1,5 +1,5 @@
import path from 'path' import path from 'path'
import { Lockfile } from '@pnpm/lockfile-types' import { Lockfile, TarballResolution } from '@pnpm/lockfile-types'
import { depPathToFilename } from '@pnpm/dependency-path' import { depPathToFilename } from '@pnpm/dependency-path'
type GetLocalLocations = (depPath: string, pkgName: string) => string[] type GetLocalLocations = (depPath: string, pkgName: string) => string[]
@ -19,7 +19,7 @@ export function extendProjectsWithTargetDirs<T> (
Object.fromEntries(projects.map((project) => [project.id, { ...project, targetDirs: [] as string[] }])) Object.fromEntries(projects.map((project) => [project.id, { ...project, targetDirs: [] as string[] }]))
Object.entries(lockfile.packages ?? {}) Object.entries(lockfile.packages ?? {})
.forEach(([depPath, pkg]) => { .forEach(([depPath, pkg]) => {
if (pkg.resolution?.['type'] !== 'directory') return if ((pkg.resolution as TarballResolution)?.type !== 'directory') return
const pkgId = pkg.id ?? depPath const pkgId = pkg.id ?? depPath
const importerId = pkgId.replace(/^file:/, '') const importerId = pkgId.replace(/^file:/, '')
if (projectsById[importerId] == null) return if (projectsById[importerId] == null) return

View File

@ -1,5 +1,5 @@
import url from 'url' import url from 'url'
import { PackageSnapshot } from '@pnpm/lockfile-types' import { PackageSnapshot, TarballResolution } from '@pnpm/lockfile-types'
import { Resolution } from '@pnpm/resolver-base' import { Resolution } from '@pnpm/resolver-base'
import { Registries } from '@pnpm/types' import { Registries } from '@pnpm/types'
import * as dp from '@pnpm/dependency-path' import * as dp from '@pnpm/dependency-path'
@ -11,18 +11,21 @@ export function pkgSnapshotToResolution (
pkgSnapshot: PackageSnapshot, pkgSnapshot: PackageSnapshot,
registries: Registries registries: Registries
): Resolution { ): Resolution {
if (pkgSnapshot.resolution['type'] || pkgSnapshot.resolution['tarball']?.startsWith('file:')) { if (
Boolean((pkgSnapshot.resolution as TarballResolution).type) ||
(pkgSnapshot.resolution as TarballResolution).tarball?.startsWith('file:')
) {
return pkgSnapshot.resolution as Resolution return pkgSnapshot.resolution as Resolution
} }
const { name } = nameVerFromPkgSnapshot(depPath, pkgSnapshot) const { name } = nameVerFromPkgSnapshot(depPath, pkgSnapshot)
const registry: string = pkgSnapshot.resolution['registry'] || const registry: string = (pkgSnapshot.resolution as TarballResolution).registry || // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing
(name[0] === '@' && registries[name.split('/')[0]]) || (name[0] === '@' && registries[name.split('/')[0]]) ||
registries.default registries.default
let tarball!: string let tarball!: string
if (!pkgSnapshot.resolution['tarball']) { if (!(pkgSnapshot.resolution as TarballResolution).tarball) {
tarball = getTarball(registry) tarball = getTarball(registry)
} else { } else {
tarball = new url.URL(pkgSnapshot.resolution['tarball'], tarball = new url.URL((pkgSnapshot.resolution as TarballResolution).tarball,
registry.endsWith('/') ? registry : `${registry}/` registry.endsWith('/') ? registry : `${registry}/`
).toString() ).toString()
} }

View File

@ -21,5 +21,6 @@
{ {
"path": "../lockfile-types" "path": "../lockfile-types"
} }
] ],
"composite": true
} }

View File

@ -18,5 +18,6 @@
{ {
"path": "../lockfile-types" "path": "../lockfile-types"
} }
] ],
"composite": true
} }

View File

@ -1,4 +1,4 @@
import { Lockfile } from '@pnpm/lockfile-types' import { Lockfile, PackageSnapshot, PackageSnapshots } from '@pnpm/lockfile-types'
import comverToSemver from 'comver-to-semver' import comverToSemver from 'comver-to-semver'
import semver from 'semver' import semver from 'semver'
@ -14,13 +14,13 @@ export function mergeLockfileChanges (ours: Lockfile, theirs: Lockfile) {
newLockfile.importers[importerId] = { newLockfile.importers[importerId] = {
specifiers: {}, specifiers: {},
} }
for (const key of ['dependencies', 'devDependencies', 'optionalDependencies']) { for (const key of ['dependencies', 'devDependencies', 'optionalDependencies'] as const) {
newLockfile.importers[importerId][key] = mergeDict( newLockfile.importers[importerId][key] = mergeDict(
ours.importers[importerId]?.[key] ?? {}, ours.importers[importerId]?.[key] ?? {},
theirs.importers[importerId]?.[key] ?? {}, theirs.importers[importerId]?.[key] ?? {},
mergeVersions mergeVersions
) )
if (Object.keys(newLockfile.importers[importerId][key]).length === 0) { if (Object.keys(newLockfile.importers[importerId][key] ?? {}).length === 0) {
delete newLockfile.importers[importerId][key] delete newLockfile.importers[importerId][key]
} }
} }
@ -31,7 +31,7 @@ export function mergeLockfileChanges (ours: Lockfile, theirs: Lockfile) {
) )
} }
const packages = {} const packages: PackageSnapshots = {}
for (const depPath of Array.from(new Set([...Object.keys(ours.packages ?? {}), ...Object.keys(theirs.packages ?? {})]))) { for (const depPath of Array.from(new Set([...Object.keys(ours.packages ?? {}), ...Object.keys(theirs.packages ?? {})]))) {
const ourPkg = ours.packages?.[depPath] const ourPkg = ours.packages?.[depPath]
const theirPkg = theirs.packages?.[depPath] const theirPkg = theirs.packages?.[depPath]
@ -39,17 +39,17 @@ export function mergeLockfileChanges (ours: Lockfile, theirs: Lockfile) {
...ourPkg, ...ourPkg,
...theirPkg, ...theirPkg,
} }
for (const key of ['dependencies', 'optionalDependencies']) { for (const key of ['dependencies', 'optionalDependencies'] as const) {
pkg[key] = mergeDict( pkg[key] = mergeDict(
ourPkg?.[key] ?? {}, ourPkg?.[key] ?? {},
theirPkg?.[key] ?? {}, theirPkg?.[key] ?? {},
mergeVersions mergeVersions
) )
if (Object.keys(pkg[key]).length === 0) { if (Object.keys(pkg[key] ?? {}).length === 0) {
delete pkg[key] delete pkg[key]
} }
} }
packages[depPath] = pkg packages[depPath] = pkg as PackageSnapshot
} }
newLockfile.packages = packages newLockfile.packages = packages
@ -63,7 +63,7 @@ function mergeDict<T> (
theirDict: Record<string, T>, theirDict: Record<string, T>,
valueMerger: ValueMerger<T> valueMerger: ValueMerger<T>
) { ) {
const newDict = {} const newDict: Record<string, T> = {}
for (const key of Object.keys(ourDict).concat(Object.keys(theirDict))) { for (const key of Object.keys(ourDict).concat(Object.keys(theirDict))) {
const changedValue = valueMerger( const changedValue = valueMerger(
ourDict[key], ourDict[key],

View File

@ -12,5 +12,6 @@
{ {
"path": "../lockfile-types" "path": "../lockfile-types"
} }
] ],
"composite": true
} }

View File

@ -2,7 +2,8 @@
"extends": "@pnpm/tsconfig", "extends": "@pnpm/tsconfig",
"compilerOptions": { "compilerOptions": {
"outDir": "lib", "outDir": "lib",
"rootDir": "src" "rootDir": "src",
"suppressImplicitAnyIndexErrors": true
}, },
"include": [ "include": [
"src/**/*.ts", "src/**/*.ts",
@ -42,5 +43,6 @@
{ {
"path": "../lockfile-file" "path": "../lockfile-file"
} }
] ],
"composite": true
} }

View File

@ -52,18 +52,18 @@ export function pruneLockfile (
const optionalDependencies = Object.keys(pkg.optionalDependencies ?? {}) const optionalDependencies = Object.keys(pkg.optionalDependencies ?? {})
const dependencies = difference(Object.keys(pkg.dependencies ?? {}), optionalDependencies) const dependencies = difference(Object.keys(pkg.dependencies ?? {}), optionalDependencies)
const devDependencies = difference(difference(Object.keys(pkg.devDependencies ?? {}), optionalDependencies), dependencies) const devDependencies = difference(difference(Object.keys(pkg.devDependencies ?? {}), optionalDependencies), dependencies)
const allDeps = [ const allDeps = new Set([
...optionalDependencies, ...optionalDependencies,
...devDependencies, ...devDependencies,
...dependencies, ...dependencies,
] ])
const specifiers: ResolvedDependencies = {} const specifiers: ResolvedDependencies = {}
const lockfileDependencies: ResolvedDependencies = {} const lockfileDependencies: ResolvedDependencies = {}
const lockfileOptionalDependencies: ResolvedDependencies = {} const lockfileOptionalDependencies: ResolvedDependencies = {}
const lockfileDevDependencies: ResolvedDependencies = {} const lockfileDevDependencies: ResolvedDependencies = {}
Object.entries(lockfileSpecs).forEach(([depName, spec]) => { Object.entries(lockfileSpecs).forEach(([depName, spec]) => {
if (!allDeps.includes(depName)) return if (!allDeps.has(depName)) return
specifiers[depName] = spec specifiers[depName] = spec
if (importer.dependencies?.[depName]) { if (importer.dependencies?.[depName]) {
lockfileDependencies[depName] = importer.dependencies[depName] lockfileDependencies[depName] = importer.dependencies[depName]
@ -79,7 +79,7 @@ export function pruneLockfile (
!lockfileDependencies[alias] && dep.startsWith('link:') && !lockfileDependencies[alias] && dep.startsWith('link:') &&
// If the linked dependency was removed from package.json // If the linked dependency was removed from package.json
// then it is removed from pnpm-lock.yaml as well // then it is removed from pnpm-lock.yaml as well
!(lockfileSpecs[alias] && !allDeps[alias]) !(lockfileSpecs[alias] && !allDeps.has(alias))
) { ) {
lockfileDependencies[alias] = dep lockfileDependencies[alias] = dep
} }

View File

@ -21,5 +21,6 @@
{ {
"path": "../lockfile-types" "path": "../lockfile-types"
} }
] ],
"composite": true
} }

Some files were not shown because too many files have changed in this diff Show More