Add support for package.json #200

Signed-off-by: Toure Dunnon <toure.dunnon@anchore.com>
This commit is contained in:
Toure Dunnon 2020-10-14 16:04:52 -04:00
parent 4c751cb1d4
commit 27c62e34f2
18 changed files with 857 additions and 109 deletions

View file

@ -130,7 +130,9 @@ unit: fixtures ## Run unit tests (with coverage)
.PHONY: integration
integration: ## Run integration tests
$(call title,Running integration tests)
go test -tags=integration -v ./test/integration
go test -v ./test/integration
# note: this is used by CI to determine if the integration test fixture cache (docker image tars) should be busted
integration-fingerprint:

9
schema/README.md Normal file
View file

@ -0,0 +1,9 @@
## Updating the JSON schema
Today the JSON schema is generated from integration test data. Specifically, when integration tests are run, the `/schema/json/examples` directory is populated with syft JSON output data. This examples directory is used to drive automatically generating the JSON schema.
The caveats with this approach is:
1) the JSON schema is only as good as the examples provided
2) there is an integration test that ensures that the JSON schema is valid relative to what the code currently generates.
This means to update the JSON schema you need to
1) Open up `test/integration/json_schema_test.go` and comment out invocations of the `validateAgainstV1Schema` function.
2) From the root of the repo run `generate-json-schema`. Now there should be a new schema generated at `/schema/json/schema.json`
3) Uncomment the `validateAgainstV1Schema` function.

View file

@ -40,6 +40,9 @@
"architecture": {
"type": "string"
},
"author": {
"type": "string"
},
"description": {
"type": "string"
},
@ -47,41 +50,48 @@
"type": "integer"
},
"files": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"properties": {
"checksum": {
"anyOf": [
{
"type": "null"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
"ownerGid": {
"type": "string"
},
"ownerUid": {
"type": "string"
},
"path": {
"type": "string"
},
"permissions": {
"type": "string"
{
"properties": {
"checksum": {
"type": "string"
},
"ownerGid": {
"type": "string"
},
"ownerUid": {
"type": "string"
},
"path": {
"type": "string"
},
"permissions": {
"type": "string"
}
},
"required": [
"checksum",
"ownerGid",
"ownerUid",
"path",
"permissions"
],
"type": "object"
}
},
"required": [
"checksum",
"ownerGid",
"ownerUid",
"path",
"permissions"
],
"type": "object"
}
]
},
"type": "array"
]
},
"type": "array"
}
]
},
"gitCommitOfApkPort": {
"type": "string"

View file

@ -37,8 +37,8 @@ type Cataloger interface {
func ImageCatalogers() []Cataloger {
return []Cataloger{
ruby.NewGemSpecCataloger(),
python.NewPythonCataloger(), // TODO: split and replace me
javascript.NewJavascriptCataloger(), // TODO: split and replace me
python.NewPythonCataloger(), // TODO: split and replace me
javascript.NewJavascriptPackageCataloger(),
deb.NewDpkgdbCataloger(),
rpmdb.NewRpmdbCataloger(),
java.NewJavaCataloger(),
@ -51,8 +51,8 @@ func ImageCatalogers() []Cataloger {
func DirectoryCatalogers() []Cataloger {
return []Cataloger{
ruby.NewGemFileLockCataloger(),
python.NewPythonCataloger(), // TODO: split and replace me
javascript.NewJavascriptCataloger(), // TODO: split and replace me
python.NewPythonCataloger(), // TODO: split and replace me
javascript.NewJavascriptLockCataloger(),
deb.NewDpkgdbCataloger(),
rpmdb.NewRpmdbCataloger(),
java.NewJavaCataloger(),

View file

@ -7,12 +7,21 @@ import (
"github.com/anchore/syft/syft/cataloger/common"
)
// NewJavascriptCataloger returns a new JavaScript cataloger object.
func NewJavascriptCataloger() *common.GenericCataloger {
// NewJavascriptPackageCataloger returns a new JavaScript cataloger object based on detection of npm based packages.
func NewJavascriptPackageCataloger() *common.GenericCataloger {
globParsers := map[string]common.ParserFn{
"**/package.json": parsePackageJSON,
}
return common.NewGenericCataloger(nil, globParsers, "javascript-package-cataloger")
}
// NewJavascriptLockCataloger returns a new Javascript cataloger object base on package lock files.
func NewJavascriptLockCataloger() *common.GenericCataloger {
globParsers := map[string]common.ParserFn{
"**/package-lock.json": parsePackageLock,
"**/yarn.lock": parseYarnLock,
}
return common.NewGenericCataloger(nil, globParsers, "javascript-cataloger")
return common.NewGenericCataloger(nil, globParsers, "javascript-lock-cataloger")
}

View file

@ -0,0 +1,54 @@
package javascript
import (
"encoding/json"
"fmt"
"io"
"github.com/anchore/syft/syft/cataloger/common"
"github.com/anchore/syft/syft/pkg"
)
// integrity check
var _ common.ParserFn = parsePackageLock
// PackageJSON represents a JavaScript package.json file
type PackageJSON struct {
Version string `json:"version"`
Latest []string `json:"latest"`
Author string `json:"author"`
License string `json:"license"`
Name string `json:"name"`
Homepage string `json:"homepage"`
Description string `json:"description"`
Dependencies map[string]string `json:"dependencies"`
}
// parsePackageJson parses a package.json and returns the discovered JavaScript packages.
func parsePackageJSON(_ string, reader io.Reader) ([]pkg.Package, error) {
packages := make([]pkg.Package, 0)
dec := json.NewDecoder(reader)
for {
var p PackageJSON
if err := dec.Decode(&p); err == io.EOF {
break
} else if err != nil {
return nil, fmt.Errorf("failed to parse package.json file: %w", err)
}
packages = append(packages, pkg.Package{
Name: p.Name,
Version: p.Version,
Licenses: []string{p.License},
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Metadata: pkg.NpmMetadata{
Author: p.Author,
Homepage: p.Homepage,
},
})
}
return packages, nil
}

View file

@ -0,0 +1,43 @@
package javascript
import (
"os"
"testing"
"github.com/anchore/syft/syft/pkg"
"github.com/go-test/deep"
)
func TestParsePackageJSON(t *testing.T) {
expected := pkg.Package{
Name: "npm",
Version: "6.14.6",
Type: pkg.NpmPkg,
Licenses: []string{"Artistic-2.0"},
Language: pkg.JavaScript,
Metadata: pkg.NpmMetadata{
Author: "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
Homepage: "https://docs.npmjs.com/",
},
}
fixture, err := os.Open("test-fixtures/pkg-json/package.json")
if err != nil {
t.Fatalf("failed to open fixture: %+v", err)
}
actual, err := parsePackageJSON(fixture.Name(), fixture)
if err != nil {
t.Fatalf("failed to parse package-lock.json: %+v", err)
}
if len(actual) != 1 {
for _, a := range actual {
t.Log(" ", a)
}
t.Fatalf("unexpected package count: %d!=1", len(actual))
}
for _, d := range deep.Equal(actual[0], expected) {
t.Errorf("diff: %+v", d)
}
}

View file

@ -66,7 +66,7 @@ func parseYarnLock(_ string, reader io.Reader) ([]pkg.Package, error) {
Name: currentName,
Version: strings.Trim(version, "\""),
Language: pkg.JavaScript,
Type: pkg.YarnPkg,
Type: pkg.NpmPkg,
})
}
}

View file

@ -13,43 +13,43 @@ func TestParseYarnLock(t *testing.T) {
Name: "@babel/code-frame",
Version: "7.10.4",
Language: pkg.JavaScript,
Type: pkg.YarnPkg,
Type: pkg.NpmPkg,
},
"@types/minimatch": {
Name: "@types/minimatch",
Version: "3.0.3",
Language: pkg.JavaScript,
Type: pkg.YarnPkg,
Type: pkg.NpmPkg,
},
"@types/qs": {
Name: "@types/qs",
Version: "6.9.4",
Language: pkg.JavaScript,
Type: pkg.YarnPkg,
Type: pkg.NpmPkg,
},
"ajv": {
Name: "ajv",
Version: "6.12.3",
Language: pkg.JavaScript,
Type: pkg.YarnPkg,
Type: pkg.NpmPkg,
},
"atob": {
Name: "atob",
Version: "2.1.2",
Language: pkg.JavaScript,
Type: pkg.YarnPkg,
Type: pkg.NpmPkg,
},
"aws-sdk": {
Name: "aws-sdk",
Version: "2.706.0",
Language: pkg.JavaScript,
Type: pkg.YarnPkg,
Type: pkg.NpmPkg,
},
"jhipster-core": {
Name: "jhipster-core",
Version: "7.3.4",
Language: pkg.JavaScript,
Type: pkg.YarnPkg,
Type: pkg.NpmPkg,
},
}
fixture, err := os.Open("test-fixtures/yarn/yarn.lock")

View file

@ -0,0 +1,314 @@
{
"version": "6.14.6",
"name": "npm",
"description": "a package manager for JavaScript",
"keywords": [
"install",
"modules",
"package manager",
"package.json"
],
"preferGlobal": true,
"config": {
"publishtest": false
},
"homepage": "https://docs.npmjs.com/",
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
"repository": {
"type": "git",
"url": "https://github.com/npm/cli"
},
"bugs": {
"url": "https://npm.community/c/bugs"
},
"directories": {
"bin": "./bin",
"doc": "./doc",
"lib": "./lib",
"man": "./man"
},
"main": "./lib/npm.js",
"bin": {
"npm": "./bin/npm-cli.js",
"npx": "./bin/npx-cli.js"
},
"dependencies": {
"JSONStream": "^1.3.5",
"abbrev": "~1.1.1",
"ansicolors": "~0.3.2",
"ansistyles": "~0.1.3",
"aproba": "^2.0.0",
"archy": "~1.0.0",
"bin-links": "^1.1.7",
"bluebird": "^3.5.5",
"byte-size": "^5.0.1",
"cacache": "^12.0.3",
"call-limit": "^1.1.1",
"chownr": "^1.1.4",
"ci-info": "^2.0.0",
"cli-columns": "^3.1.2",
"cli-table3": "^0.5.1",
"cmd-shim": "^3.0.3",
"columnify": "~1.5.4",
"config-chain": "^1.1.12",
"detect-indent": "~5.0.0",
"detect-newline": "^2.1.0",
"dezalgo": "~1.0.3",
"editor": "~1.0.0",
"figgy-pudding": "^3.5.1",
"find-npm-prefix": "^1.0.2",
"fs-vacuum": "~1.2.10",
"fs-write-stream-atomic": "~1.0.10",
"gentle-fs": "^2.3.0",
"glob": "^7.1.6",
"graceful-fs": "^4.2.4",
"has-unicode": "~2.0.1",
"hosted-git-info": "^2.8.8",
"iferr": "^1.0.2",
"infer-owner": "^1.0.4",
"inflight": "~1.0.6",
"inherits": "^2.0.4",
"ini": "^1.3.5",
"init-package-json": "^1.10.3",
"is-cidr": "^3.0.0",
"json-parse-better-errors": "^1.0.2",
"lazy-property": "~1.0.0",
"libcipm": "^4.0.7",
"libnpm": "^3.0.1",
"libnpmaccess": "^3.0.2",
"libnpmhook": "^5.0.3",
"libnpmorg": "^1.0.1",
"libnpmsearch": "^2.0.2",
"libnpmteam": "^1.0.2",
"libnpx": "^10.2.2",
"lock-verify": "^2.1.0",
"lockfile": "^1.0.4",
"lodash._baseuniq": "~4.6.0",
"lodash.clonedeep": "~4.5.0",
"lodash.union": "~4.6.0",
"lodash.uniq": "~4.5.0",
"lodash.without": "~4.4.0",
"lru-cache": "^5.1.1",
"meant": "~1.0.1",
"mississippi": "^3.0.0",
"mkdirp": "^0.5.5",
"move-concurrently": "^1.0.1",
"node-gyp": "^5.1.0",
"nopt": "^4.0.3",
"normalize-package-data": "^2.5.0",
"npm-audit-report": "^1.3.2",
"npm-cache-filename": "~1.0.2",
"npm-install-checks": "^3.0.2",
"npm-lifecycle": "^3.1.4",
"npm-package-arg": "^6.1.1",
"npm-packlist": "^1.4.8",
"npm-pick-manifest": "^3.0.2",
"npm-profile": "^4.0.4",
"npm-registry-fetch": "^4.0.5",
"npm-user-validate": "~1.0.0",
"npmlog": "~4.1.2",
"once": "~1.4.0",
"opener": "^1.5.1",
"osenv": "^0.1.5",
"pacote": "^9.5.12",
"path-is-inside": "~1.0.2",
"promise-inflight": "~1.0.1",
"qrcode-terminal": "^0.12.0",
"query-string": "^6.8.2",
"qw": "~1.0.1",
"read": "~1.0.7",
"read-cmd-shim": "^1.0.5",
"read-installed": "~4.0.3",
"read-package-json": "^2.1.1",
"read-package-tree": "^5.3.1",
"readable-stream": "^3.6.0",
"readdir-scoped-modules": "^1.1.0",
"request": "^2.88.0",
"retry": "^0.12.0",
"rimraf": "^2.7.1",
"safe-buffer": "^5.1.2",
"semver": "^5.7.1",
"sha": "^3.0.0",
"slide": "~1.1.6",
"sorted-object": "~2.0.1",
"sorted-union-stream": "~2.1.3",
"ssri": "^6.0.1",
"stringify-package": "^1.0.1",
"tar": "^4.4.13",
"text-table": "~0.2.0",
"tiny-relative-date": "^1.3.0",
"uid-number": "0.0.6",
"umask": "~1.1.0",
"unique-filename": "^1.1.1",
"unpipe": "~1.0.0",
"update-notifier": "^2.5.0",
"uuid": "^3.3.3",
"validate-npm-package-license": "^3.0.4",
"validate-npm-package-name": "~3.0.0",
"which": "^1.3.1",
"worker-farm": "^1.7.0",
"write-file-atomic": "^2.4.3"
},
"bundleDependencies": [
"abbrev",
"ansicolors",
"ansistyles",
"aproba",
"archy",
"bin-links",
"bluebird",
"byte-size",
"cacache",
"call-limit",
"chownr",
"ci-info",
"cli-columns",
"cli-table3",
"cmd-shim",
"columnify",
"config-chain",
"debuglog",
"detect-indent",
"detect-newline",
"dezalgo",
"editor",
"figgy-pudding",
"find-npm-prefix",
"fs-vacuum",
"fs-write-stream-atomic",
"gentle-fs",
"glob",
"graceful-fs",
"has-unicode",
"hosted-git-info",
"iferr",
"imurmurhash",
"infer-owner",
"inflight",
"inherits",
"ini",
"init-package-json",
"is-cidr",
"json-parse-better-errors",
"JSONStream",
"lazy-property",
"libcipm",
"libnpm",
"libnpmaccess",
"libnpmhook",
"libnpmorg",
"libnpmsearch",
"libnpmteam",
"libnpx",
"lock-verify",
"lockfile",
"lodash._baseindexof",
"lodash._baseuniq",
"lodash._bindcallback",
"lodash._cacheindexof",
"lodash._createcache",
"lodash._getnative",
"lodash.clonedeep",
"lodash.restparam",
"lodash.union",
"lodash.uniq",
"lodash.without",
"lru-cache",
"meant",
"mississippi",
"mkdirp",
"move-concurrently",
"node-gyp",
"nopt",
"normalize-package-data",
"npm-audit-report",
"npm-cache-filename",
"npm-install-checks",
"npm-lifecycle",
"npm-package-arg",
"npm-packlist",
"npm-pick-manifest",
"npm-profile",
"npm-registry-fetch",
"npm-user-validate",
"npmlog",
"once",
"opener",
"osenv",
"pacote",
"path-is-inside",
"promise-inflight",
"qrcode-terminal",
"query-string",
"qw",
"read-cmd-shim",
"read-installed",
"read-package-json",
"read-package-tree",
"read",
"readable-stream",
"readdir-scoped-modules",
"request",
"retry",
"rimraf",
"safe-buffer",
"semver",
"sha",
"slide",
"sorted-object",
"sorted-union-stream",
"ssri",
"stringify-package",
"tar",
"text-table",
"tiny-relative-date",
"uid-number",
"umask",
"unique-filename",
"unpipe",
"update-notifier",
"uuid",
"validate-npm-package-license",
"validate-npm-package-name",
"which",
"worker-farm",
"write-file-atomic"
],
"devDependencies": {
"deep-equal": "^1.0.1",
"get-stream": "^4.1.0",
"licensee": "^7.0.3",
"marked": "^0.6.3",
"marked-man": "^0.6.0",
"npm-registry-couchapp": "^2.7.4",
"npm-registry-mock": "^1.3.1",
"require-inject": "^1.4.4",
"sprintf-js": "^1.1.2",
"standard": "^11.0.1",
"tacks": "^1.3.0",
"tap": "^12.7.0",
"tar-stream": "^2.1.0"
},
"scripts": {
"dumpconf": "env | grep npm | sort | uniq",
"prepare": "node bin/npm-cli.js rebuild && node bin/npm-cli.js --no-audit --no-timing prune --prefix=. --no-global && rimraf test/*/*/node_modules && make -j4 mandocs",
"preversion": "bash scripts/update-authors.sh && git add AUTHORS && git commit -m \"update AUTHORS\" || true",
"licenses": "licensee --production --errors-only",
"tap": "tap -J --timeout 300 --no-esm",
"tap-cover": "tap -J --nyc-arg=--cache --coverage --timeout 600 --no-esm",
"lint": "standard",
"pretest": "npm run lint",
"test": "npm run test-tap --",
"test:nocleanup": "NO_TEST_CLEANUP=1 npm run test --",
"sudotest": "sudo npm run tap -- \"test/tap/*.js\"",
"sudotest:nocleanup": "sudo NO_TEST_CLEANUP=1 npm run tap -- \"test/tap/*.js\"",
"posttest": "rimraf test/npm_cache*",
"test-coverage": "npm run tap-cover -- \"test/tap/*.js\" \"test/network/*.js\"",
"test-tap": "npm run tap -- \"test/tap/*.js\" \"test/network/*.js\"",
"test-node": "tap --timeout 240 \"test/tap/*.js\" \"test/network/*.js\""
},
"license": "Artistic-2.0",
"engines": {
"node": "6 >=6.2.0 || 8 || >=9.3.0"
}
}

12
syft/pkg/npm_metadata.go Normal file
View file

@ -0,0 +1,12 @@
package pkg
// NpmMetadata holds extra information that is used in pkg.Package
type NpmMetadata struct {
Name string `mapstructure:"name" json:"name"`
Version string `mapstructure:"version" json:"version"`
Files []string `mapstructure:"files" json:"files"`
Author string `mapstructure:"author" json:"author"`
License string `mapstructure:"license" json:"license"`
Homepage string `mapstructure:"homepage" json:"homepage"`
Description string `mapstructure:"description" json:"description"`
}

View file

@ -69,14 +69,6 @@ func TestPackage_pURL(t *testing.T) {
},
expected: "pkg:npm/name@v0.1.0",
},
{
pkg: Package{
Name: "name",
Version: "v0.1.0",
Type: YarnPkg,
},
expected: "pkg:npm/name@v0.1.0",
},
{
distro: distro.Distro{
Type: distro.Ubuntu,

View file

@ -6,17 +6,15 @@ import "github.com/package-url/packageurl-go"
type Type string
const (
UnknownPkg Type = "UnknownPackage"
ApkPkg Type = "apk"
GemPkg Type = "gem"
DebPkg Type = "deb"
EggPkg Type = "egg"
// PacmanPkg Type = "pacman"
UnknownPkg Type = "UnknownPackage"
ApkPkg Type = "apk"
GemPkg Type = "gem"
DebPkg Type = "deb"
EggPkg Type = "egg"
RpmPkg Type = "rpm"
WheelPkg Type = "wheel"
PoetryPkg Type = "poetry"
NpmPkg Type = "npm"
YarnPkg Type = "yarn"
PythonRequirementsPkg Type = "python-requirements"
PythonSetupPkg Type = "python-setup"
JavaPkg Type = "java-archive"
@ -29,11 +27,9 @@ var AllPkgs = []Type{
GemPkg,
DebPkg,
EggPkg,
// PacmanPkg,
RpmPkg,
WheelPkg,
NpmPkg,
YarnPkg,
PythonRequirementsPkg,
PythonSetupPkg,
JavaPkg,
@ -51,7 +47,7 @@ func (t Type) PackageURLType() string {
return "deb"
case EggPkg, WheelPkg, PythonRequirementsPkg, PythonSetupPkg:
return packageurl.TypePyPi
case NpmPkg, YarnPkg:
case NpmPkg:
return packageurl.TypeNPM
case JavaPkg, JenkinsPluginPkg:
return packageurl.TypeMaven

View file

@ -1,5 +1,3 @@
// +build integration
package integration
import (

View file

@ -1,5 +1,3 @@
// +build integration
package integration
import (

View file

@ -1,5 +1,3 @@
// +build integration
package integration
import "github.com/anchore/syft/syft/pkg"
@ -20,6 +18,14 @@ var imageOnlyTestCases = []testCase{
"bundler": "2.1.4",
},
},
{
name: "find npm package",
pkgType: pkg.NpmPkg,
pkgLanguage: pkg.JavaScript,
pkgInfo: map[string]string{
"npm": "6.14.6",
},
},
}
var dirOnlyTestCases = []testCase{
@ -81,6 +87,15 @@ var dirOnlyTestCases = []testCase{
"unicorn": "4.8.3",
},
},
{
name: "find javascript npm packages (yarn.lock & package-lock.json)",
pkgType: pkg.NpmPkg,
pkgLanguage: pkg.JavaScript,
pkgInfo: map[string]string{
"@babel/code-frame": "7.10.4",
"get-stdin": "8.0.0",
},
},
}
var commonTestCases = []testCase{
@ -125,22 +140,6 @@ var commonTestCases = []testCase{
"requests": "2.10.0",
},
},
{
name: "find javascript npm packages",
pkgType: pkg.NpmPkg,
pkgLanguage: pkg.JavaScript,
pkgInfo: map[string]string{
"get-stdin": "8.0.0",
},
},
{
name: "find javascript yarn packages",
pkgType: pkg.YarnPkg,
pkgLanguage: pkg.JavaScript,
pkgInfo: map[string]string{
"@babel/code-frame": "7.10.4",
},
},
{
name: "find python egg packages",
pkgType: pkg.EggPkg,

View file

@ -1,5 +1,3 @@
// +build integration
package integration
import (
@ -123,39 +121,39 @@ func TestPkgCoverageDirectory(t *testing.T) {
cases = append(cases, commonTestCases...)
cases = append(cases, dirOnlyTestCases...)
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
pkgCount := 0
for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
actualPkgCount := 0
for a := range catalog.Enumerate(c.pkgType) {
for actualPkg := range catalog.Enumerate(test.pkgType) {
observedLanguages.Add(a.Language.String())
observedPkgs.Add(string(a.Type))
observedLanguages.Add(actualPkg.Language.String())
observedPkgs.Add(string(actualPkg.Type))
expectedVersion, ok := c.pkgInfo[a.Name]
expectedVersion, ok := test.pkgInfo[actualPkg.Name]
if !ok {
t.Errorf("unexpected package found: %s", a.Name)
t.Errorf("unexpected package found: %s", actualPkg.Name)
}
if expectedVersion != a.Version {
t.Errorf("unexpected package version (pkg=%s): %s", a.Name, a.Version)
if expectedVersion != actualPkg.Version {
t.Errorf("unexpected package version (pkg=%s): %s", actualPkg.Name, actualPkg.Version)
}
if a.Language != c.pkgLanguage {
t.Errorf("bad language (pkg=%+v): %+v", a.Name, a.Language)
if actualPkg.Language != test.pkgLanguage {
t.Errorf("bad language (pkg=%+v): %+v", actualPkg.Name, actualPkg.Language)
}
if a.Type != c.pkgType {
t.Errorf("bad package type (pkg=%+v): %+v", a.Name, a.Type)
if actualPkg.Type != test.pkgType {
t.Errorf("bad package type (pkg=%+v): %+v", actualPkg.Name, actualPkg.Type)
}
pkgCount++
actualPkgCount++
}
if pkgCount != len(c.pkgInfo) {
for a := range catalog.Enumerate(c.pkgType) {
t.Log(" ", a)
if actualPkgCount != len(test.pkgInfo) {
for actualPkg := range catalog.Enumerate(test.pkgType) {
t.Log(" ", actualPkg)
}
t.Fatalf("unexpected package count: %d!=%d", pkgCount, len(c.pkgInfo))
t.Fatalf("unexpected package count: %d!=%d", actualPkgCount, len(test.pkgInfo))
}
})

View file

@ -0,0 +1,314 @@
{
"version": "6.14.6",
"name": "npm",
"description": "a package manager for JavaScript",
"keywords": [
"install",
"modules",
"package manager",
"package.json"
],
"preferGlobal": true,
"config": {
"publishtest": false
},
"homepage": "https://docs.npmjs.com/",
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
"repository": {
"type": "git",
"url": "https://github.com/npm/cli"
},
"bugs": {
"url": "https://npm.community/c/bugs"
},
"directories": {
"bin": "./bin",
"doc": "./doc",
"lib": "./lib",
"man": "./man"
},
"main": "./lib/npm.js",
"bin": {
"npm": "./bin/npm-cli.js",
"npx": "./bin/npx-cli.js"
},
"dependencies": {
"JSONStream": "^1.3.5",
"abbrev": "~1.1.1",
"ansicolors": "~0.3.2",
"ansistyles": "~0.1.3",
"aproba": "^2.0.0",
"archy": "~1.0.0",
"bin-links": "^1.1.7",
"bluebird": "^3.5.5",
"byte-size": "^5.0.1",
"cacache": "^12.0.3",
"call-limit": "^1.1.1",
"chownr": "^1.1.4",
"ci-info": "^2.0.0",
"cli-columns": "^3.1.2",
"cli-table3": "^0.5.1",
"cmd-shim": "^3.0.3",
"columnify": "~1.5.4",
"config-chain": "^1.1.12",
"detect-indent": "~5.0.0",
"detect-newline": "^2.1.0",
"dezalgo": "~1.0.3",
"editor": "~1.0.0",
"figgy-pudding": "^3.5.1",
"find-npm-prefix": "^1.0.2",
"fs-vacuum": "~1.2.10",
"fs-write-stream-atomic": "~1.0.10",
"gentle-fs": "^2.3.0",
"glob": "^7.1.6",
"graceful-fs": "^4.2.4",
"has-unicode": "~2.0.1",
"hosted-git-info": "^2.8.8",
"iferr": "^1.0.2",
"infer-owner": "^1.0.4",
"inflight": "~1.0.6",
"inherits": "^2.0.4",
"ini": "^1.3.5",
"init-package-json": "^1.10.3",
"is-cidr": "^3.0.0",
"json-parse-better-errors": "^1.0.2",
"lazy-property": "~1.0.0",
"libcipm": "^4.0.7",
"libnpm": "^3.0.1",
"libnpmaccess": "^3.0.2",
"libnpmhook": "^5.0.3",
"libnpmorg": "^1.0.1",
"libnpmsearch": "^2.0.2",
"libnpmteam": "^1.0.2",
"libnpx": "^10.2.2",
"lock-verify": "^2.1.0",
"lockfile": "^1.0.4",
"lodash._baseuniq": "~4.6.0",
"lodash.clonedeep": "~4.5.0",
"lodash.union": "~4.6.0",
"lodash.uniq": "~4.5.0",
"lodash.without": "~4.4.0",
"lru-cache": "^5.1.1",
"meant": "~1.0.1",
"mississippi": "^3.0.0",
"mkdirp": "^0.5.5",
"move-concurrently": "^1.0.1",
"node-gyp": "^5.1.0",
"nopt": "^4.0.3",
"normalize-package-data": "^2.5.0",
"npm-audit-report": "^1.3.2",
"npm-cache-filename": "~1.0.2",
"npm-install-checks": "^3.0.2",
"npm-lifecycle": "^3.1.4",
"npm-package-arg": "^6.1.1",
"npm-packlist": "^1.4.8",
"npm-pick-manifest": "^3.0.2",
"npm-profile": "^4.0.4",
"npm-registry-fetch": "^4.0.5",
"npm-user-validate": "~1.0.0",
"npmlog": "~4.1.2",
"once": "~1.4.0",
"opener": "^1.5.1",
"osenv": "^0.1.5",
"pacote": "^9.5.12",
"path-is-inside": "~1.0.2",
"promise-inflight": "~1.0.1",
"qrcode-terminal": "^0.12.0",
"query-string": "^6.8.2",
"qw": "~1.0.1",
"read": "~1.0.7",
"read-cmd-shim": "^1.0.5",
"read-installed": "~4.0.3",
"read-package-json": "^2.1.1",
"read-package-tree": "^5.3.1",
"readable-stream": "^3.6.0",
"readdir-scoped-modules": "^1.1.0",
"request": "^2.88.0",
"retry": "^0.12.0",
"rimraf": "^2.7.1",
"safe-buffer": "^5.1.2",
"semver": "^5.7.1",
"sha": "^3.0.0",
"slide": "~1.1.6",
"sorted-object": "~2.0.1",
"sorted-union-stream": "~2.1.3",
"ssri": "^6.0.1",
"stringify-package": "^1.0.1",
"tar": "^4.4.13",
"text-table": "~0.2.0",
"tiny-relative-date": "^1.3.0",
"uid-number": "0.0.6",
"umask": "~1.1.0",
"unique-filename": "^1.1.1",
"unpipe": "~1.0.0",
"update-notifier": "^2.5.0",
"uuid": "^3.3.3",
"validate-npm-package-license": "^3.0.4",
"validate-npm-package-name": "~3.0.0",
"which": "^1.3.1",
"worker-farm": "^1.7.0",
"write-file-atomic": "^2.4.3"
},
"bundleDependencies": [
"abbrev",
"ansicolors",
"ansistyles",
"aproba",
"archy",
"bin-links",
"bluebird",
"byte-size",
"cacache",
"call-limit",
"chownr",
"ci-info",
"cli-columns",
"cli-table3",
"cmd-shim",
"columnify",
"config-chain",
"debuglog",
"detect-indent",
"detect-newline",
"dezalgo",
"editor",
"figgy-pudding",
"find-npm-prefix",
"fs-vacuum",
"fs-write-stream-atomic",
"gentle-fs",
"glob",
"graceful-fs",
"has-unicode",
"hosted-git-info",
"iferr",
"imurmurhash",
"infer-owner",
"inflight",
"inherits",
"ini",
"init-package-json",
"is-cidr",
"json-parse-better-errors",
"JSONStream",
"lazy-property",
"libcipm",
"libnpm",
"libnpmaccess",
"libnpmhook",
"libnpmorg",
"libnpmsearch",
"libnpmteam",
"libnpx",
"lock-verify",
"lockfile",
"lodash._baseindexof",
"lodash._baseuniq",
"lodash._bindcallback",
"lodash._cacheindexof",
"lodash._createcache",
"lodash._getnative",
"lodash.clonedeep",
"lodash.restparam",
"lodash.union",
"lodash.uniq",
"lodash.without",
"lru-cache",
"meant",
"mississippi",
"mkdirp",
"move-concurrently",
"node-gyp",
"nopt",
"normalize-package-data",
"npm-audit-report",
"npm-cache-filename",
"npm-install-checks",
"npm-lifecycle",
"npm-package-arg",
"npm-packlist",
"npm-pick-manifest",
"npm-profile",
"npm-registry-fetch",
"npm-user-validate",
"npmlog",
"once",
"opener",
"osenv",
"pacote",
"path-is-inside",
"promise-inflight",
"qrcode-terminal",
"query-string",
"qw",
"read-cmd-shim",
"read-installed",
"read-package-json",
"read-package-tree",
"read",
"readable-stream",
"readdir-scoped-modules",
"request",
"retry",
"rimraf",
"safe-buffer",
"semver",
"sha",
"slide",
"sorted-object",
"sorted-union-stream",
"ssri",
"stringify-package",
"tar",
"text-table",
"tiny-relative-date",
"uid-number",
"umask",
"unique-filename",
"unpipe",
"update-notifier",
"uuid",
"validate-npm-package-license",
"validate-npm-package-name",
"which",
"worker-farm",
"write-file-atomic"
],
"devDependencies": {
"deep-equal": "^1.0.1",
"get-stream": "^4.1.0",
"licensee": "^7.0.3",
"marked": "^0.6.3",
"marked-man": "^0.6.0",
"npm-registry-couchapp": "^2.7.4",
"npm-registry-mock": "^1.3.1",
"require-inject": "^1.4.4",
"sprintf-js": "^1.1.2",
"standard": "^11.0.1",
"tacks": "^1.3.0",
"tap": "^12.7.0",
"tar-stream": "^2.1.0"
},
"scripts": {
"dumpconf": "env | grep npm | sort | uniq",
"prepare": "node bin/npm-cli.js rebuild && node bin/npm-cli.js --no-audit --no-timing prune --prefix=. --no-global && rimraf test/*/*/node_modules && make -j4 mandocs",
"preversion": "bash scripts/update-authors.sh && git add AUTHORS && git commit -m \"update AUTHORS\" || true",
"licenses": "licensee --production --errors-only",
"tap": "tap -J --timeout 300 --no-esm",
"tap-cover": "tap -J --nyc-arg=--cache --coverage --timeout 600 --no-esm",
"lint": "standard",
"pretest": "npm run lint",
"test": "npm run test-tap --",
"test:nocleanup": "NO_TEST_CLEANUP=1 npm run test --",
"sudotest": "sudo npm run tap -- \"test/tap/*.js\"",
"sudotest:nocleanup": "sudo NO_TEST_CLEANUP=1 npm run tap -- \"test/tap/*.js\"",
"posttest": "rimraf test/npm_cache*",
"test-coverage": "npm run tap-cover -- \"test/tap/*.js\" \"test/network/*.js\"",
"test-tap": "npm run tap -- \"test/tap/*.js\" \"test/network/*.js\"",
"test-node": "tap --timeout 240 \"test/tap/*.js\" \"test/network/*.js\""
},
"license": "Artistic-2.0",
"engines": {
"node": "6 >=6.2.0 || 8 || >=9.3.0"
}
}