Skip to content

Commit 0b8a790

Browse files
committed
feat(enjoyBy): add opts.enjoyBy option to filter versions by date
1 parent 6effde4 commit 0b8a790

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,11 @@ The function will throw `ETARGET` if there was no matching manifest, and
7474
If `opts.defaultTag` is provided, it will be used instead of `latest`. That is,
7575
if that tag matches the selector, it will be used, even if a higher available
7676
version matches the range.
77+
78+
If `opts.enjoyBy` is provided, it should be something that can be passed to `new
79+
Date(x)`, such as a `Date` object or a timestamp string. It will be used to
80+
filter the selected versions such that only versions less than or equal to
81+
`enjoyBy` are considered.
82+
83+
If `opts.includeDeprecated` passed in as true, deprecated versions will be
84+
selected. By default, deprecated versions other than `defaultTag` are ignored.

index.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,28 @@ const semver = require('semver')
66

77
const PickerOpts = figgyPudding({
88
defaultTag: { default: 'latest' },
9+
enjoyBy: {},
910
includeDeprecated: { default: false }
1011
})
1112

1213
module.exports = pickManifest
1314
function pickManifest (packument, wanted, opts) {
1415
opts = PickerOpts(opts)
16+
const time = opts.enjoyBy && packument.time && +(new Date(opts.enjoyBy))
1517
const spec = npa.resolve(packument.name, wanted)
1618
const type = spec.type
1719
if (type === 'version' || type === 'range') {
1820
wanted = semver.clean(wanted, true) || wanted
1921
}
2022
const distTags = packument['dist-tags'] || {}
21-
const versions = Object.keys(packument.versions || {}).filter(v => semver.valid(v, true))
23+
const versions = Object.keys(packument.versions || {}).filter(v => {
24+
return semver.valid(v, true) && (
25+
!time || (
26+
packument.time[v] &&
27+
time >= +(new Date(packument.time[v]))
28+
)
29+
)
30+
})
2231
const undeprecated = versions.filter(v => !packument.versions[v].deprecated)
2332
let err
2433

@@ -47,6 +56,7 @@ function pickManifest (packument, wanted, opts) {
4756
!target &&
4857
tagVersion &&
4958
packument.versions[tagVersion] &&
59+
(!time || versions.indexOf(tagVersion) !== -1) &&
5060
semver.satisfies(tagVersion, wanted, true)
5161
) {
5262
target = tagVersion
@@ -66,7 +76,11 @@ function pickManifest (packument, wanted, opts) {
6676
target = tagVersion
6777
}
6878

69-
const manifest = target && packument.versions[target]
79+
const manifest = (
80+
target &&
81+
(!time || versions.indexOf(target) !== -1) &&
82+
packument.versions[target]
83+
)
7084
if (!manifest) {
7185
err = new Error(
7286
`No matching version found for ${packument.name}@${wanted}`

test/index.js

+25
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,28 @@ test('accepts opts.includeDeprecated option to disable skipping', t => {
266266
t.equal(manifest.version, '1.1.0', 'picked the right manifest')
267267
t.done()
268268
})
269+
270+
test('accepts opts.enjoyBy option to do date-based cutoffs', t => {
271+
const metadata = {
272+
'dist-tags': {
273+
latest: '3.0.0'
274+
},
275+
time: {
276+
modified: '2018-01-03T00:00:00.000Z',
277+
created: '2018-01-01T00:00:00.000Z',
278+
'1.0.0': '2018-01-01T00:00:00.000Z',
279+
'2.0.0': '2018-01-02T00:00:00.000Z',
280+
'3.0.0': '2018-01-03T00:00:00.000Z'
281+
},
282+
versions: {
283+
'1.0.0': { version: '1.0.0' },
284+
'2.0.0': { version: '2.0.0' },
285+
'3.0.0': { version: '3.0.0' }
286+
}
287+
}
288+
const manifest = pickManifest(metadata, '*', {
289+
enjoyBy: '2018-01-02'
290+
})
291+
t.equal(manifest.version, '2.0.0', 'filtered out 3.0.0 because of dates')
292+
t.done()
293+
})

0 commit comments

Comments
 (0)