From 0955e2d3ff76c7ef56dd6e4a1c6083276ada803a Mon Sep 17 00:00:00 2001 From: Makisuo Date: Sun, 1 Nov 2026 00:11:24 +0100 Subject: [PATCH 1/4] feat(lockfiles): parse npm, pnpm, yarn, bun, Go and Cargo lockfiles A Maple-agnostic package that turns a lockfile into a flat list of locked packages (ecosystem, name, version, direct/dev/transitive) and orders versions per ecosystem (npm and Cargo semver with prereleases, Go pseudo-versions and +incompatible). It is the input side of the dependency vulnerability scanner. Fixtures are generated by the real package managers (scripts/generate-fixtures.sh) and each parse is checked against the tool's own package list. --- bun.lock | 38 +- lib/lockfiles/bunfig.toml | 3 + lib/lockfiles/package.json | 26 + lib/lockfiles/scripts/bench.ts | 38 + lib/lockfiles/scripts/generate-fixtures.sh | 204 ++++ .../src/__fixtures__/bun-lock/basic/bun.lock | 125 +++ .../__fixtures__/bun-lock/basic/expected.json | 56 ++ .../__fixtures__/bun-lock/basic/package.json | 12 + .../__fixtures__/bun-lock/workspace/bun.lock | 143 +++ .../bun-lock/workspace/expected.json | 56 ++ .../bun-lock/workspace/package.json | 11 + .../workspace/packages/a/package.json | 10 + .../workspace/packages/b/package.json | 8 + .../__fixtures__/cargo-lock/basic/Cargo.lock | 209 +++++ .../__fixtures__/cargo-lock/basic/Cargo.toml | 8 + .../cargo-lock/basic/expected.json | 26 + .../__fixtures__/go-mod/basic/expected.json | 26 + .../src/__fixtures__/go-mod/basic/go.mod | 35 + .../go-mod/basic/module-graph.json | 43 + .../__fixtures__/go-sum/basic/expected.json | 43 + .../src/__fixtures__/go-sum/basic/go.sum | 86 ++ .../package-lock/v1/expected.json | 54 ++ .../package-lock/v1/package-lock.json | 385 ++++++++ .../__fixtures__/package-lock/v1/package.json | 12 + .../package-lock/v2/expected.json | 54 ++ .../package-lock/v2/package-lock.json | 888 ++++++++++++++++++ .../__fixtures__/package-lock/v2/package.json | 12 + .../package-lock/v3/expected.json | 54 ++ .../package-lock/v3/package-lock.json | 561 +++++++++++ .../__fixtures__/package-lock/v3/package.json | 12 + .../package-lock/workspace/expected.json | 54 ++ .../package-lock/workspace/package-lock.json | 586 ++++++++++++ .../package-lock/workspace/package.json | 11 + .../workspace/packages/a/package.json | 10 + .../workspace/packages/b/package.json | 8 + .../__fixtures__/pnpm-lock/v5/expected.json | 56 ++ .../__fixtures__/pnpm-lock/v5/package.json | 12 + .../__fixtures__/pnpm-lock/v5/pnpm-lock.yaml | 389 ++++++++ .../__fixtures__/pnpm-lock/v6/expected.json | 56 ++ .../__fixtures__/pnpm-lock/v6/package.json | 12 + .../__fixtures__/pnpm-lock/v6/pnpm-lock.yaml | 394 ++++++++ .../__fixtures__/pnpm-lock/v9/expected.json | 56 ++ .../__fixtures__/pnpm-lock/v9/package.json | 12 + .../__fixtures__/pnpm-lock/v9/pnpm-lock.yaml | 452 +++++++++ .../pnpm-lock/workspace/expected.json | 56 ++ .../pnpm-lock/workspace/package.json | 11 + .../workspace/packages/a/package.json | 10 + .../workspace/packages/b/package.json | 8 + .../pnpm-lock/workspace/pnpm-lock.yaml | 464 +++++++++ .../pnpm-lock/workspace/pnpm-workspace.yaml | 2 + .../yarn-berry/basic/expected.json | 57 ++ .../yarn-berry/basic/package.json | 13 + .../__fixtures__/yarn-berry/basic/yarn.lock | 522 ++++++++++ .../__fixtures__/yarn-v1/basic/expected.json | 56 ++ .../__fixtures__/yarn-v1/basic/package.json | 12 + .../src/__fixtures__/yarn-v1/basic/yarn.lock | 378 ++++++++ lib/lockfiles/src/errors.ts | 11 + lib/lockfiles/src/fixtures.test.ts | 176 ++++ lib/lockfiles/src/index.ts | 12 + lib/lockfiles/src/internal/collect.ts | 50 + lib/lockfiles/src/internal/decode.ts | 44 + lib/lockfiles/src/internal/manifests.ts | 59 ++ lib/lockfiles/src/parse.test.ts | 348 +++++++ lib/lockfiles/src/parse.ts | 49 + lib/lockfiles/src/parsers/bun.ts | 84 ++ lib/lockfiles/src/parsers/cargo.ts | 47 + lib/lockfiles/src/parsers/go.ts | 147 +++ lib/lockfiles/src/parsers/packageLock.ts | 113 +++ lib/lockfiles/src/parsers/pnpm.ts | 103 ++ lib/lockfiles/src/parsers/types.ts | 11 + lib/lockfiles/src/parsers/yarn.ts | 149 +++ lib/lockfiles/src/paths.ts | 25 + lib/lockfiles/src/types.ts | 36 + lib/lockfiles/src/versions.test.ts | 132 +++ lib/lockfiles/src/versions.ts | 93 ++ lib/lockfiles/tsconfig.json | 20 + lib/lockfiles/vitest.config.ts | 9 + 77 files changed, 8643 insertions(+), 10 deletions(-) create mode 100644 lib/lockfiles/bunfig.toml create mode 100644 lib/lockfiles/package.json create mode 100644 lib/lockfiles/scripts/bench.ts create mode 100644 lib/lockfiles/scripts/generate-fixtures.sh create mode 100644 lib/lockfiles/src/__fixtures__/bun-lock/basic/bun.lock create mode 100644 lib/lockfiles/src/__fixtures__/bun-lock/basic/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/bun-lock/basic/package.json create mode 100644 lib/lockfiles/src/__fixtures__/bun-lock/workspace/bun.lock create mode 100644 lib/lockfiles/src/__fixtures__/bun-lock/workspace/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/bun-lock/workspace/package.json create mode 100644 lib/lockfiles/src/__fixtures__/bun-lock/workspace/packages/a/package.json create mode 100644 lib/lockfiles/src/__fixtures__/bun-lock/workspace/packages/b/package.json create mode 100644 lib/lockfiles/src/__fixtures__/cargo-lock/basic/Cargo.lock create mode 100644 lib/lockfiles/src/__fixtures__/cargo-lock/basic/Cargo.toml create mode 100644 lib/lockfiles/src/__fixtures__/cargo-lock/basic/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/go-mod/basic/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/go-mod/basic/go.mod create mode 100644 lib/lockfiles/src/__fixtures__/go-mod/basic/module-graph.json create mode 100644 lib/lockfiles/src/__fixtures__/go-sum/basic/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/go-sum/basic/go.sum create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v1/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v1/package-lock.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v1/package.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v2/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v2/package-lock.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v2/package.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v3/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v3/package-lock.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/v3/package.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/workspace/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/workspace/package-lock.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/workspace/package.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/workspace/packages/a/package.json create mode 100644 lib/lockfiles/src/__fixtures__/package-lock/workspace/packages/b/package.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v5/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v5/package.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v5/pnpm-lock.yaml create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v6/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v6/package.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v6/pnpm-lock.yaml create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v9/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v9/package.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/v9/pnpm-lock.yaml create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/package.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/packages/a/package.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/packages/b/package.json create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/pnpm-lock.yaml create mode 100644 lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/pnpm-workspace.yaml create mode 100644 lib/lockfiles/src/__fixtures__/yarn-berry/basic/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/yarn-berry/basic/package.json create mode 100644 lib/lockfiles/src/__fixtures__/yarn-berry/basic/yarn.lock create mode 100644 lib/lockfiles/src/__fixtures__/yarn-v1/basic/expected.json create mode 100644 lib/lockfiles/src/__fixtures__/yarn-v1/basic/package.json create mode 100644 lib/lockfiles/src/__fixtures__/yarn-v1/basic/yarn.lock create mode 100644 lib/lockfiles/src/errors.ts create mode 100644 lib/lockfiles/src/fixtures.test.ts create mode 100644 lib/lockfiles/src/index.ts create mode 100644 lib/lockfiles/src/internal/collect.ts create mode 100644 lib/lockfiles/src/internal/decode.ts create mode 100644 lib/lockfiles/src/internal/manifests.ts create mode 100644 lib/lockfiles/src/parse.test.ts create mode 100644 lib/lockfiles/src/parse.ts create mode 100644 lib/lockfiles/src/parsers/bun.ts create mode 100644 lib/lockfiles/src/parsers/cargo.ts create mode 100644 lib/lockfiles/src/parsers/go.ts create mode 100644 lib/lockfiles/src/parsers/packageLock.ts create mode 100644 lib/lockfiles/src/parsers/pnpm.ts create mode 100644 lib/lockfiles/src/parsers/types.ts create mode 100644 lib/lockfiles/src/parsers/yarn.ts create mode 100644 lib/lockfiles/src/paths.ts create mode 100644 lib/lockfiles/src/types.ts create mode 100644 lib/lockfiles/src/versions.test.ts create mode 100644 lib/lockfiles/src/versions.ts create mode 100644 lib/lockfiles/tsconfig.json create mode 100644 lib/lockfiles/vitest.config.ts diff --git a/bun.lock b/bun.lock index 601860fc3d..80d9387c4c 100644 --- a/bun.lock +++ b/bun.lock @@ -139,7 +139,7 @@ }, "apps/cli": { "name": "@maple/cli", - "version": "0.3.0", + "version": "0.3.1", "bin": { "maple": "./src/bin.ts", }, @@ -388,7 +388,7 @@ }, "examples/effect-todo": { "name": "@maple-examples/effect-todo", - "version": "0.0.5", + "version": "0.0.6", "dependencies": { "@effect/atom-react": "4.1.0", "@effect/platform-bun": "catalog:effect", @@ -474,6 +474,22 @@ "vitest": "catalog:", }, }, + "lib/lockfiles": { + "name": "@maple/lockfiles", + "dependencies": { + "effect": "catalog:effect", + "smol-toml": "^1.9.1", + "yaml": "^2.9.1", + }, + "devDependencies": { + "@types/node": "catalog:tooling", + "@types/semver": "^7.7.1", + "fast-check": "^4.10.2", + "semver": "^7.8.1", + "typescript": "catalog:tooling", + "vitest": "catalog:", + }, + }, "lib/prometheus-otlp": { "name": "@maple/prometheus-otlp", "devDependencies": { @@ -517,7 +533,7 @@ }, "packages/alchemy-maple": { "name": "@maple-dev/alchemy", - "version": "0.2.5", + "version": "0.3.0", "dependencies": { "@maple-dev/effect-sdk": "workspace:*", }, @@ -607,7 +623,7 @@ }, "packages/browser": { "name": "@maple-dev/browser", - "version": "0.12.0", + "version": "0.13.0", "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/instrumentation": "^0.222.0", @@ -726,7 +742,7 @@ }, "packages/effect-sdk": { "name": "@maple-dev/effect-sdk", - "version": "0.12.1", + "version": "0.13.0", "dependencies": { "std-env": "^4.0.0", }, @@ -1568,6 +1584,8 @@ "@maple/local-ui": ["@maple/local-ui@workspace:apps/local-ui"], + "@maple/lockfiles": ["@maple/lockfiles@workspace:lib/lockfiles"], + "@maple/primitives": ["@maple/primitives@workspace:packages/primitives"], "@maple/prometheus-otlp": ["@maple/prometheus-otlp@workspace:lib/prometheus-otlp"], @@ -2174,6 +2192,8 @@ "@types/sax": ["@types/sax@1.2.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A=="], + "@types/semver": ["@types/semver@7.8.0", "", {}, "sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ=="], + "@types/stats.js": ["@types/stats.js@0.17.4", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="], "@types/three": ["@types/three@0.186.0", "", { "dependencies": { "@dimforge/rapier3d-compat": "~0.12.0", "@tweenjs/tween.js": "~23.1.3", "@types/stats.js": "*", "@types/webxr": ">=0.5.17", "fflate": "~0.8.3", "meshoptimizer": "~1.1.1" } }, "sha512-mxYSBpDC+D0pLfSP6sW4WZTcT+nrtmZcimMqnVmy36Hte3XpeYSrvgg4TRdaM1GemGog1AWzI5qL2VoIfMXbJQ=="], @@ -3600,7 +3620,7 @@ "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], - "smol-toml": ["smol-toml@1.9.0", "", {}, "sha512-hpd+HLON7HdZXqYchMM/+LaTTbdK0AU3NngIJ4KVyWbY9bfQqdL9cD+4yf6dUoU2Ap4VsU0JkQi6FxAI1B2mXQ=="], + "smol-toml": ["smol-toml@1.9.1", "", {}, "sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ=="], "socks": ["socks@2.8.10", "", { "dependencies": { "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" } }, "sha512-e0VyvkVTwVYViNovRkZ9aodhxVlyoMn7eJhVUPxZ+eK9P/7CBkxvvsBOHqFPEH416726W8tLXXXjKwqgTErrCQ=="], @@ -3932,8 +3952,6 @@ "@astrojs/compiler-binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], - "@astrojs/internal-helpers/smol-toml": ["smol-toml@1.9.1", "", {}, "sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ=="], - "@astrojs/mdx/es-module-lexer": ["es-module-lexer@3.0.4", "", {}, "sha512-BldNY5mwkVu+cQ5Ymn3e6hB9Sx8XHx4ZevWbiUyZbfKxJxYO27Hf0wfzkxIaD5CAJMaGl3YspKELj0ff/7nCMA=="], "@astrojs/telemetry/package-manager-detector": ["package-manager-detector@1.9.0", "", {}, "sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA=="], @@ -4074,8 +4092,6 @@ "astro/rolldown": ["rolldown@1.2.15", "", { "dependencies": { "@oxc-project/types": "=0.155.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm-eabi": "1.2.15", "@rolldown/binding-android-arm64": "1.2.15", "@rolldown/binding-darwin-arm64": "1.2.15", "@rolldown/binding-darwin-x64": "1.2.15", "@rolldown/binding-freebsd-x64": "1.2.15", "@rolldown/binding-linux-arm-gnueabihf": "1.2.15", "@rolldown/binding-linux-arm64-gnu": "1.2.15", "@rolldown/binding-linux-arm64-musl": "1.2.15", "@rolldown/binding-linux-ppc64-gnu": "1.2.15", "@rolldown/binding-linux-s390x-gnu": "1.2.15", "@rolldown/binding-linux-x64-gnu": "1.2.15", "@rolldown/binding-linux-x64-musl": "1.2.15", "@rolldown/binding-openharmony-arm64": "1.2.15", "@rolldown/binding-win32-arm64-msvc": "1.2.15", "@rolldown/binding-win32-x64-msvc": "1.2.15" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-6odND+fel5zVw3I4Yc2e69gvguDnX0CAAGiNDZSq4ik5WUcaLrkD2GLuog0XcODbor31hZ5ayEMgVDno+KPV5g=="], - "astro/smol-toml": ["smol-toml@1.9.1", "", {}, "sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ=="], - "astro/verkit": ["verkit@0.5.0", "", {}, "sha512-u4J1hr6Y+C/hit34GwL3eIcUf3wngT8TlYUjK7tk0jxydKLAq3sYvifjdTDA6U3KCKRcQCQDGf/srjxfZF3l7g=="], "astro/zod": ["zod@4.6.7", "", {}, "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg=="], @@ -4170,6 +4186,8 @@ "juice/postcss": ["postcss@8.5.28", "", { "dependencies": { "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A=="], + "knip/smol-toml": ["smol-toml@1.9.0", "", {}, "sha512-hpd+HLON7HdZXqYchMM/+LaTTbdK0AU3NngIJ4KVyWbY9bfQqdL9cD+4yf6dUoU2Ap4VsU0JkQi6FxAI1B2mXQ=="], + "local-pkg/quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], "magicast/source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], diff --git a/lib/lockfiles/bunfig.toml b/lib/lockfiles/bunfig.toml new file mode 100644 index 0000000000..8e9e807026 --- /dev/null +++ b/lib/lockfiles/bunfig.toml @@ -0,0 +1,3 @@ +# Vitest package: `bun test` fails fast here (scripts/bun-test-guard.ts). +[test] +preload = ["../../scripts/bun-test-guard.ts"] diff --git a/lib/lockfiles/package.json b/lib/lockfiles/package.json new file mode 100644 index 0000000000..335b0add44 --- /dev/null +++ b/lib/lockfiles/package.json @@ -0,0 +1,26 @@ +{ + "name": "@maple/lockfiles", + "private": true, + "type": "module", + "sideEffects": false, + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsrs --noEmit", + "test": "vitest run" + }, + "dependencies": { + "effect": "catalog:effect", + "smol-toml": "^1.9.1", + "yaml": "^2.9.1" + }, + "devDependencies": { + "@types/node": "catalog:tooling", + "@types/semver": "^7.7.1", + "fast-check": "^4.10.2", + "semver": "^7.8.1", + "typescript": "catalog:tooling", + "vitest": "catalog:" + } +} diff --git a/lib/lockfiles/scripts/bench.ts b/lib/lockfiles/scripts/bench.ts new file mode 100644 index 0000000000..1c85366b56 --- /dev/null +++ b/lib/lockfiles/scripts/bench.ts @@ -0,0 +1,38 @@ +/** + * Parses each lockfile given on the command line and prints its package count and parse time. + * Usage: bun lib/lockfiles/scripts/bench.ts bun.lock [more lockfiles...] + */ +import { readFileSync } from "node:fs" +import { Effect } from "effect" +import { parseLockfile } from "../src/index.ts" + +const RUNS = 5 + +const benchOne = (path: string) => + Effect.gen(function* () { + const content = readFileSync(path, "utf8") + const timings = yield* Effect.forEach(Array.from({ length: RUNS }), () => + Effect.gen(function* () { + const start = performance.now() + const parsed = yield* parseLockfile({ path, content }) + return { parsed, ms: performance.now() - start } + }), + ) + const sorted = timings.map((t) => t.ms).sort((a, b) => a - b) + const first = timings[0] + if (first === undefined) return + const { parsed } = first + const direct = parsed.packages.filter((p) => p.relation === "direct").length + yield* Effect.log( + `${path}: ${parsed.kind}, ${parsed.packages.length} packages (${direct} direct), ${(content.length / 1024).toFixed(0)} KiB, ` + + `first ${first.ms.toFixed(1)} ms, median ${(sorted[Math.floor(RUNS / 2)] ?? 0).toFixed(1)} ms over ${RUNS} runs` + + (parsed.warnings.length > 0 ? `, warnings: ${parsed.warnings.join("; ")}` : ""), + ) + }) + +const paths = process.argv.slice(2) +await Effect.runPromise( + paths.length === 0 + ? Effect.logError("usage: bun scripts/bench.ts [...]") + : Effect.forEach(paths, benchOne, { discard: true }), +) diff --git a/lib/lockfiles/scripts/generate-fixtures.sh b/lib/lockfiles/scripts/generate-fixtures.sh new file mode 100644 index 0000000000..acae9c8613 --- /dev/null +++ b/lib/lockfiles/scripts/generate-fixtures.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash +# Regenerates src/__fixtures__ from the real package managers: each fixture holds the lockfile, +# its manifests and expected.json (the tool's own sorted name@version list). +# h2 0.3.17 is yanked, so the cargo fixture pins 0.3.16 (still advisory-affected). +# Usage: bash lib/lockfiles/scripts/generate-fixtures.sh [fixture-name ...] +set -euo pipefail + +HERE="$(cd "$(dirname "$0")" && pwd)" +OUT="$HERE/../src/__fixtures__" +WORK="$(mktemp -d -t maple-lockfiles)" +ONLY=("$@") +export npm_config_ignore_scripts=true YARN_ENABLE_SCRIPTS=0 YARN_ENABLE_TELEMETRY=0 COREPACK_ENABLE_STRICT=0 + +cap() { perl -e 'alarm shift; exec @ARGV' "$@"; } +log() { printf '== %s\n' "$*" >&2; } +wanted() { [ ${#ONLY[@]} -eq 0 ] && return 0; local n; for n in "${ONLY[@]}"; do [ "$n" = "$1" ] && return 0; done; return 1; } + +APP_JSON='{"name":"fx","version":"1.0.0","private":true,"dependencies":{"lodash":"4.17.15","express":"4.17.1"},"devDependencies":{"minimist":"1.2.5"}}' + +# $1 dir, $2 dependency spec for the sibling workspace ("*" for npm, "workspace:*" otherwise) +write_workspace() { + mkdir -p "$1/packages/a" "$1/packages/b" + printf '%s\n' '{"name":"fx-root","version":"1.0.0","private":true,"workspaces":["packages/*"],"devDependencies":{"minimist":"1.2.5"}}' >"$1/package.json" + printf '%s\n' '{"name":"@fx/a","version":"1.0.0","dependencies":{"lodash":"4.17.15"},"devDependencies":{"minimist":"1.2.5"}}' >"$1/packages/a/package.json" + printf '{"name":"@fx/b","version":"1.0.0","dependencies":{"express":"4.17.1","@fx/a":"%s"}}\n' "$2" >"$1/packages/b/package.json" +} + +# Copies the lockfile and every package.json (relative paths kept) into the fixture dir. +# $1 project dir, $2 fixture name (kind/variant), $3 lockfile name; expected.json is read from stdin. +save() { + local dest="$OUT/$2" + rm -rf "$dest" && mkdir -p "$dest" + cp "$1/$3" "$dest/$3" + (cd "$1" && find . -name package.json -not -path '*/node_modules/*' -not -path './.yarn/*') | while read -r f; do + mkdir -p "$dest/$(dirname "$f")" && cp "$1/$f" "$dest/$f" + done + [ -f "$1/pnpm-workspace.yaml" ] && cp "$1/pnpm-workspace.yaml" "$dest/" + cat >"$dest/expected.json" + log "$2: $(node -e 'console.log(JSON.parse(require("fs").readFileSync(0,"utf8")).length)' <"$dest/expected.json") packages" +} + +# Turns a tool's listing (stdin) into a sorted, de-duplicated JSON array of name@version. +# Local packages (workspaces, link:/file: versions) are dropped: they are not registry packages. +normalize() { + node -e ' +const mode = process.argv[1] +const text = require("fs").readFileSync(0, "utf8") +const out = new Set() +const local = new Set() +const add = (name, version) => { + if (!name || !version || /^(link|file|workspace):/.test(version)) return + out.add(`${name}@${version}`) +} +const splitAt = (s) => { const i = s.lastIndexOf("@"); return i > 0 ? [s.slice(0, i), s.slice(i + 1)] : [s, ""] } +const walk = (deps) => { + for (const [name, node] of Object.entries(deps ?? {})) { + if (node.resolved?.startsWith("file:")) { local.add(name); walkNode(node); continue } + add(name, node.version) + walkNode(node) + } +} +const walkNode = (n) => { walk(n.dependencies); walk(n.devDependencies); walk(n.optionalDependencies) } +if (mode === "tree") { + const json = JSON.parse(text) + for (const project of Array.isArray(json) ? json : [json]) walkNode(project) +} else if (mode === "yarn1") { + const visit = (t) => { if (t.shadow) return; const [n, v] = splitAt(t.name); add(n, v); (t.children ?? []).forEach(visit) } + for (const line of text.split("\n").filter(Boolean)) { + const j = JSON.parse(line) + if (j.type === "tree") j.data.trees.forEach(visit) + } +} else if (mode === "berry") { + for (const line of text.split("\n").filter(Boolean)) { + const j = JSON.parse(line) + if (j.value.includes("@workspace:")) continue + add(j.value.slice(0, j.value.indexOf("@", 1)), j.children.Version) + } +} else if (mode === "bun") { + for (const line of text.split("\n")) { + const m = line.match(/[├└│─\s]+(\S+@\S+)\s*$/) + if (m) { const [n, v] = splitAt(m[1]); add(n, v) } + } +} else if (mode === "go") { + for (const line of text.split("\n")) { + const parts = line.trim().split(/\s+/) + if (parts.length < 2) continue + const arrow = parts.indexOf("=>") + if (arrow === -1) add(parts[0], parts[1]) + else if (parts.length - arrow === 3) add(parts[arrow + 1], parts[arrow + 2]) + } +} else if (mode === "gomodedit") { + const j = JSON.parse(text) + for (const r of j.Require ?? []) { + const rep = (j.Replace ?? []).find((x) => x.Old.Path === r.Path && (!x.Old.Version || x.Old.Version === r.Version)) + if (!rep) add(r.Path, r.Version) + else if (rep.New.Version) add(rep.New.Path, rep.New.Version) + } +} else if (mode === "cargo") { + for (const p of JSON.parse(text).packages) if (p.source && p.source.startsWith("registry+")) add(p.name, p.version) +} +console.log(JSON.stringify([...out].filter((e) => !local.has(e.slice(0, e.lastIndexOf("@")))).sort(), null, "\t")) +' "$1" +} + +# $1 fixture name, $2 npm command (e.g. "npx -y npm@6"), $3 "app" or "workspace" +npm_fixture() { + wanted "$1" || return 0 + local dir="$WORK/${1//\//-}" npm=($2) + mkdir -p "$dir" + if [ "$3" = workspace ]; then write_workspace "$dir" "*"; else printf '%s\n' "$APP_JSON" >"$dir/package.json"; fi + # npm 6 cannot list from the lockfile alone, so it installs; newer npm lists without node_modules. + if [ "${npm[*]}" = "npx -y npm@6" ]; then + (cd "$dir" && cap 150 "${npm[@]}" install --ignore-scripts --no-audit --no-fund >/dev/null 2>&1) + (cd "$dir" && cap 60 "${npm[@]}" ls --json 2>/dev/null || true) | normalize tree | save "$dir" "$1" package-lock.json + else + (cd "$dir" && cap 150 "${npm[@]}" install --package-lock-only --ignore-scripts --no-audit --no-fund >/dev/null 2>&1) + (cd "$dir" && cap 60 "${npm[@]}" ls --package-lock-only --all --json 2>/dev/null || true) | normalize tree | save "$dir" "$1" package-lock.json + fi +} + +# $1 fixture name, $2 pnpm command, $3 "app" or "workspace". pnpm list reads node_modules, so it installs. +pnpm_fixture() { + wanted "$1" || return 0 + local dir="$WORK/${1//\//-}" pnpm=($2) + mkdir -p "$dir" + if [ "$3" = workspace ]; then + write_workspace "$dir" "workspace:*" + printf 'packages:\n - "packages/*"\n' >"$dir/pnpm-workspace.yaml" + else printf '%s\n' "$APP_JSON" >"$dir/package.json"; fi + (cd "$dir" && cap 150 "${pnpm[@]}" install --ignore-scripts >/dev/null 2>&1) + (cd "$dir" && cap 60 "${pnpm[@]}" list -r --depth Infinity --json 2>/dev/null) | normalize tree | save "$dir" "$1" pnpm-lock.yaml +} + +yarn1_fixture() { + wanted "$1" || return 0 + local dir="$WORK/${1//\//-}" yarn=(npx -y yarn@1.22.22) + mkdir -p "$dir" && printf '%s\n' "$APP_JSON" >"$dir/package.json" + (cd "$dir" && cap 150 "${yarn[@]}" install --ignore-scripts --non-interactive >/dev/null 2>&1) + (cd "$dir" && cap 60 "${yarn[@]}" list --json 2>/dev/null) | normalize yarn1 | save "$dir" "$1" yarn.lock +} + +# typescript (dev) makes berry write a builtin patch: entry, which the parser must resolve to npm. +berry_fixture() { + wanted "$1" || return 0 + local dir="$WORK/${1//\//-}" + mkdir -p "$dir" + printf '%s\n' '{"name":"fx","version":"1.0.0","private":true,"dependencies":{"lodash":"4.17.15","express":"4.17.1"},"devDependencies":{"minimist":"1.2.5","typescript":"5.4.5"}}' >"$dir/package.json" + (cd "$dir" && touch yarn.lock && printf 'nodeLinker: node-modules\nenableGlobalCache: false\n' >.yarnrc.yml) + (cd "$dir" && cap 150 yarn install --mode=update-lockfile >/dev/null 2>&1) + (cd "$dir" && cap 60 yarn info -AR --json 2>/dev/null) | normalize berry | save "$dir" "$1" yarn.lock +} + +# $1 fixture name, $2 "app" or "workspace" +bun_fixture() { + wanted "$1" || return 0 + local dir="$WORK/${1//\//-}" + mkdir -p "$dir" + if [ "$2" = workspace ]; then write_workspace "$dir" "workspace:*"; else printf '%s\n' "$APP_JSON" >"$dir/package.json"; fi + (cd "$dir" && cap 150 bun install --ignore-scripts >/dev/null 2>&1) + (cd "$dir" && cap 60 bun pm ls --all 2>/dev/null) | normalize bun | save "$dir" "$1" bun.lock +} + +go_fixture() { + wanted go-mod/basic || wanted go-sum/basic || return 0 + local dir="$WORK/go" + mkdir -p "$dir" + # The replace pins x/text to another version so the fixture exercises module-to-module replacement. + printf "module example.com/fx\n\ngo 1.21\n\nrequire (\n\tgolang.org/x/net v0.7.0\n\tgithub.com/gin-gonic/gin v1.9.0\n)\n\nreplace golang.org/x/text => golang.org/x/text v0.8.0\n" >"$dir/go.mod" + printf 'package main\n\nimport (\n\t_ "github.com/gin-gonic/gin"\n\t_ "golang.org/x/net/html"\n)\n\nfunc main() {}\n' >"$dir/main.go" + (cd "$dir" && GOFLAGS=-mod=mod cap 150 go mod tidy >/dev/null 2>&1) + local listing + listing="$(cd "$dir" && cap 60 go list -m all)" + # expected.json is go's own reading of go.mod; module-graph.json the full graph (go list -m all), a superset. + (cd "$dir" && go mod edit -json) | normalize gomodedit | save "$dir" go-mod/basic go.mod + printf '%s\n' "$listing" | normalize go >"$OUT/go-mod/basic/module-graph.json" + printf '%s\n' "$listing" | normalize go | save "$dir" go-sum/basic go.sum +} + +cargo_fixture() { + wanted cargo-lock/basic || return 0 + local dir="$WORK/cargo" + mkdir -p "$dir/src" + printf '[package]\nname = "fx"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\ntime = "=0.1.43"\nh2 = "=0.3.16"\n' >"$dir/Cargo.toml" + printf 'fn main() {}\n' >"$dir/src/main.rs" + (cd "$dir" && cap 150 cargo generate-lockfile >/dev/null 2>&1) + (cd "$dir" && cap 60 cargo metadata --format-version 1 2>/dev/null) | normalize cargo | save "$dir" cargo-lock/basic Cargo.lock + cp "$dir/Cargo.toml" "$OUT/cargo-lock/basic/" +} + +npm_fixture package-lock/v1 "npx -y npm@6" app +npm_fixture package-lock/v2 "npx -y npm@8" app +npm_fixture package-lock/v3 "npm" app +npm_fixture package-lock/workspace "npm" workspace +pnpm_fixture pnpm-lock/v5 "npx -y pnpm@7.33.7" app +pnpm_fixture pnpm-lock/v6 "npx -y pnpm@8.15.9" app +pnpm_fixture pnpm-lock/v9 "pnpm" app +pnpm_fixture pnpm-lock/workspace "pnpm" workspace +yarn1_fixture yarn-v1/basic +berry_fixture yarn-berry/basic +bun_fixture bun-lock/basic app +bun_fixture bun-lock/workspace workspace +go_fixture +cargo_fixture +rm -rf "$WORK" diff --git a/lib/lockfiles/src/__fixtures__/bun-lock/basic/bun.lock b/lib/lockfiles/src/__fixtures__/bun-lock/basic/bun.lock new file mode 100644 index 0000000000..fb962386c8 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/bun-lock/basic/bun.lock @@ -0,0 +1,125 @@ +{ + "lockfileVersion": 2, + "configVersion": 1, + "workspaces": { + "": { + "name": "fx", + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15", + }, + "devDependencies": { + "minimist": "1.2.5", + }, + }, + }, + "packages": { + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + + "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], + + "body-parser": ["body-parser@1.19.0", "", { "dependencies": { "bytes": "3.1.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "1.7.2", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", "qs": "6.7.0", "raw-body": "2.4.0", "type-is": "~1.6.17" } }, "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw=="], + + "bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="], + + "content-disposition": ["content-disposition@0.5.3", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + + "cookie": ["cookie@0.4.0", "", {}, "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="], + + "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="], + + "debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], + + "destroy": ["destroy@1.0.4", "", {}, "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg=="], + + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + + "encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + + "express": ["express@4.17.1", "", { "dependencies": { "accepts": "~1.3.7", "array-flatten": "1.1.1", "body-parser": "1.19.0", "content-disposition": "0.5.3", "content-type": "~1.0.4", "cookie": "0.4.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.1.2", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.5", "qs": "6.7.0", "range-parser": "~1.2.1", "safe-buffer": "5.1.2", "send": "0.17.1", "serve-static": "1.14.1", "setprototypeof": "1.1.1", "statuses": "~1.5.0", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g=="], + + "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="], + + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + + "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + + "http-errors": ["http-errors@1.7.2", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" } }, "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg=="], + + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + + "inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="], + + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + + "lodash": ["lodash@4.17.15", "", {}, "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="], + + "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], + + "merge-descriptors": ["merge-descriptors@1.0.1", "", {}, "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="], + + "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], + + "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "minimist": ["minimist@1.2.5", "", {}, "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="], + + "ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + + "on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="], + + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + + "path-to-regexp": ["path-to-regexp@0.1.7", "", {}, "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="], + + "proxy-addr": ["proxy-addr@2.0.8", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ=="], + + "qs": ["qs@6.7.0", "", {}, "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="], + + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + + "raw-body": ["raw-body@2.4.0", "", { "dependencies": { "bytes": "3.1.0", "http-errors": "1.7.2", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q=="], + + "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "send": ["send@0.17.1", "", { "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", "destroy": "~1.0.4", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "~1.7.2", "mime": "1.6.0", "ms": "2.1.1", "on-finished": "~2.3.0", "range-parser": "~1.2.1", "statuses": "~1.5.0" } }, "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg=="], + + "serve-static": ["serve-static@1.14.1", "", { "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.17.1" } }, "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg=="], + + "setprototypeof": ["setprototypeof@1.1.1", "", {}, "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="], + + "statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], + + "toidentifier": ["toidentifier@1.0.0", "", {}, "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="], + + "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], + + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], + + "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + + "send/http-errors": ["http-errors@1.7.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" } }, "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw=="], + + "send/ms": ["ms@2.1.1", "", {}, "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="], + + "send/http-errors/inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + } +} diff --git a/lib/lockfiles/src/__fixtures__/bun-lock/basic/expected.json b/lib/lockfiles/src/__fixtures__/bun-lock/basic/expected.json new file mode 100644 index 0000000000..ba6273d7de --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/bun-lock/basic/expected.json @@ -0,0 +1,56 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "http-errors@1.7.3", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "inherits@2.0.4", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/bun-lock/basic/package.json b/lib/lockfiles/src/__fixtures__/bun-lock/basic/package.json new file mode 100644 index 0000000000..d18d9beeba --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/bun-lock/basic/package.json @@ -0,0 +1,12 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/bun-lock/workspace/bun.lock b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/bun.lock new file mode 100644 index 0000000000..60ddee2e2e --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/bun.lock @@ -0,0 +1,143 @@ +{ + "lockfileVersion": 2, + "configVersion": 1, + "workspaces": { + "": { + "name": "fx-root", + "devDependencies": { + "minimist": "1.2.5", + }, + }, + "packages/a": { + "name": "@fx/a", + "version": "1.0.0", + "dependencies": { + "lodash": "4.17.15", + }, + "devDependencies": { + "minimist": "1.2.5", + }, + }, + "packages/b": { + "name": "@fx/b", + "version": "1.0.0", + "dependencies": { + "@fx/a": "workspace:*", + "express": "4.17.1", + }, + }, + }, + "packages": { + "@fx/a": ["@fx/a@workspace:packages/a"], + + "@fx/b": ["@fx/b@workspace:packages/b"], + + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + + "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], + + "body-parser": ["body-parser@1.19.0", "", { "dependencies": { "bytes": "3.1.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "1.7.2", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", "qs": "6.7.0", "raw-body": "2.4.0", "type-is": "~1.6.17" } }, "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw=="], + + "bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="], + + "content-disposition": ["content-disposition@0.5.3", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + + "cookie": ["cookie@0.4.0", "", {}, "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="], + + "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="], + + "debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], + + "destroy": ["destroy@1.0.4", "", {}, "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg=="], + + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + + "encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + + "express": ["express@4.17.1", "", { "dependencies": { "accepts": "~1.3.7", "array-flatten": "1.1.1", "body-parser": "1.19.0", "content-disposition": "0.5.3", "content-type": "~1.0.4", "cookie": "0.4.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.1.2", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.5", "qs": "6.7.0", "range-parser": "~1.2.1", "safe-buffer": "5.1.2", "send": "0.17.1", "serve-static": "1.14.1", "setprototypeof": "1.1.1", "statuses": "~1.5.0", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g=="], + + "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="], + + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + + "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + + "http-errors": ["http-errors@1.7.2", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" } }, "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg=="], + + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + + "inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="], + + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + + "lodash": ["lodash@4.17.15", "", {}, "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="], + + "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], + + "merge-descriptors": ["merge-descriptors@1.0.1", "", {}, "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="], + + "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], + + "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "minimist": ["minimist@1.2.5", "", {}, "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="], + + "ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + + "on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="], + + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + + "path-to-regexp": ["path-to-regexp@0.1.7", "", {}, "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="], + + "proxy-addr": ["proxy-addr@2.0.8", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ=="], + + "qs": ["qs@6.7.0", "", {}, "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="], + + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + + "raw-body": ["raw-body@2.4.0", "", { "dependencies": { "bytes": "3.1.0", "http-errors": "1.7.2", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q=="], + + "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "send": ["send@0.17.1", "", { "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", "destroy": "~1.0.4", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "~1.7.2", "mime": "1.6.0", "ms": "2.1.1", "on-finished": "~2.3.0", "range-parser": "~1.2.1", "statuses": "~1.5.0" } }, "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg=="], + + "serve-static": ["serve-static@1.14.1", "", { "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.17.1" } }, "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg=="], + + "setprototypeof": ["setprototypeof@1.1.1", "", {}, "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="], + + "statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], + + "toidentifier": ["toidentifier@1.0.0", "", {}, "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="], + + "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], + + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], + + "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + + "send/http-errors": ["http-errors@1.7.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" } }, "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw=="], + + "send/ms": ["ms@2.1.1", "", {}, "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="], + + "send/http-errors/inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + } +} diff --git a/lib/lockfiles/src/__fixtures__/bun-lock/workspace/expected.json b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/expected.json new file mode 100644 index 0000000000..ba6273d7de --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/expected.json @@ -0,0 +1,56 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "http-errors@1.7.3", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "inherits@2.0.4", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/bun-lock/workspace/package.json b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/package.json new file mode 100644 index 0000000000..314782f67e --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/package.json @@ -0,0 +1,11 @@ +{ + "name": "fx-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "packages/*" + ], + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/bun-lock/workspace/packages/a/package.json b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/packages/a/package.json new file mode 100644 index 0000000000..24cd26d06c --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/packages/a/package.json @@ -0,0 +1,10 @@ +{ + "name": "@fx/a", + "version": "1.0.0", + "dependencies": { + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/bun-lock/workspace/packages/b/package.json b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/packages/b/package.json new file mode 100644 index 0000000000..7481e51dbd --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/bun-lock/workspace/packages/b/package.json @@ -0,0 +1,8 @@ +{ + "name": "@fx/b", + "version": "1.0.0", + "dependencies": { + "@fx/a": "workspace:*", + "express": "4.17.1" + } +} diff --git a/lib/lockfiles/src/__fixtures__/cargo-lock/basic/Cargo.lock b/lib/lockfiles/src/__fixtures__/cargo-lock/basic/Cargo.lock new file mode 100644 index 0000000000..c962d45197 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/cargo-lock/basic/Cargo.lock @@ -0,0 +1,209 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-sink" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", +] + +[[package]] +name = "fx" +version = "0.1.0" +dependencies = [ + "h2", + "time", +] + +[[package]] +name = "h2" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "libc" +version = "0.2.191" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "tokio" +version = "1.54.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b52fd3255258d26fac7264ab5a76b53c13367136dc011d3d6ad4f8ed070396a3" +dependencies = [ + "bytes", + "pin-project-lite", +] + +[[package]] +name = "tokio-util" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "libc", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/lib/lockfiles/src/__fixtures__/cargo-lock/basic/Cargo.toml b/lib/lockfiles/src/__fixtures__/cargo-lock/basic/Cargo.toml new file mode 100644 index 0000000000..a2ae04042e --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/cargo-lock/basic/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fx" +version = "0.1.0" +edition = "2021" + +[dependencies] +time = "=0.1.43" +h2 = "=0.3.16" diff --git a/lib/lockfiles/src/__fixtures__/cargo-lock/basic/expected.json b/lib/lockfiles/src/__fixtures__/cargo-lock/basic/expected.json new file mode 100644 index 0000000000..672148a41e --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/cargo-lock/basic/expected.json @@ -0,0 +1,26 @@ +[ + "autocfg@1.5.1", + "bytes@1.12.1", + "fnv@1.0.7", + "futures-core@0.3.34", + "futures-sink@0.3.34", + "futures-task@0.3.34", + "futures-util@0.3.34", + "h2@0.3.16", + "hashbrown@0.12.3", + "http@0.2.12", + "indexmap@1.9.3", + "itoa@1.0.18", + "libc@0.2.191", + "once_cell@1.21.4", + "pin-project-lite@0.2.17", + "slab@0.4.12", + "time@0.1.43", + "tokio-util@0.7.20", + "tokio@1.54.1", + "tracing-core@0.1.36", + "tracing@0.1.44", + "winapi-i686-pc-windows-gnu@0.4.0", + "winapi-x86_64-pc-windows-gnu@0.4.0", + "winapi@0.3.9" +] diff --git a/lib/lockfiles/src/__fixtures__/go-mod/basic/expected.json b/lib/lockfiles/src/__fixtures__/go-mod/basic/expected.json new file mode 100644 index 0000000000..7c9ccc8300 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/go-mod/basic/expected.json @@ -0,0 +1,26 @@ +[ + "github.com/bytedance/sonic@v1.8.0", + "github.com/chenzhuoyu/base64x@v0.0.0-20221115062448-fe3a3abad311", + "github.com/gin-contrib/sse@v0.1.0", + "github.com/gin-gonic/gin@v1.9.0", + "github.com/go-playground/locales@v0.14.1", + "github.com/go-playground/universal-translator@v0.18.1", + "github.com/go-playground/validator/v10@v10.11.2", + "github.com/goccy/go-json@v0.10.0", + "github.com/json-iterator/go@v1.1.12", + "github.com/klauspost/cpuid/v2@v2.0.9", + "github.com/leodido/go-urn@v1.2.1", + "github.com/mattn/go-isatty@v0.0.17", + "github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421", + "github.com/modern-go/reflect2@v1.0.2", + "github.com/pelletier/go-toml/v2@v2.0.6", + "github.com/twitchyliquid64/golang-asm@v0.15.1", + "github.com/ugorji/go/codec@v1.2.9", + "golang.org/x/arch@v0.0.0-20210923205945-b76863e36670", + "golang.org/x/crypto@v0.5.0", + "golang.org/x/net@v0.7.0", + "golang.org/x/sys@v0.5.0", + "golang.org/x/text@v0.8.0", + "google.golang.org/protobuf@v1.28.1", + "gopkg.in/yaml.v3@v3.0.1" +] diff --git a/lib/lockfiles/src/__fixtures__/go-mod/basic/go.mod b/lib/lockfiles/src/__fixtures__/go-mod/basic/go.mod new file mode 100644 index 0000000000..1d8ca34273 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/go-mod/basic/go.mod @@ -0,0 +1,35 @@ +module example.com/fx + +go 1.21 + +require ( + github.com/gin-gonic/gin v1.9.0 + golang.org/x/net v0.7.0 +) + +require ( + github.com/bytedance/sonic v1.8.0 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.11.2 // indirect + github.com/goccy/go-json v0.10.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.9 // indirect + golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect + golang.org/x/crypto v0.5.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace golang.org/x/text => golang.org/x/text v0.8.0 diff --git a/lib/lockfiles/src/__fixtures__/go-mod/basic/module-graph.json b/lib/lockfiles/src/__fixtures__/go-mod/basic/module-graph.json new file mode 100644 index 0000000000..f8d758e50f --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/go-mod/basic/module-graph.json @@ -0,0 +1,43 @@ +[ + "github.com/bytedance/sonic@v1.8.0", + "github.com/chenzhuoyu/base64x@v0.0.0-20221115062448-fe3a3abad311", + "github.com/davecgh/go-spew@v1.1.1", + "github.com/gin-contrib/sse@v0.1.0", + "github.com/gin-gonic/gin@v1.9.0", + "github.com/go-playground/assert/v2@v2.2.0", + "github.com/go-playground/locales@v0.14.1", + "github.com/go-playground/universal-translator@v0.18.1", + "github.com/go-playground/validator/v10@v10.11.2", + "github.com/goccy/go-json@v0.10.0", + "github.com/golang/protobuf@v1.5.0", + "github.com/google/go-cmp@v0.5.5", + "github.com/google/gofuzz@v1.0.0", + "github.com/json-iterator/go@v1.1.12", + "github.com/klauspost/cpuid/v2@v2.0.9", + "github.com/kr/pretty@v0.3.0", + "github.com/kr/text@v0.2.0", + "github.com/leodido/go-urn@v1.2.1", + "github.com/mattn/go-isatty@v0.0.17", + "github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421", + "github.com/modern-go/reflect2@v1.0.2", + "github.com/pelletier/go-toml/v2@v2.0.6", + "github.com/pmezard/go-difflib@v1.0.0", + "github.com/rogpeppe/go-internal@v1.8.0", + "github.com/stretchr/objx@v0.5.0", + "github.com/stretchr/testify@v1.8.1", + "github.com/twitchyliquid64/golang-asm@v0.15.1", + "github.com/ugorji/go/codec@v1.2.9", + "golang.org/x/arch@v0.0.0-20210923205945-b76863e36670", + "golang.org/x/crypto@v0.5.0", + "golang.org/x/mod@v0.8.0", + "golang.org/x/net@v0.7.0", + "golang.org/x/sys@v0.5.0", + "golang.org/x/term@v0.5.0", + "golang.org/x/text@v0.8.0", + "golang.org/x/tools@v0.6.0", + "golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543", + "google.golang.org/protobuf@v1.28.1", + "gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c", + "gopkg.in/yaml.v3@v3.0.1", + "rsc.io/pdf@v0.1.1" +] diff --git a/lib/lockfiles/src/__fixtures__/go-sum/basic/expected.json b/lib/lockfiles/src/__fixtures__/go-sum/basic/expected.json new file mode 100644 index 0000000000..f8d758e50f --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/go-sum/basic/expected.json @@ -0,0 +1,43 @@ +[ + "github.com/bytedance/sonic@v1.8.0", + "github.com/chenzhuoyu/base64x@v0.0.0-20221115062448-fe3a3abad311", + "github.com/davecgh/go-spew@v1.1.1", + "github.com/gin-contrib/sse@v0.1.0", + "github.com/gin-gonic/gin@v1.9.0", + "github.com/go-playground/assert/v2@v2.2.0", + "github.com/go-playground/locales@v0.14.1", + "github.com/go-playground/universal-translator@v0.18.1", + "github.com/go-playground/validator/v10@v10.11.2", + "github.com/goccy/go-json@v0.10.0", + "github.com/golang/protobuf@v1.5.0", + "github.com/google/go-cmp@v0.5.5", + "github.com/google/gofuzz@v1.0.0", + "github.com/json-iterator/go@v1.1.12", + "github.com/klauspost/cpuid/v2@v2.0.9", + "github.com/kr/pretty@v0.3.0", + "github.com/kr/text@v0.2.0", + "github.com/leodido/go-urn@v1.2.1", + "github.com/mattn/go-isatty@v0.0.17", + "github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421", + "github.com/modern-go/reflect2@v1.0.2", + "github.com/pelletier/go-toml/v2@v2.0.6", + "github.com/pmezard/go-difflib@v1.0.0", + "github.com/rogpeppe/go-internal@v1.8.0", + "github.com/stretchr/objx@v0.5.0", + "github.com/stretchr/testify@v1.8.1", + "github.com/twitchyliquid64/golang-asm@v0.15.1", + "github.com/ugorji/go/codec@v1.2.9", + "golang.org/x/arch@v0.0.0-20210923205945-b76863e36670", + "golang.org/x/crypto@v0.5.0", + "golang.org/x/mod@v0.8.0", + "golang.org/x/net@v0.7.0", + "golang.org/x/sys@v0.5.0", + "golang.org/x/term@v0.5.0", + "golang.org/x/text@v0.8.0", + "golang.org/x/tools@v0.6.0", + "golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543", + "google.golang.org/protobuf@v1.28.1", + "gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c", + "gopkg.in/yaml.v3@v3.0.1", + "rsc.io/pdf@v0.1.1" +] diff --git a/lib/lockfiles/src/__fixtures__/go-sum/basic/go.sum b/lib/lockfiles/src/__fixtures__/go-sum/basic/go.sum new file mode 100644 index 0000000000..49aadb8193 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/go-sum/basic/go.sum @@ -0,0 +1,86 @@ +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= +github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= +github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= +github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= +github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= +github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= +github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v1/expected.json b/lib/lockfiles/src/__fixtures__/package-lock/v1/expected.json new file mode 100644 index 0000000000..7d53a7a078 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v1/expected.json @@ -0,0 +1,54 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v1/package-lock.json b/lib/lockfiles/src/__fixtures__/package-lock/v1/package-lock.json new file mode 100644 index 0000000000..d963b497d9 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v1/package-lock.json @@ -0,0 +1,385 @@ +{ + "name": "fx", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "proxy-addr": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz", + "integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + } + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v1/package.json b/lib/lockfiles/src/__fixtures__/package-lock/v1/package.json new file mode 100644 index 0000000000..d18d9beeba --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v1/package.json @@ -0,0 +1,12 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v2/expected.json b/lib/lockfiles/src/__fixtures__/package-lock/v2/expected.json new file mode 100644 index 0000000000..7d53a7a078 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v2/expected.json @@ -0,0 +1,54 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v2/package-lock.json b/lib/lockfiles/src/__fixtures__/package-lock/v2/package-lock.json new file mode 100644 index 0000000000..87cc7e831f --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v2/package-lock.json @@ -0,0 +1,888 @@ +{ + "name": "fx", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "fx", + "version": "1.0.0", + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz", + "integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + } + }, + "dependencies": { + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "proxy-addr": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz", + "integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + } + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v2/package.json b/lib/lockfiles/src/__fixtures__/package-lock/v2/package.json new file mode 100644 index 0000000000..d18d9beeba --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v2/package.json @@ -0,0 +1,12 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v3/expected.json b/lib/lockfiles/src/__fixtures__/package-lock/v3/expected.json new file mode 100644 index 0000000000..7d53a7a078 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v3/expected.json @@ -0,0 +1,54 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v3/package-lock.json b/lib/lockfiles/src/__fixtures__/package-lock/v3/package-lock.json new file mode 100644 index 0000000000..7358bddb7f --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v3/package-lock.json @@ -0,0 +1,561 @@ +{ + "name": "fx", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fx", + "version": "1.0.0", + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz", + "integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "license": "MIT", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "license": "ISC" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + } + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/v3/package.json b/lib/lockfiles/src/__fixtures__/package-lock/v3/package.json new file mode 100644 index 0000000000..d18d9beeba --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/v3/package.json @@ -0,0 +1,12 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/workspace/expected.json b/lib/lockfiles/src/__fixtures__/package-lock/workspace/expected.json new file mode 100644 index 0000000000..7d53a7a078 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/workspace/expected.json @@ -0,0 +1,54 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/package-lock/workspace/package-lock.json b/lib/lockfiles/src/__fixtures__/package-lock/workspace/package-lock.json new file mode 100644 index 0000000000..8c53e599d9 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/workspace/package-lock.json @@ -0,0 +1,586 @@ +{ + "name": "fx-root", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fx-root", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ], + "devDependencies": { + "minimist": "1.2.5" + } + }, + "node_modules/@fx/a": { + "resolved": "packages/a", + "link": true + }, + "node_modules/@fx/b": { + "resolved": "packages/b", + "link": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz", + "integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "license": "MIT", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "license": "ISC" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "packages/a": { + "name": "@fx/a", + "version": "1.0.0", + "dependencies": { + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } + }, + "packages/b": { + "name": "@fx/b", + "version": "1.0.0", + "dependencies": { + "@fx/a": "*", + "express": "4.17.1" + } + } + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/workspace/package.json b/lib/lockfiles/src/__fixtures__/package-lock/workspace/package.json new file mode 100644 index 0000000000..314782f67e --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/workspace/package.json @@ -0,0 +1,11 @@ +{ + "name": "fx-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "packages/*" + ], + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/workspace/packages/a/package.json b/lib/lockfiles/src/__fixtures__/package-lock/workspace/packages/a/package.json new file mode 100644 index 0000000000..24cd26d06c --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/workspace/packages/a/package.json @@ -0,0 +1,10 @@ +{ + "name": "@fx/a", + "version": "1.0.0", + "dependencies": { + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/package-lock/workspace/packages/b/package.json b/lib/lockfiles/src/__fixtures__/package-lock/workspace/packages/b/package.json new file mode 100644 index 0000000000..508b5dc841 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/package-lock/workspace/packages/b/package.json @@ -0,0 +1,8 @@ +{ + "name": "@fx/b", + "version": "1.0.0", + "dependencies": { + "@fx/a": "*", + "express": "4.17.1" + } +} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/expected.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/expected.json new file mode 100644 index 0000000000..ba6273d7de --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/expected.json @@ -0,0 +1,56 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "http-errors@1.7.3", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "inherits@2.0.4", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/package.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/package.json new file mode 100644 index 0000000000..d18d9beeba --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/package.json @@ -0,0 +1,12 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/pnpm-lock.yaml b/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/pnpm-lock.yaml new file mode 100644 index 0000000000..4bdc50735e --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v5/pnpm-lock.yaml @@ -0,0 +1,389 @@ +lockfileVersion: 5.4 + +specifiers: + express: 4.17.1 + lodash: 4.17.15 + minimist: 1.2.5 + +dependencies: + express: 4.17.1 + lodash: 4.17.15 + +devDependencies: + minimist: 1.2.5 + +packages: + + /accepts/1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /array-flatten/1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /body-parser/1.19.0: + resolution: {integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.0 + content-type: 1.0.5 + debug: 2.6.9 + depd: 1.1.2 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.7.0 + raw-body: 2.4.0 + type-is: 1.6.18 + transitivePeerDependencies: + - supports-color + dev: false + + /bytes/3.1.0: + resolution: {integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==} + engines: {node: '>= 0.8'} + dev: false + + /content-disposition/0.5.3: + resolution: {integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.1.2 + dev: false + + /content-type/1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature/1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie/0.4.0: + resolution: {integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==} + engines: {node: '>= 0.6'} + dev: false + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /depd/1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + dev: false + + /destroy/1.0.4: + resolution: {integrity: sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==} + dev: false + + /ee-first/1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /encodeurl/1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /escape-html/1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /etag/1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /express/4.17.1: + resolution: {integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.19.0 + content-disposition: 0.5.3 + content-type: 1.0.5 + cookie: 0.4.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 1.1.2 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.1.2 + fresh: 0.5.2 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.3.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.8 + qs: 6.7.0 + range-parser: 1.2.1 + safe-buffer: 5.1.2 + send: 0.17.1 + serve-static: 1.14.1 + setprototypeof: 1.1.1 + statuses: 1.5.0 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /finalhandler/1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /forwarded/0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh/0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /http-errors/1.7.2: + resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + dev: false + + /http-errors/1.7.3: + resolution: {integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + dev: false + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /inherits/2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + dev: false + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ipaddr.js/1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /lodash/4.17.15: + resolution: {integrity: sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==} + dev: false + + /media-typer/0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /merge-descriptors/1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /methods/1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime/1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /minimist/1.2.5: + resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + dev: true + + /ms/2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms/2.1.1: + resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==} + dev: false + + /negotiator/0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /on-finished/2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /parseurl/1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-to-regexp/0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /proxy-addr/2.0.8: + resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /qs/6.7.0: + resolution: {integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==} + engines: {node: '>=0.6'} + dev: false + + /range-parser/1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body/2.4.0: + resolution: {integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.0 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /safe-buffer/5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /send/0.17.1: + resolution: {integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 1.1.2 + destroy: 1.0.4 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 1.7.3 + mime: 1.6.0 + ms: 2.1.1 + on-finished: 2.3.0 + range-parser: 1.2.1 + statuses: 1.5.0 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-static/1.14.1: + resolution: {integrity: sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.17.1 + transitivePeerDependencies: + - supports-color + dev: false + + /setprototypeof/1.1.1: + resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} + dev: false + + /statuses/1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + dev: false + + /toidentifier/1.0.0: + resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} + engines: {node: '>=0.6'} + dev: false + + /type-is/1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /unpipe/1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /utils-merge/1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /vary/1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/expected.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/expected.json new file mode 100644 index 0000000000..ba6273d7de --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/expected.json @@ -0,0 +1,56 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "http-errors@1.7.3", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "inherits@2.0.4", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/package.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/package.json new file mode 100644 index 0000000000..d18d9beeba --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/package.json @@ -0,0 +1,12 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/pnpm-lock.yaml b/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/pnpm-lock.yaml new file mode 100644 index 0000000000..273788333b --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v6/pnpm-lock.yaml @@ -0,0 +1,394 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + express: + specifier: 4.17.1 + version: 4.17.1 + lodash: + specifier: 4.17.15 + version: 4.17.15 + +devDependencies: + minimist: + specifier: 1.2.5 + version: 1.2.5 + +packages: + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /body-parser@1.19.0: + resolution: {integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.0 + content-type: 1.0.5 + debug: 2.6.9 + depd: 1.1.2 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.7.0 + raw-body: 2.4.0 + type-is: 1.6.18 + transitivePeerDependencies: + - supports-color + dev: false + + /bytes@3.1.0: + resolution: {integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==} + engines: {node: '>= 0.8'} + dev: false + + /content-disposition@0.5.3: + resolution: {integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.1.2 + dev: false + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie@0.4.0: + resolution: {integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==} + engines: {node: '>= 0.6'} + dev: false + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + dev: false + + /destroy@1.0.4: + resolution: {integrity: sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==} + dev: false + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /express@4.17.1: + resolution: {integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.19.0 + content-disposition: 0.5.3 + content-type: 1.0.5 + cookie: 0.4.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 1.1.2 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.1.2 + fresh: 0.5.2 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.3.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.8 + qs: 6.7.0 + range-parser: 1.2.1 + safe-buffer: 5.1.2 + send: 0.17.1 + serve-static: 1.14.1 + setprototypeof: 1.1.1 + statuses: 1.5.0 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /http-errors@1.7.2: + resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + dev: false + + /http-errors@1.7.3: + resolution: {integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /lodash@4.17.15: + resolution: {integrity: sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==} + dev: false + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /minimist@1.2.5: + resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms@2.1.1: + resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==} + dev: false + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /proxy-addr@2.0.8: + resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /qs@6.7.0: + resolution: {integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==} + engines: {node: '>=0.6'} + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body@2.4.0: + resolution: {integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.0 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /send@0.17.1: + resolution: {integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 1.1.2 + destroy: 1.0.4 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 1.7.3 + mime: 1.6.0 + ms: 2.1.1 + on-finished: 2.3.0 + range-parser: 1.2.1 + statuses: 1.5.0 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-static@1.14.1: + resolution: {integrity: sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.17.1 + transitivePeerDependencies: + - supports-color + dev: false + + /setprototypeof@1.1.1: + resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} + dev: false + + /statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + dev: false + + /toidentifier@1.0.0: + resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} + engines: {node: '>=0.6'} + dev: false + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/expected.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/expected.json new file mode 100644 index 0000000000..ba6273d7de --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/expected.json @@ -0,0 +1,56 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "http-errors@1.7.3", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "inherits@2.0.4", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/package.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/package.json new file mode 100644 index 0000000000..d18d9beeba --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/package.json @@ -0,0 +1,12 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/pnpm-lock.yaml b/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/pnpm-lock.yaml new file mode 100644 index 0000000000..f47172a7bd --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/v9/pnpm-lock.yaml @@ -0,0 +1,452 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + express: + specifier: 4.17.1 + version: 4.17.1 + lodash: + specifier: 4.17.15 + version: 4.17.15 + devDependencies: + minimist: + specifier: 1.2.5 + version: 1.2.5 + +packages: + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + body-parser@1.19.0: + resolution: {integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==} + engines: {node: '>= 0.8'} + + bytes@3.1.0: + resolution: {integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==} + engines: {node: '>= 0.8'} + + content-disposition@0.5.3: + resolution: {integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.4.0: + resolution: {integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==} + engines: {node: '>= 0.6'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + destroy@1.0.4: + resolution: {integrity: sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + express@4.17.1: + resolution: {integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==} + engines: {node: '>= 0.10.0'} + + finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + http-errors@1.7.2: + resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==} + engines: {node: '>= 0.6'} + + http-errors@1.7.3: + resolution: {integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==} + engines: {node: '>= 0.6'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + lodash@4.17.15: + resolution: {integrity: sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + minimist@1.2.5: + resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.1: + resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + + proxy-addr@2.0.8: + resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==} + engines: {node: '>= 0.10'} + + qs@6.7.0: + resolution: {integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==} + engines: {node: '>=0.6'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.4.0: + resolution: {integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==} + engines: {node: '>= 0.8'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + send@0.17.1: + resolution: {integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==} + engines: {node: '>= 0.8.0'} + + serve-static@1.14.1: + resolution: {integrity: sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==} + engines: {node: '>= 0.8.0'} + + setprototypeof@1.1.1: + resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + toidentifier@1.0.0: + resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} + engines: {node: '>=0.6'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + +snapshots: + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + array-flatten@1.1.1: {} + + body-parser@1.19.0: + dependencies: + bytes: 3.1.0 + content-type: 1.0.5 + debug: 2.6.9 + depd: 1.1.2 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.7.0 + raw-body: 2.4.0 + type-is: 1.6.18 + transitivePeerDependencies: + - supports-color + + bytes@3.1.0: {} + + content-disposition@0.5.3: + dependencies: + safe-buffer: 5.1.2 + + content-type@1.0.5: {} + + cookie-signature@1.0.6: {} + + cookie@0.4.0: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + depd@1.1.2: {} + + destroy@1.0.4: {} + + ee-first@1.1.1: {} + + encodeurl@1.0.2: {} + + escape-html@1.0.3: {} + + etag@1.8.1: {} + + express@4.17.1: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.19.0 + content-disposition: 0.5.3 + content-type: 1.0.5 + cookie: 0.4.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 1.1.2 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.1.2 + fresh: 0.5.2 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.3.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.8 + qs: 6.7.0 + range-parser: 1.2.1 + safe-buffer: 5.1.2 + send: 0.17.1 + serve-static: 1.14.1 + setprototypeof: 1.1.1 + statuses: 1.5.0 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + finalhandler@1.1.2: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + http-errors@1.7.2: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + + http-errors@1.7.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ipaddr.js@1.9.1: {} + + lodash@4.17.15: {} + + media-typer@0.3.0: {} + + merge-descriptors@1.0.1: {} + + methods@1.1.2: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + minimist@1.2.5: {} + + ms@2.0.0: {} + + ms@2.1.1: {} + + negotiator@0.6.3: {} + + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + + parseurl@1.3.3: {} + + path-to-regexp@0.1.7: {} + + proxy-addr@2.0.8: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + qs@6.7.0: {} + + range-parser@1.2.1: {} + + raw-body@2.4.0: + dependencies: + bytes: 3.1.0 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + safe-buffer@5.1.2: {} + + safer-buffer@2.1.2: {} + + send@0.17.1: + dependencies: + debug: 2.6.9 + depd: 1.1.2 + destroy: 1.0.4 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 1.7.3 + mime: 1.6.0 + ms: 2.1.1 + on-finished: 2.3.0 + range-parser: 1.2.1 + statuses: 1.5.0 + transitivePeerDependencies: + - supports-color + + serve-static@1.14.1: + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.17.1 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.1.1: {} + + statuses@1.5.0: {} + + toidentifier@1.0.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + unpipe@1.0.0: {} + + utils-merge@1.0.1: {} + + vary@1.1.2: {} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/expected.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/expected.json new file mode 100644 index 0000000000..ba6273d7de --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/expected.json @@ -0,0 +1,56 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "http-errors@1.7.3", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "inherits@2.0.4", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/package.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/package.json new file mode 100644 index 0000000000..314782f67e --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/package.json @@ -0,0 +1,11 @@ +{ + "name": "fx-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "packages/*" + ], + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/packages/a/package.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/packages/a/package.json new file mode 100644 index 0000000000..24cd26d06c --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/packages/a/package.json @@ -0,0 +1,10 @@ +{ + "name": "@fx/a", + "version": "1.0.0", + "dependencies": { + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/packages/b/package.json b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/packages/b/package.json new file mode 100644 index 0000000000..7481e51dbd --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/packages/b/package.json @@ -0,0 +1,8 @@ +{ + "name": "@fx/b", + "version": "1.0.0", + "dependencies": { + "@fx/a": "workspace:*", + "express": "4.17.1" + } +} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/pnpm-lock.yaml b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/pnpm-lock.yaml new file mode 100644 index 0000000000..9dcdaa13c8 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/pnpm-lock.yaml @@ -0,0 +1,464 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + minimist: + specifier: 1.2.5 + version: 1.2.5 + + packages/a: + dependencies: + lodash: + specifier: 4.17.15 + version: 4.17.15 + devDependencies: + minimist: + specifier: 1.2.5 + version: 1.2.5 + + packages/b: + dependencies: + '@fx/a': + specifier: workspace:* + version: link:../a + express: + specifier: 4.17.1 + version: 4.17.1 + +packages: + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + body-parser@1.19.0: + resolution: {integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==} + engines: {node: '>= 0.8'} + + bytes@3.1.0: + resolution: {integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==} + engines: {node: '>= 0.8'} + + content-disposition@0.5.3: + resolution: {integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.4.0: + resolution: {integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==} + engines: {node: '>= 0.6'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + destroy@1.0.4: + resolution: {integrity: sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + express@4.17.1: + resolution: {integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==} + engines: {node: '>= 0.10.0'} + + finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + http-errors@1.7.2: + resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==} + engines: {node: '>= 0.6'} + + http-errors@1.7.3: + resolution: {integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==} + engines: {node: '>= 0.6'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + lodash@4.17.15: + resolution: {integrity: sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + minimist@1.2.5: + resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.1: + resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + + proxy-addr@2.0.8: + resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==} + engines: {node: '>= 0.10'} + + qs@6.7.0: + resolution: {integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==} + engines: {node: '>=0.6'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.4.0: + resolution: {integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==} + engines: {node: '>= 0.8'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + send@0.17.1: + resolution: {integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==} + engines: {node: '>= 0.8.0'} + + serve-static@1.14.1: + resolution: {integrity: sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==} + engines: {node: '>= 0.8.0'} + + setprototypeof@1.1.1: + resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + toidentifier@1.0.0: + resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} + engines: {node: '>=0.6'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + +snapshots: + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + array-flatten@1.1.1: {} + + body-parser@1.19.0: + dependencies: + bytes: 3.1.0 + content-type: 1.0.5 + debug: 2.6.9 + depd: 1.1.2 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.7.0 + raw-body: 2.4.0 + type-is: 1.6.18 + transitivePeerDependencies: + - supports-color + + bytes@3.1.0: {} + + content-disposition@0.5.3: + dependencies: + safe-buffer: 5.1.2 + + content-type@1.0.5: {} + + cookie-signature@1.0.6: {} + + cookie@0.4.0: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + depd@1.1.2: {} + + destroy@1.0.4: {} + + ee-first@1.1.1: {} + + encodeurl@1.0.2: {} + + escape-html@1.0.3: {} + + etag@1.8.1: {} + + express@4.17.1: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.19.0 + content-disposition: 0.5.3 + content-type: 1.0.5 + cookie: 0.4.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 1.1.2 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.1.2 + fresh: 0.5.2 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.3.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.8 + qs: 6.7.0 + range-parser: 1.2.1 + safe-buffer: 5.1.2 + send: 0.17.1 + serve-static: 1.14.1 + setprototypeof: 1.1.1 + statuses: 1.5.0 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + finalhandler@1.1.2: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + http-errors@1.7.2: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + + http-errors@1.7.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ipaddr.js@1.9.1: {} + + lodash@4.17.15: {} + + media-typer@0.3.0: {} + + merge-descriptors@1.0.1: {} + + methods@1.1.2: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + minimist@1.2.5: {} + + ms@2.0.0: {} + + ms@2.1.1: {} + + negotiator@0.6.3: {} + + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + + parseurl@1.3.3: {} + + path-to-regexp@0.1.7: {} + + proxy-addr@2.0.8: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + qs@6.7.0: {} + + range-parser@1.2.1: {} + + raw-body@2.4.0: + dependencies: + bytes: 3.1.0 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + safe-buffer@5.1.2: {} + + safer-buffer@2.1.2: {} + + send@0.17.1: + dependencies: + debug: 2.6.9 + depd: 1.1.2 + destroy: 1.0.4 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 1.7.3 + mime: 1.6.0 + ms: 2.1.1 + on-finished: 2.3.0 + range-parser: 1.2.1 + statuses: 1.5.0 + transitivePeerDependencies: + - supports-color + + serve-static@1.14.1: + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.17.1 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.1.1: {} + + statuses@1.5.0: {} + + toidentifier@1.0.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + unpipe@1.0.0: {} + + utils-merge@1.0.1: {} + + vary@1.1.2: {} diff --git a/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/pnpm-workspace.yaml b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/pnpm-workspace.yaml new file mode 100644 index 0000000000..dee51e928d --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/pnpm-lock/workspace/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" diff --git a/lib/lockfiles/src/__fixtures__/yarn-berry/basic/expected.json b/lib/lockfiles/src/__fixtures__/yarn-berry/basic/expected.json new file mode 100644 index 0000000000..d85d719017 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/yarn-berry/basic/expected.json @@ -0,0 +1,57 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "http-errors@1.7.3", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "inherits@2.0.4", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "typescript@5.4.5", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/yarn-berry/basic/package.json b/lib/lockfiles/src/__fixtures__/yarn-berry/basic/package.json new file mode 100644 index 0000000000..d26742e214 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/yarn-berry/basic/package.json @@ -0,0 +1,13 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5", + "typescript": "5.4.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/yarn-berry/basic/yarn.lock b/lib/lockfiles/src/__fixtures__/yarn-berry/basic/yarn.lock new file mode 100644 index 0000000000..4d83932075 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/yarn-berry/basic/yarn.lock @@ -0,0 +1,522 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"accepts@npm:~1.3.7": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: "npm:~2.1.34" + negotiator: "npm:0.6.3" + checksum: 10c0/3a35c5f5586cfb9a21163ca47a5f77ac34fa8ceb5d17d2fa2c0d81f41cbd7f8c6fa52c77e2c039acc0f4d09e71abdc51144246900f6bef5e3c4b333f77d89362 + languageName: node + linkType: hard + +"array-flatten@npm:1.1.1": + version: 1.1.1 + resolution: "array-flatten@npm:1.1.1" + checksum: 10c0/806966c8abb2f858b08f5324d9d18d7737480610f3bd5d3498aaae6eb5efdc501a884ba019c9b4a8f02ff67002058749d05548fd42fa8643f02c9c7f22198b91 + languageName: node + linkType: hard + +"body-parser@npm:1.19.0": + version: 1.19.0 + resolution: "body-parser@npm:1.19.0" + dependencies: + bytes: "npm:3.1.0" + content-type: "npm:~1.0.4" + debug: "npm:2.6.9" + depd: "npm:~1.1.2" + http-errors: "npm:1.7.2" + iconv-lite: "npm:0.4.24" + on-finished: "npm:~2.3.0" + qs: "npm:6.7.0" + raw-body: "npm:2.4.0" + type-is: "npm:~1.6.17" + checksum: 10c0/df97c94a16495db166dba4c7812a43ba800ea252a76a1de80be944e2b884b808897febb920880c30089ac01f74f9118ca589402294c0ea5e2075488e4f91dc09 + languageName: node + linkType: hard + +"bytes@npm:3.1.0": + version: 3.1.0 + resolution: "bytes@npm:3.1.0" + checksum: 10c0/7034f475b006b9a8a37c7ecaa0947d0be181feb6d3d5231984e4c14e01c587a47e0fe85f66c630689fa6a046cfa498b6891f5af8022357e52db09365f1dfb625 + languageName: node + linkType: hard + +"content-disposition@npm:0.5.3": + version: 0.5.3 + resolution: "content-disposition@npm:0.5.3" + dependencies: + safe-buffer: "npm:5.1.2" + checksum: 10c0/988f131fedb2b79002337b5480951cc73f86e876b3e7feb6617b92e40a01f633db6f4c7765d486c02b468890465b2df96b7652b7e39caf22cc63517cf2e99839 + languageName: node + linkType: hard + +"content-type@npm:~1.0.4": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af + languageName: node + linkType: hard + +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: 10c0/b36fd0d4e3fef8456915fcf7742e58fbfcc12a17a018e0eb9501c9d5ef6893b596466f03b0564b81af29ff2538fd0aa4b9d54fe5ccbfb4c90ea50ad29fe2d221 + languageName: node + linkType: hard + +"cookie@npm:0.4.0": + version: 0.4.0 + resolution: "cookie@npm:0.4.0" + checksum: 10c0/71508a1c8a4e97bb88f42635542ef24ebe7e713f82573ac61e9b289616334d14bfb28210d7979d9ada24b0254f5fb563af938cac13bc8c0c3f60f47a2257f791 + languageName: node + linkType: hard + +"debug@npm:2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: "npm:2.0.0" + checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589 + languageName: node + linkType: hard + +"depd@npm:~1.1.2": + version: 1.1.2 + resolution: "depd@npm:1.1.2" + checksum: 10c0/acb24aaf936ef9a227b6be6d495f0d2eb20108a9a6ad40585c5bda1a897031512fef6484e4fdbb80bd249fdaa82841fa1039f416ece03188e677ba11bcfda249 + languageName: node + linkType: hard + +"destroy@npm:~1.0.4": + version: 1.0.4 + resolution: "destroy@npm:1.0.4" + checksum: 10c0/eab493808ba17a1fa22c71ef1a4e68d2c4c5222a38040606c966d2ab09117f3a7f3e05c39bffbe41a697f9de552039e43c30e46f0c3eab3faa9f82e800e172a0 + languageName: node + linkType: hard + +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 10c0/b5bb125ee93161bc16bfe6e56c6b04de5ad2aa44234d8f644813cc95d861a6910903132b05093706de2b706599367c4130eb6d170f6b46895686b95f87d017b7 + languageName: node + linkType: hard + +"encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: 10c0/f6c2387379a9e7c1156c1c3d4f9cb7bb11cf16dd4c1682e1f6746512564b053df5781029b6061296832b59fb22f459dbe250386d217c2f6e203601abb2ee0bec + languageName: node + linkType: hard + +"escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 10c0/524c739d776b36c3d29fa08a22e03e8824e3b2fd57500e5e44ecf3cc4707c34c60f9ca0781c0e33d191f2991161504c295e98f68c78fe7baa6e57081ec6ac0a3 + languageName: node + linkType: hard + +"etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 10c0/12be11ef62fb9817314d790089a0a49fae4e1b50594135dcb8076312b7d7e470884b5100d249b28c18581b7fd52f8b485689ffae22a11ed9ec17377a33a08f84 + languageName: node + linkType: hard + +"express@npm:4.17.1": + version: 4.17.1 + resolution: "express@npm:4.17.1" + dependencies: + accepts: "npm:~1.3.7" + array-flatten: "npm:1.1.1" + body-parser: "npm:1.19.0" + content-disposition: "npm:0.5.3" + content-type: "npm:~1.0.4" + cookie: "npm:0.4.0" + cookie-signature: "npm:1.0.6" + debug: "npm:2.6.9" + depd: "npm:~1.1.2" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + finalhandler: "npm:~1.1.2" + fresh: "npm:0.5.2" + merge-descriptors: "npm:1.0.1" + methods: "npm:~1.1.2" + on-finished: "npm:~2.3.0" + parseurl: "npm:~1.3.3" + path-to-regexp: "npm:0.1.7" + proxy-addr: "npm:~2.0.5" + qs: "npm:6.7.0" + range-parser: "npm:~1.2.1" + safe-buffer: "npm:5.1.2" + send: "npm:0.17.1" + serve-static: "npm:1.14.1" + setprototypeof: "npm:1.1.1" + statuses: "npm:~1.5.0" + type-is: "npm:~1.6.18" + utils-merge: "npm:1.0.1" + vary: "npm:~1.1.2" + checksum: 10c0/17bbe941cb98167d54d24f1b1f252e9e1757ad036b0ba7a836c51d3f1a7bf329ccbf72739d214599818ccec91115b7c5b87ad2d2a006e20142310af4d7c6f7bf + languageName: node + linkType: hard + +"finalhandler@npm:~1.1.2": + version: 1.1.2 + resolution: "finalhandler@npm:1.1.2" + dependencies: + debug: "npm:2.6.9" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + on-finished: "npm:~2.3.0" + parseurl: "npm:~1.3.3" + statuses: "npm:~1.5.0" + unpipe: "npm:~1.0.0" + checksum: 10c0/6a96e1f5caab085628c11d9fdceb82ba608d5e426c6913d4d918409baa271037a47f28fbba73279e8ad614f0b8fa71ea791d265e408d760793829edd8c2f4584 + languageName: node + linkType: hard + +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: 10c0/9b67c3fac86acdbc9ae47ba1ddd5f2f81526fa4c8226863ede5600a3f7c7416ef451f6f1e240a3cc32d0fd79fcfe6beb08fd0da454f360032bde70bf80afbb33 + languageName: node + linkType: hard + +"fresh@npm:0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 10c0/c6d27f3ed86cc5b601404822f31c900dd165ba63fff8152a3ef714e2012e7535027063bc67ded4cb5b3a49fa596495d46cacd9f47d6328459cf570f08b7d9e5a + languageName: node + linkType: hard + +"fx@workspace:.": + version: 0.0.0-use.local + resolution: "fx@workspace:." + dependencies: + express: "npm:4.17.1" + lodash: "npm:4.17.15" + minimist: "npm:1.2.5" + typescript: "npm:5.4.5" + languageName: unknown + linkType: soft + +"http-errors@npm:1.7.2": + version: 1.7.2 + resolution: "http-errors@npm:1.7.2" + dependencies: + depd: "npm:~1.1.2" + inherits: "npm:2.0.3" + setprototypeof: "npm:1.1.1" + statuses: "npm:>= 1.5.0 < 2" + toidentifier: "npm:1.0.0" + checksum: 10c0/49d3b2d52ee4bb24110fb4cff13a52e960501f63803d99bf50b6f93825335eab85bfd4809a90b5a5432ed13efe06c3979553a7a967cd196db1b0e23056068365 + languageName: node + linkType: hard + +"http-errors@npm:~1.7.2": + version: 1.7.3 + resolution: "http-errors@npm:1.7.3" + dependencies: + depd: "npm:~1.1.2" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.1.1" + statuses: "npm:>= 1.5.0 < 2" + toidentifier: "npm:1.0.0" + checksum: 10c0/5c3443c340d35b2f18ce908266c4ae93305b7d900bef765ac8dc56fa90125b9fe18a1ed9ebf6af23dc3ba7763731921a2682bf968e199eccf383eb8f508be6c2 + languageName: node + linkType: hard + +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 10c0/c6886a24cc00f2a059767440ec1bc00d334a89f250db8e0f7feb4961c8727118457e27c495ba94d082e51d3baca378726cd110aaf7ded8b9bbfd6a44760cf1d4 + languageName: node + linkType: hard + +"inherits@npm:2.0.3": + version: 2.0.3 + resolution: "inherits@npm:2.0.3" + checksum: 10c0/6e56402373149ea076a434072671f9982f5fad030c7662be0332122fe6c0fa490acb3cc1010d90b6eff8d640b1167d77674add52dfd1bb85d545cf29e80e73e7 + languageName: node + linkType: hard + +"inherits@npm:2.0.4": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 + languageName: node + linkType: hard + +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: 10c0/0486e775047971d3fdb5fb4f063829bac45af299ae0b82dcf3afa2145338e08290563a2a70f34b732d795ecc8311902e541a8530eeb30d75860a78ff4e94ce2a + languageName: node + linkType: hard + +"lodash@npm:4.17.15": + version: 4.17.15 + resolution: "lodash@npm:4.17.15" + checksum: 10c0/c029ab298357d007252d5802348f1deb343099ba734ae6e6776a908e4995db5b8ed4ae51ff83a2937a1f6e3c41a0c8941eb941926e1a7f2ddfc3d235ec1e8aa7 + languageName: node + linkType: hard + +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: 10c0/d160f31246907e79fed398470285f21bafb45a62869dc469b1c8877f3f064f5eabc4bcc122f9479b8b605bc5c76187d7871cf84c4ee3ecd3e487da1993279928 + languageName: node + linkType: hard + +"merge-descriptors@npm:1.0.1": + version: 1.0.1 + resolution: "merge-descriptors@npm:1.0.1" + checksum: 10c0/b67d07bd44cfc45cebdec349bb6e1f7b077ee2fd5beb15d1f7af073849208cb6f144fe403e29a36571baf3f4e86469ac39acf13c318381e958e186b2766f54ec + languageName: node + linkType: hard + +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 10c0/bdf7cc72ff0a33e3eede03708c08983c4d7a173f91348b4b1e4f47d4cdbf734433ad971e7d1e8c77247d9e5cd8adb81ea4c67b0a2db526b758b2233d7814b8b2 + languageName: node + linkType: hard + +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa + languageName: node + linkType: hard + +"mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: "npm:1.52.0" + checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 + languageName: node + linkType: hard + +"mime@npm:1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: 10c0/b92cd0adc44888c7135a185bfd0dddc42c32606401c72896a842ae15da71eb88858f17669af41e498b463cd7eb998f7b48939a25b08374c7924a9c8a6f8a81b0 + languageName: node + linkType: hard + +"minimist@npm:1.2.5": + version: 1.2.5 + resolution: "minimist@npm:1.2.5" + checksum: 10c0/c143b0c199af4df7a55c7a37b6465cdd438acdc6a3a345ba0fe9d94dfcc2042263f650879bc73be607c843deeaeaadf39c864e55bc6d80b36a025eca1a062ee7 + languageName: node + linkType: hard + +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 10c0/f8fda810b39fd7255bbdc451c46286e549794fcc700dc9cd1d25658bbc4dc2563a5de6fe7c60f798a16a60c6ceb53f033cb353f493f0cf63e5199b702943159d + languageName: node + linkType: hard + +"ms@npm:2.1.1": + version: 2.1.1 + resolution: "ms@npm:2.1.1" + checksum: 10c0/056140c631e740369fa21142417aba1bd629ab912334715216c666eb681c8f015c622dd4e38bc1d836b30852b05641331661703af13a0397eb0ca420fc1e75d9 + languageName: node + linkType: hard + +"negotiator@npm:0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 + languageName: node + linkType: hard + +"on-finished@npm:~2.3.0": + version: 2.3.0 + resolution: "on-finished@npm:2.3.0" + dependencies: + ee-first: "npm:1.1.1" + checksum: 10c0/c904f9e518b11941eb60279a3cbfaf1289bd0001f600a950255b1dede9fe3df8cd74f38483550b3bb9485165166acb5db500c3b4c4337aec2815c88c96fcc2ea + languageName: node + linkType: hard + +"parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5 + languageName: node + linkType: hard + +"path-to-regexp@npm:0.1.7": + version: 0.1.7 + resolution: "path-to-regexp@npm:0.1.7" + checksum: 10c0/50a1ddb1af41a9e68bd67ca8e331a705899d16fb720a1ea3a41e310480948387daf603abb14d7b0826c58f10146d49050a1291ba6a82b78a382d1c02c0b8f905 + languageName: node + linkType: hard + +"proxy-addr@npm:~2.0.5": + version: 2.0.8 + resolution: "proxy-addr@npm:2.0.8" + dependencies: + forwarded: "npm:0.2.0" + ipaddr.js: "npm:1.9.1" + checksum: 10c0/58398f36e5b1f72b1011ca21844c0c41a9a3b6f2f0d101bcdb19abb3f3dd9626b27a96e53da777ded901eb67faed0304a4bc1d435b235e436f66f8e5e1fe1f5e + languageName: node + linkType: hard + +"qs@npm:6.7.0": + version: 6.7.0 + resolution: "qs@npm:6.7.0" + checksum: 10c0/04e6934d8cfa4f352e5bf5fe16eeed75dccad16d1e03b53ece849839b7439940f0df8bf0bc4750306d65baf95ebe165315f61122067e33bfee7b7ef4e3945813 + languageName: node + linkType: hard + +"range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0 + languageName: node + linkType: hard + +"raw-body@npm:2.4.0": + version: 2.4.0 + resolution: "raw-body@npm:2.4.0" + dependencies: + bytes: "npm:3.1.0" + http-errors: "npm:1.7.2" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: 10c0/c7ff86d9d4a91f0d9ab3e2eb45b2197d2534e0f24fded16989085fe71207539f63100a6fd49507a5ff1907ff38511e510a3e6098102b9e8711cd84d7344a703a + languageName: node + linkType: hard + +"safe-buffer@npm:5.1.2": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: 10c0/780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"send@npm:0.17.1": + version: 0.17.1 + resolution: "send@npm:0.17.1" + dependencies: + debug: "npm:2.6.9" + depd: "npm:~1.1.2" + destroy: "npm:~1.0.4" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + fresh: "npm:0.5.2" + http-errors: "npm:~1.7.2" + mime: "npm:1.6.0" + ms: "npm:2.1.1" + on-finished: "npm:~2.3.0" + range-parser: "npm:~1.2.1" + statuses: "npm:~1.5.0" + checksum: 10c0/712e27d5d4f38d6097a649bbe8846a30a6f9d1995e78e1c133a7a351ec26508b0d8fb707dadb6e003f3753d3f9310667e04633522883b81300abd9978b28afd2 + languageName: node + linkType: hard + +"serve-static@npm:1.14.1": + version: 1.14.1 + resolution: "serve-static@npm:1.14.1" + dependencies: + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + parseurl: "npm:~1.3.3" + send: "npm:0.17.1" + checksum: 10c0/f4ebc459bff763ae372e4148c2af13e2b813033f384cb2bc4e1c129c722fa14bfaf6e85f41c95363d49f97de7244e7961c929b2f942ddbd4c520c9610322dae5 + languageName: node + linkType: hard + +"setprototypeof@npm:1.1.1": + version: 1.1.1 + resolution: "setprototypeof@npm:1.1.1" + checksum: 10c0/1084b783f2d77908b0a593619e1214c2118c44c7c3277f6099dd7ca8acfc056c009e5d1b2860eae5e8b0ba9bc0a978c15613ff102ccc1093bb48aa6e0ed75e2f + languageName: node + linkType: hard + +"statuses@npm:>= 1.5.0 < 2, statuses@npm:~1.5.0": + version: 1.5.0 + resolution: "statuses@npm:1.5.0" + checksum: 10c0/e433900956357b3efd79b1c547da4d291799ac836960c016d10a98f6a810b1b5c0dcc13b5a7aa609a58239b5190e1ea176ad9221c2157d2fd1c747393e6b2940 + languageName: node + linkType: hard + +"toidentifier@npm:1.0.0": + version: 1.0.0 + resolution: "toidentifier@npm:1.0.0" + checksum: 10c0/27a37b8b21126e7216d40c02f410065b1de35b0f844368d0ccaabba7987595703006d45e5c094b086220cbbc5864d4b99766b460110e4bc15b9db574c5c58be2 + languageName: node + linkType: hard + +"type-is@npm:~1.6.17, type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: "npm:0.3.0" + mime-types: "npm:~2.1.24" + checksum: 10c0/a23daeb538591b7efbd61ecf06b6feb2501b683ffdc9a19c74ef5baba362b4347e42f1b4ed81f5882a8c96a3bfff7f93ce3ffaf0cbbc879b532b04c97a55db9d + languageName: node + linkType: hard + +"typescript@npm:5.4.5": + version: 5.4.5 + resolution: "typescript@npm:5.4.5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/2954022ada340fd3d6a9e2b8e534f65d57c92d5f3989a263754a78aba549f7e6529acc1921913560a4b816c46dce7df4a4d29f9f11a3dc0d4213bb76d043251e + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A5.4.5#optional!builtin": + version: 5.4.5 + resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/db2ad2a16ca829f50427eeb1da155e7a45e598eec7b086d8b4e8ba44e5a235f758e606d681c66992230d3fc3b8995865e5fd0b22a2c95486d0b3200f83072ec9 + languageName: node + linkType: hard + +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c + languageName: node + linkType: hard + +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: 10c0/02ba649de1b7ca8854bfe20a82f1dfbdda3fb57a22ab4a8972a63a34553cf7aa51bc9081cf7e001b035b88186d23689d69e71b510e610a09a4c66f68aa95b672 + languageName: node + linkType: hard + +"vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f + languageName: node + linkType: hard diff --git a/lib/lockfiles/src/__fixtures__/yarn-v1/basic/expected.json b/lib/lockfiles/src/__fixtures__/yarn-v1/basic/expected.json new file mode 100644 index 0000000000..ba6273d7de --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/yarn-v1/basic/expected.json @@ -0,0 +1,56 @@ +[ + "accepts@1.3.8", + "array-flatten@1.1.1", + "body-parser@1.19.0", + "bytes@3.1.0", + "content-disposition@0.5.3", + "content-type@1.0.5", + "cookie-signature@1.0.6", + "cookie@0.4.0", + "debug@2.6.9", + "depd@1.1.2", + "destroy@1.0.4", + "ee-first@1.1.1", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "etag@1.8.1", + "express@4.17.1", + "finalhandler@1.1.2", + "forwarded@0.2.0", + "fresh@0.5.2", + "http-errors@1.7.2", + "http-errors@1.7.3", + "iconv-lite@0.4.24", + "inherits@2.0.3", + "inherits@2.0.4", + "ipaddr.js@1.9.1", + "lodash@4.17.15", + "media-typer@0.3.0", + "merge-descriptors@1.0.1", + "methods@1.1.2", + "mime-db@1.52.0", + "mime-types@2.1.35", + "mime@1.6.0", + "minimist@1.2.5", + "ms@2.0.0", + "ms@2.1.1", + "negotiator@0.6.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "path-to-regexp@0.1.7", + "proxy-addr@2.0.8", + "qs@6.7.0", + "range-parser@1.2.1", + "raw-body@2.4.0", + "safe-buffer@5.1.2", + "safer-buffer@2.1.2", + "send@0.17.1", + "serve-static@1.14.1", + "setprototypeof@1.1.1", + "statuses@1.5.0", + "toidentifier@1.0.0", + "type-is@1.6.18", + "unpipe@1.0.0", + "utils-merge@1.0.1", + "vary@1.1.2" +] diff --git a/lib/lockfiles/src/__fixtures__/yarn-v1/basic/package.json b/lib/lockfiles/src/__fixtures__/yarn-v1/basic/package.json new file mode 100644 index 0000000000..d18d9beeba --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/yarn-v1/basic/package.json @@ -0,0 +1,12 @@ +{ + "name": "fx", + "version": "1.0.0", + "private": true, + "dependencies": { + "express": "4.17.1", + "lodash": "4.17.15" + }, + "devDependencies": { + "minimist": "1.2.5" + } +} diff --git a/lib/lockfiles/src/__fixtures__/yarn-v1/basic/yarn.lock b/lib/lockfiles/src/__fixtures__/yarn-v1/basic/yarn.lock new file mode 100644 index 0000000000..7a50921a62 --- /dev/null +++ b/lib/lockfiles/src/__fixtures__/yarn-v1/basic/yarn.lock @@ -0,0 +1,378 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +accepts@~1.3.7: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +express@4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.0" + content-disposition "0.5.3" + content-type "~1.0.4" + cookie "0.4.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +lodash@4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +minimist@1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +proxy-addr@~2.0.5: + version "2.0.8" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.8.tgz#624e760fd8ab06b1b8320c2f8506d4422cf8e932" + integrity sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== diff --git a/lib/lockfiles/src/errors.ts b/lib/lockfiles/src/errors.ts new file mode 100644 index 0000000000..0992ebee67 --- /dev/null +++ b/lib/lockfiles/src/errors.ts @@ -0,0 +1,11 @@ +import { Schema } from "effect" + +export class LockfileParseError extends Schema.TaggedError< + LockfileParseError, + { readonly brand: unique symbol } +>()("@maple/lockfiles/LockfileParseError", { message: Schema.String, path: Schema.String }) {} + +export class LockfileUnsupportedError extends Schema.TaggedError< + LockfileUnsupportedError, + { readonly brand: unique symbol } +>()("@maple/lockfiles/LockfileUnsupportedError", { message: Schema.String, path: Schema.String }) {} diff --git a/lib/lockfiles/src/fixtures.test.ts b/lib/lockfiles/src/fixtures.test.ts new file mode 100644 index 0000000000..1dba69ce06 --- /dev/null +++ b/lib/lockfiles/src/fixtures.test.ts @@ -0,0 +1,176 @@ +import { readdirSync, readFileSync, statSync } from "node:fs" +import { join, relative } from "node:path" +import { Effect, Schema } from "effect" +import { describe, expect, it } from "vitest" +import { lockfileKindOf, parseLockfile, type ParsedLockfile } from "./index.ts" + +const ROOT = join(import.meta.dirname, "__fixtures__") + +const decodeIds = Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Array(Schema.String))) + +const filesUnder = (dir: string): ReadonlyArray => + readdirSync(dir).flatMap((name) => { + const path = join(dir, name) + return statSync(path).isDirectory() ? filesUnder(path) : [path] + }) + +interface Fixture { + readonly name: string + readonly lockfile: string + readonly manifests: ReadonlyMap + readonly expected: ReadonlyArray +} + +const fixtures: ReadonlyArray = readdirSync(ROOT).flatMap((kind) => + readdirSync(join(ROOT, kind)).flatMap((variant) => { + const dir = join(ROOT, kind, variant) + const files = filesUnder(dir).map((path) => relative(dir, path)) + const lockfile = files.find((file) => !file.includes("/") && lockfileKindOf(file) !== undefined) + if (lockfile === undefined) return [] + const manifests = new Map( + files + .filter((f) => f.endsWith("package.json")) + .map((f): readonly [string, string] => [f, readFileSync(join(dir, f), "utf8")]), + ) + const expected = decodeIds(readFileSync(join(dir, "expected.json"), "utf8")) + return [{ name: `${kind}/${variant}`, lockfile: join(dir, lockfile), manifests, expected }] + }), +) + +const parseFixture = (fixture: Fixture, withManifests = true): Promise => + Effect.runPromise( + parseLockfile({ + path: fixture.lockfile, + content: readFileSync(fixture.lockfile, "utf8"), + manifests: withManifests ? fixture.manifests : undefined, + }), + ) + +const ids = (parsed: ParsedLockfile): ReadonlyArray => + parsed.packages.map((p) => `${p.name}@${p.version}`).sort() + +const relationOf = (parsed: ParsedLockfile, name: string) => + parsed.packages.filter((p) => p.name === name).map((p) => p.relation) + +describe("fixtures generated by the real package managers", () => { + it("covers every lockfile format but bun.lockb", () => { + expect(new Set(fixtures.map((f) => f.name.split("/")[0]))).toEqual( + new Set([ + "package-lock", + "pnpm-lock", + "yarn-v1", + "yarn-berry", + "bun-lock", + "go-mod", + "go-sum", + "cargo-lock", + ]), + ) + }) + + it.each(fixtures.filter((f) => f.name !== "go-sum/basic"))( + "$name matches the tool's own package list", + async (fixture) => { + expect(ids(await parseFixture(fixture))).toEqual([...fixture.expected].sort()) + }, + ) +}) + +const fixture = (name: string): Fixture => { + const found = fixtures.find((f) => f.name === name) + if (found === undefined) return expect.unreachable(`missing fixture ${name}`) + return found +} + +const readJson = (name: string, file: string): ReadonlyArray => + decodeIds(readFileSync(join(ROOT, name, file), "utf8")) + +describe("Go fixtures", () => { + // go list -m all walks the whole module graph, including test-only deps of deps that go.mod never pins. + it("go.mod modules are a subset of the full module graph", async () => { + const parsed = ids(await parseFixture(fixture("go-mod/basic"))) + expect(readJson("go-mod/basic", "module-graph.json")).toEqual(expect.arrayContaining([...parsed])) + }) + + // go.sum keeps zip hashes only for modules whose code was downloaded, all of them in the graph. + it("go.sum modules are a subset of the module graph and a superset of go.mod", async () => { + const sum = await parseFixture(fixture("go-sum/basic")) + const mod = ids(await parseFixture(fixture("go-mod/basic"))).filter( + (id) => !id.startsWith("golang.org/x/text@"), + ) + expect(fixture("go-sum/basic").expected).toEqual(expect.arrayContaining([...ids(sum)])) + expect(ids(sum)).toEqual(expect.arrayContaining(mod)) + expect(new Set(sum.packages.map((p) => p.relation))).toEqual(new Set(["unknown"])) + expect(sum.warnings).toHaveLength(1) + }) + + it("marks requires direct unless commented indirect and applies replace", async () => { + const parsed = await parseFixture(fixture("go-mod/basic")) + expect(relationOf(parsed, "github.com/gin-gonic/gin")).toEqual(["direct"]) + expect(relationOf(parsed, "golang.org/x/net")).toEqual(["direct"]) + expect(relationOf(parsed, "golang.org/x/crypto")).toEqual(["transitive"]) + expect(parsed.packages.filter((p) => p.name === "golang.org/x/text").map((p) => p.version)).toEqual([ + "v0.8.0", + ]) + }) +}) + +const APP_FIXTURES = [ + "package-lock/v1", + "package-lock/v2", + "package-lock/v3", + "pnpm-lock/v5", + "pnpm-lock/v6", + "pnpm-lock/v9", + "yarn-v1/basic", + "yarn-berry/basic", + "bun-lock/basic", +] +const WORKSPACE_FIXTURES = ["package-lock/workspace", "pnpm-lock/workspace", "bun-lock/workspace"] + +describe("npm relations", () => { + it.each([...APP_FIXTURES, ...WORKSPACE_FIXTURES])( + "%s: dependencies direct, devDependencies dev", + async (name) => { + const parsed = await parseFixture(fixture(name)) + expect(relationOf(parsed, "lodash")).toEqual(["direct"]) + expect(relationOf(parsed, "express")).toEqual(["direct"]) + expect(relationOf(parsed, "minimist")).toEqual(["dev"]) + expect(relationOf(parsed, "accepts")).toEqual(["transitive"]) + expect(parsed.packages.every((p) => p.ecosystem === "npm")).toBe(true) + }, + ) + + it.each(WORKSPACE_FIXTURES)("%s: workspace packages are not reported", async (name) => { + const parsed = await parseFixture(fixture(name)) + expect(parsed.packages.filter((p) => p.name.startsWith("@fx/"))).toEqual([]) + }) + + it.each(["yarn-v1/basic", "yarn-berry/basic"])( + "%s: relations are unknown without manifests", + async (name) => { + const parsed = await parseFixture(fixture(name), false) + expect(new Set(parsed.packages.map((p) => p.relation))).toEqual(new Set(["unknown"])) + expect(parsed.warnings.some((w) => w.includes("package.json"))).toBe(true) + }, + ) + + it("detects berry from content and resolves its builtin patch entry to the npm version", async () => { + const parsed = await parseFixture(fixture("yarn-berry/basic")) + expect(parsed.kind).toBe("yarn-berry") + expect(parsed.packages.filter((p) => p.name === "typescript")).toEqual([ + { ecosystem: "npm", name: "typescript", version: "5.4.5", relation: "dev" }, + ]) + }) +}) + +describe("Cargo fixture", () => { + it("marks the root crate's dependencies direct and skips the workspace member", async () => { + const parsed = await parseFixture(fixture("cargo-lock/basic")) + expect(relationOf(parsed, "time")).toEqual(["direct"]) + expect(relationOf(parsed, "h2")).toEqual(["direct"]) + expect(relationOf(parsed, "bytes")).toEqual(["transitive"]) + expect(relationOf(parsed, "fx")).toEqual([]) + expect(parsed.packages.every((p) => p.ecosystem === "crates.io")).toBe(true) + }) +}) diff --git a/lib/lockfiles/src/index.ts b/lib/lockfiles/src/index.ts new file mode 100644 index 0000000000..1de5190282 --- /dev/null +++ b/lib/lockfiles/src/index.ts @@ -0,0 +1,12 @@ +export type { + Ecosystem, + LockedPackage, + LockfileInput, + LockfileKind, + ParsedLockfile, + Relation, +} from "./types.ts" +export { LockfileParseError, LockfileUnsupportedError } from "./errors.ts" +export { isIgnoredLockfilePath, lockfileKindOf } from "./paths.ts" +export { parseLockfile } from "./parse.ts" +export { compareCargoVersions, compareGoVersions, compareNpmVersions, compareVersions } from "./versions.ts" diff --git a/lib/lockfiles/src/internal/collect.ts b/lib/lockfiles/src/internal/collect.ts new file mode 100644 index 0000000000..57c1f20fdb --- /dev/null +++ b/lib/lockfiles/src/internal/collect.ts @@ -0,0 +1,50 @@ +import type { Ecosystem, LockedPackage, Relation } from "../types.ts" + +const RANK = { direct: 3, dev: 2, transitive: 1, unknown: 0 } satisfies Record + +const strongest = (a: Relation, b: Relation): Relation => (RANK[a] >= RANK[b] ? a : b) + +/** One entry per (name, version), keeping the strongest relation, sorted for stable output. */ +export const dedupePackages = (packages: ReadonlyArray): ReadonlyArray => { + const byKey = packages.reduce((acc, pkg) => { + const key = `${pkg.name}@${pkg.version}` + const seen = acc.get(key) + acc.set(key, seen === undefined ? pkg : { ...seen, relation: strongest(seen.relation, pkg.relation) }) + return acc + }, new Map()) + return [...byKey.values()].sort((a, b) => + a.name === b.name + ? a.version < b.version + ? -1 + : a.version > b.version + ? 1 + : 0 + : a.name < b.name + ? -1 + : 1, + ) +} + +export const pkg = ( + ecosystem: Ecosystem, + name: string, + version: string, + relation: Relation, +): LockedPackage => ({ + ecosystem, + name, + version, + relation, +}) + +/** Splits `name@version` (scoped names keep their leading `@`). */ +export const splitNameAt = (spec: string): { readonly name: string; readonly rest: string } | undefined => { + const at = spec.indexOf("@", 1) + return at <= 0 ? undefined : { name: spec.slice(0, at), rest: spec.slice(at + 1) } +} + +/** Registry versions start with a digit; protocols (file:, link:, git+...) and URLs do not. */ +export const isRegistryVersion = (version: string): boolean => /^\d[^:/\s]*$/.test(version) + +export const isRecord = (u: unknown): u is Record => + typeof u === "object" && u !== null && !Array.isArray(u) diff --git a/lib/lockfiles/src/internal/decode.ts b/lib/lockfiles/src/internal/decode.ts new file mode 100644 index 0000000000..2058ffd1d7 --- /dev/null +++ b/lib/lockfiles/src/internal/decode.ts @@ -0,0 +1,44 @@ +import { Effect, Schema } from "effect" +import { parse as parseToml } from "smol-toml" +import { parse as parseYaml } from "yaml" +import { LockfileParseError } from "../errors.ts" + +const parseError = (path: string, what: string) => (cause: unknown) => + new LockfileParseError({ + path, + message: `${what}: ${cause instanceof Error ? cause.message : String(cause)}`, + }) + +/** Matches a JSON string literal (kept) or a trailing comma before `]`/`}` (dropped). */ +const STRING_OR_TRAILING_COMMA = /"(?:[^"\\]|\\.)*"|,(\s*[\]}])/g + +export const stripTrailingCommas = (text: string): string => + text.replace(STRING_OR_TRAILING_COMMA, (match: string, closer: string | undefined) => closer ?? match) + +export const decodeJson = ( + schema: Schema.Decoder, + path: string, + content: string, +): Effect.Effect => + Schema.decodeEffect(Schema.fromJsonString(schema))(content).pipe( + Effect.mapError(parseError(path, "invalid JSON lockfile")), + ) + +export const decodeUnknown = ( + schema: Schema.Decoder, + path: string, + input: unknown, +): Effect.Effect => + Schema.decodeUnknownEffect(schema)(input).pipe( + Effect.mapError(parseError(path, "unexpected lockfile shape")), + ) + +export const parseYamlText = (path: string, content: string): Effect.Effect => + Effect.try({ + // The library's alias cap stops a lockfile of nested anchors from expanding past memory. + try: () => parseYaml(content), + catch: parseError(path, "invalid YAML"), + }) + +export const parseTomlText = (path: string, content: string): Effect.Effect => + Effect.try({ try: () => parseToml(content), catch: parseError(path, "invalid TOML") }) diff --git a/lib/lockfiles/src/internal/manifests.ts b/lib/lockfiles/src/internal/manifests.ts new file mode 100644 index 0000000000..32212ff766 --- /dev/null +++ b/lib/lockfiles/src/internal/manifests.ts @@ -0,0 +1,59 @@ +import { Effect, Schema } from "effect" +import { decodeJson } from "./decode.ts" + +const Deps = Schema.optionalKey(Schema.Record(Schema.String, Schema.String)) + +const PackageJson = Schema.Struct({ + name: Schema.optionalKey(Schema.String), + dependencies: Deps, + devDependencies: Deps, + optionalDependencies: Deps, + peerDependencies: Deps, +}) + +/** Dependency name to the ranges manifests request it with. */ +export type RangesByName = ReadonlyMap> + +export interface ManifestDeps { + readonly direct: RangesByName + readonly dev: RangesByName + /** Names of the workspace packages themselves. */ + readonly local: ReadonlySet + readonly warnings: ReadonlyArray + readonly found: boolean +} + +const addRanges = (target: Map>, deps: Readonly> | undefined) => + Object.entries(deps ?? {}).forEach(([name, range]) => { + const ranges = target.get(name) ?? new Set() + ranges.add(range) + target.set(name, ranges) + }) + +/** Reads every `package.json` among the manifests; an undecodable one becomes a warning. */ +export const readPackageJsons = Effect.fn("lockfiles.readPackageJsons")(function* ( + manifests: ReadonlyMap | undefined, +) { + const entries = [...(manifests ?? new Map())].filter( + ([path]) => path === "package.json" || path.endsWith("/package.json"), + ) + const decoded = yield* Effect.forEach(entries, ([path, content]) => + decodeJson(PackageJson, path, content).pipe(Effect.result), + ) + const direct = new Map>() + const dev = new Map>() + const local = new Set() + const warnings = decoded.flatMap((result) => { + if (result._tag === "Failure") + return [`skipped manifest ${result.failure.path}: ${result.failure.message}`] + const manifest = result.success + if (manifest.name !== undefined) local.add(manifest.name) + addRanges(direct, manifest.dependencies) + addRanges(direct, manifest.optionalDependencies) + addRanges(direct, manifest.peerDependencies) + addRanges(dev, manifest.devDependencies) + return [] + }) + const result: ManifestDeps = { direct, dev, local, warnings, found: entries.length > 0 } + return result +}) diff --git a/lib/lockfiles/src/parse.test.ts b/lib/lockfiles/src/parse.test.ts new file mode 100644 index 0000000000..671060082d --- /dev/null +++ b/lib/lockfiles/src/parse.test.ts @@ -0,0 +1,348 @@ +import { Effect } from "effect" +import { describe, expect, it } from "vitest" +import { isIgnoredLockfilePath, lockfileKindOf, parseLockfile, type ParsedLockfile } from "./index.ts" + +const parse = (path: string, content: string, manifests?: Record): Promise => + Effect.runPromise( + parseLockfile({ + path, + content, + manifests: manifests === undefined ? undefined : new Map(Object.entries(manifests)), + }), + ) + +const failure = (path: string, content: string) => + Effect.runPromise(Effect.flip(parseLockfile({ path, content }))) + +const summary = (parsed: ParsedLockfile): ReadonlyArray => + parsed.packages.map((p) => `${p.name}@${p.version}:${p.relation}`) + +describe("lockfileKindOf / isIgnoredLockfilePath", () => { + it.each([ + ["package-lock.json", "package-lock"], + ["apps/web/npm-shrinkwrap.json", "package-lock"], + ["pnpm-lock.yaml", "pnpm-lock"], + ["a/yarn.lock", "yarn-v1"], + ["bun.lock", "bun-lock"], + ["bun.lockb", "bun-lockb"], + ["svc/go.mod", "go-mod"], + ["go.sum", "go-sum"], + ["crates/x/Cargo.lock", "cargo-lock"], + ["package.json", undefined], + ["cargo.lock", undefined], + ["yarn.lock.bak", undefined], + ])("%s is %s", (path, kind) => { + expect(lockfileKindOf(path)).toBe(kind) + }) + + it.each([ + ["node_modules/x/package-lock.json", true], + ["a/vendor/go.mod", true], + ["pkg/testdata/go.sum", true], + ["test/fixtures/yarn.lock", true], + ["src/__fixtures__/bun.lock", true], + [".git/x/Cargo.lock", true], + ["apps/web/package-lock.json", false], + ["vendored/go.mod", false], + ])("%s ignored: %s", (path, ignored) => { + expect(isIgnoredLockfilePath(path)).toBe(ignored) + }) +}) + +describe("unsupported and malformed input", () => { + it("rejects bun.lockb with the text-lockfile instruction", async () => { + const error = await failure("bun.lockb", "\u0000binary") + expect(error._tag).toBe("@maple/lockfiles/LockfileUnsupportedError") + expect(error.message).toContain("bun install --save-text-lockfile") + }) + + it("rejects files that are not lockfiles", async () => { + expect((await failure("requirements.txt", "flask==1.0"))._tag).toBe( + "@maple/lockfiles/LockfileUnsupportedError", + ) + }) + + it.each([ + ["package-lock.json", "{ not json"], + ["package-lock.json", '{"packages": {"node_modules/a": {"version": 1}}}'], + ["pnpm-lock.yaml", "packages: [unclosed"], + ["pnpm-lock.yaml", "just: a map"], + ["yarn.lock", '__metadata:\n version: 8\n"a@npm:1": [\n'], + ["yarn.lock", 'lodash@^4:\n resolved "x"\n'], + ["bun.lock", '{"lockfileVersion": 1, "packages": {'], + ["go.mod", "module x\nrequire (\n\tgithub.com/a/b\n)\n"], + ["go.mod", "this is not go.mod\n"], + ["go.mod", "module x\nrequire (\n"], + ["go.sum", "github.com/a/b v1.0.0\n"], + ["Cargo.lock", '[[package]]\nname = "a"\nversion = '], + ["Cargo.lock", '[[package]]\nversion = "1.0.0"\n'], + ])("%s: %j fails with LockfileParseError", async (path, content) => { + const error = await failure(path, content) + expect(error._tag).toBe("@maple/lockfiles/LockfileParseError") + expect(error.path).toBe(path) + }) +}) + +describe("npm lockfile details", () => { + it("package-lock v3: scoped and nested names, link entries skipped, aliases use the real name", async () => { + const lock = { + lockfileVersion: 3, + packages: { + "": { dependencies: { "@types/node": "^20", alias: "npm:left-pad@1.3.0" } }, + "node_modules/@types/node": { version: "20.1.0" }, + "node_modules/@types/node/node_modules/undici-types": { version: "5.26.5" }, + "node_modules/alias": { name: "left-pad", version: "1.3.0" }, + "node_modules/local": { resolved: "packages/local", link: true }, + }, + } + expect(summary(await parse("package-lock.json", JSON.stringify(lock)))).toEqual([ + "@types/node@20.1.0:direct", + "left-pad@1.3.0:direct", + "undici-types@5.26.5:transitive", + ]) + }) + + it("pnpm: v5 and v6 keys with peer suffixes and scopes", async () => { + const v5 = [ + "lockfileVersion: 5.4", + "dependencies:", + " '@emotion/react': 11.0.0_react@18.2.0", + "packages:", + " /@emotion/react/11.0.0_react@18.2.0:", + " dev: false", + " /string_decoder/1.1.1:", + " dev: true", + " /react/18.2.0: {}", + ].join("\n") + expect(summary(await parse("pnpm-lock.yaml", v5))).toEqual([ + "@emotion/react@11.0.0:direct", + "react@18.2.0:transitive", + "string_decoder@1.1.1:dev", + ]) + const v6 = [ + "lockfileVersion: '6.0'", + "devDependencies:", + " '@testing-library/react':", + " specifier: ^14", + " version: 14.0.0(react-dom@18.2.0)(react@18.2.0)", + "packages:", + " /@testing-library/react@14.0.0(react-dom@18.2.0)(react@18.2.0):", + " dev: true", + ].join("\n") + expect(summary(await parse("pnpm-lock.yaml", v6))).toEqual(["@testing-library/react@14.0.0:dev"]) + }) + + it("pnpm v9: snapshots peer suffixes collapse onto the package", async () => { + const v9 = [ + "lockfileVersion: '9.0'", + "importers:", + " .:", + " dependencies:", + " '@tanstack/react-query':", + " specifier: ^5", + " version: 5.0.0(react@18.2.0)", + " local:", + " specifier: link:../local", + " version: link:../local", + "packages:", + " '@tanstack/react-query@5.0.0':", + " resolution: {integrity: sha512-x}", + " react@18.2.0:", + " resolution: {integrity: sha512-y}", + "snapshots:", + " '@tanstack/react-query@5.0.0(react@18.2.0)':", + " dependencies:", + " react: 18.2.0", + " react@18.2.0: {}", + ].join("\n") + expect(summary(await parse("pnpm-lock.yaml", v9))).toEqual([ + "@tanstack/react-query@5.0.0:direct", + "react@18.2.0:transitive", + ]) + }) + + it("yarn v1: scoped multi-specifier headers, aliases and git entries", async () => { + const lock = [ + "# yarn lockfile v1", + "", + '"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4":', + ' version "7.12.13"', + ' resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz"', + "", + '"pad@npm:left-pad@1.3.0":', + ' version "1.3.0"', + "", + '"mylib@github:me/mylib#abc":', + ' version "0.1.0"', + ].join("\n") + const parsed = await parse("yarn.lock", lock, { + "package.json": JSON.stringify({ + devDependencies: { "@babel/code-frame": "^7.10.4" }, + dependencies: { pad: "npm:left-pad@1.3.0" }, + }), + }) + expect(summary(parsed)).toEqual(["@babel/code-frame@7.12.13:dev", "left-pad@1.3.0:direct"]) + expect(parsed.warnings).toEqual(["skipped 1 non-registry packages (git, tarball or local)"]) + }) + + it("yarn berry: patch entries resolve to the underlying npm version, workspaces are skipped", async () => { + const lock = [ + "__metadata:", + " version: 8", + '"resolve@npm:^1.20.0":', + " version: 1.22.8", + ' resolution: "resolve@npm:1.22.8"', + '"resolve@patch:resolve@npm%3A^1.20.0#optional!builtin":', + " version: 1.22.8", + ' resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d"', + '"@scope/pkg@npm:2.0.0":', + " version: 2.0.0", + ' resolution: "@scope/pkg@npm:2.0.0"', + '"app@workspace:.":', + " version: 0.0.0-use.local", + ' resolution: "app@workspace:."', + ].join("\n") + const parsed = await parse("yarn.lock", lock, { + "package.json": JSON.stringify({ name: "app", dependencies: { resolve: "^1.20.0" } }), + }) + expect(parsed.kind).toBe("yarn-berry") + expect(summary(parsed)).toEqual(["@scope/pkg@2.0.0:transitive", "resolve@1.22.8:direct"]) + expect(parsed.warnings).toEqual([]) + }) + + it("bun.lock: JSONC trailing commas outside strings, comma-bracket text inside strings kept", async () => { + const lock = `{ + "lockfileVersion": 1, + "workspaces": { "": { "name": "app", "dependencies": { "@scope/a": "^1", }, }, }, + "packages": { + "@scope/a": ["@scope/a@1.0.0", "", { "dependencies": { "b": "2" } }, "sha512-,]"], + "@scope/a/b": ["b@2.0.0", "", {}, "sha512-y"], + "c": ["c@github:me/c#abc", {}], + }, +}` + const parsed = await parse("bun.lock", lock) + expect(summary(parsed)).toEqual(["@scope/a@1.0.0:direct", "b@2.0.0:transitive"]) + expect(parsed.warnings).toEqual(["skipped 1 non-registry packages (git, tarball or local)"]) + }) + + it("deduplicates by name and version, keeping the strongest relation", async () => { + const lock = { + lockfileVersion: 3, + packages: { + "": { dependencies: { ms: "2.1.3" } }, + "packages/a": { devDependencies: { ms: "2.1.3" } }, + "node_modules/ms": { version: "2.1.3" }, + "node_modules/debug/node_modules/ms": { version: "2.1.3", dev: true }, + "node_modules/x/node_modules/ms": { version: "2.0.0", dev: true }, + }, + } + expect(summary(await parse("package-lock.json", JSON.stringify(lock)))).toEqual([ + "ms@2.0.0:dev", + "ms@2.1.3:direct", + ]) + }) +}) + +describe("package-lock v1 aliases", () => { + it("reports an npm: alias under the real package name and version", async () => { + const lock = { + lockfileVersion: 1, + dependencies: { + "lodash-old": { version: "npm:lodash@4.17.15" }, + "@scope/alias": { version: "npm:@babel/core@7.0.0", dev: true }, + }, + } + const manifest = JSON.stringify({ dependencies: { "lodash-old": "npm:lodash@4.17.15" } }) + expect( + summary(await parse("package-lock.json", JSON.stringify(lock), { "package.json": manifest })), + ).toEqual(expect.arrayContaining(["lodash@4.17.15:direct", "@babel/core@7.0.0:dev"])) + }) +}) + +describe("go.mod replace precedence", () => { + it("lets a version-specific replace win over a wildcard written before it", async () => { + const mod = [ + "module example.com/app", + "go 1.22", + "require example.com/x v1.0.0", + "replace example.com/x => example.com/y v2.0.0", + "replace example.com/x v1.0.0 => example.com/z v3.0.0", + ].join("\n") + expect(summary(await parse("go.mod", mod))).toEqual(["example.com/z@v3.0.0:direct"]) + }) +}) + +describe("Go and Cargo details", () => { + it("go.mod: single-line requires, local replacements dropped, versioned replacements scoped", async () => { + const mod = [ + "module example.com/app", + "", + "go 1.22", + "toolchain go1.22.1", + "", + "require github.com/a/b v1.2.3", + "require (", + '\t"github.com/c/d" v0.0.0-20191109021931-daa7c04131f5 // indirect', + "\tgithub.com/e/f v2.0.0+incompatible", + "\tgithub.com/local/x v1.0.0", + "\tgithub.com/g/h v1.1.0 // indirect; pinned", + ")", + "exclude github.com/a/b v1.2.2", + "replace github.com/local/x => ../x", + "replace (", + "\tgithub.com/g/h v1.0.0 => github.com/g/h v1.0.1", + "\tgithub.com/e/f => github.com/fork/f v2.1.0+incompatible", + ")", + "retract v0.1.0", + ].join("\n") + const parsed = await parse("go.mod", mod) + expect(summary(parsed)).toEqual([ + "github.com/a/b@v1.2.3:direct", + "github.com/c/d@v0.0.0-20191109021931-daa7c04131f5:transitive", + "github.com/fork/f@v2.1.0+incompatible:direct", + "github.com/g/h@v1.1.0:transitive", + ]) + expect(parsed.warnings).toEqual(["github.com/local/x is replaced by a local directory"]) + expect(parsed.packages.every((p) => p.ecosystem === "Go")).toBe(true) + }) + + it("go.sum: keeps module zip lines only", async () => { + const sum = [ + "github.com/a/b v1.2.3 h1:abc=", + "github.com/a/b v1.2.3/go.mod h1:def=", + "github.com/c/d v0.1.0/go.mod h1:ghi=", + ].join("\n") + expect(summary(await parse("go.sum", sum))).toEqual(["github.com/a/b@v1.2.3:unknown"]) + }) + + it("Cargo.lock: v1 style versioned member deps, git and path packages skipped", async () => { + const lock = [ + "[[package]]", + 'name = "app"', + 'version = "0.1.0"', + 'dependencies = ["serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "mine", "local"]', + "", + "[[package]]", + 'name = "serde"', + 'version = "1.0.100"', + 'source = "registry+https://github.com/rust-lang/crates.io-index"', + "", + "[[package]]", + 'name = "serde"', + 'version = "0.9.0"', + 'source = "sparse+https://index.crates.io/"', + "", + "[[package]]", + 'name = "mine"', + 'version = "0.2.0"', + 'source = "git+https://github.com/me/mine#abc"', + "", + "[[package]]", + 'name = "local"', + 'version = "0.1.0"', + ].join("\n") + const parsed = await parse("Cargo.lock", lock) + expect(summary(parsed)).toEqual(["serde@0.9.0:transitive", "serde@1.0.100:direct"]) + expect(parsed.warnings).toEqual(["skipped 1 git or path packages"]) + }) +}) diff --git a/lib/lockfiles/src/parse.ts b/lib/lockfiles/src/parse.ts new file mode 100644 index 0000000000..33f9aef5e7 --- /dev/null +++ b/lib/lockfiles/src/parse.ts @@ -0,0 +1,49 @@ +import { Effect } from "effect" +import { LockfileParseError, LockfileUnsupportedError } from "./errors.ts" +import { dedupePackages } from "./internal/collect.ts" +import { parseBunLock } from "./parsers/bun.ts" +import { parseCargoLock } from "./parsers/cargo.ts" +import { parseGoMod, parseGoSum } from "./parsers/go.ts" +import { parsePackageLock } from "./parsers/packageLock.ts" +import { parsePnpmLock } from "./parsers/pnpm.ts" +import type { Parser } from "./parsers/types.ts" +import { parseYarnLock } from "./parsers/yarn.ts" +import { lockfileKindOf } from "./paths.ts" +import type { LockfileInput, LockfileKind, ParsedLockfile } from "./types.ts" + +const PARSERS = { + "package-lock": parsePackageLock, + "pnpm-lock": parsePnpmLock, + "yarn-v1": parseYarnLock, + "yarn-berry": parseYarnLock, + "bun-lock": parseBunLock, + "go-mod": parseGoMod, + "go-sum": parseGoSum, + "cargo-lock": parseCargoLock, +} satisfies Record, Parser> + +export const parseLockfile = Effect.fn("lockfiles.parseLockfile")(function* ( + input: LockfileInput, +): Effect.fn.Return { + const kind = lockfileKindOf(input.path) + if (kind === undefined) { + return yield* new LockfileUnsupportedError({ + path: input.path, + message: `not a supported lockfile: ${input.path}`, + }) + } + if (kind === "bun-lockb") { + return yield* new LockfileUnsupportedError({ + path: input.path, + message: + "bun.lockb is binary: run `bun install --save-text-lockfile` and commit the generated bun.lock", + }) + } + const output = yield* PARSERS[kind](input) + return { + path: input.path, + kind: output.kind, + packages: dedupePackages(output.packages), + warnings: output.warnings, + } +}) diff --git a/lib/lockfiles/src/parsers/bun.ts b/lib/lockfiles/src/parsers/bun.ts new file mode 100644 index 0000000000..21fad4b643 --- /dev/null +++ b/lib/lockfiles/src/parsers/bun.ts @@ -0,0 +1,84 @@ +import { Effect, Schema } from "effect" +import { isRegistryVersion, pkg, splitNameAt } from "../internal/collect.ts" +import { decodeJson, stripTrailingCommas } from "../internal/decode.ts" +import type { LockedPackage, LockfileInput, Relation } from "../types.ts" +import type { ParserOutput } from "./types.ts" + +const Deps = Schema.optionalKey(Schema.Record(Schema.String, Schema.String)) + +const Workspace = Schema.Struct({ + name: Schema.optionalKey(Schema.String), + dependencies: Deps, + devDependencies: Deps, + optionalDependencies: Deps, + peerDependencies: Deps, +}) +type Workspace = typeof Workspace.Type + +const BunLock = Schema.Struct({ + lockfileVersion: Schema.Finite, + workspaces: Schema.optionalKey(Schema.Record(Schema.String, Workspace)), + packages: Schema.optionalKey(Schema.Record(Schema.String, Schema.Array(Schema.Unknown))), +}) + +/** Package keys are install paths of dependency names (`express/debug`, `@fx/a/lodash`); split them. */ +const keySegments = (key: string): ReadonlyArray => + key.split("/").reduce>((segments, part) => { + const last = segments.at(-1) + if (last !== undefined && last.startsWith("@") && !last.includes("/")) + segments[segments.length - 1] = `${last}/${part}` + else segments.push(part) + return segments + }, []) + +interface DepNames { + readonly direct: ReadonlySet + readonly dev: ReadonlySet +} + +const namesOf = (workspaces: ReadonlyArray): DepNames => ({ + direct: new Set( + workspaces.flatMap((w) => [ + ...Object.keys(w.dependencies ?? {}), + ...Object.keys(w.optionalDependencies ?? {}), + ...Object.keys(w.peerDependencies ?? {}), + ]), + ), + dev: new Set(workspaces.flatMap((w) => Object.keys(w.devDependencies ?? {}))), +}) + +export const parseBunLock = Effect.fn("lockfiles.parseBunLock")(function* (input: LockfileInput) { + const lock = yield* decodeJson(BunLock, input.path, stripTrailingCommas(input.content)) + const workspaces = Object.values(lock.workspaces ?? {}) + const all = namesOf(workspaces) + const byWorkspaceName = new Map( + workspaces.flatMap((w): ReadonlyArray => + w.name === undefined ? [] : [[w.name, namesOf([w])]], + ), + ) + const entries = Object.entries(lock.packages ?? {}).map(([key, entry]) => ({ + key, + spec: typeof entry[0] === "string" ? splitNameAt(entry[0]) : undefined, + })) + const skipped = entries.filter( + ({ spec }) => + spec === undefined || !(isRegistryVersion(spec.rest) || spec.rest.startsWith("workspace:")), + ).length + const packages = entries.flatMap(({ key, spec }): ReadonlyArray => { + if (spec === undefined || !isRegistryVersion(spec.rest)) return [] + const segments = keySegments(key) + const parent = segments.slice(0, -1).join("/") + const depName = segments.at(-1) ?? "" + const scope = parent === "" ? all : byWorkspaceName.get(parent) + const relation: Relation = + scope?.direct.has(depName) === true + ? "direct" + : scope?.dev.has(depName) === true + ? "dev" + : "transitive" + return [pkg("npm", spec.name, spec.rest, relation)] + }) + const warnings = skipped > 0 ? [`skipped ${skipped} non-registry packages (git, tarball or local)`] : [] + const output: ParserOutput = { kind: "bun-lock", packages, warnings } + return output +}) diff --git a/lib/lockfiles/src/parsers/cargo.ts b/lib/lockfiles/src/parsers/cargo.ts new file mode 100644 index 0000000000..ca01b4f695 --- /dev/null +++ b/lib/lockfiles/src/parsers/cargo.ts @@ -0,0 +1,47 @@ +import { Effect, Schema } from "effect" +import { pkg } from "../internal/collect.ts" +import { decodeUnknown, parseTomlText } from "../internal/decode.ts" +import type { LockedPackage, LockfileInput } from "../types.ts" +import type { ParserOutput } from "./types.ts" + +const CargoPackage = Schema.Struct({ + name: Schema.String, + version: Schema.String, + source: Schema.optionalKey(Schema.String), + dependencies: Schema.optionalKey(Schema.Array(Schema.String)), +}) + +const CargoLock = Schema.Struct({ + package: Schema.optionalKey(Schema.Array(CargoPackage)), +}) + +/** Registry sources: `registry+` or `sparse+`; git and path sources are not. */ +const isRegistrySource = (source: string | undefined): boolean => + source !== undefined && (source.startsWith("registry+") || source.startsWith("sparse+")) + +/** Member dependency entries: `name`, `name version` or `name version (source)`. */ +const parseDependency = (entry: string): { readonly name: string; readonly version: string | undefined } => { + const [name = "", version] = entry.trim().split(/\s+/) + return { name, version } +} + +export const parseCargoLock = Effect.fn("lockfiles.parseCargoLock")(function* (input: LockfileInput) { + const lock = yield* decodeUnknown(CargoLock, input.path, yield* parseTomlText(input.path, input.content)) + const all = lock.package ?? [] + const members = all.filter((p) => p.source === undefined) + const directDeps = members.flatMap((m) => (m.dependencies ?? []).map(parseDependency)) + const direct = new Set( + directDeps.map((d) => (d.version === undefined ? d.name : `${d.name}@${d.version}`)), + ) + const isDirect = (name: string, version: string): boolean => + direct.has(name) || direct.has(`${name}@${version}`) + const packages = all.flatMap((p): ReadonlyArray => + isRegistrySource(p.source) + ? [pkg("crates.io", p.name, p.version, isDirect(p.name, p.version) ? "direct" : "transitive")] + : [], + ) + const skipped = all.length - members.length - packages.length + const warnings = skipped > 0 ? [`skipped ${skipped} git or path packages`] : [] + const output: ParserOutput = { kind: "cargo-lock", packages, warnings } + return output +}) diff --git a/lib/lockfiles/src/parsers/go.ts b/lib/lockfiles/src/parsers/go.ts new file mode 100644 index 0000000000..8e0eb2e2e9 --- /dev/null +++ b/lib/lockfiles/src/parsers/go.ts @@ -0,0 +1,147 @@ +import { Effect } from "effect" +import { LockfileParseError } from "../errors.ts" +import { pkg } from "../internal/collect.ts" +import type { LockedPackage, LockfileInput } from "../types.ts" +import type { ParserOutput } from "./types.ts" + +interface Require { + readonly path: string + readonly version: string + readonly indirect: boolean +} + +interface Replace { + readonly oldPath: string + readonly oldVersion: string | undefined + readonly newPath: string + readonly newVersion: string | undefined +} + +interface GoModState { + readonly block: string | undefined + readonly requires: ReadonlyArray + readonly replaces: ReadonlyArray + readonly errors: ReadonlyArray +} + +const DIRECTIVES = new Set([ + "module", + "go", + "toolchain", + "require", + "replace", + "exclude", + "retract", + "tool", + "godebug", + "ignore", +]) + +const tokenize = (code: string): ReadonlyArray => + code + .split(/\s+/) + .filter((t) => t !== "") + .map((t) => t.replace(/^"(.*)"$/, "$1").replace(/^`(.*)`$/, "$1")) + +const parseReplace = (tokens: ReadonlyArray): Replace | undefined => { + const arrow = tokens.indexOf("=>") + const left = tokens.slice(0, arrow) + const right = tokens.slice(arrow + 1) + const [oldPath, oldVersion] = left + const [newPath, newVersion] = right + if (arrow === -1 || oldPath === undefined || newPath === undefined || left.length > 2 || right.length > 2) + return undefined + return { oldPath, oldVersion, newPath, newVersion } +} + +/** Applies one directive line (`require x v1`, or a bare `x v1` inside a block) to the state. */ +const apply = ( + state: GoModState, + kind: string, + tokens: ReadonlyArray, + indirect: boolean, + line: string, +): GoModState => { + if (kind === "require") { + const [path, version] = tokens + return path !== undefined && version !== undefined && tokens.length === 2 + ? { ...state, requires: [...state.requires, { path, version, indirect }] } + : { ...state, errors: [...state.errors, `bad require: ${line}`] } + } + if (kind === "replace") { + const replace = parseReplace(tokens) + return replace === undefined + ? { ...state, errors: [...state.errors, `bad replace: ${line}`] } + : { ...state, replaces: [...state.replaces, replace] } + } + return state +} + +const step = (state: GoModState, rawLine: string): GoModState => { + const commentAt = rawLine.indexOf("//") + const code = (commentAt === -1 ? rawLine : rawLine.slice(0, commentAt)).trim() + const indirect = commentAt !== -1 && /^\/\/\s*indirect\b/.test(rawLine.slice(commentAt)) + if (code === "") return state + if (state.block !== undefined) { + return code === ")" + ? { ...state, block: undefined } + : apply(state, state.block, tokenize(code), indirect, code) + } + const [directive = "", ...rest] = tokenize(code) + if (!DIRECTIVES.has(directive)) + return { ...state, errors: [...state.errors, `unknown directive: ${code}`] } + if (rest.length === 1 && rest[0] === "(") return { ...state, block: directive } + return apply(state, directive, rest, indirect, code) +} + +const resolve = (req: Require, replaces: ReadonlyArray): Require | undefined => { + // A version-specific replace wins over a wildcard one, wherever each appears in the file. + const match = + replaces.find((r) => r.oldPath === req.path && r.oldVersion === req.version) ?? + replaces.find((r) => r.oldPath === req.path && r.oldVersion === undefined) + if (match === undefined) return req + return match.newVersion === undefined + ? undefined + : { ...req, path: match.newPath, version: match.newVersion } +} + +export const parseGoMod = Effect.fn("lockfiles.parseGoMod")(function* (input: LockfileInput) { + const initial: GoModState = { block: undefined, requires: [], replaces: [], errors: [] } + const state = input.content.split(/\r?\n/).reduce(step, initial) + const errors = + state.block === undefined ? state.errors : [...state.errors, `unclosed ${state.block} block`] + if (errors.length > 0) + return yield* new LockfileParseError({ path: input.path, message: errors.slice(0, 3).join("; ") }) + const resolved = state.requires.map((req) => ({ req, to: resolve(req, state.replaces) })) + const packages = resolved.flatMap(({ to }): ReadonlyArray => + to === undefined ? [] : [pkg("Go", to.path, to.version, to.indirect ? "transitive" : "direct")], + ) + const warnings = resolved.flatMap(({ req, to }) => + to === undefined ? [`${req.path} is replaced by a local directory`] : [], + ) + const output: ParserOutput = { kind: "go-mod", packages, warnings } + return output +}) + +export const parseGoSum = Effect.fn("lockfiles.parseGoSum")(function* (input: LockfileInput) { + const lines = input.content + .split(/\r?\n/) + .map((line) => line.trim()) + .filter((line) => line !== "") + const rows = lines.map((line) => line.split(/\s+/)) + const bad = rows.find((row) => row.length !== 3 || !(row[2] ?? "").includes(":")) + if (bad !== undefined) + return yield* new LockfileParseError({ + path: input.path, + message: `bad go.sum line: ${bad.join(" ")}`, + }) + const packages = rows.flatMap(([path = "", version = ""]): ReadonlyArray => + version.endsWith("/go.mod") ? [] : [pkg("Go", path, version, "unknown")], + ) + const output: ParserOutput = { + kind: "go-sum", + packages, + warnings: ["go.sum lists more module versions than the build uses; prefer go.mod when both exist"], + } + return output +}) diff --git a/lib/lockfiles/src/parsers/packageLock.ts b/lib/lockfiles/src/parsers/packageLock.ts new file mode 100644 index 0000000000..50c1af1f26 --- /dev/null +++ b/lib/lockfiles/src/parsers/packageLock.ts @@ -0,0 +1,113 @@ +import { Effect, Schema } from "effect" +import { isRecord, isRegistryVersion, pkg, splitNameAt } from "../internal/collect.ts" +import { decodeJson } from "../internal/decode.ts" +import { readPackageJsons } from "../internal/manifests.ts" +import type { LockedPackage, LockfileInput, Relation } from "../types.ts" +import type { ParserOutput } from "./types.ts" + +const Deps = Schema.optionalKey(Schema.Record(Schema.String, Schema.String)) + +const PackageEntry = Schema.Struct({ + name: Schema.optionalKey(Schema.String), + version: Schema.optionalKey(Schema.String), + dev: Schema.optionalKey(Schema.Boolean), + devOptional: Schema.optionalKey(Schema.Boolean), + link: Schema.optionalKey(Schema.Boolean), + dependencies: Deps, + optionalDependencies: Deps, + peerDependencies: Deps, + devDependencies: Deps, +}) +type PackageEntry = typeof PackageEntry.Type + +const PackageLock = Schema.Struct({ + lockfileVersion: Schema.optionalKey(Schema.Finite), + packages: Schema.optionalKey(Schema.Record(Schema.String, PackageEntry)), + dependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.Unknown)), +}) + +const NODE_MODULES = "node_modules/" + +/** v2/v3: `packages` keyed by install path; roots are "" and workspace dirs (no node_modules segment). */ +const fromPackagesMap = (packages: Readonly>): ReadonlyArray => { + const rootDeps = new Map( + Object.entries(packages) + .filter(([path]) => !path.includes(NODE_MODULES)) + .map(([path, entry]) => [ + path, + new Set([ + ...Object.keys(entry.dependencies ?? {}), + ...Object.keys(entry.optionalDependencies ?? {}), + ...Object.keys(entry.peerDependencies ?? {}), + ]), + ]), + ) + // Workspaces hoist their dependencies into the root node_modules, so the root answers for all of them. + const hoisted = new Set([...rootDeps.values()].flatMap((names) => [...names])) + return Object.entries(packages).flatMap(([path, entry]) => { + const at = path.lastIndexOf(NODE_MODULES) + if (at === -1 || entry.link === true || entry.version === undefined) return [] + const installName = path.slice(at + NODE_MODULES.length) + const name = entry.name ?? installName + if (!isRegistryVersion(entry.version)) return [] + const parent = path.slice(0, Math.max(at - 1, 0)) + const isDirect = (parent === "" ? hoisted : rootDeps.get(parent))?.has(installName) === true + const relation: Relation = isDirect + ? "direct" + : entry.dev === true || entry.devOptional === true + ? "dev" + : "transitive" + return [pkg("npm", name, entry.version, relation)] + }) +} + +/** v1: nested `dependencies` tree; top-level only tells direct apart with the manifest. */ +const fromDependencyTree = ( + deps: Readonly>, + directNames: ReadonlySet | undefined, + topLevel: boolean, +): ReadonlyArray => + Object.entries(deps).flatMap(([name, node]): ReadonlyArray => { + if (!isRecord(node)) return [] + const recorded = typeof node.version === "string" ? node.version : "" + const nested = isRecord(node.dependencies) + ? fromDependencyTree(node.dependencies, directNames, false) + : [] + // An `npm:` alias records the real package as `version: "npm:real@1.0.0"`. + const alias = recorded.startsWith("npm:") ? splitNameAt(recorded.slice("npm:".length)) : undefined + const realName = alias?.name ?? name + const version = alias?.rest ?? recorded + if (!isRegistryVersion(version)) return nested + const relation: Relation = + topLevel && directNames?.has(name) === true + ? "direct" + : node.dev === true + ? "dev" + : directNames === undefined + ? "unknown" + : "transitive" + return [pkg("npm", realName, version, relation), ...nested] + }) + +export const parsePackageLock = Effect.fn("lockfiles.parsePackageLock")(function* (input: LockfileInput) { + const lock = yield* decodeJson(PackageLock, input.path, input.content) + if (lock.packages !== undefined && Object.keys(lock.packages).length > 0) { + const output: ParserOutput = { + kind: "package-lock", + packages: fromPackagesMap(lock.packages), + warnings: [], + } + return output + } + const manifest = yield* readPackageJsons(input.manifests) + const directNames = manifest.found ? new Set(manifest.direct.keys()) : undefined + const warnings = manifest.found + ? manifest.warnings + : [...manifest.warnings, "lockfileVersion 1 without package.json: direct dependencies are unknown"] + const output: ParserOutput = { + kind: "package-lock", + packages: fromDependencyTree(lock.dependencies ?? {}, directNames, true), + warnings, + } + return output +}) diff --git a/lib/lockfiles/src/parsers/pnpm.ts b/lib/lockfiles/src/parsers/pnpm.ts new file mode 100644 index 0000000000..79dc4b4913 --- /dev/null +++ b/lib/lockfiles/src/parsers/pnpm.ts @@ -0,0 +1,103 @@ +import { Effect } from "effect" +import { isRecord, isRegistryVersion, pkg, splitNameAt } from "../internal/collect.ts" +import { parseYamlText } from "../internal/decode.ts" +import { LockfileParseError } from "../errors.ts" +import type { LockedPackage, LockfileInput, Relation } from "../types.ts" +import type { ParserOutput } from "./types.ts" + +interface NameVersion { + readonly name: string + readonly version: string +} + +/** Drops peer suffixes: v6+ `(react@18.2.0)` groups, v5 `_react@18.2.0` tails. */ +const stripPeers = (version: string): string => version.replace(/\(.*$/, "").replace(/_.*$/, "") + +const V5_KEY = /^((?:@[^/]+\/)?[^/@]+)\/(\d[^/]*)$/ + +/** Package keys: v5 `/name/1.0.0`, v6 `/name@1.0.0`, v9 `name@1.0.0`, optionally registry-prefixed. */ +const parsePnpmKey = (key: string): NameVersion | undefined => { + const bare = key + .replace(/\(.*$/, "") + .replace(/^[^/@]*\.[^/@]*\//, "") + .replace(/^\//, "") + const v5 = V5_KEY.exec(bare) + if (v5 !== null) { + const version = stripPeers(v5[2] ?? "") + return isRegistryVersion(version) ? { name: v5[1] ?? "", version } : undefined + } + const at = splitNameAt(bare) + return at !== undefined && isRegistryVersion(at.rest) ? { name: at.name, version: at.rest } : undefined +} + +/** Importer dependency values: v5 a version string, v6+ `{ specifier, version }`; aliases are keys. */ +const importerVersion = (name: string, value: unknown): NameVersion | undefined => { + const raw = + typeof value === "string" + ? value + : isRecord(value) && typeof value.version === "string" + ? value.version + : "" + if (isRegistryVersion(stripPeers(raw))) return { name, version: stripPeers(raw) } + return parsePnpmKey(raw) +} + +const importerKeys = (importer: unknown, fields: ReadonlyArray): ReadonlyArray => + isRecord(importer) + ? fields.flatMap((field) => { + const deps = importer[field] + return isRecord(deps) + ? Object.entries(deps).flatMap(([name, value]) => { + const nv = importerVersion(name, value) + return nv === undefined ? [] : [`${nv.name}@${nv.version}`] + }) + : [] + }) + : [] + +const PROD_FIELDS = ["dependencies", "optionalDependencies"] + +const entryNameVersion = (key: string, value: unknown): NameVersion | undefined => { + const fromKey = parsePnpmKey(key) + if (fromKey !== undefined) return fromKey + // Tarball and git keys carry the registry identity in explicit name/version fields, when they have one. + return isRecord(value) && + typeof value.name === "string" && + typeof value.version === "string" && + isRegistryVersion(value.version) + ? { name: value.name, version: value.version } + : undefined +} + +export const parsePnpmLock = Effect.fn("lockfiles.parsePnpmLock")(function* (input: LockfileInput) { + const doc = yield* parseYamlText(input.path, input.content) + if (!isRecord(doc) || doc.lockfileVersion === undefined) { + return yield* new LockfileParseError({ + path: input.path, + message: "pnpm-lock.yaml has no lockfileVersion", + }) + } + const importers = isRecord(doc.importers) ? Object.values(doc.importers) : [doc] + const direct = new Set(importers.flatMap((importer) => importerKeys(importer, PROD_FIELDS))) + const dev = new Set(importers.flatMap((importer) => importerKeys(importer, ["devDependencies"]))) + const entries = [ + ...(isRecord(doc.packages) ? Object.entries(doc.packages) : []), + ...(isRecord(doc.snapshots) ? Object.entries(doc.snapshots) : []), + ] + const skipped = new Set() + const packages = entries.flatMap(([key, value]): ReadonlyArray => { + const nv = entryNameVersion(key, value) + if (nv === undefined) { + skipped.add(key) + return [] + } + const id = `${nv.name}@${nv.version}` + const devFlag = isRecord(value) && value.dev === true + const relation: Relation = direct.has(id) ? "direct" : dev.has(id) || devFlag ? "dev" : "transitive" + return [pkg("npm", nv.name, nv.version, relation)] + }) + const warnings = + skipped.size > 0 ? [`skipped ${skipped.size} non-registry packages (git, tarball or local)`] : [] + const output: ParserOutput = { kind: "pnpm-lock", packages, warnings } + return output +}) diff --git a/lib/lockfiles/src/parsers/types.ts b/lib/lockfiles/src/parsers/types.ts new file mode 100644 index 0000000000..a40425f43c --- /dev/null +++ b/lib/lockfiles/src/parsers/types.ts @@ -0,0 +1,11 @@ +import type { Effect } from "effect" +import type { LockfileParseError } from "../errors.ts" +import type { LockedPackage, LockfileInput, LockfileKind } from "../types.ts" + +export interface ParserOutput { + readonly kind: LockfileKind + readonly packages: ReadonlyArray + readonly warnings: ReadonlyArray +} + +export type Parser = (input: LockfileInput) => Effect.Effect diff --git a/lib/lockfiles/src/parsers/yarn.ts b/lib/lockfiles/src/parsers/yarn.ts new file mode 100644 index 0000000000..2c9d7151f9 --- /dev/null +++ b/lib/lockfiles/src/parsers/yarn.ts @@ -0,0 +1,149 @@ +import { Effect } from "effect" +import { isRecord, isRegistryVersion, pkg, splitNameAt } from "../internal/collect.ts" +import { parseYamlText } from "../internal/decode.ts" +import { readPackageJsons, type ManifestDeps } from "../internal/manifests.ts" +import type { LockedPackage, LockfileInput, Relation } from "../types.ts" +import { LockfileParseError } from "../errors.ts" +import type { ParserOutput } from "./types.ts" + +interface Specifier { + readonly name: string + readonly range: string +} + +interface Block { + readonly specifiers: ReadonlyArray + readonly version: string | undefined +} + +const unquote = (s: string): string => s.trim().replace(/^"(.*)"$/, "$1") + +const parseSpecifiers = (header: string): ReadonlyArray => + header + .replace(/:\s*$/, "") + .split(",") + .flatMap((raw) => { + const at = splitNameAt(unquote(raw)) + return at === undefined ? [] : [{ name: at.name, range: at.rest }] + }) + +const VERSION_LINE = /^ {2}version:? +"?([^"\s]+)"?\s*$/ + +/** yarn v1: unindented `"a@^1", a@^1.2:` headers, each followed by an indented `version "1.2.3"`. */ +const parseV1Blocks = (content: string): ReadonlyArray => + content.split(/\r?\n/).reduce>((blocks, line) => { + if (line === "" || line.startsWith("#")) return blocks + if (!/^\s/.test(line)) { + blocks.push({ specifiers: parseSpecifiers(line), version: undefined }) + return blocks + } + const version = VERSION_LINE.exec(line)?.[1] + const last = blocks.at(-1) + if (version !== undefined && last !== undefined && last.version === undefined) { + blocks[blocks.length - 1] = { ...last, version } + } + return blocks + }, []) + +/** Real registry name of a specifier: `alias@npm:real@^1` names `real`; non-registry ranges have none. */ +const registryName = (spec: Specifier): string | undefined => { + if (spec.range.startsWith("npm:")) { + const real = splitNameAt(spec.range.slice(4)) + return real === undefined ? spec.name : real.name + } + return /[:/]/.test(spec.range) ? undefined : spec.name +} + +const requestedBy = (ranges: ManifestDeps["direct"], spec: Specifier): boolean => { + const wanted = ranges.get(spec.name) + return ( + wanted !== undefined && + (wanted.has(spec.range) || (spec.range.startsWith("npm:") && wanted.has(spec.range.slice(4)))) + ) +} + +const relationOf = (manifest: ManifestDeps, specs: ReadonlyArray): Relation => + !manifest.found + ? "unknown" + : specs.some((s) => requestedBy(manifest.direct, s)) + ? "direct" + : specs.some((s) => requestedBy(manifest.dev, s)) + ? "dev" + : "transitive" + +const parseYarnV1 = (blocks: ReadonlyArray, manifest: ManifestDeps) => { + const packages = blocks.flatMap((block): ReadonlyArray => { + const first = block.specifiers[0] + const name = first === undefined ? undefined : registryName(first) + if (name === undefined || block.version === undefined || !isRegistryVersion(block.version)) return [] + return [pkg("npm", name, block.version, relationOf(manifest, block.specifiers))] + }) + return { packages, skipped: blocks.length - packages.length } +} + +/** decodeURIComponent throws on stray `%`; this cannot. */ +const percentDecode = (s: string): string => + s.replace(/%([0-9A-Fa-f]{2})/g, (_, hex: string) => String.fromCharCode(Number.parseInt(hex, 16))) + +/** Berry `resolution`: `name@npm:1.0.0`, or a patch wrapping one (`name@patch:name@npm%3A1.0.0#...`). */ +const berryRegistryName = (resolution: string): string | undefined => { + const at = splitNameAt(resolution) + if (at === undefined) return undefined + if (at.rest.startsWith("npm:")) return at.name + if (!at.rest.startsWith("patch:")) return undefined + const inner = at.rest.slice("patch:".length).split("#")[0] ?? "" + return berryRegistryName(percentDecode(inner)) +} + +const parseYarnBerry = (doc: Record, manifest: ManifestDeps) => { + const entries = Object.entries(doc).filter(([key]) => key !== "__metadata") + const packages = entries.flatMap(([key, value]): ReadonlyArray => { + if (!isRecord(value) || typeof value.resolution !== "string") return [] + const name = berryRegistryName(value.resolution) + const version = typeof value.version === "string" ? value.version : "" + if (name === undefined || !isRegistryVersion(version)) return [] + return [pkg("npm", name, version, relationOf(manifest, parseSpecifiers(key)))] + }) + const workspaces = entries.filter(([key]) => key.includes("@workspace:")).length + return { packages, skipped: entries.length - packages.length - workspaces } +} + +const berryResult = Effect.fn(function* (input: LockfileInput, manifest: ManifestDeps) { + const doc = yield* parseYamlText(input.path, input.content) + if (!isRecord(doc)) + return yield* new LockfileParseError({ path: input.path, message: "yarn.lock is not a YAML mapping" }) + return parseYarnBerry(doc, manifest) +}) + +const v1Result = Effect.fn(function* (input: LockfileInput, manifest: ManifestDeps) { + const blocks = parseV1Blocks(input.content) + const broken = blocks.find((b) => b.specifiers.length === 0 || b.version === undefined) + if (broken !== undefined) { + return yield* new LockfileParseError({ + path: input.path, + message: "yarn.lock has an entry without specifiers or version", + }) + } + return parseYarnV1(blocks, manifest) +}) + +const isBerry = (content: string): boolean => /^__metadata:/m.test(content) + +export const parseYarnLock = Effect.fn("lockfiles.parseYarnLock")(function* (input: LockfileInput) { + const manifest = yield* readPackageJsons(input.manifests) + const berry = isBerry(input.content) + const result = berry ? yield* berryResult(input, manifest) : yield* v1Result(input, manifest) + const warnings = [ + ...manifest.warnings, + ...(manifest.found ? [] : ["no package.json provided: relations are unknown"]), + ...(result.skipped > 0 + ? [`skipped ${result.skipped} non-registry packages (git, tarball or local)`] + : []), + ] + const output: ParserOutput = { + kind: berry ? "yarn-berry" : "yarn-v1", + packages: result.packages, + warnings, + } + return output +}) diff --git a/lib/lockfiles/src/paths.ts b/lib/lockfiles/src/paths.ts new file mode 100644 index 0000000000..2032ce7b7a --- /dev/null +++ b/lib/lockfiles/src/paths.ts @@ -0,0 +1,25 @@ +import type { LockfileKind } from "./types.ts" + +const KIND_BY_NAME: ReadonlyMap = new Map([ + ["package-lock.json", "package-lock"], + ["npm-shrinkwrap.json", "package-lock"], + ["pnpm-lock.yaml", "pnpm-lock"], + ["yarn.lock", "yarn-v1"], + ["bun.lock", "bun-lock"], + ["bun.lockb", "bun-lockb"], + ["go.mod", "go-mod"], + ["go.sum", "go-sum"], + ["Cargo.lock", "cargo-lock"], +]) + +const IGNORED_SEGMENTS = new Set(["node_modules", "vendor", "testdata", "fixtures", "__fixtures__", ".git"]) + +const segmentsOf = (path: string): ReadonlyArray => path.split(/[\\/]+/).filter((s) => s !== "") + +/** Kind by basename. yarn.lock is "yarn-v1" here; the parser detects berry from its content. */ +export const lockfileKindOf = (path: string): LockfileKind | undefined => + KIND_BY_NAME.get(segmentsOf(path).at(-1) ?? "") + +/** Paths a scan skips: vendored, test or dependency trees. */ +export const isIgnoredLockfilePath = (path: string): boolean => + segmentsOf(path).some((segment) => IGNORED_SEGMENTS.has(segment)) diff --git a/lib/lockfiles/src/types.ts b/lib/lockfiles/src/types.ts new file mode 100644 index 0000000000..c356e43752 --- /dev/null +++ b/lib/lockfiles/src/types.ts @@ -0,0 +1,36 @@ +/** OSV ecosystem names. */ +export type Ecosystem = "npm" | "Go" | "crates.io" + +export type LockfileKind = + | "package-lock" + | "pnpm-lock" + | "yarn-v1" + | "yarn-berry" + | "bun-lock" + | "bun-lockb" + | "go-mod" + | "go-sum" + | "cargo-lock" + +export type Relation = "direct" | "dev" | "transitive" | "unknown" + +export interface LockedPackage { + readonly ecosystem: Ecosystem + readonly name: string + readonly version: string + readonly relation: Relation +} + +export interface ParsedLockfile { + readonly path: string + readonly kind: LockfileKind + readonly packages: ReadonlyArray + readonly warnings: ReadonlyArray +} + +export interface LockfileInput { + readonly path: string + readonly content: string + /** Manifests keyed by path relative to the lockfile's directory (e.g. "packages/a/package.json"). */ + readonly manifests?: ReadonlyMap +} diff --git a/lib/lockfiles/src/versions.test.ts b/lib/lockfiles/src/versions.test.ts new file mode 100644 index 0000000000..cd1e2e414d --- /dev/null +++ b/lib/lockfiles/src/versions.test.ts @@ -0,0 +1,132 @@ +import fc from "fast-check" +import semver from "semver" +import { describe, expect, it } from "vitest" +import { compareCargoVersions, compareGoVersions, compareNpmVersions, compareVersions } from "./index.ts" + +const numeric = fc.oneof(fc.integer({ min: 0, max: 3 }), fc.integer({ min: 0, max: 2 ** 40 })).map(String) +const alnumId = fc.stringMatching(/^[0-9a-zA-Z-]{1,6}$/).filter((s) => !/^\d+$/.test(s)) +const preId = fc.oneof(numeric, alnumId, fc.constantFrom("alpha", "beta", "rc", "0", "1")) +const build = fc.array(fc.stringMatching(/^[0-9a-zA-Z-]{1,4}$/), { minLength: 1, maxLength: 2 }) + +/** Valid SemVer 2.0 strings, small parts weighted so equal cores and prerelease ties are common. */ +const semverString = fc + .record({ + core: fc.tuple(numeric, numeric, numeric), + pre: fc.option(fc.array(preId, { minLength: 1, maxLength: 3 }), { nil: undefined }), + build: fc.option(build, { nil: undefined }), + }) + .map( + ({ core, pre, build }) => + `${core.join(".")}${pre === undefined ? "" : `-${pre.join(".")}`}${build === undefined ? "" : `+${build.join(".")}`}`, + ) + +describe("compareNpmVersions", () => { + it("agrees in sign with node-semver", () => { + fc.assert( + fc.property(semverString, semverString, (a, b) => { + expect(compareNpmVersions(a, b)).toBe(Math.sign(semver.compare(a, b))) + }), + { numRuns: 5000 }, + ) + }) + + it("is antisymmetric and ignores build metadata", () => { + fc.assert( + fc.property(semverString, semverString, (a, b) => { + expect(compareNpmVersions(a, b)).toBe(-compareNpmVersions(b, a) || 0) + expect(compareNpmVersions(`${a.split("+")[0]}+zzz`, a)).toBe(0) + }), + ) + }) + + it.each([ + ["v1.2.3", "1.2.3", 0], + ["=1.2.3", "1.2.3", 0], + ["1.0.0-alpha", "1.0.0-alpha.1", -1], + ["1.0.0-alpha.beta", "1.0.0-beta", -1], + ["1.0.0-beta.11", "1.0.0-rc.1", -1], + ["1.0.0-beta.2", "1.0.0-beta.11", -1], + ["1.0.0-rc.1", "1.0.0", -1], + ["10.0.0", "9.99.99", 1], + ["not-a-version", "0.0.0", -1], + ])("%s vs %s is %i", (a, b, expected) => { + expect(compareNpmVersions(a, b)).toBe(expected) + expect(compareVersions("npm", a, b)).toBe(expected) + }) +}) + +describe("compareCargoVersions", () => { + it.each([ + ["0.3.16", "0.3.17", -1], + ["1.0.0-alpha.1", "1.0.0-alpha", 1], + ["1.0.0+build.5", "1.0.0", 0], + ["0.1.43", "0.1.5", 1], + ["1.0.0-0.3.7", "1.0.0-x.7.z.92", -1], + ])("%s vs %s is %i", (a, b, expected) => { + expect(compareCargoVersions(a, b)).toBe(expected) + expect(compareVersions("crates.io", a, b)).toBe(expected) + }) +}) + +/** golang.org/x/mod/semver semver_test.go: ascending order, "" marks invalid, equal canonical forms tie. */ +const GO_TESTS: ReadonlyArray = [ + ["bad", ""], + ["v1-alpha.beta.gamma", ""], + ["v1-pre", ""], + ["v1+meta", ""], + ["v1-pre+meta", ""], + ["v1.2-pre", ""], + ["v1.2-pre+meta", ""], + ["v1.0.0-alpha", "v1.0.0-alpha"], + ["v1.0.0-alpha.1", "v1.0.0-alpha.1"], + ["v1.0.0-alpha.beta", "v1.0.0-alpha.beta"], + ["v1.0.0-beta", "v1.0.0-beta"], + ["v1.0.0-beta.2", "v1.0.0-beta.2"], + ["v1.0.0-beta.11", "v1.0.0-beta.11"], + ["v1.0.0-rc.1", "v1.0.0-rc.1"], + ["v1", "v1.0.0"], + ["v1.0", "v1.0.0"], + ["v1.0.0", "v1.0.0"], + ["v1.2", "v1.2.0"], + ["v1.2.0", "v1.2.0"], + ["v1.2.3-456", "v1.2.3-456"], + ["v1.2.3-456.789", "v1.2.3-456.789"], + ["v1.2.3-456-789", "v1.2.3-456-789"], + ["v1.2.3-456a", "v1.2.3-456a"], + ["v1.2.3-pre", "v1.2.3-pre"], + ["v1.2.3-pre+meta", "v1.2.3-pre"], + ["v1.2.3-pre.1", "v1.2.3-pre.1"], + ["v1.2.3-zzz", "v1.2.3-zzz"], + ["v1.2.3", "v1.2.3"], + ["v1.2.3+meta", "v1.2.3"], + ["v1.2.3+meta-pre", "v1.2.3"], + ["v1.2.3+meta-pre.sha.256a", "v1.2.3"], +] + +describe("compareGoVersions", () => { + it("orders Go's own semver test table", () => { + GO_TESTS.forEach(([a, canonA], i) => + GO_TESTS.forEach(([b, canonB], j) => { + const expected = canonA === canonB ? 0 : i < j ? -1 : 1 + expect({ a, b, cmp: compareGoVersions(a, b) }).toEqual({ a, b, cmp: expected }) + }), + ) + }) + + it.each([ + ["v0.0.0-20191109021931-daa7c04131f5", "v0.0.1", -1], + ["v0.0.0-20191109021931-daa7c04131f5", "v0.0.0-20200101000000-aaaaaaaaaaaa", -1], + ["v1.2.3", "v1.2.4-0.20191109021931-daa7c04131f5", -1], + ["v1.2.4-0.20191109021931-daa7c04131f5", "v1.2.4", -1], + ["v1.2.4-pre", "v1.2.4-pre.0.20191109021931-daa7c04131f5", -1], + ["v1.2.4-pre.0.20191109021931-daa7c04131f5", "v1.2.4-pre.1", -1], + ["v2.0.0+incompatible", "v2.0.0", 0], + ["v2.0.1+incompatible", "v2.0.0", 1], + ["1.2.3", "v1.2.3", 0], + ["v1.02.3", "v0.0.1", -1], + ["v1.2.3-01", "v0.0.1", -1], + ])("%s vs %s is %i", (a, b, expected) => { + expect(compareGoVersions(a, b)).toBe(expected) + expect(compareVersions("Go", a, b)).toBe(expected) + }) +}) diff --git a/lib/lockfiles/src/versions.ts b/lib/lockfiles/src/versions.ts new file mode 100644 index 0000000000..e4214689c9 --- /dev/null +++ b/lib/lockfiles/src/versions.ts @@ -0,0 +1,93 @@ +import type { Ecosystem } from "./types.ts" + +interface SemVer { + readonly major: string + readonly minor: string + readonly patch: string + readonly prerelease: ReadonlyArray +} + +const NUM = "0|[1-9]\\d*" +const PRE_ID = `(?:${NUM}|\\d*[a-zA-Z-][0-9a-zA-Z-]*)` +const PRE = `(?:-(${PRE_ID}(?:\\.${PRE_ID})*))?` +const BUILD = "(?:\\+[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*)?" +const SEMVER = new RegExp(`^(${NUM})\\.(${NUM})\\.(${NUM})${PRE}${BUILD}$`) +// Go allows `v1` and `v1.2` (meaning .0), but only a full major.minor.patch may carry a prerelease or build. +const GO_SEMVER = new RegExp(`^v?(${NUM})(?:\\.(${NUM})(?:\\.(${NUM})${PRE}${BUILD})?)?$`) + +const isNumeric = (id: string): boolean => /^\d+$/.test(id) + +/** Numeric strings of any length, compared without overflow. */ +const compareNumeric = (a: string, b: string): number => { + const x = a.replace(/^0+(?=\d)/, "") + const y = b.replace(/^0+(?=\d)/, "") + return x.length !== y.length ? x.length - y.length : x < y ? -1 : x > y ? 1 : 0 +} + +/** SemVer 2.0 rule 11: numeric < alphanumeric, numbers numerically, text by ASCII, more fields wins. */ +const compareIdentifier = (a: string, b: string): number => { + const an = isNumeric(a) + const bn = isNumeric(b) + if (an && bn) return compareNumeric(a, b) + if (an !== bn) return an ? -1 : 1 + return a < b ? -1 : a > b ? 1 : 0 +} + +const comparePrerelease = (a: ReadonlyArray, b: ReadonlyArray): number => { + if (a.length === 0 || b.length === 0) return b.length - a.length + const differing = a.findIndex((id, i) => i < b.length && compareIdentifier(id, b[i] ?? "") !== 0) + return differing === -1 ? a.length - b.length : compareIdentifier(a[differing] ?? "", b[differing] ?? "") +} + +const compareParsed = (a: SemVer, b: SemVer): number => + compareNumeric(a.major, b.major) || + compareNumeric(a.minor, b.minor) || + compareNumeric(a.patch, b.patch) || + comparePrerelease(a.prerelease, b.prerelease) + +const toSemVer = (m: RegExpExecArray): SemVer => ({ + major: m[1] ?? "0", + minor: m[2] ?? "0", + patch: m[3] ?? "0", + prerelease: m[4] === undefined ? [] : m[4].split("."), +}) + +const parseSemVer = (version: string): SemVer | undefined => { + const m = SEMVER.exec(version.trim().replace(/^=?\s*v?/, "")) + return m === null ? undefined : toSemVer(m) +} + +const parseGo = (version: string): SemVer | undefined => { + const m = GO_SEMVER.exec(version.trim()) + return m === null ? undefined : toSemVer(m) +} + +/** Invalid versions sort below valid ones; two invalid ones fall back to `ifBothInvalid`. */ +const compareWith = + (parse: (v: string) => SemVer | undefined, ifBothInvalid: (a: string, b: string) => number) => + (a: string, b: string): number => { + const x = parse(a) + const y = parse(b) + if (x === undefined || y === undefined) { + return x === undefined && y === undefined ? ifBothInvalid(a, b) : x === undefined ? -1 : 1 + } + return Math.sign(compareParsed(x, y)) + } + +const byString = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0) + +/** SemVer 2.0 precedence; build metadata ignored, a leading `v` or `=` tolerated. */ +export const compareNpmVersions: (a: string, b: string) => number = compareWith(parseSemVer, byString) + +/** Go module versions (golang.org/x/mod/semver): pseudo-versions are prereleases, `+incompatible` is build metadata. All invalid versions compare equal. */ +export const compareGoVersions: (a: string, b: string) => number = compareWith(parseGo, () => 0) + +/** Cargo uses SemVer 2.0 precedence like npm. */ +export const compareCargoVersions: (a: string, b: string) => number = compareWith(parseSemVer, byString) + +export const compareVersions = (ecosystem: Ecosystem, a: string, b: string): number => + ecosystem === "Go" + ? compareGoVersions(a, b) + : ecosystem === "crates.io" + ? compareCargoVersions(a, b) + : compareNpmVersions(a, b) diff --git a/lib/lockfiles/tsconfig.json b/lib/lockfiles/tsconfig.json new file mode 100644 index 0000000000..5fe940bacb --- /dev/null +++ b/lib/lockfiles/tsconfig.json @@ -0,0 +1,20 @@ +{ + "include": ["src/**/*.ts", "scripts/**/*.ts"], + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2023"], + "types": ["node"], + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "resolveJsonModule": true, + "noEmit": true, + "skipLibCheck": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + } +} diff --git a/lib/lockfiles/vitest.config.ts b/lib/lockfiles/vitest.config.ts new file mode 100644 index 0000000000..c4e65d8391 --- /dev/null +++ b/lib/lockfiles/vitest.config.ts @@ -0,0 +1,9 @@ +import { configDefaults, defineConfig } from "vitest/config" + +export default defineConfig({ + test: { + environment: "node", + include: ["src/**/*.test.ts"], + exclude: [...configDefaults.exclude, "**/.claude/**", "**/.context/**", "**/worktrees/**"], + }, +}) From 7ff3dec776737fb8fbb2d2391fbd10587bcdf3cf Mon Sep 17 00:00:00 2001 From: Makisuo Date: Sun, 1 Nov 2026 01:06:33 +0100 Subject: [PATCH 2/4] chore(lockfiles): run the bench and fixture scripts from package.json knip reported scripts/bench.ts as an unused file; a package script is an entry point. --- lib/lockfiles/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/lockfiles/package.json b/lib/lockfiles/package.json index 335b0add44..aef80cadc7 100644 --- a/lib/lockfiles/package.json +++ b/lib/lockfiles/package.json @@ -8,7 +8,9 @@ }, "scripts": { "typecheck": "tsrs --noEmit", - "test": "vitest run" + "test": "vitest run", + "bench": "bun scripts/bench.ts", + "fixtures:generate": "bash scripts/generate-fixtures.sh" }, "dependencies": { "effect": "catalog:effect", From 8a97f93881df51f567bff26c05b2a9dd5e8fafc4 Mon Sep 17 00:00:00 2001 From: Makisuo Date: Sun, 1 Nov 2026 01:11:28 +0100 Subject: [PATCH 3/4] fix(lockfiles): report yarn berry npm: aliases under the real package A berry alias resolves as alias@npm:real@1.0.0, and the alias name was reported, so the real package's advisories were never found. --- lib/lockfiles/src/parse.test.ts | 21 +++++++++++++++++++++ lib/lockfiles/src/parsers/yarn.ts | 5 +++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/lockfiles/src/parse.test.ts b/lib/lockfiles/src/parse.test.ts index 671060082d..924a1c1623 100644 --- a/lib/lockfiles/src/parse.test.ts +++ b/lib/lockfiles/src/parse.test.ts @@ -243,6 +243,27 @@ describe("npm lockfile details", () => { }) }) +describe("yarn berry aliases", () => { + it("reports an npm: alias under the real package name", async () => { + const lock = [ + "__metadata:", + " version: 8", + "", + '"string-width-cjs@npm:string-width@^4.2.0":', + " version: 4.2.3", + ' resolution: "string-width-cjs@npm:string-width@4.2.3"', + "", + '"@scoped/alias@npm:@babel/core@^7.0.0":', + " version: 7.0.0", + ' resolution: "@scoped/alias@npm:@babel/core@7.0.0"', + "", + ].join("\n") + expect(summary(await parse("yarn.lock", lock))).toEqual( + expect.arrayContaining(["string-width@4.2.3:unknown", "@babel/core@7.0.0:unknown"]), + ) + }) +}) + describe("package-lock v1 aliases", () => { it("reports an npm: alias under the real package name and version", async () => { const lock = { diff --git a/lib/lockfiles/src/parsers/yarn.ts b/lib/lockfiles/src/parsers/yarn.ts index 2c9d7151f9..8df544c72d 100644 --- a/lib/lockfiles/src/parsers/yarn.ts +++ b/lib/lockfiles/src/parsers/yarn.ts @@ -85,11 +85,12 @@ const parseYarnV1 = (blocks: ReadonlyArray, manifest: ManifestDeps) => { const percentDecode = (s: string): string => s.replace(/%([0-9A-Fa-f]{2})/g, (_, hex: string) => String.fromCharCode(Number.parseInt(hex, 16))) -/** Berry `resolution`: `name@npm:1.0.0`, or a patch wrapping one (`name@patch:name@npm%3A1.0.0#...`). */ +/** Berry `resolution`: `name@npm:1.0.0`, an alias, or a patch wrapping one (`name@patch:name@npm%3A1.0.0#...`). */ const berryRegistryName = (resolution: string): string | undefined => { const at = splitNameAt(resolution) if (at === undefined) return undefined - if (at.rest.startsWith("npm:")) return at.name + // An alias resolves as `alias@npm:real@1.0.0`; a plain entry as `name@npm:1.0.0`. + if (at.rest.startsWith("npm:")) return splitNameAt(at.rest.slice("npm:".length))?.name ?? at.name if (!at.rest.startsWith("patch:")) return undefined const inner = at.rest.slice("patch:".length).split("#")[0] ?? "" return berryRegistryName(percentDecode(inner)) From 1739974f0cbc08de6fd8ec4d080d0506c4fcf0d8 Mon Sep 17 00:00:00 2001 From: Makisuo Date: Sun, 1 Nov 2026 01:27:47 +0100 Subject: [PATCH 4/4] fix(lockfiles): pnpm 11 multi-document lockfiles, crates.io-only Cargo sources - A pnpm 11 lockfile with a pinned package manager starts with an env document; every document is read and their packages joined. - A Cargo alternate registry uses the same registry+/sparse+ prefixes; only crates.io's two indexes count, so an internal crate is never looked up as the crates.io one of that name. - The bench prints an unknown direct count when relations are unknown. --- lib/lockfiles/scripts/bench.ts | 5 ++- lib/lockfiles/src/internal/decode.ts | 27 +++++++++++- lib/lockfiles/src/parse.test.ts | 62 +++++++++++++++++++++++++++- lib/lockfiles/src/parsers/cargo.ts | 12 +++--- lib/lockfiles/src/parsers/pnpm.ts | 13 +++--- 5 files changed, 105 insertions(+), 14 deletions(-) diff --git a/lib/lockfiles/scripts/bench.ts b/lib/lockfiles/scripts/bench.ts index 1c85366b56..3863948292 100644 --- a/lib/lockfiles/scripts/bench.ts +++ b/lib/lockfiles/scripts/bench.ts @@ -22,7 +22,10 @@ const benchOne = (path: string) => const first = timings[0] if (first === undefined) return const { parsed } = first - const direct = parsed.packages.filter((p) => p.relation === "direct").length + // Without manifests some formats (yarn) cannot tell direct dependencies apart. + const direct = parsed.packages.some((p) => p.relation === "unknown") + ? "unknown" + : String(parsed.packages.filter((p) => p.relation === "direct").length) yield* Effect.log( `${path}: ${parsed.kind}, ${parsed.packages.length} packages (${direct} direct), ${(content.length / 1024).toFixed(0)} KiB, ` + `first ${first.ms.toFixed(1)} ms, median ${(sorted[Math.floor(RUNS / 2)] ?? 0).toFixed(1)} ms over ${RUNS} runs` + diff --git a/lib/lockfiles/src/internal/decode.ts b/lib/lockfiles/src/internal/decode.ts index 2058ffd1d7..2bcdacb4f6 100644 --- a/lib/lockfiles/src/internal/decode.ts +++ b/lib/lockfiles/src/internal/decode.ts @@ -1,6 +1,6 @@ import { Effect, Schema } from "effect" import { parse as parseToml } from "smol-toml" -import { parse as parseYaml } from "yaml" +import { parse as parseYaml, parseAllDocuments } from "yaml" import { LockfileParseError } from "../errors.ts" const parseError = (path: string, what: string) => (cause: unknown) => @@ -42,3 +42,28 @@ export const parseYamlText = (path: string, content: string): Effect.Effect => Effect.try({ try: () => parseToml(content), catch: parseError(path, "invalid TOML") }) + +/** Every document of a YAML stream, as plain values; a document with errors fails the whole read. */ +export const parseYamlDocuments = ( + path: string, + content: string, +): Effect.Effect, LockfileParseError> => + Effect.try({ + try: () => { + const parsed = parseAllDocuments(content) + return Array.isArray(parsed) ? parsed : [] + }, + catch: parseError(path, "invalid YAML"), + }).pipe( + Effect.flatMap((docs) => { + const broken = docs.find((doc) => doc.errors.length > 0) + return broken === undefined + ? Effect.try({ + try: () => docs.map((doc) => doc.toJS()), + catch: parseError(path, "invalid YAML"), + }) + : Effect.fail( + parseError(path, "invalid YAML")(broken.errors[0]?.message ?? "unreadable document"), + ) + }), + ) diff --git a/lib/lockfiles/src/parse.test.ts b/lib/lockfiles/src/parse.test.ts index 924a1c1623..e1ceb318d4 100644 --- a/lib/lockfiles/src/parse.test.ts +++ b/lib/lockfiles/src/parse.test.ts @@ -243,6 +243,66 @@ describe("npm lockfile details", () => { }) }) +describe("pnpm 11 multi-document lockfiles", () => { + it("reads every document, the package manager's env document and the project's", async () => { + const lock = [ + "---", + "lockfileVersion: '9.0'", + "importers:", + " .:", + " packageManagerDependencies:", + " pnpm:", + " specifier: 11.0.0", + " version: 11.0.0", + "packages:", + " pnpm@11.0.0:", + " resolution: {integrity: sha512-x}", + "---", + "lockfileVersion: '9.0'", + "importers:", + " .:", + " dependencies:", + " lodash:", + " specifier: 4.17.15", + " version: 4.17.15", + "packages:", + " lodash@4.17.15:", + " resolution: {integrity: sha512-y}", + "", + ].join("\n") + expect(summary(await parse("pnpm-lock.yaml", lock))).toEqual( + expect.arrayContaining(["lodash@4.17.15:direct", "pnpm@11.0.0:transitive"]), + ) + }) +}) + +describe("Cargo registries", () => { + it("keeps crates.io crates from either index and skips alternate registries", async () => { + const lock = [ + "version = 4", + "[[package]]", + 'name = "app"', + 'version = "0.1.0"', + "[[package]]", + 'name = "serde"', + 'version = "1.0.0"', + 'source = "sparse+https://index.crates.io/"', + "[[package]]", + 'name = "time"', + 'version = "0.1.43"', + 'source = "registry+https://github.com/rust-lang/crates.io-index"', + "[[package]]", + 'name = "internal"', + 'version = "2.0.0"', + 'source = "sparse+https://crates.example.com/index/"', + "", + ].join("\n") + const parsed = await parse("Cargo.lock", lock) + expect(parsed.packages.map((p) => p.name).sort()).toEqual(["serde", "time"]) + expect(parsed.warnings).toEqual(["skipped 1 git, path or alternate-registry packages"]) + }) +}) + describe("yarn berry aliases", () => { it("reports an npm: alias under the real package name", async () => { const lock = [ @@ -364,6 +424,6 @@ describe("Go and Cargo details", () => { ].join("\n") const parsed = await parse("Cargo.lock", lock) expect(summary(parsed)).toEqual(["serde@0.9.0:transitive", "serde@1.0.100:direct"]) - expect(parsed.warnings).toEqual(["skipped 1 git or path packages"]) + expect(parsed.warnings).toEqual(["skipped 1 git, path or alternate-registry packages"]) }) }) diff --git a/lib/lockfiles/src/parsers/cargo.ts b/lib/lockfiles/src/parsers/cargo.ts index ca01b4f695..1b2061712b 100644 --- a/lib/lockfiles/src/parsers/cargo.ts +++ b/lib/lockfiles/src/parsers/cargo.ts @@ -15,9 +15,11 @@ const CargoLock = Schema.Struct({ package: Schema.optionalKey(Schema.Array(CargoPackage)), }) -/** Registry sources: `registry+` or `sparse+`; git and path sources are not. */ -const isRegistrySource = (source: string | undefined): boolean => - source !== undefined && (source.startsWith("registry+") || source.startsWith("sparse+")) +/** crates.io, through either index; an alternate registry's crate is not the crates.io one of that name. */ +const CRATES_IO_SOURCES: ReadonlySet = new Set([ + "registry+https://github.com/rust-lang/crates.io-index", + "sparse+https://index.crates.io/", +]) /** Member dependency entries: `name`, `name version` or `name version (source)`. */ const parseDependency = (entry: string): { readonly name: string; readonly version: string | undefined } => { @@ -36,12 +38,12 @@ export const parseCargoLock = Effect.fn("lockfiles.parseCargoLock")(function* (i const isDirect = (name: string, version: string): boolean => direct.has(name) || direct.has(`${name}@${version}`) const packages = all.flatMap((p): ReadonlyArray => - isRegistrySource(p.source) + p.source !== undefined && CRATES_IO_SOURCES.has(p.source) ? [pkg("crates.io", p.name, p.version, isDirect(p.name, p.version) ? "direct" : "transitive")] : [], ) const skipped = all.length - members.length - packages.length - const warnings = skipped > 0 ? [`skipped ${skipped} git or path packages`] : [] + const warnings = skipped > 0 ? [`skipped ${skipped} git, path or alternate-registry packages`] : [] const output: ParserOutput = { kind: "cargo-lock", packages, warnings } return output }) diff --git a/lib/lockfiles/src/parsers/pnpm.ts b/lib/lockfiles/src/parsers/pnpm.ts index 79dc4b4913..85828ff4e8 100644 --- a/lib/lockfiles/src/parsers/pnpm.ts +++ b/lib/lockfiles/src/parsers/pnpm.ts @@ -1,6 +1,6 @@ import { Effect } from "effect" import { isRecord, isRegistryVersion, pkg, splitNameAt } from "../internal/collect.ts" -import { parseYamlText } from "../internal/decode.ts" +import { parseYamlDocuments } from "../internal/decode.ts" import { LockfileParseError } from "../errors.ts" import type { LockedPackage, LockfileInput, Relation } from "../types.ts" import type { ParserOutput } from "./types.ts" @@ -70,20 +70,21 @@ const entryNameVersion = (key: string, value: unknown): NameVersion | undefined } export const parsePnpmLock = Effect.fn("lockfiles.parsePnpmLock")(function* (input: LockfileInput) { - const doc = yield* parseYamlText(input.path, input.content) - if (!isRecord(doc) || doc.lockfileVersion === undefined) { + // pnpm 11 can write an env document (the pinned package manager) before the project's. + const docs = (yield* parseYamlDocuments(input.path, input.content)).filter(isRecord) + if (!docs.some((doc) => doc.lockfileVersion !== undefined)) { return yield* new LockfileParseError({ path: input.path, message: "pnpm-lock.yaml has no lockfileVersion", }) } - const importers = isRecord(doc.importers) ? Object.values(doc.importers) : [doc] + const importers = docs.flatMap((doc) => (isRecord(doc.importers) ? Object.values(doc.importers) : [doc])) const direct = new Set(importers.flatMap((importer) => importerKeys(importer, PROD_FIELDS))) const dev = new Set(importers.flatMap((importer) => importerKeys(importer, ["devDependencies"]))) - const entries = [ + const entries = docs.flatMap((doc) => [ ...(isRecord(doc.packages) ? Object.entries(doc.packages) : []), ...(isRecord(doc.snapshots) ? Object.entries(doc.snapshots) : []), - ] + ]) const skipped = new Set() const packages = entries.flatMap(([key, value]): ReadonlyArray => { const nv = entryNameVersion(key, value)