UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

130 lines (129 loc) 5.51 kB
import "../../../constants/error-messages.js"; import { regEx } from "../../../util/regex.js"; import { logger } from "../../../logger/index.js"; import { joinUrlParts } from "../../../util/url.js"; import { add, find } from "../../../util/host-rules.js"; import { ExternalHostError } from "../../../types/errors/external-host-error.js"; import { asTimestamp } from "../../../util/timestamp.js"; import { PackageHttpCacheProvider } from "../../../util/http/cache/package-http-cache-provider.js"; import { defaultRegistryUrl } from "./common.js"; import { CachedPackument, NpmResponse } from "./schema.js"; import { isNonEmptyString, isString } from "@sindresorhus/is"; import { z } from "zod/v4"; //#region lib/modules/datasource/npm/get.ts const SHORT_REPO_REGEX = regEx(/^((?<platform>bitbucket|github|gitlab):)?(?<shortRepo>[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)$/); const platformMapping = { bitbucket: "https://bitbucket.org/", github: "https://github.com/", gitlab: "https://gitlab.com/" }; const PackageSource = z.union([z.string().nonempty().transform((repository) => { let sourceUrl = null; const sourceDirectory = null; const shortMatch = repository.match(SHORT_REPO_REGEX); if (shortMatch?.groups) { const { platform = "github", shortRepo } = shortMatch.groups; sourceUrl = platformMapping[platform] + shortRepo; } else sourceUrl = repository; return { sourceUrl, sourceDirectory }; }), z.object({ url: z.string().nonempty().nullish(), directory: z.string().nonempty().nullish() }).transform(({ url, directory }) => { const res = { sourceUrl: null, sourceDirectory: null }; if (url) res.sourceUrl = url; if (directory) res.sourceDirectory = directory; return res; })]).catch({ sourceUrl: null, sourceDirectory: null }); async function getDependency(http, registryUrl, packageName) { logger.trace(`npm.getDependency(${packageName})`); const packageUrl = joinUrlParts(registryUrl, packageName.replace("/", "%2F")); try { const options = { cacheProvider: new PackageHttpCacheProvider({ namespace: "datasource-npm:cache-provider", checkAuthorizationHeader: false, checkCacheControlHeader: true, writeSchema: CachedPackument }) }; if (registryUrl === "https://registry.npmjs.org" && find({ url: "https://registry.npmjs.org" })?.abortOnError === void 0) { logger.trace({ packageName, registry: defaultRegistryUrl }, "setting abortOnError hostRule for well known host"); add({ matchHost: defaultRegistryUrl, abortOnError: true }); } const resp = await http.getJson(packageUrl, options, NpmResponse); const { body: res } = resp; if (!res.versions || !Object.keys(res.versions).length) { logger.debug(`No versions returned for npm dependency ${packageName}`); return null; } const latestVersion = res.versions[res["dist-tags"]?.latest ?? ""]; res.repository ??= latestVersion?.repository; res.homepage ??= latestVersion?.homepage; const { sourceUrl, sourceDirectory } = PackageSource.parse(res.repository); const dep = { homepage: res.homepage, releases: [], tags: res["dist-tags"], registryUrl }; if (sourceUrl) dep.sourceUrl = sourceUrl; if (sourceDirectory) dep.sourceDirectory = sourceDirectory; if (latestVersion?.deprecated) dep.deprecationMessage = `On registry \`${registryUrl}\`, the "latest" version of dependency \`${packageName}\` has the following deprecation notice:\n\n\`${latestVersion.deprecated}\`\n\nMarking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.`; dep.releases = Object.keys(res.versions).map((version) => { const release = { version, gitRef: res.versions?.[version].gitHead, dependencies: res.versions?.[version].dependencies, devDependencies: res.versions?.[version].devDependencies, attestation: isString(res.versions?.[version].dist?.attestations?.url) }; const releaseTimestamp = asTimestamp(res.time?.[version]); if (releaseTimestamp) release.releaseTimestamp = releaseTimestamp; if (res.versions?.[version].deprecated) release.isDeprecated = true; const nodeConstraint = res.versions?.[version].engines?.node; if (isNonEmptyString(nodeConstraint)) release.constraints = { node: [nodeConstraint] }; const source = PackageSource.parse(res.versions?.[version].repository); if (source.sourceUrl && source.sourceUrl !== dep.sourceUrl) release.sourceUrl = source.sourceUrl; if (source.sourceDirectory && source.sourceDirectory !== dep.sourceDirectory) release.sourceDirectory = source.sourceDirectory; if (dep.deprecationMessage) release.isDeprecated = true; return release; }); if (!resp.headers?.["cache-control"]?.toLocaleLowerCase()?.split(regEx(/\s*,\s*/))?.includes("public")) dep.isPrivate = true; logger.trace({ dep }, "dep"); return dep; } catch (err) { const actualError = err instanceof ExternalHostError ? err.err : err; if (actualError.message === "host-disabled" || [ 401, 402, 403, 404 ].includes(actualError.statusCode) || ["ENOTFOUND"].includes(actualError.code)) return null; if (err instanceof ExternalHostError) { if (actualError.name === "ParseError" && actualError.body) { actualError.body = "err.body deleted by Renovate"; err.err = actualError; } throw err; } logger.debug({ err }, "Unknown npm lookup error"); return null; } } //#endregion export { getDependency }; //# sourceMappingURL=get.js.map