query-registry
Version:
Query the npm registry for packuments, manifests, packages and download counts
1,235 lines (1,145 loc) • 30.9 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
var validatePackageName = require('validate-npm-package-name');
var makeError = require('make-error');
var unfetch = require('isomorphic-unfetch');
var lru = require('tiny-lru');
var gitUrlParse = require('git-url-parse');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return n;
}
var validatePackageName__default = /*#__PURE__*/_interopDefaultLegacy(validatePackageName);
var makeError__default = /*#__PURE__*/_interopDefaultLegacy(makeError);
var unfetch__default = /*#__PURE__*/_interopDefaultLegacy(unfetch);
var lru__default = /*#__PURE__*/_interopDefaultLegacy(lru);
var gitUrlParse__default = /*#__PURE__*/_interopDefaultLegacy(gitUrlParse);
/**
* npm registry
*
* @see {@link https://registry.npmjs.org}
*/
const npmRegistry = 'https://registry.npmjs.org';
/**
* npm registry mirror by Cloudflare
*
* @remarks
* This registry has CORS enabled and can be used to retrieve
* package manifests and packuments in the browser.
*
* @see {@link https://npmjs.cf}
* @see {@link https://registry.npmjs.cf}
*/
const cloudflareRegistry = 'https://registry.npmjs.cf';
/**
* npm registry mirror by Yarn
*
* @see {@link https://registry.yarnpkg.com}
*/
const yarnRegistry = 'https://registry.yarnpkg.com';
/**
* Mirrors of the npm registry.
*
* @see {@link cloudflareRegistry}
* @see {@link yarnRegistry}
*/
const npmRegistryMirrors = [cloudflareRegistry, yarnRegistry];
/**
* Downloads API for the npm registry
*
* @see {@link https://api.npmjs.org}
*/
const npmRegistryDownloadsAPI = 'https://api.npmjs.org';
function normalizeRawAbbreviatedPackument({
rawAbbreviatedPackument
}) {
const {
'dist-tags': distTags,
name: id,
modified: modifiedAt
} = rawAbbreviatedPackument;
return { ...rawAbbreviatedPackument,
id,
distTags,
modifiedAt
};
}
/**
* `FetchError` represents an error that happened when fetching a URL.
*
* The `instanceof` operator can be used to check for this error.
*/
class FetchError extends makeError.BaseError {
constructor(
/** URL originally fetched */
url,
/** Response received */
response) {
super(`fetch: request to ${url} failed with status ${response.statusText}`);
this.url = void 0;
this.response = void 0;
this.url = url;
this.response = response;
}
}
/**
* `InvalidPackageNameError` is thrown when the name of a package
* is not valid according to the npm registry naming rules.
*
* The `instanceof` operator can be used to check for this error.
*
* @see {@link https://www.npmjs.com/package/validate-npm-package-name}
*/
const InvalidPackageNameError = /*#__PURE__*/makeError__default["default"]('InvalidPackageNameError');
/**
* `InvalidPackageVersionError` is thrown when a package's version does not exist.
*
* The `instanceof` operator can be used to check for this error.
*/
const InvalidPackageVersionError = /*#__PURE__*/makeError__default["default"]('InvalidPackageVersionError');
async function log(formatter, ...args) {
{
try {
const {
debug
} = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('debug')); });
const logger = debug('query-registry');
logger(formatter, args);
} catch {}
}
}
function assertValidPackageName({
name
}) {
const {
validForOldPackages,
validForNewPackages
} = validatePackageName__default["default"](name);
const valid = validForOldPackages || validForNewPackages;
if (!valid) {
log('assertValidPackageName: invalid package name: %O', {
name
});
throw new InvalidPackageNameError(`invalid package name: '${name}'`);
}
}
const maxItems = 250;
const fiveMinutesTTL = 5 * 60 * 1000;
const cache = /*#__PURE__*/lru__default["default"](maxItems, fiveMinutesTTL);
async function fetch({
url,
headers,
cached = true
}) {
const cacheKey = `headers=${JSON.stringify(headers)};url=${url}`;
const cachedJSON = cache.get(cacheKey);
if (cached && cachedJSON) {
log('fetch: returning cached response: %O', {
cacheKey,
url,
cachedJSON
});
return cachedJSON;
}
const response = await unfetch__default["default"](url, {
headers
});
if (!response.ok) {
log('fetch: request failed: %O', {
url,
headers,
status: response.statusText,
response
});
throw new FetchError(url, response);
}
const json = await response.json();
if (cached) {
cache.set(cacheKey, json);
}
log('fetch: returning fresh response: %O', {
url,
json
});
return json;
}
async function fetchFromRegistry({
endpoint,
headers,
query,
registry = npmRegistry,
mirrors = npmRegistryMirrors,
cached
}) {
const urls = [registry, ...mirrors].map(host => {
const url = new URL(endpoint, host);
url.search = query != null ? query : '';
return url.href;
});
let lastError;
for (const url of urls) {
try {
const json = await fetch({
url,
headers,
cached
});
return json;
} catch (err) {
// Keep last fetch error
lastError = err;
}
}
log('fetchFromRegistry: cannot retrieve data from registry or mirrors: %O', {
endpoint,
headers,
query,
registry,
mirrors,
lastError
});
throw lastError;
}
/**
* `getRawAbbreviatedPackument` returns the abbreviated packument (package document)
* containing only the metadata necessary to install a package present on the registry.
*
* Note: the abbreviated packument is returned as retrieved from the registry.
*
* @param name - package name
* @param registry - URL of the registry (default: npm registry)
* @param mirrors - URLs of the registry mirrors (default: npm registry mirrors)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the abbreviated packument for package `query-registry` from the npm registry:
*
* ```typescript
* import { getRawAbbreviatedPackument } from 'query-registry';
*
* (async () => {
* const packument = await getRawAbbreviatedPackument({ name: 'query-registry' });
*
* // Output: 'query-registry'
* console.log(packument.name);
* })();
* ```
*
* @see {@link RawAbbreviatedPackument}
* @see {@link npmRegistry}
* @see {@link npmRegistryMirrors}
*/
async function getRawAbbreviatedPackument({
name,
registry,
mirrors,
cached
}) {
assertValidPackageName({
name
});
const endpoint = `/${name}`;
const headers = {
Accept: 'application/vnd.npm.install-v1+json'
};
return fetchFromRegistry({
endpoint,
headers,
registry,
mirrors,
cached
});
}
/**
* `getAbbreviatedPackument` returns the abbreviated packument (package document)
* containing only the metadata necessary to install a package present on the registry.
*
* @remarks
* To get all the metadata (full packument) about a package see {@link getPackument}.
*
* @param name - package name
* @param registry - URL of the registry (default: npm registry)
* @param mirrors - URLs of the registry mirrors (default: npm registry mirrors)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the abbreviated packument for package `query-registry` from the npm registry:
*
* ```typescript
* import { getAbbreviatedPackument } from 'query-registry';
*
* (async () => {
* const packument = await getAbbreviatedPackument({ name: 'query-registry' });
*
* // Output: 'query-registry'
* console.log(packument.name);
* })();
* ```
*
* @see {@link AbbreviatedPackument}
* @see {@link RawAbbreviatedPackument}
* @see {@link npmRegistry}
* @see {@link npmRegistryMirrors}
*/
async function getAbbreviatedPackument({
name,
registry,
mirrors,
cached
}) {
const rawAbbreviatedPackument = await getRawAbbreviatedPackument({
name,
registry,
mirrors,
cached
});
return normalizeRawAbbreviatedPackument({
rawAbbreviatedPackument
});
}
async function fetchDownloadsFromRegistry({
endpoint,
registryDownloadsAPI = npmRegistryDownloadsAPI,
cached
}) {
return fetchFromRegistry({
endpoint,
registry: registryDownloadsAPI,
mirrors: [],
cached
});
}
function normalizeRawDownloadPeriod({
rawDownloadPeriod = 'last-week'
}) {
if (typeof rawDownloadPeriod === 'string') {
return rawDownloadPeriod;
}
if (rawDownloadPeriod instanceof Date) {
return getDay(rawDownloadPeriod);
}
const {
start,
end
} = rawDownloadPeriod;
return `${getDay(start)}:${getDay(end)}`;
}
function getDay(date) {
return date.toISOString().split('T')[0];
}
/**
* `getDailyPackageDownloads` returns the number of downloads for a package
* for each day in a given time period.
*
* @param name - package name
* @param period - time period in which downloads happened (default: `last-week`)
* @param registryDownloadsAPI - URL of the registry's downloads API (default: npm registry)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the day by day weekly downloads for package `query-registry` from the npm registry:
*
* ```typescript
* import { getDailyPackageDownloads } from 'query-registry';
*
* (async () => {
* const downloads = await getDailyPackageDownloads({ name: 'query-registry' });
*
* // Output: 'query-registry'
* console.log(downloads.package);
*
* // Output: 'number'
* console.log(typeof downloads.downloads[0].downloads);
* })();
* ```
*
* @example
* Get the day by day monthly downloads for package `query-registry` from the npm registry:
*
* ```typescript
* import { getDailyPackageDownloads } from 'query-registry';
*
* (async () => {
* const downloads = await getDailyPackageDownloads({ name: 'query-registry', period: 'last-month' });
*
* // Output: 'query-registry'
* console.log(downloads.package);
*
* // Output: 'number'
* console.log(typeof downloads.downloads[0].downloads);
* })();
* ```
*
* @see {@link DailyPackageDownloads}
* @see {@link DownloadPeriod}
* @see {@link npmRegistryDownloadsAPI}
* @see {@link https://github.com/npm/registry/blob/master/docs/download-counts.md#ranges}
*/
async function getDailyPackageDownloads({
name,
period: rawDownloadPeriod,
registryDownloadsAPI,
cached
}) {
assertValidPackageName({
name
});
const period = normalizeRawDownloadPeriod({
rawDownloadPeriod
});
const endpoint = `/downloads/range/${period}/${name}`;
return fetchDownloadsFromRegistry({
endpoint,
registryDownloadsAPI,
cached
});
}
/**
* `getDailyRegistryDownloads` returns the number of downloads for all registry packages
* for each day in a given time period.
*
* @param period - time period in which downloads happened (default: `last-week`)
* @param registryDownloadsAPI - URL of the registry's downloads API (default: npm registry)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the day by day weekly downloads for the npm registry:
*
* ```typescript
* import { getDailyRegistryDownloads } from 'query-registry';
*
* (async () => {
* const downloads = await getDailyRegistryDownloads();
*
* // Output: 'number'
* console.log(typeof downloads.downloads[0].downloads);
* })();
* ```
*
* @example
* Get the day by day monthly downloads for the npm registry:
*
* ```typescript
* import { getDailyRegistryDownloads } from 'query-registry';
*
* (async () => {
* const downloads = await getDailyRegistryDownloads({ period: 'last-month' });
*
* // Output: 'number'
* console.log(typeof downloads.downloads[0].downloads);
* })();
* ```
*
* @see {@link DailyRegistryDownloads}
* @see {@link DownloadPeriod}
* @see {@link npmRegistryDownloadsAPI}
* @see {@link https://github.com/npm/registry/blob/master/docs/download-counts.md#ranges}
*/
async function getDailyRegistryDownloads({
period: rawDownloadPeriod,
registryDownloadsAPI,
cached
} = {}) {
const period = normalizeRawDownloadPeriod({
rawDownloadPeriod
});
const endpoint = `/downloads/range/${period}`;
return fetchDownloadsFromRegistry({
endpoint,
registryDownloadsAPI,
cached
});
}
/**
* `getPackageDownloads` returns the number of downloads for a package
* in a given time period.
*
* @param name - package name
* @param period - time period in which downloads happened (default: `last-week`)
* @param registryDownloadsAPI - URL of the registry's downloads API (default: npm registry)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the weekly downloads for package `query-registry` from the npm registry:
*
* ```typescript
* import { getPackageDownloads } from 'query-registry';
*
* (async () => {
* const downloads = await getPackageDownloads({ name: 'query-registry' });
*
* // Output: 'query-registry'
* console.log(downloads.package);
*
* // Output: 'number'
* console.log(typeof downloads.downloads);
* })();
* ```
*
* @example
* Get the monthly downloads for package `query-registry` from the npm registry:
*
* ```typescript
* import { getPackageDownloads } from 'query-registry';
*
* (async () => {
* const downloads = await getPackageDownloads({ name: 'query-registry', period: 'last-month' });
*
* // Output: 'query-registry'
* console.log(downloads.package);
*
* // Output: 'number'
* console.log(typeof downloads.downloads);
* })();
* ```
*
* @see {@link PackageDownloads}
* @see {@link DownloadPeriod}
* @see {@link npmRegistryDownloadsAPI}
* @see {@link https://github.com/npm/registry/blob/master/docs/download-counts.md#point-values}
*/
async function getPackageDownloads({
name,
period: rawDownloadPeriod,
registryDownloadsAPI,
cached
}) {
assertValidPackageName({
name
});
const period = normalizeRawDownloadPeriod({
rawDownloadPeriod
});
const endpoint = `/downloads/point/${period}/${name}`;
return fetchDownloadsFromRegistry({
endpoint,
registryDownloadsAPI,
cached
});
}
function extractRawPackageManifest({
rawPackument,
version = 'latest'
}) {
var _distTags$version;
const {
name,
'dist-tags': distTags,
versions
} = rawPackument;
const versionNumber = (_distTags$version = distTags[version]) != null ? _distTags$version : version;
const manifest = versions[versionNumber];
if (!manifest) {
log('getPackageManifest: invalid package version: %O', {
name,
version
});
throw new InvalidPackageVersionError(`invalid package version: '${name}@${version}'`);
}
return manifest;
}
/**
* `getRawPackument` returns the packument (package document) containing
* all the metadata about a package present on the registry.
*
* Note: the packument is returned as retrieved from the registry.
*
* @param name - package name
* @param registry - URL of the registry (default: npm registry)
* @param mirrors - URLs of the registry mirrors (default: npm registry mirrors)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the packument for package `query-registry` from the npm registry:
*
* ```typescript
* import { getRawPackument } from 'query-registry';
*
* (async () => {
* const packument = await getRawPackument({ name: 'query-registry' });
*
* // Output: 'query-registry'
* console.log(packument.name);
* })();
* ```
*
* @see {@link RawPackument}
* @see {@link npmRegistry}
* @see {@link npmRegistryMirrors}
*/
async function getRawPackument({
name,
registry,
mirrors,
cached
}) {
assertValidPackageName({
name
});
const endpoint = `/${name}`;
return fetchFromRegistry({
endpoint,
registry,
mirrors,
cached
});
}
/**
* `getRawPackageManifest` returns the manifest describing
* a specific version of a package.
*
* Note: the manifest is returned as retrieved from the registry.
*
* @param name - package name
* @param version - package version (default: `latest`)
* @param registry - URL of the registry (default: npm registry)
* @param mirrors - URLs of the registry mirrors (default: npm registry mirrors)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the latest manifest for package `query-registry` from the npm registry:
*
* ```typescript
* import { getRawPackageManifest } from 'query-registry';
*
* (async () => {
* const manifest = await getRawPackageManifest({ name: 'query-registry' });
*
* // Output: 'query-registry'
* console.log(manifest.name);
* })();
* ```
*
* @example
* Get the manifest for package `query-registry@1.0.0` from the npm registry:
*
* ```typescript
* import { getRawPackageManifest } from 'query-registry';
*
* (async () => {
* const manifest = await getRawPackageManifest({ name: 'query-registry', version: '1.0.0' });
*
* // Output: 'query-registry'
* console.log(manifest.name);
*
* // Output: '1.0.0'
* console.log(manifest.version);
* })();
* ```
*
* @see {@link RawPackageManifest}
* @see {@link npmRegistry}
* @see {@link npmRegistryMirrors}
*/
async function getRawPackageManifest({
name,
version,
registry,
mirrors,
cached
}) {
const rawPackument = await getRawPackument({
name,
registry,
mirrors,
cached
});
return extractRawPackageManifest({
rawPackument,
version
});
}
async function getDefinitelyTypedName({
rawPackageManifest,
registry,
mirrors,
cached
}) {
const {
name,
types,
typings
} = rawPackageManifest;
const definitelyTypedName = toDefinitelyTypedName({
name
});
const alreadyTyped = name === definitelyTypedName || !!types || !!typings;
if (alreadyTyped) {
return undefined;
}
let ok = false;
try {
const {
deprecated
} = await getRawPackageManifest({
name: definitelyTypedName,
registry,
mirrors,
cached
});
ok = deprecated === undefined;
} catch {}
return ok ? definitelyTypedName : undefined;
}
/**
* `toDefinitelyTypedName` returns the name of the corresponding
* DefinitelyTyped package (for example,
* `foo` => `@types/foo`,
* `@bar/baz` => `@types/bar__baz`).
*/
function toDefinitelyTypedName({
name
}) {
return name.startsWith('@types/') ? name : `@types/${name.replace('@', '').replace('/', '__')}`;
}
/**
* `getUntypedName` returns the name of the normal package
* corresponding to a DefinitelyTyped package.
*/
function getUntypedName({
name
}) {
if (!name.startsWith('@types/')) {
return undefined;
} // ['foo', undefined] or ['@bar', 'baz']
const [scopeOrName, scopedName] = name.replace('@types/', '').split('__');
return scopedName ? `@${scopeOrName}/${scopedName}` : scopeOrName;
}
function normalizeRawLicense({
rawLicense
}) {
if (!rawLicense) {
return undefined;
}
if (typeof rawLicense !== 'string') {
return undefined;
}
return rawLicense;
}
function normalizeRawRepository({
rawRepository
}) {
if (isRepository(rawRepository)) {
return normalizeRepository({
rawRepository
});
}
if (typeof rawRepository === 'string') {
return normalizeRepository({
rawRepository: {
url: rawRepository
}
});
}
return undefined;
}
function isRepository(rawRepository) {
return rawRepository && typeof rawRepository === 'object' && typeof rawRepository['url'] === 'string' && ['string', 'undefined'].includes(typeof rawRepository['type']) && ['string', 'undefined'].includes(typeof rawRepository['directory']);
}
function normalizeRepository({
rawRepository
}) {
const {
url,
directory: repositoryDir
} = rawRepository;
const info = parseGitURL({
url
});
if (!info) {
return undefined;
}
const {
source,
full_name: repositoryID,
filepath
} = info; // Add domain to sources derived from npm-style shortcuts
const host = source.replace(/^$/, 'github.com').replace(/^github$/, 'github.com').replace(/^gitlab$/, 'gitlab.com').replace(/^bitbucket$/, 'bitbucket.org');
const parsedDir = filepath !== '' ? filepath : undefined;
return {
type: 'git',
url: `https://${host}/${repositoryID}`,
directory: repositoryDir != null ? repositoryDir : parsedDir
};
}
function parseGitURL({
url
}) {
let info;
try {
info = gitUrlParse__default["default"](url);
} catch {}
return info;
}
async function normalizeRawPackageManifest({
rawPackageManifest,
rawPackument,
registry,
mirrors,
cached
}) {
const {
_id: id,
name,
version,
license: rawLicense,
repository: rawRepository,
_npmUser: publisher
} = rawPackageManifest;
const createdAt = rawPackument.time[version];
const license = normalizeRawLicense({
rawLicense
});
const gitRepository = normalizeRawRepository({
rawRepository
});
const definitelyTypedName = await getDefinitelyTypedName({
rawPackageManifest,
registry,
mirrors,
cached
});
const untypedName = getUntypedName({
name
});
return { ...rawPackageManifest,
id,
createdAt,
publisher,
license,
gitRepository,
definitelyTypedName,
untypedName
};
}
/**
* `getPackageManifest` returns the manifest describing
* a specific version of a package.
*
* @param name - package name
* @param version - package version (default: `latest`)
* @param registry - URL of the registry (default: npm registry)
* @param mirrors - URLs of the registry mirrors (default: npm registry mirrors)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the latest manifest for package `query-registry` from the npm registry:
*
* ```typescript
* import { getPackageManifest } from 'query-registry';
*
* (async () => {
* const manifest = await getPackageManifest({ name: 'query-registry' });
*
* // Output: 'query-registry'
* console.log(manifest.name);
* })();
* ```
*
* @example
* Get the manifest for package `query-registry@1.0.0` from the npm registry:
*
* ```typescript
* import { getPackageManifest } from 'query-registry';
*
* (async () => {
* const manifest = await getPackageManifest({ name: 'query-registry', version: '1.0.0' });
*
* // Output: 'query-registry'
* console.log(manifest.name);
*
* // Output: '1.0.0'
* console.log(manifest.version);
* })();
* ```
*
* @see {@link PackageManifest}
* @see {@link RawPackageManifest}
* @see {@link npmRegistry}
* @see {@link npmRegistryMirrors}
*/
async function getPackageManifest({
name,
version,
registry,
mirrors,
cached
}) {
const rawPackument = await getRawPackument({
name,
registry,
mirrors,
cached
});
const rawPackageManifest = extractRawPackageManifest({
rawPackument,
version
});
const packageManifest = await normalizeRawPackageManifest({
rawPackageManifest,
rawPackument,
registry,
mirrors,
cached
});
return packageManifest;
}
function normalizeRawPackument({
rawPackument
}) {
const {
_id: id,
'dist-tags': distTags,
time,
license: rawLicense,
repository: rawRepository
} = rawPackument;
const license = normalizeRawLicense({
rawLicense
});
const gitRepository = normalizeRawRepository({
rawRepository
});
const versionsToTimestamps = Object.fromEntries(Object.entries(time).filter(([key]) => {
return !['created', 'modified'].includes(key);
}));
return { ...rawPackument,
id,
distTags,
versionsToTimestamps,
license,
gitRepository
};
}
/**
* `getPackument` returns the packument (package document) containing
* all the metadata about a package present on the registry.
*
* @param name - package name
* @param registry - URL of the registry (default: npm registry)
* @param mirrors - URLs of the registry mirrors (default: npm registry mirrors)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the packument for package `query-registry` from the npm registry:
*
* ```typescript
* import { getPackument } from 'query-registry';
*
* (async () => {
* const packument = await getPackument({ name: 'query-registry' });
*
* // Output: 'query-registry'
* console.log(packument.name);
* })();
* ```
*
* @see {@link Packument}
* @see {@link RawPackument}
* @see {@link npmRegistry}
* @see {@link npmRegistryMirrors}
*/
async function getPackument({
name,
registry,
mirrors,
cached
}) {
const rawPackument = await getRawPackument({
name,
registry,
mirrors,
cached
});
return normalizeRawPackument({
rawPackument
});
}
/**
* `getRegistryDownloads` returns the number of downloads for all registry packages
* in a given time period.
*
* @param period - time period in which downloads happened (default: `last-week`)
* @param registryDownloadsAPI - URL of the registry's downloads API (default: npm registry)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the weekly downloads for the npm registry:
*
* ```typescript
* import { getRegistryDownloads } from 'query-registry';
*
* (async () => {
* const downloads = await getRegistryDownloads();
*
* // Output: 'number'
* console.log(typeof downloads.downloads);
* })();
* ```
*
* @example
* Get the monthly downloads for the npm registry:
*
* ```typescript
* import { getRegistryDownloads } from 'query-registry';
*
* (async () => {
* const downloads = await getRegistryDownloads({ period: 'last-month' });
*
* // Output: 'number'
* console.log(typeof downloads.downloads);
* })();
* ```
*
* @see {@link RegistryDownloads}
* @see {@link DownloadPeriod}
* @see {@link npmRegistryDownloadsAPI}
* @see {@link https://github.com/npm/registry/blob/master/docs/download-counts.md#point-values}
*/
async function getRegistryDownloads({
period: rawDownloadPeriod,
registryDownloadsAPI,
cached
} = {}) {
const period = normalizeRawDownloadPeriod({
rawDownloadPeriod
});
const endpoint = `/downloads/point/${period}`;
return fetchDownloadsFromRegistry({
endpoint,
registryDownloadsAPI,
cached
});
}
/**
* `getRegistryMetadata` returns the metadata describing the registry itself.
*
* @param registry - URL of the registry (default: npm registry)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the metadata for the npm registry:
*
* ```typescript
* import { getRegistryMetadata } from 'query-registry';
*
* (async () => {
* const metadata = await getRegistryMetadata();
*
* // Output: 'registry'
* console.log(metadata.db_name);
* })();
* ```
*
* @example
* Get the metadata for a custom registry:
*
* ```typescript
* import { getRegistryMetadata } from 'query-registry';
*
* (async () => {
* const metadata = await getRegistryMetadata({ registry: 'https://example.com' });
* })();
* ```
*
* @see {@link RegistryMetadata}
* @see {@link npmRegistry}
*/
async function getRegistryMetadata({
registry,
cached
} = {}) {
const endpoint = '/';
return fetchFromRegistry({
registry,
mirrors: [],
endpoint,
cached
});
}
function normalizeRawSearchCriteria({
rawSearchCriteria
}) {
// Convert SearchCriteria to a URL query string
return Object.entries(rawSearchCriteria).filter(([, value]) => ['string', 'number'].includes(typeof value)).map(([key, value]) => `${key}=${value}`).join('&');
}
/**
* `searchPackages` returns the packages corresponding to a given query.
*
* @param query - one or more search criteria
* @param registry - URL of the registry (default: npm registry)
* @param mirrors - URLs of the registry mirrors (default: npm registry mirrors)
* @param cached - accept cached responses (default: `true`)
*
* @example
* Get the search results for text query `query-registry` from the npm registry:
*
* ```typescript
* import { searchPackages } from 'query-registry';
*
* (async () => {
* const results = await searchPackages({ query: { text: 'query-registry' } });
*
* // Output: 'query-registry'
* console.log(results.objects[0].package.name);
* })();
* ```
*
* @see {@link SearchResults}
* @see {@link SearchCriteria}
* @see {@link npmRegistry}
* @see {@link npmRegistryMirrors}
*/
async function searchPackages({
query: rawSearchCriteria,
registry,
mirrors,
cached
}) {
const endpoint = '/-/v1/search';
const query = normalizeRawSearchCriteria({
rawSearchCriteria
});
return fetchFromRegistry({
endpoint,
query,
registry,
mirrors,
cached
});
}
exports.FetchError = FetchError;
exports.InvalidPackageNameError = InvalidPackageNameError;
exports.InvalidPackageVersionError = InvalidPackageVersionError;
exports.cloudflareRegistry = cloudflareRegistry;
exports.getAbbreviatedPackument = getAbbreviatedPackument;
exports.getDailyPackageDownloads = getDailyPackageDownloads;
exports.getDailyRegistryDownloads = getDailyRegistryDownloads;
exports.getPackageDownloads = getPackageDownloads;
exports.getPackageManifest = getPackageManifest;
exports.getPackument = getPackument;
exports.getRawAbbreviatedPackument = getRawAbbreviatedPackument;
exports.getRawPackageManifest = getRawPackageManifest;
exports.getRawPackument = getRawPackument;
exports.getRegistryDownloads = getRegistryDownloads;
exports.getRegistryMetadata = getRegistryMetadata;
exports.npmRegistry = npmRegistry;
exports.npmRegistryDownloadsAPI = npmRegistryDownloadsAPI;
exports.npmRegistryMirrors = npmRegistryMirrors;
exports.searchPackages = searchPackages;
exports.yarnRegistry = yarnRegistry;
//# sourceMappingURL=query-registry.cjs.development.js.map
;