Skip to content

pnpm lock parser: peer-dep suffixed keys produce duplicate/incorrect entries #21

@julienp

Description

@julienp

When pnpm resolves a package against different sets of peer dependencies, it records multiple snapshots of the same package using a suffix notation, e.g.:

debug@2.2.0(supports-color@1.2.0):

The parser currently splits on the last @ to extract the version, which lands inside the suffix instead of at the version boundary. The result is a bogus dependency name like debug@2.2.0(supports-color with version 1.2.0).

In npm-land we can also have multiple versions of a package in the lockfile, how should that be represented in the results?

Test program
package main

import (
"fmt"
"os"
"os/exec"
"strings"

"github.com/git-pkgs/manifests"

)

const packageJSON = { "name": "pnpm-issue-repro", "dependencies": { "mocha": "2.5.3", "supports-color": "1.2.0", "debug": "^4.0.0" } }

func main() {
dir, err := os.MkdirTemp("", "pnpm-issue-*")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
fmt.Println("working dir:", dir)

if err := os.WriteFile(dir+"/package.json", []byte(packageJSON), 0644); err != nil {
	panic(err)
}

fmt.Println("running pnpm install...")
cmd := exec.Command("pnpm", "install", "--no-frozen-lockfile")
cmd.Dir = dir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
	panic(err)
}

content, err := os.ReadFile(dir + "/pnpm-lock.yaml")
if err != nil {
	panic(err)
}

fmt.Println("\n--- relevant lockfile lines ---")
for _, line := range strings.Split(string(content), "\n") {
	if strings.Contains(line, "debug") {
		fmt.Println(line)
	}
}

fmt.Println("\n--- parse results (via manifests library) ---")
result, err := manifests.Parse("pnpm-lock.yaml", content)
if err != nil {
	panic(err)
}
for _, dep := range result.Dependencies {
	if strings.Contains(dep.Name, "debug") || strings.Contains(dep.Name, "supports-color") {
		fmt.Printf("  name=%-45s version=%s\n", dep.Name, dep.Version)
	}
}

}

--- relevant lockfile lines ---
      debug:
  debug@2.2.0:
  debug@4.4.3:
  debug@2.2.0(supports-color@1.2.0):
  debug@4.4.3(supports-color@1.2.0):
      debug: 2.2.0(supports-color@1.2.0)

--- parse results (via manifests library) ---
  name=debug                                         version=2.2.0
  name=supports-color                                version=1.2.0
  name=debug@2.2.0(supports-color                    version=1.2.0)
  name=debug@4.4.3(supports-color                    version=1.2.0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions