forked from pkgjs/nv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
143 lines (119 loc) · 3.59 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
'use strict'
const got = require('got')
const semver = require('semver')
const _cache = new Map()
module.exports = async function (alias = 'lts_active', opts = {}) {
const now = opts.now || new Date()
const cache = opts.cache || _cache
const a = Array.isArray(alias) ? alias : [alias]
const versions = await getLatestVersionsByCodename(now, cache)
// Reduce to an object
const m = a.reduce((m, a) => {
const vers = resolveAlias(versions, a)
if (Array.isArray(vers)) {
vers.forEach((v) => {
m[v.version] = v
})
} else {
m[vers.version] = vers
}
return m
}, {})
// Sort and pluck version
return Object.values(m).sort((v1, v2) => {
return semver.gt(v1.version, v2.version) ? 1 : -1
})
}
function resolveAlias (versions, alias) {
if (typeof alias === 'string' && versions[alias.toLowerCase()]) {
return versions[alias.toLowerCase()]
}
if (typeof alias === 'number' && versions[`v${alias}`]) {
return versions[`v${alias}`]
}
}
function getSchedule (cache) {
return got('https://raw.githubusercontent.com/nodejs/Release/master/schedule.json', {
cache
}).json()
}
function getVersions (cache) {
return got('https://nodejs.org/dist/index.json', {
cache
}).json()
}
async function getLatestVersionsByCodename (now, cache) {
const schedule = await getSchedule(cache)
const versions = await getVersions(cache)
// Composite aliases point to the HEAD for each release line
const maintained = {}
const active = {}
const ltsActive = {}
const lts = {}
const aliases = versions.reduce((obj, ver) => {
const { major, minor, patch } = splitVersion(ver.version)
const versionName = major !== '0' ? `v${major}` : `v${major}.${minor}`
const codename = ver.lts ? ver.lts.toLowerCase() : versionName
const version = `${major}.${minor}.${patch}`
const s = schedule[versionName]
// Version Object
const v = {
version,
major,
minor,
patch,
codename,
versionName,
start: s && s.start && new Date(s.start),
lts: s && s.lts && new Date(s.lts),
maintenance: s && s.maintenance && new Date(s.maintenance),
end: s && s.end && new Date(s.end)
}
// All versions get added to all
obj.all.push(v)
// The new version is higher than the last stored version for this release line
if (!obj[versionName] || semver.gt(ver.version, obj[versionName].version)) {
// Version and codename alias
obj[versionName] = obj[codename] = v
if (now > v.start && now < v.end) {
maintained[versionName] = v
if (now < v.maintenance) {
active[versionName] = v
}
// Latest lts
if (now > v.lts) {
lts[versionName] = v
if (now < v.maintenance) {
ltsActive[versionName] = v
}
if (!obj.lts_latest || semver.gt(ver.version, obj.lts_latest.version)) {
obj.lts_latest = v
}
}
// The newest supported release
if (!obj.current || semver.gt(ver.version, obj.current.version)) {
obj.current = v
}
}
}
return obj
}, {
all: []
})
// Add composite aliases
;[
['maintained', maintained],
['active', active],
['lts_active', ltsActive],
['lts', lts]
].forEach(([alias, vers]) => {
aliases[alias] = Object.values(vers)
})
// nvm --lts='lts/*'
aliases['lts/*'] = aliases.lts_latest
return aliases
}
function splitVersion (ver) {
const [, major, minor, patch] = /^v([0-9]*)\.([0-9]*)\.([0-9]*)/.exec(ver).map((n) => parseInt(n, 10))
return { major, minor, patch }
}