support scoped registries - fixes #25

This commit is contained in:
silverwind 2019-06-27 19:15:01 +02:00
parent ae8ae7c184
commit ab472118a4
Signed by: silverwind
GPG Key ID: 2E62B41C93869443
2 changed files with 53 additions and 23 deletions

12
test.js

@ -50,7 +50,7 @@ async function main() {
},
"styled-components": {
old: "2.5.0-1",
new: "5.0.0-4.canary-sheet",
new: "5.0.0-beta.6",
info: "https://github.com/styled-components/styled-components",
},
}
@ -65,7 +65,7 @@ async function main() {
},
"prismjs": {
old: "1.0.0",
new: "9000.0.2",
new: "9000.0.1",
info: "https://github.com/LeaVerou/prism",
},
"html-webpack-plugin": {
@ -85,7 +85,7 @@ async function main() {
},
"styled-components": {
old: "2.5.0-1",
new: "5.0.0-4.canary-sheet",
new: "5.0.0-beta.6",
info: "https://github.com/styled-components/styled-components",
},
}
@ -100,7 +100,7 @@ async function main() {
},
"prismjs": {
old: "1.0.0",
new: "9000.0.2",
new: "9000.0.1",
info: "https://github.com/LeaVerou/prism",
},
"svgstore": {
@ -125,7 +125,7 @@ async function main() {
},
"styled-components": {
old: "2.5.0-1",
new: "5.0.0-4.canary-sheet",
new: "5.0.0-beta.6",
info: "https://github.com/styled-components/styled-components",
},
}
@ -165,7 +165,7 @@ async function main() {
},
"styled-components": {
old: "2.5.0-1",
new: "4.2.0",
new: "4.3.2",
info: "https://github.com/styled-components/styled-components",
},
}

@ -110,9 +110,7 @@ if (args.registry) {
registry = npmRegisty;
}
}
if (!registry.endsWith("/")) {
registry += "/";
}
registry = normalizeRegistryUrl(registry);
let packageFile;
const deps = {};
@ -198,40 +196,64 @@ if (!Object.keys(deps).length) {
const fetch = require("make-fetch-happen");
const hostedGitInfo = require("hosted-git-info");
const registryAuthToken = require("registry-auth-token");
const registryUrl = require("registry-auth-token/registry-url");
function fetchFromRegistry(name, registry) {
function getAuthAndRegistry(name, registry) {
let auth;
try {
auth = registryAuthToken(registry);
if (!name.startsWith("@")) {
auth = registryAuthToken(registry);
} else {
const scope = (/@[a-z0-9][\w-.]+/.exec(name) || [])[0];
const url = normalizeRegistryUrl(registryUrl(scope));
if (url !== registry) {
try {
const newAuth = registryAuthToken(url);
if (newAuth && newAuth.token) {
auth = newAuth;
registry = url;
}
} catch (err) {}
}
}
} catch (err) {
finish(err);
}
return [auth, registry];
}
function fetchFromRegistry(name, registry, auth) {
// on scoped packages replace "/" with "%2f"
if (/@[a-z0-9][\w-.]+\/[a-z0-9][\w-.]*/gi.test(name)) {
name = name.replace(/\//g, "%2f");
}
const opts = (auth && auth.token) ? {headers: {Authorization: `Bearer ${auth.token}`}} : undefined;
return fetch(registry + name, opts);
return fetch(`${registry}/${name}`, opts);
}
const get = async name => {
let res = await fetchFromRegistry(name, registry);
const get = async (name, originalRegistry) => {
const [auth, registry] = getAuthAndRegistry(name, originalRegistry);
let res = await fetchFromRegistry(name, registry, auth);
if (registry === npmRegisty || (res.status >= 200 && res.status < 300)) {
return await res.json();
return [await res.json(), registry];
} else { // retry on official registry if custom registry fails
res = await fetchFromRegistry(name, npmRegisty);
if (res.status >= 200 && res.status < 300) {
return await res.json();
return [await res.json(), registry];
} else {
throw new Error(`Received ${res.status} ${res.statusText} for ${name}`);
}
}
};
const getInfoUrl = ({repository, homepage}) => {
if (repository) {
const getInfoUrl = ({repository, homepage}, registry, name) => {
if (registry === "https://npm.pkg.github.com") {
return `https://github.com/${name.replace(/^@/, "")}`;
} else if (repository) {
const gitUrl = typeof repository === "string" ? repository : repository.url;
const info = hostedGitInfo.fromUrl(gitUrl);
if (info && info.browse) return info.browse();
@ -240,8 +262,8 @@ const getInfoUrl = ({repository, homepage}) => {
return homepage || "";
};
Promise.all(Object.keys(deps).map(name => get(name))).then(dati => {
for (const data of dati) {
Promise.all(Object.keys(deps).map(name => get(name, registry))).then(dati => {
for (const [data, registry] of dati) {
if (data && data.error) {
throw new Error(data.error);
}
@ -267,7 +289,7 @@ Promise.all(Object.keys(deps).map(name => get(name))).then(dati => {
delete deps[data.name];
} else {
deps[data.name].new = newRange;
deps[data.name].info = getInfoUrl(data.versions[newVersion] || data);
deps[data.name].info = getInfoUrl(data.versions[newVersion] || data, registry, data.name);
}
}
@ -329,6 +351,14 @@ function finish(obj, opts = {}) {
}
}
function normalizeRegistryUrl(url) {
if (url.endsWith("/")) {
return url.substring(0, url.length - 1);
} else {
return url;
}
}
function highlightDiff(a, b, added) {
const aParts = a.split(/\./);
const bParts = b.split(/\./);
@ -435,7 +465,7 @@ function findVersion(data, versions, opts) {
const diff = semver.diff(tempVersion, parsed.version);
if (!diff || !semvers.includes(diff)) continue;
if (opts.useGreatest) {
if (opts.useGreatest || !("time" in data)) { // some registries like github don't have data.time available, fall back to greatest on them
if (semver.gte(semver.coerce(parsed.version).version, tempVersion)) {
tempVersion = parsed.version;
}
@ -453,7 +483,7 @@ function findVersion(data, versions, opts) {
function findNewVersion(data, opts) {
if (opts.range === "*") return "*";
const versions = Object.keys(data.time).filter(version => semver.valid(version));
const versions = Object.keys(data.versions).filter(version => semver.valid(version));
const version = findVersion(data, versions, opts);
if (opts.useGreatest) {