* fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * fix: node service has bad colors #4809 * chore: minor service test rename Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>
This commit is contained in:
@@ -1,23 +1,24 @@
|
||||
'use strict'
|
||||
|
||||
const NPMBase = require('../npm/npm-base')
|
||||
const { versionColorForRange } = require('./node-version-color')
|
||||
|
||||
const keywords = ['npm']
|
||||
|
||||
module.exports = class NodeVersion extends NPMBase {
|
||||
module.exports = class NodeVersionBase extends NPMBase {
|
||||
static get category() {
|
||||
return 'platform-support'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return this.buildRoute('node/v', { withTag: true })
|
||||
return this.buildRoute(`node/${this.path}`, { withTag: true })
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
const type = this.type
|
||||
const prefix = `node-${type}`
|
||||
return [
|
||||
{
|
||||
title: 'node',
|
||||
title: `${prefix}`,
|
||||
pattern: ':packageName',
|
||||
namedParams: { packageName: 'passport' },
|
||||
staticPreview: this.renderStaticPreview({
|
||||
@@ -26,7 +27,7 @@ module.exports = class NodeVersion extends NPMBase {
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'node (scoped)',
|
||||
title: `${prefix} (scoped)`,
|
||||
pattern: '@:scope/:packageName',
|
||||
namedParams: { scope: 'stdlib', packageName: 'stdlib' },
|
||||
staticPreview: this.renderStaticPreview({
|
||||
@@ -35,7 +36,7 @@ module.exports = class NodeVersion extends NPMBase {
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'node (tag)',
|
||||
title: `${prefix} (tag)`,
|
||||
pattern: ':packageName/:tag',
|
||||
namedParams: { packageName: 'passport', tag: 'latest' },
|
||||
staticPreview: this.renderStaticPreview({
|
||||
@@ -45,7 +46,7 @@ module.exports = class NodeVersion extends NPMBase {
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'node (scoped with tag)',
|
||||
title: `${prefix} (scoped with tag)`,
|
||||
pattern: '@:scope/:packageName/:tag',
|
||||
namedParams: { scope: 'stdlib', packageName: 'stdlib', tag: 'latest' },
|
||||
staticPreview: this.renderStaticPreview({
|
||||
@@ -55,7 +56,7 @@ module.exports = class NodeVersion extends NPMBase {
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'node (scoped with tag, custom registry)',
|
||||
title: `${prefix} (scoped with tag, custom registry)`,
|
||||
pattern: '@:scope/:packageName/:tag',
|
||||
namedParams: { scope: 'stdlib', packageName: 'stdlib', tag: 'latest' },
|
||||
queryParams: { registry_uri: 'https://registry.npmjs.com' },
|
||||
@@ -68,16 +69,12 @@ module.exports = class NodeVersion extends NPMBase {
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'node' }
|
||||
}
|
||||
|
||||
static renderStaticPreview({ tag, nodeVersionRange }) {
|
||||
// Since this badge has an async `render()` function, but `get examples()` has to
|
||||
// be synchronous, this method exists. It should return the same value as the
|
||||
// real `render()`. There's a unit test to check that.
|
||||
return {
|
||||
label: tag ? `node@${tag}` : undefined,
|
||||
label: tag ? `${this.defaultBadgeData.label}@${tag}` : undefined,
|
||||
message: nodeVersionRange,
|
||||
color: 'brightgreen',
|
||||
}
|
||||
@@ -86,7 +83,7 @@ module.exports = class NodeVersion extends NPMBase {
|
||||
static async render({ tag, nodeVersionRange }) {
|
||||
// Atypically, the `render()` function of this badge is `async` because it needs to pull
|
||||
// data from the server.
|
||||
const label = tag ? `node@${tag}` : undefined
|
||||
const label = tag ? `${this.defaultBadgeData.label}@${tag}` : undefined
|
||||
|
||||
if (nodeVersionRange === undefined) {
|
||||
return {
|
||||
@@ -98,7 +95,7 @@ module.exports = class NodeVersion extends NPMBase {
|
||||
return {
|
||||
label,
|
||||
message: nodeVersionRange,
|
||||
color: await versionColorForRange(nodeVersionRange),
|
||||
color: await this.colorResolver(nodeVersionRange),
|
||||
}
|
||||
}
|
||||
}
|
||||
22
services/node/node-current.service.js
Normal file
22
services/node/node-current.service.js
Normal file
@@ -0,0 +1,22 @@
|
||||
'use strict'
|
||||
|
||||
const NodeVersionBase = require('./node-base')
|
||||
const { versionColorForRangeCurrent } = require('./node-version-color')
|
||||
|
||||
module.exports = class NodeCurrentVersion extends NodeVersionBase {
|
||||
static get path() {
|
||||
return 'v'
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'node' }
|
||||
}
|
||||
|
||||
static get type() {
|
||||
return 'current'
|
||||
}
|
||||
|
||||
static get colorResolver() {
|
||||
return versionColorForRangeCurrent
|
||||
}
|
||||
}
|
||||
23
services/node/node-current.spec.js
Normal file
23
services/node/node-current.spec.js
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict'
|
||||
|
||||
const { test, given } = require('sazerac')
|
||||
const NodeVersion = require('./node-current.service')
|
||||
|
||||
describe('node static renderStaticPreview', function() {
|
||||
it('should have parity with render()', async function() {
|
||||
const nodeVersionRange = '>= 6.0.0'
|
||||
|
||||
const expectedNoTag = await NodeVersion.renderStaticPreview({
|
||||
nodeVersionRange,
|
||||
})
|
||||
const expectedLatestTag = await NodeVersion.renderStaticPreview({
|
||||
nodeVersionRange,
|
||||
tag: 'latest',
|
||||
})
|
||||
|
||||
test(NodeVersion.renderStaticPreview.bind(NodeVersion), () => {
|
||||
given({ nodeVersionRange }).expect(expectedNoTag)
|
||||
given({ nodeVersionRange, tag: 'latest' }).expect(expectedLatestTag)
|
||||
})
|
||||
})
|
||||
})
|
||||
157
services/node/node-current.tester.js
Normal file
157
services/node/node-current.tester.js
Normal file
@@ -0,0 +1,157 @@
|
||||
'use strict'
|
||||
|
||||
const { expect } = require('chai')
|
||||
const { Range } = require('semver')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { mockPackageData, mockCurrentSha } = require('./testUtils/test-utils')
|
||||
|
||||
function expectSemverRange(message) {
|
||||
expect(() => new Range(message)).not.to.throw()
|
||||
}
|
||||
|
||||
t.create('gets the node version of passport')
|
||||
.get('/passport.json')
|
||||
.expectBadge({ label: 'node' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('engines satisfies current node version')
|
||||
.get('/passport.json')
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'passport',
|
||||
engines: '>=0.4.0',
|
||||
})
|
||||
)
|
||||
.intercept(mockCurrentSha(13))
|
||||
.expectBadge({ label: 'node', message: `>=0.4.0`, color: `brightgreen` })
|
||||
|
||||
t.create('engines does not satisfy current node version')
|
||||
.get('/passport.json')
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'passport',
|
||||
engines: '12',
|
||||
})
|
||||
)
|
||||
.intercept(mockCurrentSha(13))
|
||||
.expectBadge({ label: 'node', message: `12`, color: `yellow` })
|
||||
|
||||
t.create('gets the node version of @stdlib/stdlib')
|
||||
.get('/@stdlib/stdlib.json')
|
||||
.expectBadge({ label: 'node' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('engines satisfies current node version - scoped')
|
||||
.get('/@stdlib/stdlib.json')
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'stdlib',
|
||||
engines: '>=0.4.0',
|
||||
scope: '@stdlib',
|
||||
tag: '',
|
||||
registry: '',
|
||||
})
|
||||
)
|
||||
.intercept(mockCurrentSha(13))
|
||||
.expectBadge({ label: 'node', message: `>=0.4.0`, color: `brightgreen` })
|
||||
|
||||
t.create('engines does not satisfy current node version - scoped')
|
||||
.get('/@stdlib/stdlib.json')
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'stdlib',
|
||||
engines: '12',
|
||||
scope: '@stdlib',
|
||||
tag: '',
|
||||
registry: '',
|
||||
})
|
||||
)
|
||||
.intercept(mockCurrentSha(13))
|
||||
.expectBadge({ label: 'node', message: `12`, color: `yellow` })
|
||||
|
||||
t.create("gets the tagged release's node version version of ionic")
|
||||
.get('/ionic/testing.json')
|
||||
.expectBadge({ label: 'node@testing' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('engines satisfies current node version - tagged')
|
||||
.get('/ionic/testing.json')
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'ionic',
|
||||
engines: '>=0.4.0',
|
||||
tag: 'testing',
|
||||
})
|
||||
)
|
||||
.intercept(mockCurrentSha(13))
|
||||
.expectBadge({
|
||||
label: 'node@testing',
|
||||
message: `>=0.4.0`,
|
||||
color: `brightgreen`,
|
||||
})
|
||||
|
||||
t.create('engines does not satisfy current node version - tagged')
|
||||
.get('/ionic/testing.json')
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'ionic',
|
||||
engines: '12',
|
||||
tag: 'testing',
|
||||
})
|
||||
)
|
||||
.intercept(mockCurrentSha(13))
|
||||
.expectBadge({ label: 'node@testing', message: `12`, color: `yellow` })
|
||||
|
||||
t.create("gets the tagged release's node version of @cycle/core")
|
||||
.get('/@cycle/core/canary.json')
|
||||
.expectBadge({ label: 'node@canary' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('engines satisfies current node version - scoped and tagged')
|
||||
.get('/@cycle/core/canary.json')
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'core',
|
||||
engines: '>=0.4.0',
|
||||
scope: '@cycle',
|
||||
tag: 'canary',
|
||||
})
|
||||
)
|
||||
.intercept(mockCurrentSha(13))
|
||||
.expectBadge({
|
||||
label: 'node@canary',
|
||||
message: `>=0.4.0`,
|
||||
color: `brightgreen`,
|
||||
})
|
||||
|
||||
t.create('engines does not satisfy current node version - scoped and tagged')
|
||||
.get('/@cycle/core/canary.json')
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'core',
|
||||
engines: '12',
|
||||
scope: '@cycle',
|
||||
tag: 'canary',
|
||||
})
|
||||
)
|
||||
.intercept(mockCurrentSha(13))
|
||||
.expectBadge({ label: 'node@canary', message: `12`, color: `yellow` })
|
||||
|
||||
t.create('gets the node version of passport from a custom registry')
|
||||
.get('/passport.json?registry_uri=https://registry.npmjs.com')
|
||||
.expectBadge({ label: 'node' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('invalid package name')
|
||||
.get('/frodo-is-not-a-package.json')
|
||||
.expectBadge({ label: 'node', message: 'package not found' })
|
||||
22
services/node/node-lts.service.js
Normal file
22
services/node/node-lts.service.js
Normal file
@@ -0,0 +1,22 @@
|
||||
'use strict'
|
||||
|
||||
const NodeVersionBase = require('./node-base')
|
||||
const { versionColorForRangeLts } = require('./node-version-color')
|
||||
|
||||
module.exports = class NodeLtsVersion extends NodeVersionBase {
|
||||
static get path() {
|
||||
return 'v-lts'
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'node-lts' }
|
||||
}
|
||||
|
||||
static get type() {
|
||||
return 'lts'
|
||||
}
|
||||
|
||||
static get colorResolver() {
|
||||
return versionColorForRangeLts
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
const { test, given } = require('sazerac')
|
||||
const NodeVersion = require('./node.service')
|
||||
const NodeVersion = require('./node-lts.service')
|
||||
|
||||
describe('renderStaticPreview', function() {
|
||||
describe('node-lts renderStaticPreview', function() {
|
||||
it('should have parity with render()', async function() {
|
||||
const nodeVersionRange = '>= 6.0.0'
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('renderStaticPreview', function() {
|
||||
tag: 'latest',
|
||||
})
|
||||
|
||||
test(NodeVersion.renderStaticPreview, () => {
|
||||
test(NodeVersion.renderStaticPreview.bind(NodeVersion), () => {
|
||||
given({ nodeVersionRange }).expect(expectedNoTag)
|
||||
given({ nodeVersionRange, tag: 'latest' }).expect(expectedLatestTag)
|
||||
})
|
||||
217
services/node/node-lts.tester.js
Normal file
217
services/node/node-lts.tester.js
Normal file
@@ -0,0 +1,217 @@
|
||||
'use strict'
|
||||
|
||||
const { expect } = require('chai')
|
||||
const { Range } = require('semver')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const {
|
||||
mockPackageData,
|
||||
mockReleaseSchedule,
|
||||
mockVersionsSha,
|
||||
} = require('./testUtils/test-utils')
|
||||
|
||||
function expectSemverRange(message) {
|
||||
expect(() => new Range(message)).not.to.throw()
|
||||
}
|
||||
|
||||
t.create('gets the node version of passport')
|
||||
.get('/passport.json')
|
||||
.expectBadge({ label: 'node-lts' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('engines satisfies all lts node versions')
|
||||
.get('/passport.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'passport',
|
||||
engines: '10 - 12',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts', message: `10 - 12`, color: `brightgreen` })
|
||||
|
||||
t.create('engines does not satisfy all lts node versions')
|
||||
.get('/passport.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'passport',
|
||||
engines: '8',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts', message: `8`, color: `orange` })
|
||||
|
||||
t.create('engines satisfies some lts node versions')
|
||||
.get('/passport.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'passport',
|
||||
engines: '10',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts', message: `10`, color: `yellow` })
|
||||
|
||||
t.create('gets the node version of @stdlib/stdlib')
|
||||
.get('/@stdlib/stdlib.json')
|
||||
.expectBadge({ label: 'node-lts' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('engines satisfies all lts node versions - scoped')
|
||||
.get('/@stdlib/stdlib.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'stdlib',
|
||||
engines: '10 - 12',
|
||||
scope: '@stdlib',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts', message: `10 - 12`, color: `brightgreen` })
|
||||
|
||||
t.create('engines does not satisfy all lts node versions - scoped')
|
||||
.get('/@stdlib/stdlib.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'stdlib',
|
||||
engines: '8',
|
||||
scope: '@stdlib',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts', message: `8`, color: `orange` })
|
||||
|
||||
t.create('engines satisfies some lts node versions - scoped')
|
||||
.get('/@stdlib/stdlib.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'stdlib',
|
||||
engines: '10',
|
||||
scope: '@stdlib',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts', message: `10`, color: `yellow` })
|
||||
|
||||
t.create("gets the tagged release's node version version of ionic")
|
||||
.get('/ionic/testing.json')
|
||||
.expectBadge({ label: 'node-lts@testing' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('engines satisfies all lts node versions - tagged')
|
||||
.get('/ionic/testing.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'ionic',
|
||||
engines: '10 - 12',
|
||||
tag: 'testing',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({
|
||||
label: 'node-lts@testing',
|
||||
message: `10 - 12`,
|
||||
color: `brightgreen`,
|
||||
})
|
||||
|
||||
t.create('engines does not satisfy all lts node versions - tagged')
|
||||
.get('/ionic/testing.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'ionic',
|
||||
engines: '8',
|
||||
tag: 'testing',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts@testing', message: `8`, color: `orange` })
|
||||
|
||||
t.create('engines satisfies some lts node versions - tagged')
|
||||
.get('/ionic/testing.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'ionic',
|
||||
engines: '10',
|
||||
tag: 'testing',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts@testing', message: `10`, color: `yellow` })
|
||||
|
||||
t.create("gets the tagged release's node version of @cycle/core")
|
||||
.get('/@cycle/core/canary.json')
|
||||
.expectBadge({ label: 'node-lts@canary' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('engines satisfies all lts node versions - scoped and tagged')
|
||||
.get('/@cycle/core/canary.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'core',
|
||||
engines: '10 - 12',
|
||||
scope: '@cycle',
|
||||
tag: 'canary',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({
|
||||
label: 'node-lts@canary',
|
||||
message: `10 - 12`,
|
||||
color: `brightgreen`,
|
||||
})
|
||||
|
||||
t.create('engines does not satisfy all lts node versions - scoped and tagged')
|
||||
.get('/@cycle/core/canary.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'core',
|
||||
engines: '8',
|
||||
scope: '@cycle',
|
||||
tag: 'canary',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts@canary', message: `8`, color: `orange` })
|
||||
|
||||
t.create('engines satisfies some lts node versions - scoped and tagged')
|
||||
.get('/@cycle/core/canary.json')
|
||||
.intercept(mockReleaseSchedule())
|
||||
.intercept(
|
||||
mockPackageData({
|
||||
packageName: 'core',
|
||||
engines: '10',
|
||||
scope: '@cycle',
|
||||
tag: 'canary',
|
||||
})
|
||||
)
|
||||
.intercept(mockVersionsSha())
|
||||
.expectBadge({ label: 'node-lts@canary', message: `10`, color: `yellow` })
|
||||
|
||||
t.create('gets the node version of passport from a custom registry')
|
||||
.get('/passport.json?registry_uri=https://registry.npmjs.com')
|
||||
.expectBadge({ label: 'node-lts' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('invalid package name')
|
||||
.get('/frodo-is-not-a-package.json')
|
||||
.expectBadge({ label: 'node-lts', message: 'package not found' })
|
||||
@@ -1,12 +1,19 @@
|
||||
'use strict'
|
||||
|
||||
const { promisify } = require('util')
|
||||
const moment = require('moment')
|
||||
const semver = require('semver')
|
||||
const { regularUpdate } = require('../../core/legacy/regular-update')
|
||||
|
||||
function getLatestVersion() {
|
||||
const dateFormat = 'YYYY-MM-DD'
|
||||
|
||||
function getVersion(version) {
|
||||
let semver = ``
|
||||
if (version) {
|
||||
semver = `-${version}.x`
|
||||
}
|
||||
return promisify(regularUpdate)({
|
||||
url: 'https://nodejs.org/dist/latest/SHASUMS256.txt',
|
||||
url: `https://nodejs.org/dist/latest${semver}/SHASUMS256.txt`,
|
||||
intervalMillis: 24 * 3600 * 1000,
|
||||
json: false,
|
||||
scraper: shasums => {
|
||||
@@ -14,14 +21,57 @@ function getLatestVersion() {
|
||||
const taris = shasums.indexOf('node-v')
|
||||
const tarie = shasums.indexOf('\n', taris)
|
||||
const tarball = shasums.slice(taris, tarie)
|
||||
const version = tarball.split('-')[1]
|
||||
return version
|
||||
return tarball.split('-')[1]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function versionColorForRange(range) {
|
||||
const latestVersion = await getLatestVersion()
|
||||
function ltsVersionsScraper(versions) {
|
||||
const currentDate = moment().format(dateFormat)
|
||||
return Object.keys(versions).filter(function(version) {
|
||||
const data = versions[version]
|
||||
return data.lts && data.lts < currentDate && data.end > currentDate
|
||||
})
|
||||
}
|
||||
|
||||
async function getCurrentVersion() {
|
||||
return getVersion()
|
||||
}
|
||||
|
||||
async function getLtsVersions() {
|
||||
const versions = await promisify(regularUpdate)({
|
||||
url:
|
||||
'https://raw.githubusercontent.com/nodejs/Release/master/schedule.json',
|
||||
intervalMillis: 24 * 3600 * 1000,
|
||||
json: true,
|
||||
scraper: ltsVersionsScraper,
|
||||
})
|
||||
return Promise.all(versions.map(getVersion))
|
||||
}
|
||||
|
||||
async function versionColorForRangeLts(range) {
|
||||
const ltsVersions = await getLtsVersions()
|
||||
try {
|
||||
const matchesAll = ltsVersions.reduce(function(satisfies, version) {
|
||||
return satisfies && semver.satisfies(version, range)
|
||||
}, true)
|
||||
const matchesSome = ltsVersions.reduce(function(satisfies, version) {
|
||||
return satisfies || semver.satisfies(version, range)
|
||||
}, false)
|
||||
if (matchesAll) {
|
||||
return 'brightgreen'
|
||||
} else if (matchesSome) {
|
||||
return 'yellow'
|
||||
} else {
|
||||
return 'orange'
|
||||
}
|
||||
} catch (e) {
|
||||
return 'lightgray'
|
||||
}
|
||||
}
|
||||
|
||||
async function versionColorForRangeCurrent(range) {
|
||||
const latestVersion = await getCurrentVersion()
|
||||
try {
|
||||
if (semver.satisfies(latestVersion, range)) {
|
||||
return 'brightgreen'
|
||||
@@ -36,6 +86,6 @@ async function versionColorForRange(range) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getLatestVersion,
|
||||
versionColorForRange,
|
||||
versionColorForRangeCurrent,
|
||||
versionColorForRangeLts,
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const { expect } = require('chai')
|
||||
const { Range } = require('semver')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
function expectSemverRange(message) {
|
||||
expect(() => new Range(message)).not.to.throw()
|
||||
}
|
||||
|
||||
t.create('gets the node version of passport')
|
||||
.get('/passport.json')
|
||||
.expectBadge({ label: 'node' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('gets the node version of @stdlib/stdlib')
|
||||
.get('/@stdlib/stdlib.json')
|
||||
.expectBadge({ label: 'node' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create("gets the tagged release's node version version of ionic")
|
||||
.get('/ionic/next.json')
|
||||
.expectBadge({ label: 'node@next' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('gets the node version of passport from a custom registry')
|
||||
.get('/passport.json?registry_uri=https://registry.npmjs.com')
|
||||
.expectBadge({ label: 'node' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create("gets the tagged release's node version of @cycle/core")
|
||||
.get('/@cycle/core/canary.json')
|
||||
.expectBadge({ label: 'node@canary' })
|
||||
.afterJSON(json => {
|
||||
expectSemverRange(json.message)
|
||||
})
|
||||
|
||||
t.create('invalid package name')
|
||||
.get('/frodo-is-not-a-package.json')
|
||||
.expectBadge({ label: 'node', message: 'package not found' })
|
||||
11
services/node/testUtils/packageJsonTemplate.json
Normal file
11
services/node/testUtils/packageJsonTemplate.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "jaredhanson",
|
||||
"email": "jaredhanson@gmail.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
29
services/node/testUtils/packageJsonVersionsTemplate.json
Normal file
29
services/node/testUtils/packageJsonVersionsTemplate.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"dist-tags": {
|
||||
"latest": "0.0.91"
|
||||
},
|
||||
"versions": {
|
||||
"0.0.90": {
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "jaredhanson",
|
||||
"email": "jaredhanson@gmail.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
"0.0.91": {
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "jaredhanson",
|
||||
"email": "jaredhanson@gmail.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
169
services/node/testUtils/test-utils.js
Normal file
169
services/node/testUtils/test-utils.js
Normal file
@@ -0,0 +1,169 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const moment = require('moment')
|
||||
|
||||
const dateFormat = 'YYYY-MM-DD'
|
||||
|
||||
const templates = {
|
||||
packageJsonVersionsTemplate: fs.readFileSync(
|
||||
path.join(__dirname, `packageJsonVersionsTemplate.json`),
|
||||
'utf-8'
|
||||
),
|
||||
packageJsonTemplate: fs.readFileSync(
|
||||
path.join(__dirname, `packageJsonTemplate.json`),
|
||||
'utf-8'
|
||||
),
|
||||
}
|
||||
|
||||
const getTemplate = template => JSON.parse(templates[template])
|
||||
|
||||
const mockPackageData = ({ packageName, engines, scope, tag }) => nock => {
|
||||
let packageJson
|
||||
let urlPath
|
||||
if (scope || tag) {
|
||||
if (scope) {
|
||||
urlPath = `/${scope}%2F${packageName}`
|
||||
} else {
|
||||
urlPath = `/${packageName}`
|
||||
}
|
||||
packageJson = getTemplate('packageJsonVersionsTemplate')
|
||||
packageJson['dist-tags'][tag || 'latest'] = '0.0.91'
|
||||
packageJson.versions['0.0.91'].engines.node = engines
|
||||
} else {
|
||||
urlPath = `/${packageName}/latest`
|
||||
packageJson = getTemplate('packageJsonTemplate')
|
||||
packageJson.engines.node = engines
|
||||
}
|
||||
return nock('https://registry.npmjs.org/')
|
||||
.get(urlPath)
|
||||
.reply(200, packageJson)
|
||||
}
|
||||
|
||||
const mockCurrentSha = latestVersion => nock => {
|
||||
const latestSha = `node-v${latestVersion}.12.0-aix-ppc64.tar.gz`
|
||||
return nock('https://nodejs.org/dist/')
|
||||
.get(`/latest/SHASUMS256.txt`)
|
||||
.reply(200, latestSha)
|
||||
}
|
||||
|
||||
const mockVersionsSha = () => nock => {
|
||||
let scope = nock('https://nodejs.org/dist/')
|
||||
for (const version of [10, 12]) {
|
||||
const latestSha = `node-v${version}.12.0-aix-ppc64.tar.gz`
|
||||
scope = scope
|
||||
.get(`/latest-v${version}.x/SHASUMS256.txt`)
|
||||
.reply(200, latestSha)
|
||||
}
|
||||
return scope
|
||||
}
|
||||
|
||||
const mockReleaseSchedule = () => nock => {
|
||||
const currentDate = moment()
|
||||
const schedule = {
|
||||
'v0.10': {
|
||||
start: '2013-03-11',
|
||||
end: '2016-10-31',
|
||||
},
|
||||
'v0.12': {
|
||||
start: '2015-02-06',
|
||||
end: '2016-12-31',
|
||||
},
|
||||
v4: {
|
||||
start: '2015-09-08',
|
||||
lts: '2015-10-12',
|
||||
maintenance: '2017-04-01',
|
||||
end: '2018-04-30',
|
||||
codename: 'Argon',
|
||||
},
|
||||
v5: {
|
||||
start: '2015-10-29',
|
||||
maintenance: '2016-04-30',
|
||||
end: '2016-06-30',
|
||||
},
|
||||
v6: {
|
||||
start: '2016-04-26',
|
||||
lts: '2016-10-18',
|
||||
maintenance: '2018-04-30',
|
||||
end: '2019-04-30',
|
||||
codename: 'Boron',
|
||||
},
|
||||
v7: {
|
||||
start: '2016-10-25',
|
||||
maintenance: '2017-04-30',
|
||||
end: '2017-06-30',
|
||||
},
|
||||
v8: {
|
||||
start: '2017-05-30',
|
||||
lts: '2017-10-31',
|
||||
maintenance: '2019-01-01',
|
||||
end: '2019-12-31',
|
||||
codename: 'Carbon',
|
||||
},
|
||||
v9: {
|
||||
start: '2017-10-01',
|
||||
maintenance: '2018-04-01',
|
||||
end: '2018-06-30',
|
||||
},
|
||||
v10: {
|
||||
start: '2018-04-24',
|
||||
lts: currentDate
|
||||
.clone()
|
||||
.subtract(6, 'month')
|
||||
.format(dateFormat),
|
||||
maintenance: '2020-04-30',
|
||||
end: currentDate
|
||||
.clone()
|
||||
.add(1, 'month')
|
||||
.format(dateFormat),
|
||||
codename: 'Dubnium',
|
||||
},
|
||||
v11: {
|
||||
start: '2018-10-23',
|
||||
maintenance: '2019-04-22',
|
||||
end: '2019-06-01',
|
||||
},
|
||||
v12: {
|
||||
start: '2019-04-23',
|
||||
lts: currentDate
|
||||
.clone()
|
||||
.subtract(1, 'month')
|
||||
.format(dateFormat),
|
||||
maintenance: '2020-10-20',
|
||||
end: currentDate
|
||||
.clone()
|
||||
.add(6, 'month')
|
||||
.format(dateFormat),
|
||||
codename: 'Erbium',
|
||||
},
|
||||
v13: {
|
||||
start: '2019-10-22',
|
||||
maintenance: '2020-04-01',
|
||||
end: '2020-06-01',
|
||||
},
|
||||
v14: {
|
||||
start: '2020-04-21',
|
||||
lts: currentDate
|
||||
.clone()
|
||||
.add(4, 'month')
|
||||
.format(dateFormat),
|
||||
maintenance: '2021-10-19',
|
||||
end: currentDate
|
||||
.clone()
|
||||
.add(12, 'month')
|
||||
.format(dateFormat),
|
||||
codename: '',
|
||||
},
|
||||
}
|
||||
return nock('https://raw.githubusercontent.com/')
|
||||
.get(`/nodejs/Release/master/schedule.json`)
|
||||
.reply(200, schedule)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mockPackageData,
|
||||
mockCurrentSha,
|
||||
mockVersionsSha,
|
||||
mockReleaseSchedule,
|
||||
}
|
||||
@@ -98,11 +98,15 @@ module.exports = class NpmBase extends BaseJsonService {
|
||||
async fetchPackageData({ registryUrl, scope, packageName, tag }) {
|
||||
registryUrl = registryUrl || this.constructor.defaultRegistryUrl
|
||||
let url
|
||||
if (scope === undefined) {
|
||||
if (scope === undefined && tag === undefined) {
|
||||
// e.g. https://registry.npmjs.org/express/latest
|
||||
// Use this endpoint as an optimization. It covers the vast majority of
|
||||
// these badges, and the response is smaller.
|
||||
url = `${registryUrl}/${packageName}/latest`
|
||||
} else if (scope === undefined && tag !== undefined) {
|
||||
// e.g. https://registry.npmjs.org/express
|
||||
// because https://registry.npmjs.org/express/canary does not work
|
||||
url = `${registryUrl}/${packageName}`
|
||||
} else {
|
||||
// e.g. https://registry.npmjs.org/@cedx%2Fgulp-david
|
||||
// because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work
|
||||
@@ -120,7 +124,7 @@ module.exports = class NpmBase extends BaseJsonService {
|
||||
})
|
||||
|
||||
let packageData
|
||||
if (scope === undefined) {
|
||||
if (scope === undefined && tag === undefined) {
|
||||
packageData = json
|
||||
} else {
|
||||
const registryTag = tag || 'latest'
|
||||
|
||||
Reference in New Issue
Block a user