@tsed/cli-core
Version:
Build your CLI with TypeScript and Decorators
116 lines (115 loc) • 3.69 kB
JavaScript
var NpmRegistryClient_1;
import { __decorate } from "tslib";
import url from "node:url";
import { inject, Injectable } from "@tsed/di";
import registry_url from "registry-url";
import { CliHttpClient } from "./CliHttpClient.js";
const HOST = registry_url();
const REGEX_REGISTRY_ENFORCED_HTTPS = /^https?:\/\/([^\/]+\.)?(yarnpkg\.com|npmjs\.(org|com))(\/|$)/;
const REGEX_REGISTRY_PREFIX = /^(https?:)?\/\//i;
export function addSuffix(pattern, suffix) {
if (!pattern.endsWith(suffix)) {
return pattern + suffix;
}
return pattern;
}
export const SCOPE_SEPARATOR = "%2f";
let NpmRegistryClient = NpmRegistryClient_1 = class NpmRegistryClient {
constructor() {
this.httpClient = inject(CliHttpClient);
}
static escapeName(name) {
// scoped packages contain slashes and the npm registry expects them to be escaped
return name.replace("/", SCOPE_SEPARATOR);
}
async request(pathname, opts = {}) {
const registry = opts.registry || HOST;
const requestUrl = this.getRequestUrl(registry, pathname);
const headers = {
Accept: opts.unfiltered ? "application/json" : "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*",
...opts.headers
};
try {
return await this.httpClient.get(requestUrl, {
...opts,
headers
});
}
catch (error) {
if (opts.retry) {
await new Promise((resolve) => setTimeout(resolve, 200));
opts.retry -= 1;
opts.unfiltered = true;
return this.request(NpmRegistryClient_1.escapeName(pathname), opts);
}
throw error;
}
}
getRequestUrl(registry, pathname) {
let resolved = pathname;
if (!REGEX_REGISTRY_PREFIX.test(pathname)) {
resolved = url.resolve(addSuffix(registry, "/"), pathname);
}
if (REGEX_REGISTRY_ENFORCED_HTTPS.test(resolved)) {
resolved = resolved.replace(/^http:\/\//, "https://");
}
return resolved;
}
/**
* Search a module on npm registry
* @param text
* @param options
*/
async search(text, options = {}) {
const { objects: result } = await this.request(`-/v1/search`, {
headers: {
"Accept-Encoding": "gzip"
},
qs: {
text,
size: 100,
from: 0,
quality: 0.65,
popularity: 0.98,
maintenance: 0.5,
...options
}
});
return result;
}
async info(packageName, retry = 0) {
try {
return await this.request(packageName, {
headers: {
"Accept-Encoding": "gzip"
},
unfiltered: false,
retry
});
}
catch (er) {
return retry == 0 ? this.fallback(packageName) : null;
}
}
async fallback(packageName) {
const [{ package: pkg }] = await this.search(packageName);
return {
...pkg,
"dist-tags": {
latest: pkg.version
},
versions: {
[pkg.version]: {
name: packageName,
version: pkg.version,
dependencies: {},
devDependencies: {}
}
}
};
}
};
NpmRegistryClient = NpmRegistryClient_1 = __decorate([
Injectable()
], NpmRegistryClient);
export { NpmRegistryClient };