mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-23 23:29:17 -05:00
fix: add support for npm lockfile v3 in import (#6931)
closes #6233 --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
6
.changeset/hungry-geckos-roll.md
Normal file
6
.changeset/hungry-geckos-roll.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-installation": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Add support for npm lockfile v3 in `pnpm import` [#6233](https://github.com/pnpm/pnpm/issues/6233).
|
||||
1
__fixtures__/has-package-lock-v3-json/.gitignore
vendored
Normal file
1
__fixtures__/has-package-lock-v3-json/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!package-lock.json
|
||||
22
__fixtures__/has-package-lock-v3-json/package-lock.json
generated
Normal file
22
__fixtures__/has-package-lock-v3-json/package-lock.json
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "has-package-lock-json",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@pnpm.e2e/pkg-with-1-dep": "100.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@pnpm.e2e/dep-of-pkg-with-1-dep": {
|
||||
"version": "101.0.0"
|
||||
},
|
||||
"node_modules/@pnpm.e2e/pkg-with-1-dep": {
|
||||
"version": "100.0.0",
|
||||
"dependencies": {
|
||||
"@pnpm.e2e/dep-of-pkg-with-1-dep": "100.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
__fixtures__/has-package-lock-v3-json/package.json
Normal file
11
__fixtures__/has-package-lock-v3-json/package.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "has-package-lock-v3-json",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@pnpm.e2e/dep-of-pkg-with-1-dep": "^101.0.0",
|
||||
"@pnpm.e2e/pkg-with-1-dep": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "exit 1"
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ packages:
|
||||
- '!has-npm-shrinkwrap-json'
|
||||
- '!has-outdated-deps'
|
||||
- '!has-package-lock-json'
|
||||
- '!has-package-lock-v3-json'
|
||||
- '!hello-world-js-bin'
|
||||
- '!has-yarn-lock'
|
||||
- '!has-yarn2-lock'
|
||||
|
||||
@@ -28,11 +28,20 @@ import { yarnLockFileKeyNormalizer } from './yarnUtil'
|
||||
|
||||
interface NpmPackageLock {
|
||||
dependencies: LockedPackagesMap
|
||||
packages: LockedPackagesMap
|
||||
name?: string
|
||||
}
|
||||
|
||||
interface LockedPackage {
|
||||
version: string
|
||||
dependencies?: LockedPackagesMap
|
||||
lockfileVersion: number
|
||||
name?: string
|
||||
dependencies?: LockedPackagesMap | SimpleDependenciesMap
|
||||
packages?: LockedPackagesMap
|
||||
}
|
||||
|
||||
interface SimpleDependenciesMap {
|
||||
[name: string]: string
|
||||
}
|
||||
|
||||
interface LockedPackagesMap {
|
||||
@@ -109,7 +118,11 @@ export async function handler (
|
||||
await exists(path.join(opts.dir, 'npm-shrinkwrap.json'))
|
||||
) {
|
||||
const npmPackageLock = await readNpmLockfile(opts.dir)
|
||||
getAllVersionsByPackageNames(npmPackageLock, versionsByPackageNames)
|
||||
if (npmPackageLock.lockfileVersion < 3) {
|
||||
getAllVersionsByPackageNamesPreV3(npmPackageLock, versionsByPackageNames)
|
||||
} else {
|
||||
getAllVersionsByPackageNames(npmPackageLock, versionsByPackageNames)
|
||||
}
|
||||
} else {
|
||||
throw new PnpmError('LOCKFILE_NOT_FOUND', 'No lockfile found')
|
||||
}
|
||||
@@ -224,7 +237,7 @@ async function readNpmLockfile (dir: string) {
|
||||
throw new PnpmError('NPM_LOCKFILE_NOT_FOUND', 'No package-lock.json or npm-shrinkwrap.json found')
|
||||
}
|
||||
|
||||
function getPreferredVersions (versionsByPackageNames: Record<string, Set<string>>) {
|
||||
function getPreferredVersions (versionsByPackageNames: VersionsByPackageNames) {
|
||||
const preferredVersions = mapValues(
|
||||
(versions) => Object.fromEntries(Array.from(versions).map((version) => [version, 'version'])),
|
||||
versionsByPackageNames
|
||||
@@ -232,11 +245,11 @@ function getPreferredVersions (versionsByPackageNames: Record<string, Set<string
|
||||
return preferredVersions
|
||||
}
|
||||
|
||||
function getAllVersionsByPackageNames (
|
||||
type VersionsByPackageNames = Record<string, Set<string>>
|
||||
|
||||
function getAllVersionsByPackageNamesPreV3 (
|
||||
npmPackageLock: NpmPackageLock | LockedPackage,
|
||||
versionsByPackageNames: {
|
||||
[packageName: string]: Set<string>
|
||||
}
|
||||
versionsByPackageNames: VersionsByPackageNames
|
||||
) {
|
||||
if (npmPackageLock.dependencies == null) return
|
||||
for (const [packageName, { version }] of Object.entries(npmPackageLock.dependencies)) {
|
||||
@@ -246,7 +259,48 @@ function getAllVersionsByPackageNames (
|
||||
versionsByPackageNames[packageName].add(version)
|
||||
}
|
||||
for (const dep of Object.values(npmPackageLock.dependencies)) {
|
||||
getAllVersionsByPackageNames(dep, versionsByPackageNames)
|
||||
getAllVersionsByPackageNamesPreV3(dep, versionsByPackageNames)
|
||||
}
|
||||
}
|
||||
|
||||
function getAllVersionsByPackageNames (
|
||||
pkg: NpmPackageLock | LockedPackage,
|
||||
versionsByPackageNames: VersionsByPackageNames
|
||||
): void {
|
||||
if (pkg.dependencies) {
|
||||
extractDependencies(versionsByPackageNames, pkg.dependencies as LockedPackagesMap)
|
||||
}
|
||||
if ('packages' in pkg && pkg.packages) {
|
||||
extractDependencies(versionsByPackageNames, pkg.packages)
|
||||
}
|
||||
}
|
||||
|
||||
function extractDependencies (
|
||||
versionsByPackageNames: VersionsByPackageNames,
|
||||
dependencies: LockedPackagesMap
|
||||
): void {
|
||||
for (let [pkgName, pkgDetails] of Object.entries(dependencies)) {
|
||||
if (pkgName.includes('node_modules')) {
|
||||
pkgName = pkgName.substring(pkgName.lastIndexOf('node_modules/') + 13)
|
||||
}
|
||||
if (!versionsByPackageNames[pkgName]) {
|
||||
versionsByPackageNames[pkgName] = new Set<string>()
|
||||
}
|
||||
if (pkgDetails.version) {
|
||||
versionsByPackageNames[pkgName].add(pkgDetails.version)
|
||||
}
|
||||
|
||||
if (pkgDetails.packages) {
|
||||
extractDependencies(versionsByPackageNames, pkgDetails.packages)
|
||||
}
|
||||
if (pkgDetails.dependencies) {
|
||||
for (const [pkgName1, version] of Object.entries(pkgDetails.dependencies)) {
|
||||
if (!versionsByPackageNames[pkgName1]) {
|
||||
versionsByPackageNames[pkgName1] = new Set<string>()
|
||||
}
|
||||
versionsByPackageNames[pkgName1].add(version)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,3 +131,22 @@ test('import fails when no lockfiles are found', async () => {
|
||||
new PnpmError('LOCKFILE_NOT_FOUND', 'No lockfile found')
|
||||
)
|
||||
})
|
||||
|
||||
test('import from package-lock.json v3', async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/dep-of-pkg-with-1-dep', version: '100.1.0', distTag: 'latest' })
|
||||
f.prepare('has-package-lock-v3-json')
|
||||
|
||||
await importCommand.handler({
|
||||
...DEFAULT_OPTS,
|
||||
dir: process.cwd(),
|
||||
}, [])
|
||||
|
||||
const project = assertProject(process.cwd())
|
||||
const lockfile = await project.readLockfile()
|
||||
expect(lockfile.packages).toHaveProperty(['/@pnpm.e2e/dep-of-pkg-with-1-dep@100.0.0'])
|
||||
expect(lockfile.packages).not.toHaveProperty(['/@pnpm.e2e/dep-of-pkg-with-1-dep@100.1.0'])
|
||||
|
||||
// node_modules is not created
|
||||
await project.hasNot('@pnpm.e2e/dep-of-pkg-with-1-dep')
|
||||
await project.hasNot('@pnpm.e2e/pkg-with-1-dep')
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user