Skip to content

Commit

Permalink
feat: support auth for the search command
Browse files Browse the repository at this point in the history
  • Loading branch information
favoyang committed Aug 9, 2020
1 parent b41725f commit a96708e
Show file tree
Hide file tree
Showing 7 changed files with 512 additions and 577 deletions.
1 change: 1 addition & 0 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ program
program
.command("search <keyword>")
.aliases(["s", "se", "find"])
.option("--clean-cache", "clean local cache before search")
.description("Search package by keyword")
.action(async function(keyword, options) {
const retCode = await search(keyword, options);
Expand Down
95 changes: 40 additions & 55 deletions lib/cmd-search.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,40 @@
const { log } = require("./logger");
const npmSearch = require("libnpmsearch");
const npmFetch = require("npm-registry-fetch");
const Table = require("cli-table");

const { log } = require("./logger");
const {
env,
cleanCache,
getCache,
parseEnv,
getLatestVersion,
httpGet
getNpmFetchOptions,
parseEnv
} = require("./core");
const { isConnectionError, is404Error } = require("./error-handler");

const searchEndpoint = async function(keyword, registry) {
if (!registry) registry = env.registry;
let serverUrl = `${registry}/-/v1/search?text=${keyword}&size=20&from=0&quality=0.65&popularity=0.98&maintenance=0.5`;
try {
log.http("request", `GET ${serverUrl}`);
const response = await httpGet(serverUrl).accept("json");
response.body = JSON.parse(response.text);
log.http(`${response.status}`, serverUrl);
log.verbose("response", response.body);
const objects = response.body.objects || [];
return objects.map(x => {
let pkg = x.package;
let name = `${pkg.name}${pkg.displayName ? "\n" + pkg.displayName : ""}`;
const distTags = pkg["dist-tags"];
const version = distTags && distTags["latest"] ? distTags["latest"] : "";
let author = pkg.author ? pkg.author.name : "";
let date =
pkg.time && pkg.time.modified ? pkg.time.modified.split("T")[0] : "";
let keywords = (pkg.keywords || []).join(", ");
let item = [name, version, author, date, keywords];
return item;
const results = await npmSearch(keyword, getNpmFetchOptions());
log.verbose("npmsearch", results);
return results.map(x => {
return [
x.name,
x["dist-tags"] ? x["dist-tags"].latest : "",
x.time && x.time.modified ? x.time.modified.split("T")[0] : "",
""
];
});
} catch (err) {
if (err.response && err.response.status)
log.http(`${err.response.status}`, serverUrl);
if (isConnectionError(err))
log.http("request", `can not reach to ${serverUrl}`);
else if (!is404Error(err)) log.error("", err.message);
if (!is404Error(err)) log.error("", err.message);
log.warn("", "fast search endpoint is not available, using old search.");
}
};

const searchOld = async function(keyword) {
const searchOld = async function(keyword, shouldCleanCache) {
// clean cache if needed
if (shouldCleanCache) cleanCache();
// load cache
let cache = getCache();
let cacheKey = env.namespace + ".all";
Expand All @@ -55,40 +48,35 @@ const searchOld = async function(keyword) {
);
// all endpoint
let serverUrl = cached._updated
? `${env.registry}/-/all/since?stale=update_after&startkey=${cached._updated}`
: `${env.registry}/-/all`;
? `/-/all/since?stale=update_after&startkey=${cached._updated}`
: `/-/all`;
try {
log.http("request", `GET ${serverUrl}`);
const response = await httpGet(serverUrl).accept("json");
response.body = JSON.parse(response.text);
log.http(`${response.status}`, serverUrl);
log.http("response", response.body);
const results = await npmFetch.json(serverUrl, getNpmFetchOptions());
log.verbose("endpoint.all", results);
let objects = [];
if (response.body) {
// resposne.body is an array of objects
if (Array.isArray(response.body)) objects = response.body;
// response.body is an object
else {
if ("_updated" in response.body) delete response.body["_updated"];
objects = Object.values(response.body);
if (results) {
if (Array.isArray(results)) {
// results is an array of objects
objects = results;
} else {
// results is an object
if ("_updated" in results) delete results["_updated"];
objects = Object.values(results);
}
}
// contact cached objects and remote objects
const allObjects = objects.concat(cached.objects || []);
// save to cache
cached.objects = allObjects;
cached._updated =
Date.parse(response.header.date) || Math.round(new Date().getTime());
cached._updated = Math.round(new Date().getTime());
cache[cacheKey] = cached;
// prepare rows
const rows = allObjects.map(pkg => {
let name = `${pkg.name}${pkg.displayName ? "\n" + pkg.displayName : ""}`;
let name = pkg.name;
let version = getLatestVersion(pkg);
let author = pkg.author && pkg.author.name ? pkg.author.name : "";
let date =
pkg.time && pkg.time.modified ? pkg.time.modified.split("T")[0] : "";
let keywords = (pkg.keywords || []).join(", ");
let item = [name, version, author, date, keywords];
let item = [name, version, date, ""];
return item;
});
// filter keyword
Expand All @@ -97,18 +85,15 @@ const searchOld = async function(keyword) {
row => row.filter(x => x.toLowerCase().includes(klc)).length > 0
);
} catch (err) {
if (err.response && err.response.status)
log.http(`${err.response.status}`, serverUrl);
if (isConnectionError(err))
log.http("request", `can not reach to ${serverUrl}`);
else if (!is404Error(err)) log.error("", err.message);
if (!is404Error(err)) log.error("", err.message);
log.warn("", "/-/all endpoint is not available");
}
};

const getTable = function() {
var table = new Table({
head: ["Name", "Version", "Author", "Date"],
colWidths: [46, 22, 14, 12]
head: ["Name", "Version", "Date"],
colWidths: [42, 20, 12]
});
return table;
};
Expand All @@ -122,7 +107,7 @@ module.exports = async function(keyword, options) {
let results = await searchEndpoint(keyword);
// search old search
if (results === undefined) {
results = (await searchOld(keyword)) || [];
results = (await searchOld(keyword, options.cleanCache)) || [];
}
// search upstream
// if (env.upstream) {
Expand Down
38 changes: 21 additions & 17 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ const mkdirp = require("mkdirp");
const isIp = require("is-ip");
const isWsl = require("is-wsl");
const keyFileStorage = require("key-file-storage").default;
const superagent = require("superagent");
// extend with Request#proxy()
require("superagent-proxy")(superagent);
const TOML = require("@iarna/toml");

const { execute } = require("./utils/process");
Expand Down Expand Up @@ -83,7 +80,7 @@ const parseEnv = async function(options, { checkPath }) {
const [username, password] = text.split(":", 2);
env.auth[reg] = {
username,
password,
password: Buffer.from(password).toString("base64"),
email: regAuth.email,
alwaysAuth: regAuth.alwaysAuth || false
};
Expand Down Expand Up @@ -132,14 +129,21 @@ const parseName = function(pkg) {
return { name, version };
};

// Superagent.get with proxy
const httpGet = function(url) {
const req = superagent.get(url);
var proxy = process.env.http_proxy;
if (proxy) {
req.proxy(proxy);
// Get npm fetch options
const getNpmFetchOptions = function() {
const opts = {
log,
registry: env.registry
};
const auth = env.auth[env.registry];
if (auth) {
opts.alwaysAuth = auth.alwaysAuth;
opts.email = auth.email;
opts.password = auth.password;
opts.token = auth.token;
opts.username = auth.username;
}
return req;
return opts;
};

// Fetch package info json from registry
Expand Down Expand Up @@ -372,18 +376,18 @@ const saveUpmConfig = async function(config, configDir) {
};

module.exports = {
env,
getCache,
cleanCache,
fetchPackageInfo,
env,
fetchPackageDependencies,
fetchPackageInfo,
getCache,
getLatestVersion,
httpGet,
getNpmFetchOptions,
getUpmConfigDir,
loadManifest,
loadUpmConfig,
parseEnv,
parseName,
saveManifest,
getUpmConfigDir,
loadUpmConfig,
saveUpmConfig
};
2 changes: 1 addition & 1 deletion lib/error-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const isConnectionError = function(err) {
};

const is404Error = function(err) {
return err.response && err.response.notFound;
return (err.response && err.response.notFound) || err.message.includes("404");
};

const is503Error = function(err) {
Expand Down
Loading

0 comments on commit a96708e

Please sign in to comment.