This commit is contained in:
Jon Ruskin 2023-02-08 08:35:01 -07:00
Родитель 799794e021
Коммит 335ea96585
12 изменённых файлов: 696 добавлений и 3 удалений

39
.github/workflows/test.yml поставляемый
Просмотреть файл

@ -342,6 +342,45 @@ jobs:
- name: Run tests
run: script/test pipenv
pnpm:
runs-on: ubuntu-latest
needs: core
strategy:
matrix:
pnpm_version: [ 7 ]
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
name: Install pnpm
id: pnpm-install
with:
version: ${{ matrix.pnpm_version }}
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Set up fixtures
run: script/source-setup/pnpm
- name: Run tests
run: script/test pnpm
swift:
runs-on: ubuntu-20.04
needs: core

18
docs/sources/pnpm.md Normal file
Просмотреть файл

@ -0,0 +1,18 @@
# pnpm
The npm source will detect dependencies when `pnpm-lock.yaml` is found at an apps `source_path`. It uses `pnpm licenses list` to enumerate dependencies and metadata.
**NOTE** [pnpm licenses list](https://pnpm.io/cli/licenses) is an experimental CLI command and subject to change. If changes to pnpm result in unexpected or broken behavior in licensed please open an [issue](https://github.com/github/licensed/issues/new).
## Including development dependencies
By default, the npm source will exclude all development dependencies. To include development or test dependencies, set `production_only: false` in the licensed configuration.
```yml
pnpm:
production_only: false
```
## Using licensed with pnpm workspaces
Licensed will locate all dependencies from all pnpm workspaces and cannot enumerate dependencies from individual project workspaces. This is a limitation from the pnpm CLI.

Просмотреть файл

@ -6,19 +6,20 @@ module Licensed
require "licensed/sources/bundler"
require "licensed/sources/cabal"
require "licensed/sources/cargo"
require "licensed/sources/cocoapods"
require "licensed/sources/composer"
require "licensed/sources/dep"
require "licensed/sources/git_submodule"
require "licensed/sources/go"
require "licensed/sources/gradle"
require "licensed/sources/manifest"
require "licensed/sources/mix"
require "licensed/sources/npm"
require "licensed/sources/nuget"
require "licensed/sources/pip"
require "licensed/sources/pipenv"
require "licensed/sources/pnpm"
require "licensed/sources/swift"
require "licensed/sources/gradle"
require "licensed/sources/mix"
require "licensed/sources/yarn"
require "licensed/sources/cocoapods"
end
end

Просмотреть файл

@ -0,0 +1,52 @@
# frozen_string_literal: true
require "json"
module Licensed
module Sources
class PNPM < Source
# Returns true when pnpm is installed and a pnpm-lock.yaml file is found,
# otherwise false
def enabled?
return false unless Licensed::Shell.tool_available?("pnpm")
File.exist?(File.join(config.pwd, "pnpm-lock.yaml"))
end
def enumerate_dependencies
packages.map do |package|
name_with_version = "#{package["name"]}@#{package["version"]}"
Dependency.new(
name: name_with_version,
version: package["version"],
path: package["path"],
metadata: {
"type" => PNPM.type,
"name" => package["name"],
"summary" => package["description"],
"homepage" => package["homepage"]
}
)
end
end
# Returns package metadata returned from `pnpm licensed list`
def packages
JSON.parse(package_metadata_command).values.flatten
rescue JSON::ParserError => e
message = "Licensed was unable to parse the output from 'pnpm licenses list'. JSON Error: #{e.message}"
raise Licensed::Sources::Source::Error, message
end
# Returns the output from running `pnpm licenses list` to get package metadata
def package_metadata_command
args = %w(--json --long)
args << "--prod" unless include_non_production?
Licensed::Shell.execute("pnpm", "licenses", "list", *args, allow_failure: true)
end
# Returns whether to include non production dependencies based on the licensed configuration settings
def include_non_production?
config.dig("pnpm", "production_only") == false
end
end
end
end

17
script/source-setup/pnpm Executable file
Просмотреть файл

@ -0,0 +1,17 @@
#!/bin/bash
set -e
if [ -z "$(which pnpm)" ]; then
echo "A local pnpm installation is required for pnpm development." >&2
exit 127
fi
# setup test fixtures
BASE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
cd $BASE_PATH/test/fixtures/pnpm
if [ "$1" == "-f" ]; then
git clean -ffX .
fi
pnpm install --shamefully-hoist

1
test/fixtures/pnpm/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
node_modules

4
test/fixtures/pnpm/.licensed.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
expected_dependency: autoprefixer
root: .
sources:
pnpm: true

17
test/fixtures/pnpm/package.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,17 @@
{
"name": "licensed-fixtures",
"version": "1.0.0",
"description": "pnpm test fixture",
"repository": "https://github.com/github/licensed",
"license": "MIT",
"dependencies": {
"@github/query-selector": "1.0.3",
"@optimizely/optimizely-sdk": "4.0.0",
"autoprefixer": "5.2.0",
"node-fetch": "2.6.7",
"@nestjs/core": "8.2.6"
},
"devDependencies": {
"string.prototype.startswith": "0.2.0"
}
}

10
test/fixtures/pnpm/packages/a/package.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
{
"name": "licensed-fixtures-a",
"version": "1.0.0",
"description": "",
"author": "",
"license": "MIT",
"dependencies": {
"callbackify": "1.1.0"
}
}

417
test/fixtures/pnpm/pnpm-lock.yaml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,417 @@
lockfileVersion: 5.4
importers:
.:
specifiers:
'@github/query-selector': 1.0.3
'@nestjs/core': 8.2.6
'@optimizely/optimizely-sdk': 4.0.0
autoprefixer: 5.2.0
node-fetch: 2.6.7
string.prototype.startswith: 0.2.0
dependencies:
'@github/query-selector': 1.0.3
'@nestjs/core': 8.2.6
'@optimizely/optimizely-sdk': 4.0.0
autoprefixer: 5.2.0
node-fetch: 2.6.7
devDependencies:
string.prototype.startswith: 0.2.0
packages/a:
specifiers:
callbackify: 1.1.0
dependencies:
callbackify: 1.1.0
packages:
/@github/query-selector/1.0.3:
resolution: {integrity: sha512-iS9XoSVLnE4IA6U5FmqxdlKWluF/ABw7MmJ2b2KqHl3bJ8qBMDKwnzRy7i3kbzZWx5J2JkUt/bBVCeJllBUqsw==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
dev: false
/@nestjs/core/8.2.6:
resolution: {integrity: sha512-NwPcEIMmCsucs3QaDlQvkoU1FlFM2wm/WjaqLQhkSoIEmAR1gNtBo88f5io5cpMwCo1k5xYhqGlaSl6TfngwWQ==}
requiresBuild: true
peerDependencies:
'@nestjs/common': ^8.0.0
'@nestjs/microservices': ^8.0.0
'@nestjs/platform-express': ^8.0.0
'@nestjs/websockets': ^8.0.0
reflect-metadata: ^0.1.12
rxjs: ^7.1.0
peerDependenciesMeta:
'@nestjs/microservices':
optional: true
'@nestjs/platform-express':
optional: true
'@nestjs/websockets':
optional: true
dependencies:
'@nuxtjs/opencollective': 0.3.2
fast-safe-stringify: 2.1.1
iterare: 1.2.1
object-hash: 2.2.0
path-to-regexp: 3.2.0
tslib: 2.3.1
uuid: 8.3.2
transitivePeerDependencies:
- encoding
dev: false
/@nuxtjs/opencollective/0.3.2:
resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==}
engines: {node: '>=8.0.0', npm: '>=5.0.0'}
hasBin: true
dependencies:
chalk: 4.1.2
consola: 2.15.3
node-fetch: 2.6.7
transitivePeerDependencies:
- encoding
dev: false
/@optimizely/js-sdk-datafile-manager/0.5.0:
resolution: {integrity: sha512-ZDov8jphA+Ez+fA0anioA8ooJrraCFbeGm7GejzPTCZPMisNGtchrpdHr9TMd+hld+TOMBZ5NbqfMvvYhbB34A==}
engines: {node: '>=6.0.0'}
peerDependencies:
'@react-native-community/async-storage': ^1.2.0
dependencies:
'@optimizely/js-sdk-logging': 0.1.0
'@optimizely/js-sdk-utils': 0.2.0
decompress-response: 4.2.1
dev: false
/@optimizely/js-sdk-event-processor/0.4.0:
resolution: {integrity: sha512-5fqBG9N66O+9KWktUTH/OmMiQ4SKi42gP7qqWNKe0Ciu5PlBMTREKmo8+EixcDvDW8yQBvIPBj6GWzKz0RVAxg==}
dependencies:
'@optimizely/js-sdk-logging': 0.1.0
'@optimizely/js-sdk-utils': 0.2.0
dev: false
/@optimizely/js-sdk-logging/0.1.0:
resolution: {integrity: sha512-Bs2zHvsdNIk2QSg05P6mKIlROHoBIRNStbrVwlePm603CucojKRPlFJG4rt7sFZQOo8xS8I7z1BmE4QI3/ZE9A==}
dependencies:
'@optimizely/js-sdk-utils': 0.1.0
dev: false
/@optimizely/js-sdk-utils/0.1.0:
resolution: {integrity: sha512-p7499GgVaX94YmkrwOiEtLgxgjXTPbUQsvETaAil5J7zg1TOA4Wl8ClalLSvCh+AKWkxGdkL4/uM/zfbxPSNNw==}
dependencies:
uuid: 3.4.0
dev: false
/@optimizely/js-sdk-utils/0.2.0:
resolution: {integrity: sha512-aHEccRVc5YjWAdIVtniKfUE3tuzHriIWZTS4sLEq/lXkNTITSL1jrBEJD91CVY5BahWu/aG/aOafrA7XGH3sDQ==}
dependencies:
uuid: 3.4.0
dev: false
/@optimizely/optimizely-sdk/4.0.0:
resolution: {integrity: sha512-ufwndTjg6wPXnJmbW/3SK2F3Dt7E1S1VQZ5oCoYrsLZ2oFrhES/urbWWTzC1t83gAokbqzSEZDuc/OBdZ6c9SA==}
engines: {node: '>=4.0.0'}
dependencies:
'@optimizely/js-sdk-datafile-manager': 0.5.0
'@optimizely/js-sdk-event-processor': 0.4.0
'@optimizely/js-sdk-logging': 0.1.0
'@optimizely/js-sdk-utils': 0.2.0
json-schema: 0.2.5
murmurhash: 0.0.2
uuid: 3.4.0
transitivePeerDependencies:
- '@react-native-community/async-storage'
dev: false
/amdefine/1.0.1:
resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==}
engines: {node: '>=0.4.2'}
dev: false
/ansi-styles/4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
dependencies:
color-convert: 2.0.1
dev: false
/autoprefixer-core/5.2.1:
resolution: {integrity: sha512-1X4srCG0vAe2ArX9d3Kfkuo5yREFZwKE5mH+VHZHIhmx0V8UjDPAKmNgJlWxxNbCAraHiDPTcT2kc+3i73jR/Q==}
dependencies:
browserslist: 0.4.0
caniuse-db: 1.0.30001450
num2fraction: 1.2.2
postcss: 4.1.16
dev: false
/autoprefixer/5.2.0:
resolution: {integrity: sha512-SSm4bPAjdQzWuShw81m3/Bfvf6FBH3Vtu7lEOBvDfpRaQeOXxmPsEXaUtC/7eqgGTYS1iryAQzhrBva0AZp9Gg==}
hasBin: true
dependencies:
autoprefixer-core: 5.2.1
fs-extra: 0.18.4
postcss: 4.1.16
dev: false
/balanced-match/1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: false
/brace-expansion/1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
dev: false
/browserslist/0.4.0:
resolution: {integrity: sha512-/JVhaf9S6ru3THyiuwX5j86pT79r5UtgwV3s6w+KpGlmUzPxfMbI5OBxO88iFtqgdqPuNirprachS3m1611qKA==}
deprecated: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools.
dependencies:
caniuse-db: 1.0.30001450
dev: false
/callbackify/1.1.0:
resolution: {integrity: sha512-dypYUxqOLco4orSE0+0DcMkdBNHGT11/bNdQkLVtq3sWdShwtgdet18BgAoBHPZpDK2WfisIWJpYAFV321+Jtw==}
dev: false
/caniuse-db/1.0.30001450:
resolution: {integrity: sha512-HqXvh7yrdHTNLVaXu9t/8lkG49xXe97jD6zWvbnT6aQBGPl1I5ukZbSAlOLjJ6/hV8BduRMl1eR6ggNi/O0hTA==}
dev: false
/chalk/4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
dev: false
/color-convert/2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
dependencies:
color-name: 1.1.4
dev: false
/color-name/1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
dev: false
/concat-map/0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: false
/consola/2.15.3:
resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==}
dev: false
/decompress-response/4.2.1:
resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==}
engines: {node: '>=8'}
dependencies:
mimic-response: 2.1.0
dev: false
/es6-promise/2.3.0:
resolution: {integrity: sha512-oyOjMhyKMLEjOOtvkwg0G4pAzLQ9WdbbeX7WdqKzvYXu+UFgD0Zo/Brq5Q49zNmnGPPzV5rmYvrr0jz1zWx8Iw==}
dev: false
/fast-safe-stringify/2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
dev: false
/fs-extra/0.18.4:
resolution: {integrity: sha512-1ZuhVunbFx1rVDW1eKmK2J6VCmkGYAnu8hGDuIHd+iaC0xNhskABDDMnFYTA9ewAhbDxZygxf5XLe/QOwWVgOQ==}
dependencies:
graceful-fs: 3.0.12
jsonfile: 2.4.0
rimraf: 2.7.1
dev: false
/fs.realpath/1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: false
/glob/7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
dev: false
/graceful-fs/3.0.12:
resolution: {integrity: sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==}
engines: {node: '>=0.4.0'}
dependencies:
natives: 1.1.6
dev: false
/graceful-fs/4.2.10:
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
requiresBuild: true
dev: false
optional: true
/has-flag/4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
dev: false
/inflight/1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies:
once: 1.4.0
wrappy: 1.0.2
dev: false
/inherits/2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: false
/iterare/1.2.1:
resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
engines: {node: '>=6'}
dev: false
/js-base64/2.1.9:
resolution: {integrity: sha512-f+5mYh8iF7FlF7zgmj/yqvvYQUHI0kAxGiLjIfNxZzqJ7RQNc4sjgp8crVJw0Kzv2O6aFGZWgMTnO71I9utHSg==}
dev: false
/json-schema/0.2.5:
resolution: {integrity: sha512-gWJOWYFrhQ8j7pVm0EM8Slr+EPVq1Phf6lvzvD/WCeqkrx/f2xBI0xOsRRS9xCn3I4vKtP519dvs3TP09r24wQ==}
dev: false
/jsonfile/2.4.0:
resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==}
optionalDependencies:
graceful-fs: 4.2.10
dev: false
/mimic-response/2.1.0:
resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==}
engines: {node: '>=8'}
dev: false
/minimatch/3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies:
brace-expansion: 1.1.11
dev: false
/murmurhash/0.0.2:
resolution: {integrity: sha512-LKlwdZKWzvCQpMszb2HO5leJ7P9T4m5XuDKku8bM0uElrzqK9cn0+iozwQS8jO4SNjrp4w7olalgd8WgsIjhWA==}
dev: false
/natives/1.1.6:
resolution: {integrity: sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==}
deprecated: This module relies on Node.js's internals and will break at some point. Do not use it, and update to graceful-fs@4.x.
dev: false
/node-fetch/2.6.7:
resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==}
engines: {node: 4.x || >=6.0.0}
peerDependencies:
encoding: ^0.1.0
peerDependenciesMeta:
encoding:
optional: true
dependencies:
whatwg-url: 5.0.0
dev: false
/num2fraction/1.2.2:
resolution: {integrity: sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==}
dev: false
/object-hash/2.2.0:
resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==}
engines: {node: '>= 6'}
dev: false
/once/1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies:
wrappy: 1.0.2
dev: false
/path-is-absolute/1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
dev: false
/path-to-regexp/3.2.0:
resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==}
dev: false
/postcss/4.1.16:
resolution: {integrity: sha512-aAutxE8MvL1bHylFMYb2c2nniFax8XDztHzZ+x5DVsNJnoW6VHvGSNSqdW3+ip255HCWfPjayVVFzMmyiL7opA==}
dependencies:
es6-promise: 2.3.0
js-base64: 2.1.9
source-map: 0.4.4
dev: false
/rimraf/2.7.1:
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
hasBin: true
dependencies:
glob: 7.2.3
dev: false
/source-map/0.4.4:
resolution: {integrity: sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==}
engines: {node: '>=0.8.0'}
dependencies:
amdefine: 1.0.1
dev: false
/string.prototype.startswith/0.2.0:
resolution: {integrity: sha512-4Rj/0GFJbva6TUkI5gC/MOwJrcY19CvgIAqLlTpKhGJVoHiWtXh5UWSX9uGE3Es4eUhFSoWJ0RVCt9j3QcK7IQ==}
dev: true
/supports-color/7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
dependencies:
has-flag: 4.0.0
dev: false
/tr46/0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
dev: false
/tslib/2.3.1:
resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
dev: false
/uuid/3.4.0:
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
hasBin: true
dev: false
/uuid/8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
hasBin: true
dev: false
/webidl-conversions/3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
dev: false
/whatwg-url/5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
dependencies:
tr46: 0.0.3
webidl-conversions: 3.0.1
dev: false
/wrappy/1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: false

2
test/fixtures/pnpm/pnpm-workspace.yaml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
packages:
- packages/a

115
test/sources/pnpm_test.rb Normal file
Просмотреть файл

@ -0,0 +1,115 @@
# frozen_string_literal: true
require "test_helper"
require "tmpdir"
require "fileutils"
if Licensed::Shell.tool_available?("pnpm")
describe Licensed::Sources::PNPM do
let(:config) { Licensed::AppConfiguration.new({ "source_path" => Dir.pwd }) }
let(:fixtures) { File.expand_path("../../fixtures/pnpm", __FILE__) }
let(:source) { Licensed::Sources::PNPM.new(config) }
describe "enabled?" do
it "is true if pnpm-lock.yaml exists" do
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
File.write "pnpm-lock.yaml", ""
assert source.enabled?
end
end
end
it "is false no pnpm configuration exists" do
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
refute source.enabled?
end
end
end
end
describe "dependencies" do
it "includes declared dependencies" do
Dir.chdir fixtures do
dep = source.dependencies.detect { |d| d.name == "autoprefixer@5.2.0" }
assert dep
assert_equal "pnpm", dep.record["type"]
assert_equal "5.2.0", dep.version
assert dep.record["homepage"]
assert dep.record["summary"]
end
end
it "includes homepage information if available" do
Dir.chdir fixtures do
dep = source.dependencies.detect { |d| d.name == "amdefine@1.0.1" }
assert dep
assert_equal "pnpm", dep.record["type"]
assert dep.record["homepage"]
end
end
it "handles scoped dependency names" do
Dir.chdir fixtures do
dep = source.dependencies.detect { |d| d.name == "@github/query-selector@1.0.3" }
assert dep
assert_equal "1.0.3", dep.version
assert dep.record["homepage"]
assert dep.record["summary"]
end
end
it "includes indirect dependencies" do
Dir.chdir fixtures do
assert source.dependencies.detect { |dep| dep.name == "autoprefixer-core@5.2.1" }
end
end
it "does not include dev dependencies by default" do
Dir.chdir fixtures do
refute source.dependencies.detect { |dep| dep.name == "string.prototype.startswith@0.2.0" }
end
end
it "includes dev dependencies if configured" do
Dir.chdir fixtures do
config["pnpm"] = { "production_only" => false }
assert source.dependencies.detect { |dep| dep.name == "string.prototype.startswith@0.2.0" }
end
end
it "does not include ignored dependencies" do
Dir.chdir fixtures do
config.ignore({ "type" => Licensed::Sources::PNPM.type, "name" => "autoprefixer@5.2.0" })
refute source.dependencies.detect { |dep| dep.name == "autoprefixer@5.2.0" }
end
end
it "raises a Licensed::Sources::Source:Error if pnpm licenses list returns invalid JSON" do
Dir.chdir fixtures do
source.stub(:package_metadata_command, "") do
assert_raises Licensed::Sources::Source::Error do
source.dependencies
end
end
end
end
it "includes dependencies from workspaces" do
Dir.chdir fixtures do
dep = source.dependencies.detect { |d| d.name == "callbackify@1.1.0" }
assert dep
assert_equal "pnpm", dep.record["type"]
assert_equal "1.1.0", dep.version
end
end
it "does not include workspace projects" do
Dir.chdir fixtures do
refute source.dependencies.detect { |d| d.name == "licensed-fixtures@1.0.0" }
refute source.dependencies.detect { |d| d.name == "licensed-fixtures-a@1.0.0" }
end
end
end
end
end