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.
|
---|