From 762e4837c6e0d4212d0f3abdd84c8624d0217e37 Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sat, 18 Nov 2017 01:31:27 +0100 Subject: [PATCH 01/10] [npm] add badges examples with custom npm registry --- lib/all-badge-examples.js | 63 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/lib/all-badge-examples.js b/lib/all-badge-examples.js index ed423ac137e1b..a0d63939ab4b4 100644 --- a/lib/all-badge-examples.js +++ b/lib/all-badge-examples.js @@ -647,6 +647,34 @@ const allBadgeExamples = [ 'node' ] }, + { + title: 'custom registry :: npm', + previewUri: '/npm/https/registry.npm.taobao.org/v/npm.svg', + keywords: [ + 'node' + ] + }, + { + title: 'custom registry :: npm (scoped)', + previewUri: '/npm/https/registry.npm.taobao.org/v/@cycle/core.svg', + keywords: [ + 'node' + ] + }, + { + title: 'custom registry :: npm (tag)', + previewUri: '/npm/https/registry.npm.taobao.org/v/npm/next.svg', + keywords: [ + 'node' + ] + }, + { + title: 'custom registry :: npm (scoped with tag)', + previewUri: '/npm/https/registry.npm.taobao.org/v/@cycle/core/canary.svg', + keywords: [ + 'node' + ] + }, { title: 'node', previewUri: '/node/v/passport.svg', @@ -675,6 +703,34 @@ const allBadgeExamples = [ 'node' ] }, + { + title: 'custom registry :: node', + previewUri: '/node/https/registry.npm.taobao.org/v/passport.svg', + keywords: [ + 'node' + ] + }, + { + title: 'custom registry :: node (scoped)', + previewUri: '/node/https/registry.npm.taobao.org/v/@stdlib/stdlib.svg', + keywords: [ + 'node' + ] + }, + { + title: 'custom registry :: node (tag)', + previewUri: '/node/https/registry.npm.taobao.org/v/passport/latest.svg', + keywords: [ + 'node' + ] + }, + { + title: 'custom registry :: node (scoped with tag)', + previewUri: '/node/https/registry.npm.taobao.org/v/@stdlib/stdlib/latest.svg', + keywords: [ + 'node' + ] + }, { title: 'PyPI', previewUri: '/pypi/v/nine.svg', @@ -1116,6 +1172,13 @@ const allBadgeExamples = [ 'node' ] }, + { + title: 'custom registry :: npm', + previewUri: '/npm/https/registry.npm.taobao.org/l/express.svg', + keywords: [ + 'node' + ] + }, { title: 'apm', previewUri: '/apm/l/vim-mode.svg', From 9eddf382f10f16c24d1b5818884585fe965d7a97 Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sat, 18 Nov 2017 01:50:33 +0100 Subject: [PATCH 02/10] [npm] add helper to get npm registry url --- lib/npm-provider.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/npm-provider.js b/lib/npm-provider.js index 3d85b2981101d..a0cd4346f2971 100644 --- a/lib/npm-provider.js +++ b/lib/npm-provider.js @@ -36,6 +36,15 @@ function mapNpmDownloads(camp, urlComponent, apiUriComponent) { })); } +// npm registry url +function getNpmRegistryUrl(maybeProtocol, maybeHost) { + const protocol = maybeProtocol || 'https'; + const host = maybeHost || 'registry.npmjs.org'; + const url = `${protocol}://${host}`; + return url; +} + module.exports = { - mapNpmDownloads + mapNpmDownloads, + getNpmRegistryUrl }; From 5a54d3a6046b1b4b6ae60c3129166550e9410ea3 Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sat, 18 Nov 2017 01:51:27 +0100 Subject: [PATCH 03/10] [npm] implement custom npm registry support extend routes to optionally match protocol (http or https) and host. utilise ./lib/npm-provider::getNpmRegistryUrl to construct custom npm registry urls or fallback to standard one. --- server.js | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/server.js b/server.js index 24c535e360a71..2255787a713b6 100644 --- a/server.js +++ b/server.js @@ -68,7 +68,8 @@ const { isSnapshotVersion: isNexusSnapshotVersion } = require('./lib/nexus-version'); const { - mapNpmDownloads + mapNpmDownloads, + getNpmRegistryUrl } = require('./lib/npm-provider'); const { teamcityBadge @@ -1579,12 +1580,14 @@ cache(function (data, match, sendBadge, request) { })); // npm version integration. -camp.route(/^\/npm\/v\/(?:@([^/]+))?\/?([^/]*)\/?([^/]*)\.(svg|png|gif|jpg|json)$/, +camp.route(/^\/npm(?:\/(http(?:s)?)\/([^/]+))?\/v\/(?:@([^/]+))?\/?([^/]*)\/?([^/]*)\.(svg|png|gif|jpg|json)$/, cache(function(data, match, sendBadge, request) { - // e.g. cycle, core, next, svg - const [, scope, packageName, tag, format] = match; + // e.g. https, registry.npmjs.org, cycle, core, next, svg + const [, protocol, host, scope, packageName, tag, format ] = match; + const registryUrl = getNpmRegistryUrl(protocol, host); const pkg = encodeURIComponent(scope ? `@${scope}/${packageName}` : packageName); - const apiUrl = `https://registry.npmjs.org/-/package/${pkg}/dist-tags`; + const apiUrl = `${registryUrl}/-/package/${pkg}/dist-tags`; + const name = tag ? `npm@${tag}` : 'npm'; const badgeData = getBadgeData(name, data); // Using the Accept header because of this bug: @@ -1609,22 +1612,22 @@ cache(function(data, match, sendBadge, request) { })); // npm license integration. -camp.route(/^\/npm\/l\/(?:@([^/]+)\/)?([^/]+)\.(svg|png|gif|jpg|json)$/, +camp.route(/^\/npm(?:\/(http(?:s)?)\/([^/]+))?\/l\/(?:@([^/]+)\/)?([^/]+)\.(svg|png|gif|jpg|json)$/, cache(function(data, match, sendBadge, request) { - const scope = match[1]; // "user" (when a scope "@user" is supplied) - const packageName = match[2]; // "express" - const format = match[3]; // "svg" + // e.g. https, registry.npmjs.org, cycle, core, svg + const [, protocol, host, scope, packageName, format ] = match; + const registryUrl = getNpmRegistryUrl(protocol, host); let apiUrl; if (scope === 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. - apiUrl = `https://registry.npmjs.org/${packageName}/latest`; + apiUrl = `${registryUrl}/${packageName}/latest`; } else { // e.g. https://registry.npmjs.org/@cedx%2Fgulp-david // because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work const path = encodeURIComponent(`${scope}/${packageName}`); - apiUrl = `https://registry.npmjs.org/@${path}`; + apiUrl = `${registryUrl}/@${path}`; } const badgeData = getBadgeData('license', data); request(apiUrl, { headers: { 'Accept': '*/*' } }, function(err, res, buffer) { @@ -1658,22 +1661,23 @@ cache(function(data, match, sendBadge, request) { })); // npm node version integration. -camp.route(/^\/node\/v\/(?:@([^/]+))?\/?([^/]*)\/?([^/]*)\.(svg|png|gif|jpg|json)$/, +camp.route(/^\/node(?:\/(http(?:s)?)\/([^/]+))?\/v\/(?:@([^/]+))?\/?([^/]*)\/?([^/]*)\.(svg|png|gif|jpg|json)$/, cache(function(data, match, sendBadge, request) { - // e.g. @stdlib, stdlib, next, svg - const [, scope, packageName, tag, format] = match; + // e.g. https, registry.npmjs.org, @stdlib, stdlib, next, svg + const [, protocol, host, scope, packageName, tag, format] = match; + const registryUrl = getNpmRegistryUrl(protocol, host); const registryTag = tag || 'latest'; let apiUrl; if (scope === 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. - apiUrl = `https://registry.npmjs.org/${packageName}/${registryTag}`; + apiUrl = `${registryUrl}/${packageName}/${registryTag}`; } else { // e.g. https://registry.npmjs.org/@cedx%2Fgulp-david // because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work const path = encodeURIComponent(`${scope}/${packageName}`); - apiUrl = `https://registry.npmjs.org/@${path}`; + apiUrl = `${registryUrl}/@${path}`; } const name = tag ? `node@${tag}` : 'node'; const badgeData = getBadgeData(name, data); From 733c65beb6021773fe4f0f18d5afc00ae5217f27 Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sun, 19 Nov 2017 01:58:15 +0100 Subject: [PATCH 04/10] [npm] reduce amount of examples --- lib/all-badge-examples.js | 55 +++++++-------------------------------- 1 file changed, 10 insertions(+), 45 deletions(-) diff --git a/lib/all-badge-examples.js b/lib/all-badge-examples.js index a0d63939ab4b4..a6c491b391e14 100644 --- a/lib/all-badge-examples.js +++ b/lib/all-badge-examples.js @@ -641,36 +641,22 @@ const allBadgeExamples = [ ] }, { - title: 'npm (scoped with tag)', - previewUri: '/npm/v/@cycle/core/canary.svg', - keywords: [ - 'node' - ] - }, - { - title: 'custom registry :: npm', - previewUri: '/npm/https/registry.npm.taobao.org/v/npm.svg', + title: 'npm (custom registry)', + previewUri: '/npm/v/npm.svg?registry_uri=https://registry.npm.taobao.org', keywords: [ 'node' ] }, { - title: 'custom registry :: npm (scoped)', - previewUri: '/npm/https/registry.npm.taobao.org/v/@cycle/core.svg', - keywords: [ - 'node' - ] - }, - { - title: 'custom registry :: npm (tag)', - previewUri: '/npm/https/registry.npm.taobao.org/v/npm/next.svg', + title: 'npm (scoped with tag)', + previewUri: '/npm/v/@cycle/core/canary.svg', keywords: [ 'node' ] }, { - title: 'custom registry :: npm (scoped with tag)', - previewUri: '/npm/https/registry.npm.taobao.org/v/@cycle/core/canary.svg', + title: 'npm (scoped with tag, custom registry)', + previewUri: '/npm/v/@cycle/core/canary.svg?registry_uri=https://registry.npm.taobao.org', keywords: [ 'node' ] @@ -704,29 +690,8 @@ const allBadgeExamples = [ ] }, { - title: 'custom registry :: node', - previewUri: '/node/https/registry.npm.taobao.org/v/passport.svg', - keywords: [ - 'node' - ] - }, - { - title: 'custom registry :: node (scoped)', - previewUri: '/node/https/registry.npm.taobao.org/v/@stdlib/stdlib.svg', - keywords: [ - 'node' - ] - }, - { - title: 'custom registry :: node (tag)', - previewUri: '/node/https/registry.npm.taobao.org/v/passport/latest.svg', - keywords: [ - 'node' - ] - }, - { - title: 'custom registry :: node (scoped with tag)', - previewUri: '/node/https/registry.npm.taobao.org/v/@stdlib/stdlib/latest.svg', + title: 'node (scoped with tag, custom registry)', + previewUri: '/node/v/@stdlib/stdlib/latest.svg?registry_uri=https://registry.npm.taobao.org', keywords: [ 'node' ] @@ -1173,8 +1138,8 @@ const allBadgeExamples = [ ] }, { - title: 'custom registry :: npm', - previewUri: '/npm/https/registry.npm.taobao.org/l/express.svg', + title: 'npm (custom registry)', + previewUri: '/npm/l/express.svg?registry_uri=https://registry.npm.taobao.org', keywords: [ 'node' ] From 21ed1a2d1aa0a47a1466382700058bd4b1dfec22 Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sun, 19 Nov 2017 02:36:23 +0100 Subject: [PATCH 05/10] [npm] move getNpmRegistryUrl to ./lib/npm-badge-helpers --- lib/npm-badge-helpers.js | 12 ++++++++++++ lib/npm-provider.js | 11 +---------- server.js | 6 ++++-- 3 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 lib/npm-badge-helpers.js diff --git a/lib/npm-badge-helpers.js b/lib/npm-badge-helpers.js new file mode 100644 index 0000000000000..c62c70d7c6a1b --- /dev/null +++ b/lib/npm-badge-helpers.js @@ -0,0 +1,12 @@ +'use strict'; + +const defaultRegistryUrl = 'https://registry.npmjs.org'; + +function getNpmRegistryUrl(maybeRegistryUrl) { + const registryUrl = maybeRegistryUrl || defaultRegistryUrl; + return registryUrl; +} + +module.exports = { + getNpmRegistryUrl +}; diff --git a/lib/npm-provider.js b/lib/npm-provider.js index a0cd4346f2971..3d85b2981101d 100644 --- a/lib/npm-provider.js +++ b/lib/npm-provider.js @@ -36,15 +36,6 @@ function mapNpmDownloads(camp, urlComponent, apiUriComponent) { })); } -// npm registry url -function getNpmRegistryUrl(maybeProtocol, maybeHost) { - const protocol = maybeProtocol || 'https'; - const host = maybeHost || 'registry.npmjs.org'; - const url = `${protocol}://${host}`; - return url; -} - module.exports = { - mapNpmDownloads, - getNpmRegistryUrl + mapNpmDownloads }; diff --git a/server.js b/server.js index 2255787a713b6..fdaf144191480 100644 --- a/server.js +++ b/server.js @@ -68,9 +68,11 @@ const { isSnapshotVersion: isNexusSnapshotVersion } = require('./lib/nexus-version'); const { - mapNpmDownloads, - getNpmRegistryUrl + mapNpmDownloads } = require('./lib/npm-provider'); +const { + getNpmRegistryUrl +} = require('./lib/npm-badge-helpers'); const { teamcityBadge } = require('./lib/teamcity-badge-helpers'); From 90352c5af9573b6a41b5598fd3cc474393c33e9e Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sun, 19 Nov 2017 03:50:53 +0100 Subject: [PATCH 06/10] [npm] keep only defaultNpmRegistryUri as a constant reference --- lib/npm-badge-helpers.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/npm-badge-helpers.js b/lib/npm-badge-helpers.js index c62c70d7c6a1b..c809630b9920a 100644 --- a/lib/npm-badge-helpers.js +++ b/lib/npm-badge-helpers.js @@ -1,12 +1,7 @@ 'use strict'; -const defaultRegistryUrl = 'https://registry.npmjs.org'; - -function getNpmRegistryUrl(maybeRegistryUrl) { - const registryUrl = maybeRegistryUrl || defaultRegistryUrl; - return registryUrl; -} +const defaultNpmRegistryUri = 'https://registry.npmjs.org'; module.exports = { - getNpmRegistryUrl + defaultNpmRegistryUri, }; From c16c0076f76c0e8ce9296e5230cb24ff25c843ce Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sun, 19 Nov 2017 03:59:14 +0100 Subject: [PATCH 07/10] [npm] rework custom registry support to utilise query params --- server.js | 301 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 155 insertions(+), 146 deletions(-) diff --git a/server.js b/server.js index fdaf144191480..d462ba0c1241c 100644 --- a/server.js +++ b/server.js @@ -71,7 +71,7 @@ const { mapNpmDownloads } = require('./lib/npm-provider'); const { - getNpmRegistryUrl + defaultNpmRegistryUri } = require('./lib/npm-badge-helpers'); const { teamcityBadge @@ -1582,167 +1582,176 @@ cache(function (data, match, sendBadge, request) { })); // npm version integration. -camp.route(/^\/npm(?:\/(http(?:s)?)\/([^/]+))?\/v\/(?:@([^/]+))?\/?([^/]*)\/?([^/]*)\.(svg|png|gif|jpg|json)$/, -cache(function(data, match, sendBadge, request) { - // e.g. https, registry.npmjs.org, cycle, core, next, svg - const [, protocol, host, scope, packageName, tag, format ] = match; - const registryUrl = getNpmRegistryUrl(protocol, host); - const pkg = encodeURIComponent(scope ? `@${scope}/${packageName}` : packageName); - const apiUrl = `${registryUrl}/-/package/${pkg}/dist-tags`; - - const name = tag ? `npm@${tag}` : 'npm'; - const badgeData = getBadgeData(name, data); - // Using the Accept header because of this bug: - // - request(apiUrl, { headers: { 'Accept': '*/*' } }, (err, res, buffer) => { - if (err != null) { - badgeData.text[1] = 'inaccessible'; - sendBadge(format, badgeData); - return; - } - try { - const data = JSON.parse(buffer); - const version = data[tag || 'latest']; - badgeData.text[1] = versionText(version); - badgeData.colorscheme = versionColor(version); - sendBadge(format, badgeData); - } catch(e) { - badgeData.text[1] = 'invalid'; - sendBadge(format, badgeData); - } - }); -})); - -// npm license integration. -camp.route(/^\/npm(?:\/(http(?:s)?)\/([^/]+))?\/l\/(?:@([^/]+)\/)?([^/]+)\.(svg|png|gif|jpg|json)$/, -cache(function(data, match, sendBadge, request) { - // e.g. https, registry.npmjs.org, cycle, core, svg - const [, protocol, host, scope, packageName, format ] = match; - const registryUrl = getNpmRegistryUrl(protocol, host); - let apiUrl; - if (scope === 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. - apiUrl = `${registryUrl}/${packageName}/latest`; - } else { - // e.g. https://registry.npmjs.org/@cedx%2Fgulp-david - // because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work - const path = encodeURIComponent(`${scope}/${packageName}`); - apiUrl = `${registryUrl}/@${path}`; - } - const badgeData = getBadgeData('license', data); - request(apiUrl, { headers: { 'Accept': '*/*' } }, function(err, res, buffer) { - if (err != null) { - badgeData.text[1] = 'inaccessible'; - sendBadge(format, badgeData); - return; - } - try { - const data = JSON.parse(buffer); - let license; - if (scope === undefined) { - license = data.license; - } else { - const latestVersion = data['dist-tags'].latest; - license = data.versions[latestVersion].license; +camp.route(/^\/npm\/v\/(?:@([^/]+))?\/?([^/]*)\/?([^/]*)\.(svg|png|gif|jpg|json)$/, +cache({ + queryParams: ['registry_uri'], + handler: function(queryParams, match, sendBadge, request) { + // e.g. cycle, core, next, svg + const [, scope, packageName, tag, format] = match; + const registryUri = queryParams.registry_uri || defaultNpmRegistryUri; + const pkg = encodeURIComponent(scope ? `@${scope}/${packageName}` : packageName); + const apiUrl = `${registryUri}/-/package/${pkg}/dist-tags`; + + const name = tag ? `npm@${tag}` : 'npm'; + const badgeData = getBadgeData(name, queryParams); + // Using the Accept header because of this bug: + // + request(apiUrl, { headers: { 'Accept': '*/*' } }, (err, res, buffer) => { + if (err != null) { + badgeData.text[1] = 'inaccessible'; + sendBadge(format, badgeData); + return; } - if (Array.isArray(license)) { - license = license.join(', '); - } else if (typeof license == 'object') { - license = license.type; + try { + const data = JSON.parse(buffer); + const version = data[tag || 'latest']; + badgeData.text[1] = versionText(version); + badgeData.colorscheme = versionColor(version); + sendBadge(format, badgeData); + } catch(e) { + badgeData.text[1] = 'invalid'; + sendBadge(format, badgeData); } - badgeData.text[1] = license; - badgeData.colorscheme = 'blue'; - sendBadge(format, badgeData); - } catch(e) { - badgeData.text[1] = 'invalid'; - sendBadge(format, badgeData); - } - }); + }); + } })); -// npm node version integration. -camp.route(/^\/node(?:\/(http(?:s)?)\/([^/]+))?\/v\/(?:@([^/]+))?\/?([^/]*)\/?([^/]*)\.(svg|png|gif|jpg|json)$/, -cache(function(data, match, sendBadge, request) { - // e.g. https, registry.npmjs.org, @stdlib, stdlib, next, svg - const [, protocol, host, scope, packageName, tag, format] = match; - const registryUrl = getNpmRegistryUrl(protocol, host); - const registryTag = tag || 'latest'; - let apiUrl; - if (scope === undefined) { +// npm license integration. +camp.route(/^\/npm\/l\/(?:@([^/]+)\/)?([^/]+)\.(svg|png|gif|jpg|json)$/, +cache({ + queryParams: ['registry_uri'], + handler: function(queryParams, match, sendBadge, request) { + // e.g. cycle, core, svg + const [, scope, packageName, format ] = match; + const registryUri = queryParams.registry_uri || defaultNpmRegistryUri; + let apiUrl; + if (scope === 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. - apiUrl = `${registryUrl}/${packageName}/${registryTag}`; - } else { - // e.g. https://registry.npmjs.org/@cedx%2Fgulp-david - // because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work - const path = encodeURIComponent(`${scope}/${packageName}`); - apiUrl = `${registryUrl}/@${path}`; - } - const name = tag ? `node@${tag}` : 'node'; - const badgeData = getBadgeData(name, data); - // Using the Accept header because of this bug: - // - request(apiUrl, { headers: { 'Accept': '*/*' } }, (err, res, buffer) => { - if (err != null) { - badgeData.text[1] = 'inaccessible'; - sendBadge(format, badgeData); - return; + apiUrl = `${registryUri}/${packageName}/latest`; + } else { + // e.g. https://registry.npmjs.org/@cedx%2Fgulp-david + // because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work + const path = encodeURIComponent(`${scope}/${packageName}`); + apiUrl = `${registryUri}/@${path}`; } - try { - const data = JSON.parse(buffer); - if (data.error === 'not_found') { - badgeData.text[1] = 'package not found'; + const badgeData = getBadgeData('license', queryParams); + request(apiUrl, { headers: { 'Accept': '*/*' } }, function(err, res, buffer) { + if (err != null) { + badgeData.text[1] = 'inaccessible'; sendBadge(format, badgeData); return; } - let releaseData; - if (scope === undefined) { - releaseData = data; - } else { - const version = data['dist-tags'][registryTag]; - releaseData = data.versions[version]; + try { + const data = JSON.parse(buffer); + let license; + if (scope === undefined) { + license = data.license; + } else { + const latestVersion = data['dist-tags'].latest; + license = data.versions[latestVersion].license; + } + if (Array.isArray(license)) { + license = license.join(', '); + } else if (typeof license == 'object') { + license = license.type; + } + badgeData.text[1] = license; + badgeData.colorscheme = 'blue'; + sendBadge(format, badgeData); + } catch(e) { + badgeData.text[1] = 'invalid'; + sendBadge(format, badgeData); } - const versionRange = (releaseData.engines || {}).node; - if (! versionRange) { - badgeData.text[1] = 'not specified'; + }); + } +})); + +// npm node version integration. +camp.route(/^\/node\/v\/(?:@([^/]+))?\/?([^/]*)\/?([^/]*)\.(svg|png|gif|jpg|json)$/, +cache({ + queryParams: ['registry_uri'], + handler: function(queryParams, match, sendBadge, request) { + // e.g. @stdlib, stdlib, next, svg + const [, scope, packageName, tag, format] = match; + const registryUri = queryParams.registry_uri || defaultNpmRegistryUri; + const registryTag = tag || 'latest'; + let apiUrl; + if (scope === 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. + apiUrl = `${registryUri}/${packageName}/${registryTag}`; + } else { + // e.g. https://registry.npmjs.org/@cedx%2Fgulp-david + // because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work + const path = encodeURIComponent(`${scope}/${packageName}`); + apiUrl = `${registryUri}/@${path}`; + } + const name = tag ? `node@${tag}` : 'node'; + const badgeData = getBadgeData(name, queryParams); + // Using the Accept header because of this bug: + // + request(apiUrl, { headers: { 'Accept': '*/*' } }, (err, res, buffer) => { + if (err != null) { + badgeData.text[1] = 'inaccessible'; sendBadge(format, badgeData); return; } - badgeData.text[1] = versionRange; - regularUpdate('http://nodejs.org/dist/latest/SHASUMS256.txt', - (24 * 3600 * 1000), - shasums => { - // tarball index start, tarball index end - 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; - }, (err, version) => { - if (err != null) { - badgeData.text[1] = 'invalid'; - sendBadge(format, badgeData); - return; - } - try { - if (semver.satisfies(version, versionRange)) { - badgeData.colorscheme = 'brightgreen'; - } else if (semver.gtr(version, versionRange)) { - badgeData.colorscheme = 'yellow'; - } else { - badgeData.colorscheme = 'orange'; - } - } catch(e) { } + try { + const data = JSON.parse(buffer); + if (data.error === 'not_found') { + badgeData.text[1] = 'package not found'; sendBadge(format, badgeData); - }); - } catch(e) { - badgeData.text[1] = 'invalid'; - sendBadge(format, badgeData); - } - }); + return; + } + let releaseData; + if (scope === undefined) { + releaseData = data; + } else { + const version = data['dist-tags'][registryTag]; + releaseData = data.versions[version]; + } + const versionRange = (releaseData.engines || {}).node; + if (! versionRange) { + badgeData.text[1] = 'not specified'; + sendBadge(format, badgeData); + return; + } + badgeData.text[1] = versionRange; + regularUpdate('http://nodejs.org/dist/latest/SHASUMS256.txt', + (24 * 3600 * 1000), + shasums => { + // tarball index start, tarball index end + 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; + }, (err, version) => { + if (err != null) { + badgeData.text[1] = 'invalid'; + sendBadge(format, badgeData); + return; + } + try { + if (semver.satisfies(version, versionRange)) { + badgeData.colorscheme = 'brightgreen'; + } else if (semver.gtr(version, versionRange)) { + badgeData.colorscheme = 'yellow'; + } else { + badgeData.colorscheme = 'orange'; + } + } catch(e) { } + sendBadge(format, badgeData); + }); + } catch(e) { + badgeData.text[1] = 'invalid'; + sendBadge(format, badgeData); + } + }); + } })); // Anaconda Cloud / conda package manager integration From 6c71b35ee5e62132293ed800de7f3bf04cb57796 Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sun, 19 Nov 2017 05:03:51 +0100 Subject: [PATCH 08/10] [npm] add service-tests for custom registry support --- service-tests/node.js | 5 +++++ service-tests/npm.js | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/service-tests/node.js b/service-tests/node.js index 856f713d2b1bc..7780025a7d846 100644 --- a/service-tests/node.js +++ b/service-tests/node.js @@ -30,6 +30,11 @@ t.create("gets the tagged release's node version version of ionic") .expectJSONTypes(Joi.object({ name: 'node@next' }).unknown()) .afterJSON(json => { assertIsSemverRange(json.value); }); +t.create('gets the node version of passport from a custom registry') + .get('/v/passport.json?registry_uri=https://registry.npm.taobao.org') + .expectJSONTypes(Joi.object({ name: 'node' }).unknown()) + .afterJSON(json => { assertIsSemverRange(json.value); }); + t.create("gets the tagged release's node version of @cycle/core") .get('/v/@cycle/core/canary.json') .expectJSONTypes(Joi.object({ name: 'node@canary' }).unknown()) diff --git a/service-tests/npm.js b/service-tests/npm.js index 1f051e32fb9c5..09aeca7b722d6 100644 --- a/service-tests/npm.js +++ b/service-tests/npm.js @@ -19,10 +19,18 @@ t.create('gets the tagged package version of npm') .get('/v/npm/next.json') .expectJSONTypes(Joi.object().keys({ name: 'npm@next', value: isSemver })); +t.create('gets the package version of left-pad from a custom registry') + .get('/v/left-pad.json?registry_uri=https://registry.npm.taobao.org') + .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver })); + t.create('gets the tagged package version of @cycle/core') .get('/v/@cycle/core/canary.json') .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver })); +t.create('gets the tagged package version of @cycle/core from a custom registry') + .get('/v/@cycle/core/canary.json?registry_uri=https://registry.npm.taobao.org') + .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver })); + t.create('invalid package name') .get('/v/frodo-is-not-a-package.json') .expectJSON({ name: 'npm', value: 'invalid' }); From 852dc6a18999ea38454b362c706e20497c0ecef0 Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sun, 19 Nov 2017 23:32:50 +0100 Subject: [PATCH 09/10] [npm] change custom registry from registry.npm.taobao.org to registry.npmjs.com in examples and tests --- lib/all-badge-examples.js | 8 ++++---- service-tests/node.js | 2 +- service-tests/npm.js | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/all-badge-examples.js b/lib/all-badge-examples.js index a6c491b391e14..ada0c358d17c9 100644 --- a/lib/all-badge-examples.js +++ b/lib/all-badge-examples.js @@ -642,7 +642,7 @@ const allBadgeExamples = [ }, { title: 'npm (custom registry)', - previewUri: '/npm/v/npm.svg?registry_uri=https://registry.npm.taobao.org', + previewUri: '/npm/v/npm.svg?registry_uri=https://registry.npmjs.com', keywords: [ 'node' ] @@ -656,7 +656,7 @@ const allBadgeExamples = [ }, { title: 'npm (scoped with tag, custom registry)', - previewUri: '/npm/v/@cycle/core/canary.svg?registry_uri=https://registry.npm.taobao.org', + previewUri: '/npm/v/@cycle/core/canary.svg?registry_uri=https://registry.npmjs.com', keywords: [ 'node' ] @@ -691,7 +691,7 @@ const allBadgeExamples = [ }, { title: 'node (scoped with tag, custom registry)', - previewUri: '/node/v/@stdlib/stdlib/latest.svg?registry_uri=https://registry.npm.taobao.org', + previewUri: '/node/v/@stdlib/stdlib/latest.svg?registry_uri=https://registry.npmjs.com', keywords: [ 'node' ] @@ -1139,7 +1139,7 @@ const allBadgeExamples = [ }, { title: 'npm (custom registry)', - previewUri: '/npm/l/express.svg?registry_uri=https://registry.npm.taobao.org', + previewUri: '/npm/l/express.svg?registry_uri=https://registry.npmjs.com', keywords: [ 'node' ] diff --git a/service-tests/node.js b/service-tests/node.js index 7780025a7d846..675d8625a2bf0 100644 --- a/service-tests/node.js +++ b/service-tests/node.js @@ -31,7 +31,7 @@ t.create("gets the tagged release's node version version of ionic") .afterJSON(json => { assertIsSemverRange(json.value); }); t.create('gets the node version of passport from a custom registry') - .get('/v/passport.json?registry_uri=https://registry.npm.taobao.org') + .get('/v/passport.json?registry_uri=https://registry.npmjs.com') .expectJSONTypes(Joi.object({ name: 'node' }).unknown()) .afterJSON(json => { assertIsSemverRange(json.value); }); diff --git a/service-tests/npm.js b/service-tests/npm.js index 09aeca7b722d6..8be3f47c033c8 100644 --- a/service-tests/npm.js +++ b/service-tests/npm.js @@ -20,7 +20,7 @@ t.create('gets the tagged package version of npm') .expectJSONTypes(Joi.object().keys({ name: 'npm@next', value: isSemver })); t.create('gets the package version of left-pad from a custom registry') - .get('/v/left-pad.json?registry_uri=https://registry.npm.taobao.org') + .get('/v/left-pad.json?registry_uri=https://registry.npmjs.com') .expectJSONTypes(Joi.object().keys({ name: 'npm', value: isSemver })); t.create('gets the tagged package version of @cycle/core') @@ -28,7 +28,7 @@ t.create('gets the tagged package version of @cycle/core') .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver })); t.create('gets the tagged package version of @cycle/core from a custom registry') - .get('/v/@cycle/core/canary.json?registry_uri=https://registry.npm.taobao.org') + .get('/v/@cycle/core/canary.json?registry_uri=https://registry.npmjs.com') .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver })); t.create('invalid package name') From 90f8899fdc1d1b675b665c56e1d1bca83727a48f Mon Sep 17 00:00:00 2001 From: Vladimir Starkov Date: Sun, 19 Nov 2017 23:59:06 +0100 Subject: [PATCH 10/10] [npm] add tests for a license part --- service-tests/npm.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/service-tests/npm.js b/service-tests/npm.js index 8be3f47c033c8..0bb5143ce01fc 100644 --- a/service-tests/npm.js +++ b/service-tests/npm.js @@ -31,6 +31,14 @@ t.create('gets the tagged package version of @cycle/core from a custom registry' .get('/v/@cycle/core/canary.json?registry_uri=https://registry.npmjs.com') .expectJSONTypes(Joi.object().keys({ name: 'npm@canary', value: isSemver })); +t.create('gets the license of express') + .get('/l/express.json') + .expectJSONTypes(Joi.object().keys({ name: 'license', value: 'MIT' })); + +t.create('gets the license of express from a custom registry') + .get('/l/express.json?registry_uri=https://registry.npmjs.com') + .expectJSONTypes(Joi.object().keys({ name: 'license', value: 'MIT' })); + t.create('invalid package name') .get('/v/frodo-is-not-a-package.json') .expectJSON({ name: 'npm', value: 'invalid' });