index.js 0000644 00000007322 15173120535 0006217 0 ustar 00 'use strict'
const figgyPudding = require('figgy-pudding')
const npa = require('npm-package-arg')
const semver = require('semver')
const PickerOpts = figgyPudding({
defaultTag: { default: 'latest' },
enjoyBy: {},
includeDeprecated: { default: false }
})
module.exports = pickManifest
function pickManifest (packument, wanted, opts) {
opts = PickerOpts(opts)
const time = opts.enjoyBy && packument.time && +(new Date(opts.enjoyBy))
const spec = npa.resolve(packument.name, wanted)
const type = spec.type
if (type === 'version' || type === 'range') {
wanted = semver.clean(wanted, true) || wanted
}
const distTags = packument['dist-tags'] || {}
const versions = Object.keys(packument.versions || {}).filter(v => {
return semver.valid(v, true)
})
const policyRestrictions = packument.policyRestrictions
const restrictedVersions = policyRestrictions
? Object.keys(policyRestrictions.versions) : []
function enjoyableBy (v) {
return !time || (
packument.time[v] && time >= +(new Date(packument.time[v]))
)
}
let err
if (!versions.length && !restrictedVersions.length) {
err = new Error(`No valid versions available for ${packument.name}`)
err.code = 'ENOVERSIONS'
err.name = packument.name
err.type = type
err.wanted = wanted
throw err
}
let target
if (type === 'tag' && enjoyableBy(distTags[wanted])) {
target = distTags[wanted]
} else if (type === 'version') {
target = wanted
} else if (type !== 'range' && enjoyableBy(distTags[wanted])) {
throw new Error('Only tag, version, and range are supported')
}
const tagVersion = distTags[opts.defaultTag]
if (
!target &&
tagVersion &&
packument.versions[tagVersion] &&
enjoyableBy(tagVersion) &&
semver.satisfies(tagVersion, wanted, true)
) {
target = tagVersion
}
if (!target && !opts.includeDeprecated) {
const undeprecated = versions.filter(v => !packument.versions[v].deprecated && enjoyableBy(v)
)
target = semver.maxSatisfying(undeprecated, wanted, true)
}
if (!target) {
const stillFresh = versions.filter(enjoyableBy)
target = semver.maxSatisfying(stillFresh, wanted, true)
}
if (!target && wanted === '*' && enjoyableBy(tagVersion)) {
// This specific corner is meant for the case where
// someone is using `*` as a selector, but all versions
// are pre-releases, which don't match ranges at all.
target = tagVersion
}
if (
!target &&
time &&
type === 'tag' &&
distTags[wanted] &&
!enjoyableBy(distTags[wanted])
) {
const stillFresh = versions.filter(v =>
enjoyableBy(v) && semver.lte(v, distTags[wanted], true)
).sort(semver.rcompare)
target = stillFresh[0]
}
if (!target && restrictedVersions) {
target = semver.maxSatisfying(restrictedVersions, wanted, true)
}
const manifest = (
target &&
packument.versions[target]
)
if (!manifest) {
// Check if target is forbidden
const isForbidden = target && policyRestrictions && policyRestrictions.versions[target]
const pckg = `${packument.name}@${wanted}${
opts.enjoyBy
? ` with an Enjoy By date of ${
new Date(opts.enjoyBy).toLocaleString()
}. Maybe try a different date?`
: ''
}`
if (isForbidden) {
err = new Error(`Could not download ${pckg} due to policy violations.\n${policyRestrictions.message}\n`)
err.code = 'E403'
} else {
err = new Error(`No matching version found for ${pckg}.`)
err.code = 'ETARGET'
}
err.name = packument.name
err.type = type
err.wanted = wanted
err.versions = versions
err.distTags = distTags
err.defaultTag = opts.defaultTag
throw err
} else {
return manifest
}
}
README.md 0000644 00000006406 15173120535 0006033 0 ustar 00 # npm-pick-manifest [](https://npm.im/npm-pick-manifest) [](https://npm.im/npm-pick-manifest) [](https://travis-ci.org/npm/npm-pick-manifest) [](https://ci.appveyor.com/project/npm/npm-pick-manifest) [](https://coveralls.io/github/npm/npm-pick-manifest?branch=latest)
[`npm-pick-manifest`](https://github.com/npm/npm-pick-manifest) is a standalone
implementation of [npm](https://npmjs.com)'s semver range resolution algorithm.
## Install
`$ npm install --save npm-pick-manifest`
## Table of Contents
* [Example](#example)
* [Features](#features)
* [Contributing](#contributing)
* [API](#api)
* [`pickManifest()`](#pick-manifest)
### Example
```javascript
const pickManifest = require('npm-pick-manifest')
fetch('https://registry.npmjs.org/npm-pick-manifest').then(res => {
return res.json()
}).then(packument => {
return pickManifest(packument, '^1.0.0')
}) // get same manifest as npm would get if you `npm i npm-pick-manifest@^1.0.0`
```
### Features
* Uses npm's exact semver resolution algorithm
* Supports ranges, tags, and versions
### Contributing
The npm-pick-manifest team enthusiastically welcomes contributions and project participation!
There's a bunch of things you can do if you want to contribute! The [Contributor
Guide](CONTRIBUTING.md) has all the information you need for everything from
reporting bugs to contributing entire new features. Please don't hesitate to
jump in if you'd like to, or even ask us questions if something isn't clear.
### API
#### <a name="pick-manifest"></a> `> pickManifest(packument, selector, [opts]) -> manifest`
Returns the manifest that matches `selector`, or throws an error.
Packuments are anything returned by metadata URLs from the npm registry. That
is, they're objects with the following shape (only fields used by
`npm-pick-manifest` included):
```javascript
{
name: 'some-package',
'dist-tags': {
foo: '1.0.1'
},
versions: {
'1.0.0': { version: '1.0.0' },
'1.0.1': { version: '1.0.1' },
'1.0.2': { version: '1.0.2' },
'2.0.0': { version: '2.0.0' }
}
}
```
The algorithm will follow npm's algorithm for semver resolution, and only `tag`,
`range`, and `version` selectors are supported.
The function will throw `ETARGET` if there was no matching manifest, and
`ENOVERSIONS` if the packument object has no valid versions in `versions`.
If `opts.defaultTag` is provided, it will be used instead of `latest`. That is,
if that tag matches the selector, it will be used, even if a higher available
version matches the range.
If `opts.enjoyBy` is provided, it should be something that can be passed to `new
Date(x)`, such as a `Date` object or a timestamp string. It will be used to
filter the selected versions such that only versions less than or equal to
`enjoyBy` are considered.
If `opts.includeDeprecated` passed in as true, deprecated versions will be
selected. By default, deprecated versions other than `defaultTag` are ignored.
CHANGELOG.md 0000644 00000010420 15173120536 0006355 0 ustar 00 # Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="3.0.2"></a>
## [3.0.2](https://github.com/npm/npm-pick-manifest/compare/v3.0.1...v3.0.2) (2019-08-30)
<a name="3.0.1"></a>
## [3.0.1](https://github.com/npm/npm-pick-manifest/compare/v3.0.0...v3.0.1) (2019-08-28)
### Bug Fixes
* throw 403 for forbidden major/minor versions ([003286e](https://github.com/npm/npm-pick-manifest/commit/003286e)), closes [#2](https://github.com/npm/npm-pick-manifest/issues/2)
<a name="3.0.0"></a>
# [3.0.0](https://github.com/npm/npm-pick-manifest/compare/v2.2.3...v3.0.0) (2019-08-20)
### Features
* throw forbidden error when package is blocked by policy ([ad2a962](https://github.com/npm/npm-pick-manifest/commit/ad2a962)), closes [#1](https://github.com/npm/npm-pick-manifest/issues/1)
### BREAKING CHANGES
* This adds a new error code when package versions are
blocked.
PR-URL: https://github.com/npm/npm-pick-manifest/pull/1
Credit: @claudiahdz
<a name="2.2.3"></a>
## [2.2.3](https://github.com/npm/npm-pick-manifest/compare/v2.2.2...v2.2.3) (2018-10-31)
### Bug Fixes
* **enjoyBy:** rework semantics for enjoyBy again ([5e89b62](https://github.com/npm/npm-pick-manifest/commit/5e89b62))
<a name="2.2.2"></a>
## [2.2.2](https://github.com/npm/npm-pick-manifest/compare/v2.2.1...v2.2.2) (2018-10-31)
### Bug Fixes
* **enjoyBy:** rework semantics for enjoyBy ([5684f45](https://github.com/npm/npm-pick-manifest/commit/5684f45))
<a name="2.2.1"></a>
## [2.2.1](https://github.com/npm/npm-pick-manifest/compare/v2.2.0...v2.2.1) (2018-10-30)
<a name="2.2.0"></a>
# [2.2.0](https://github.com/npm/npm-pick-manifest/compare/v2.1.0...v2.2.0) (2018-10-30)
### Bug Fixes
* **audit:** npm audit fix --force ([d5ae6c4](https://github.com/npm/npm-pick-manifest/commit/d5ae6c4))
### Features
* **enjoyBy:** add opts.enjoyBy option to filter versions by date ([0b8a790](https://github.com/npm/npm-pick-manifest/commit/0b8a790))
<a name="2.1.0"></a>
# [2.1.0](https://github.com/npm/npm-pick-manifest/compare/v2.0.1...v2.1.0) (2017-10-18)
### Features
* **selection:** allow manually disabling deprecation skipping ([0d239d3](https://github.com/npm/npm-pick-manifest/commit/0d239d3))
<a name="2.0.1"></a>
## [2.0.1](https://github.com/npm/npm-pick-manifest/compare/v2.0.0...v2.0.1) (2017-10-18)
<a name="2.0.0"></a>
# [2.0.0](https://github.com/npm/npm-pick-manifest/compare/v1.0.4...v2.0.0) (2017-10-03)
### Bug Fixes
* **license:** relicense project according to npm policy (#3) ([ed743a0](https://github.com/npm/npm-pick-manifest/commit/ed743a0))
### Features
* **selection:** Avoid matching deprecated packages if possible ([3fc6c3a](https://github.com/npm/npm-pick-manifest/commit/3fc6c3a))
### BREAKING CHANGES
* **selection:** deprecated versions may be skipped now
* **license:** This moves the license from CC0 to ISC and properly documents the copyright as belonging to npm, Inc.
<a name="1.0.4"></a>
## [1.0.4](https://github.com/npm/npm-pick-manifest/compare/v1.0.3...v1.0.4) (2017-06-29)
### Bug Fixes
* **npa:** bump npa version for bugfixes ([7cdaca7](https://github.com/npm/npm-pick-manifest/commit/7cdaca7))
* **semver:** use loose semver parsing for *all* ops ([bbc0daa](https://github.com/npm/npm-pick-manifest/commit/bbc0daa))
<a name="1.0.3"></a>
## [1.0.3](https://github.com/npm/npm-pick-manifest/compare/v1.0.2...v1.0.3) (2017-05-04)
### Bug Fixes
* **semver:** use semver.clean() instead ([f4133b5](https://github.com/npm/npm-pick-manifest/commit/f4133b5))
<a name="1.0.2"></a>
## [1.0.2](https://github.com/npm/npm-pick-manifest/compare/v1.0.1...v1.0.2) (2017-05-04)
### Bug Fixes
* **picker:** spaces in `wanted` prevented match ([97a7d0a](https://github.com/npm/npm-pick-manifest/commit/97a7d0a))
<a name="1.0.1"></a>
## [1.0.1](https://github.com/npm/npm-pick-manifest/compare/v1.0.0...v1.0.1) (2017-04-24)
### Bug Fixes
* **deps:** forgot to add semver ([1876f4f](https://github.com/npm/npm-pick-manifest/commit/1876f4f))
<a name="1.0.0"></a>
# 1.0.0 (2017-04-24)
### Features
* **api:** initial implementation. ([b086912](https://github.com/npm/npm-pick-manifest/commit/b086912))
### BREAKING CHANGES
* **api:** ex nihilo
LICENSE.md 0000644 00000001363 15173120536 0006156 0 ustar 00 ISC License
Copyright (c) npm, Inc.
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE COPYRIGHT HOLDER DISCLAIMS
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
package.json 0000644 00000004565 15173120536 0007047 0 ustar 00 {
"_from": "npm-pick-manifest@3.0.2",
"_id": "npm-pick-manifest@3.0.2",
"_inBundle": false,
"_integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==",
"_location": "/npm-pick-manifest",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "npm-pick-manifest@3.0.2",
"name": "npm-pick-manifest",
"escapedName": "npm-pick-manifest",
"rawSpec": "3.0.2",
"saveSpec": null,
"fetchSpec": "3.0.2"
},
"_requiredBy": [
"#USER",
"/",
"/pacote"
],
"_resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz",
"_shasum": "f4d9e5fd4be2153e5f4e5f9b7be8dc419a99abb7",
"_spec": "npm-pick-manifest@3.0.2",
"_where": "/Users/claudiahdz/npm/cli",
"author": {
"name": "Kat Marchán",
"email": "kzm@sykosomatic.org"
},
"bugs": {
"url": "https://github.com/npm/npm-pick-manifest/issues"
},
"bundleDependencies": false,
"config": {
"nyc": {
"exclude": [
"node_modules/**",
"test/**"
]
}
},
"dependencies": {
"figgy-pudding": "^3.5.1",
"npm-package-arg": "^6.0.0",
"semver": "^5.4.1"
},
"deprecated": false,
"description": "Resolves a matching manifest from a package metadata document according to standard npm semver resolution rules.",
"devDependencies": {
"nyc": "^13.1.0",
"standard": "^10.0.3",
"standard-version": "^4.4.0",
"tap": "^12.0.1",
"weallbehave": "^1.2.0",
"weallcontribute": "^1.0.8"
},
"files": [
"*.js"
],
"homepage": "https://github.com/npm/npm-pick-manifest#readme",
"keywords": [
"npm",
"semver",
"package manager"
],
"license": "ISC",
"main": "index.js",
"name": "npm-pick-manifest",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/npm-pick-manifest.git"
},
"scripts": {
"postrelease": "npm publish && git push --follow-tags",
"prerelease": "npm t",
"pretest": "standard",
"release": "standard-version -s",
"test": "tap -J --100 --coverage test/*.js",
"update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'",
"update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"
},
"version": "3.0.2"
}