[6a3a178] | 1 | # npm-pick-manifest [![npm version](https://img.shields.io/npm/v/npm-pick-manifest.svg)](https://npm.im/npm-pick-manifest) [![license](https://img.shields.io/npm/l/npm-pick-manifest.svg)](https://npm.im/npm-pick-manifest) [![Travis](https://img.shields.io/travis/npm/npm-pick-manifest.svg)](https://travis-ci.org/npm/npm-pick-manifest) [![Coverage Status](https://coveralls.io/repos/github/npm/npm-pick-manifest/badge.svg?branch=latest)](https://coveralls.io/github/npm/npm-pick-manifest?branch=latest)
|
---|
| 2 |
|
---|
| 3 | [`npm-pick-manifest`](https://github.com/npm/npm-pick-manifest) is a standalone
|
---|
| 4 | implementation of [npm](https://npmjs.com)'s semver range resolution algorithm.
|
---|
| 5 |
|
---|
| 6 | ## Install
|
---|
| 7 |
|
---|
| 8 | `$ npm install --save npm-pick-manifest`
|
---|
| 9 |
|
---|
| 10 | ## Table of Contents
|
---|
| 11 |
|
---|
| 12 | * [Example](#example)
|
---|
| 13 | * [Features](#features)
|
---|
| 14 | * [API](#api)
|
---|
| 15 | * [`pickManifest()`](#pick-manifest)
|
---|
| 16 |
|
---|
| 17 | ### Example
|
---|
| 18 |
|
---|
| 19 | ```javascript
|
---|
| 20 | const pickManifest = require('npm-pick-manifest')
|
---|
| 21 |
|
---|
| 22 | fetch('https://registry.npmjs.org/npm-pick-manifest').then(res => {
|
---|
| 23 | return res.json()
|
---|
| 24 | }).then(packument => {
|
---|
| 25 | return pickManifest(packument, '^1.0.0')
|
---|
| 26 | }) // get same manifest as npm would get if you `npm i npm-pick-manifest@^1.0.0`
|
---|
| 27 | ```
|
---|
| 28 |
|
---|
| 29 | ### Features
|
---|
| 30 |
|
---|
| 31 | * Uses npm's exact [semver resolution algorithm](http://npm.im/semver).
|
---|
| 32 | * Supports ranges, tags, and versions.
|
---|
| 33 | * Prefers non-deprecated versions to deprecated versions.
|
---|
| 34 | * Prefers versions whose `engines` requirements are satisfied over those
|
---|
| 35 | that will raise a warning or error at install time.
|
---|
| 36 |
|
---|
| 37 | ### API
|
---|
| 38 |
|
---|
| 39 | #### <a name="pick-manifest"></a> `> pickManifest(packument, selector, [opts]) -> manifest`
|
---|
| 40 |
|
---|
| 41 | Returns the manifest that best matches `selector`, or throws an error.
|
---|
| 42 |
|
---|
| 43 | Packuments are anything returned by metadata URLs from the npm registry. That
|
---|
| 44 | is, they're objects with the following shape (only fields used by
|
---|
| 45 | `npm-pick-manifest` included):
|
---|
| 46 |
|
---|
| 47 | ```javascript
|
---|
| 48 | {
|
---|
| 49 | name: 'some-package',
|
---|
| 50 | 'dist-tags': {
|
---|
| 51 | foo: '1.0.1'
|
---|
| 52 | },
|
---|
| 53 | versions: {
|
---|
| 54 | '1.0.0': { version: '1.0.0' },
|
---|
| 55 | '1.0.1': { version: '1.0.1' },
|
---|
| 56 | '1.0.2': { version: '1.0.2' },
|
---|
| 57 | '2.0.0': { version: '2.0.0' }
|
---|
| 58 | }
|
---|
| 59 | }
|
---|
| 60 | ```
|
---|
| 61 |
|
---|
| 62 | The algorithm will follow npm's algorithm for semver resolution, and only
|
---|
| 63 | `tag`, `range`, and `version` selectors are supported.
|
---|
| 64 |
|
---|
| 65 | The function will throw `ETARGET` if there was no matching manifest, and
|
---|
| 66 | `ENOVERSIONS` if the packument object has no valid versions in `versions`.
|
---|
| 67 | If the only matching manifest is included in a `policyRestrictions` section
|
---|
| 68 | of the packument, then an `E403` is raised.
|
---|
| 69 |
|
---|
| 70 | #### <a name="pick-manifest-options"></a> Options
|
---|
| 71 |
|
---|
| 72 | All options are optional.
|
---|
| 73 |
|
---|
| 74 | * `includeStaged` - Boolean, default `false`. Include manifests in the
|
---|
| 75 | `stagedVersions.versions` set, to support installing [staged
|
---|
| 76 | packages](https://github.com/npm/rfcs/pull/92) when appropriate. Note
|
---|
| 77 | that staged packages are always treated as lower priority than actual
|
---|
| 78 | publishes, even when `includeStaged` is set.
|
---|
| 79 | * `defaultTag` - String, default `'latest'`. The default `dist-tag` to
|
---|
| 80 | install when no specifier is provided. Note that the version indicated
|
---|
| 81 | by this specifier will be given top priority if it matches a supplied
|
---|
| 82 | semver range.
|
---|
| 83 | * `before` - String, Date, or Number, default `null`. This is passed to
|
---|
| 84 | `new Date()`, so anything that works there will be valid. Do not
|
---|
| 85 | consider _any_ manifests that were published after the date indicated.
|
---|
| 86 | Note that this is only relevant when the packument includes a `time`
|
---|
| 87 | field listing the publish date of all the packages.
|
---|
| 88 | * `nodeVersion` - String, default `process.version`. The Node.js version
|
---|
| 89 | to use when checking manifests for `engines` requirement satisfaction.
|
---|
| 90 | * `npmVersion` - String, default `null`. The npm version to use when
|
---|
| 91 | checking manifest for `engines` requirement satisfaction. (If `null`,
|
---|
| 92 | then this particular check is skipped.)
|
---|
| 93 | * `avoid` - String, default `null`. A SemVer range of
|
---|
| 94 | versions that should be avoided. An avoided version MAY be selected if
|
---|
| 95 | there is no other option, so when using this for version selection ensure
|
---|
| 96 | that you check the result against the range to see if there was no
|
---|
| 97 | alternative available.
|
---|
| 98 | * `avoidStrict` Boolean, default `false`. If set to true, then
|
---|
| 99 | `pickManifest` will never return a version in the `avoid` range. If the
|
---|
| 100 | only available version in the `wanted` range is a version that should be
|
---|
| 101 | avoided, then it will return a version _outside_ the `wanted` range,
|
---|
| 102 | preferring to do so without making a SemVer-major jump, if possible. If
|
---|
| 103 | there are no versions outside the `avoid` range, then throw an
|
---|
| 104 | `ETARGET` error. It does this by calling pickManifest first with the
|
---|
| 105 | `wanted` range, then with a `^` affixed to the version returned by the
|
---|
| 106 | `wanted` range, and then with a `*` version range, and throwing if
|
---|
| 107 | nothing could be found to satisfy the avoidance request.
|
---|
| 108 |
|
---|
| 109 | Return value is the manifest as it exists in the packument, possibly
|
---|
| 110 | decorated with the following boolean flags:
|
---|
| 111 |
|
---|
| 112 | * `_shouldAvoid` The version is in the `avoid` range. Watch out!
|
---|
| 113 | * `_outsideDependencyRange` The version is outside the `wanted` range,
|
---|
| 114 | because `avoidStrict: true` was set.
|
---|
| 115 | * `_isSemVerMajor` The `_outsideDependencyRange` result is a SemVer-major
|
---|
| 116 | step up from the version returned by the `wanted` range.
|
---|
| 117 |
|
---|
| 118 | ### Algorithm
|
---|
| 119 |
|
---|
| 120 | 1. Create list of all versions in `versions`,
|
---|
| 121 | `policyRestrictions.versions`, and (if `includeStaged` is set)
|
---|
| 122 | `stagedVersions.versions`.
|
---|
| 123 | 2. If a `dist-tag` is requested,
|
---|
| 124 | 1. If the manifest is not after the specified `before` date, then
|
---|
| 125 | select that from the set.
|
---|
| 126 | 2. If the manifest is after the specified `before` date, then re-start
|
---|
| 127 | the selection looking for the highest SemVer range that is equal to
|
---|
| 128 | or less than the `dist-tag` target.
|
---|
| 129 | 3. If a specific version is requested,
|
---|
| 130 | 1. If the manifest is not after the specified `before` date, then
|
---|
| 131 | select the specified manifest.
|
---|
| 132 | 2. If the manifest is after the specified `before` date, then raise
|
---|
| 133 | `ETARGET` error. (NB: this is a breaking change from v5, where a
|
---|
| 134 | specified version would override the `before` setting.)
|
---|
| 135 | 4. (At this point we know a range is requested.)
|
---|
| 136 | 5. If the `defaultTag` refers to a `dist-tag` that satisfies the range (or
|
---|
| 137 | if the range is `'*'` or `''`), and the manifest is published before the
|
---|
| 138 | `before` setting, then select that manifest.
|
---|
| 139 | 6. If nothing is yet selected, sort by the following heuristics in order,
|
---|
| 140 | and select the top item:
|
---|
| 141 | 1. Prioritize versions that are not in the `avoid` range over those
|
---|
| 142 | that are.
|
---|
| 143 | 2. Prioritize versions that are not in `policyRestrictions` over those
|
---|
| 144 | that are.
|
---|
| 145 | 3. Prioritize published versions over staged versions.
|
---|
| 146 | 4. Prioritize versions that are not deprecated, and which have a
|
---|
| 147 | satisfied engines requirement, over those that are either deprecated
|
---|
| 148 | or have an engines mismatch.
|
---|
| 149 | 5. Prioritize versions that have a satisfied engines requirement over
|
---|
| 150 | those that do not.
|
---|
| 151 | 6. Prioritize versions that are not are not deprecated (but have a
|
---|
| 152 | mismatched engines requirement) over those that are deprecated.
|
---|
| 153 | 7. Prioritize higher SemVer precedence over lower SemVer precedence.
|
---|
| 154 | 7. If no manifest was selected, raise an `ETARGET` error.
|
---|
| 155 | 8. If the selected item is in the `policyRestrictions.versions` list, raise
|
---|
| 156 | an `E403` error.
|
---|
| 157 | 9. Return the selected manifest.
|
---|