diff --git a/lib/datasource/cargo/index.js b/lib/datasource/cargo/index.ts similarity index 83% rename from lib/datasource/cargo/index.js rename to lib/datasource/cargo/index.ts index ccda70e2e93640101db77ba3767740d9f266ae75..9896a4f22a0f2332fb59b52c3a28a9147b04d8cc 100644 --- a/lib/datasource/cargo/index.js +++ b/lib/datasource/cargo/index.ts @@ -1,25 +1,27 @@ -const { logger } = require('../../logger'); -const got = require('../../util/got'); +import { logger } from '../../logger'; +import got from '../../util/got'; +import { PkgReleaseConfig, ReleaseResult, Release } from '../common'; -module.exports = { - getPkgReleases, -}; - -async function getPkgReleases({ lookupName }) { +export async function getPkgReleases({ + lookupName, +}: PkgReleaseConfig): Promise<ReleaseResult> { if (!lookupName) { return null; } const cacheNamespace = 'datasource-cargo'; const cacheKey = lookupName; - const cachedResult = await renovateCache.get(cacheNamespace, cacheKey); + const cachedResult = await renovateCache.get<ReleaseResult>( + cacheNamespace, + cacheKey + ); // istanbul ignore if if (cachedResult) { return cachedResult; } const len = lookupName.length; - let path; + let path: string; // Ignored because there is no way to test this without hitting up GitHub API /* istanbul ignore next */ if (len === 1) { @@ -72,11 +74,11 @@ async function getPkgReleases({ lookupName }) { ); return null; } - const result = { + const result: ReleaseResult = { releases: [], }; - result.releases = res.map(version => { - const release = { + result.releases = res.map((version: { vers: string; yanked: boolean }) => { + const release: Release = { version: version.vers, }; if (version.yanked) { diff --git a/lib/datasource/common.ts b/lib/datasource/common.ts new file mode 100644 index 0000000000000000000000000000000000000000..b6373f0c5a7d827432480fe9964519d8b3e41370 --- /dev/null +++ b/lib/datasource/common.ts @@ -0,0 +1,51 @@ +export interface Config { + datasource?: string; + depName?: string; + lookupName?: string; + registryUrls?: string[]; +} +export interface PkgReleaseConfig extends Config { + compatibility?: Record<string, string>; + depType?: string; + lookupType?: string; + npmrc?: string; + versionScheme?: string; +} + +export type DigestConfig = Config; + +export interface Release { + changelogUrl?: string; + gitref?: string; + isDeprecated?: boolean; + + releaseDate?: string; + releaseTimestamp?: any; + version: string; +} + +export interface ReleaseResult { + changelogUrl?: string; + dependencyUrl?: string; + deprecationMessage?: string; + display?: string; + dockerRegistry?: string; + dockerRepository?: string; + group?: string; + homepage?: string; + name?: string; + pkgName?: string; + releases: Release[]; + sourceUrl?: string; + tags?: string[]; + versions?: any; +} + +// TODO: Proper typing +export type Preset = any; + +export interface Datasource { + getDigest?(config: DigestConfig, newValue?: string): Promise<string>; + getPreset?(packageName: string, presetName?: string): Promise<Preset>; + getPkgReleases(config: PkgReleaseConfig): Promise<ReleaseResult>; +} diff --git a/lib/datasource/dart/index.js b/lib/datasource/dart/index.ts similarity index 71% rename from lib/datasource/dart/index.js rename to lib/datasource/dart/index.ts index e8d9f4df4a7978dc1426dbeb1b2625865c244bda..432892ddf648af83eec74a7becfa5cbc667dc5db 100644 --- a/lib/datasource/dart/index.js +++ b/lib/datasource/dart/index.ts @@ -1,11 +1,24 @@ -const got = require('../../util/got'); -const { logger } = require('../../logger'); +import got from '../../util/got'; +import { logger } from '../../logger'; +import { ReleaseResult, PkgReleaseConfig } from '../common'; -async function getPkgReleases({ lookupName }) { - /** @type any */ - let result = null; +export async function getPkgReleases({ + lookupName, +}: PkgReleaseConfig): Promise<ReleaseResult> { + let result: ReleaseResult = null; const pkgUrl = `https://pub.dartlang.org/api/packages/${lookupName}`; - let raw = null; + interface DartResult { + versions?: { + version: string; + }[]; + latest?: { + pubspec?: { homepage?: string; repository?: string }; + }; + } + + let raw: { + body: DartResult; + } = null; try { raw = await got(pkgUrl, { json: true, @@ -53,7 +66,3 @@ async function getPkgReleases({ lookupName }) { return result; } - -module.exports = { - getPkgReleases, -}; diff --git a/lib/datasource/docker/index.js b/lib/datasource/docker/index.ts similarity index 87% rename from lib/datasource/docker/index.js rename to lib/datasource/docker/index.ts index c0a071ee7f2e9bb61d20edad1ebb4bb7e405d483..7fa0f6a3783be80549d0d5ea7e0294817579fa02 100644 --- a/lib/datasource/docker/index.js +++ b/lib/datasource/docker/index.ts @@ -1,24 +1,18 @@ import is from '@sindresorhus/is'; +import hasha from 'hasha'; +import URL from 'url'; +import parseLinkHeader from 'parse-link-header'; +import wwwAuthenticate from 'www-authenticate'; +import { logger } from '../../logger'; +import got from '../../util/got'; +import * as hostRules from '../../util/host-rules'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; -const hasha = require('hasha'); -const URL = require('url'); -const parseLinkHeader = require('parse-link-header'); -const wwwAuthenticate = require('www-authenticate'); -const { logger } = require('../../logger'); +// TODO: add got typings when available +// TODO: replace www-authenticate with https://www.npmjs.com/package/auth-header ? -const got = require('../../util/got'); -const hostRules = require('../../util/host-rules'); - -export { getDigest, getPkgReleases }; - -/** - * - * @param {string} lookupName - * @param {string[]=} registryUrls - */ -function getRegistryRepository(lookupName, registryUrls) { - /** @type string */ - let registry; +function getRegistryRepository(lookupName: string, registryUrls: string[]) { + let registry: string; const split = lookupName.split('/'); if (split.length > 1 && split[0].includes('.')) { [registry] = split; @@ -43,7 +37,7 @@ function getRegistryRepository(lookupName, registryUrls) { }; } -async function getAuthHeaders(registry, repository) { +async function getAuthHeaders(registry: string, repository: string) { try { const apiCheckUrl = `${registry}/v2/`; const apiCheckResponse = await got(apiCheckUrl, { throwHttpErrors: false }); @@ -54,8 +48,9 @@ async function getAuthHeaders(registry, repository) { apiCheckResponse.headers['www-authenticate'] ); - /** @type any */ - const opts = hostRules.find({ hostType: 'docker', url: apiCheckUrl }); + const opts: hostRules.HostRule & { + headers?: Record<string, string>; + } = hostRules.find({ hostType: 'docker', url: apiCheckUrl }); opts.json = true; if (opts.username && opts.password) { const auth = Buffer.from(`${opts.username}:${opts.password}`).toString( @@ -124,7 +119,7 @@ async function getAuthHeaders(registry, repository) { } } -function digestFromManifestStr(str) { +function digestFromManifestStr(str: hasha.HashaInput) { return 'sha256:' + hasha(str, { algorithm: 'sha256' }); } @@ -135,7 +130,11 @@ function extractDigestFromResponse(manifestResponse) { return manifestResponse.headers['docker-content-digest']; } -async function getManifestResponse(registry, repository, tag) { +async function getManifestResponse( + registry: string, + repository: string, + tag: string +) { logger.debug(`getManifestResponse(${registry}, ${repository}, ${tag})`); try { const headers = await getAuthHeaders(registry, repository); @@ -218,10 +217,11 @@ async function getManifestResponse(registry, repository, tag) { * This function will: * - Look up a sha256 digest for a tag on its registry * - Return the digest as a string - * @param {{registryUrls? : string[], lookupName: string}} args - * @param {string=} newValue */ -async function getDigest({ registryUrls, lookupName }, newValue) { +export async function getDigest( + { registryUrls, lookupName }: PkgReleaseConfig, + newValue?: string +): Promise<string> { const { registry, repository } = getRegistryRepository( lookupName, registryUrls @@ -265,12 +265,18 @@ async function getDigest({ registryUrls, lookupName }, newValue) { } } -async function getTags(registry, repository) { - let tags = []; +async function getTags( + registry: string, + repository: string +): Promise<string[]> { + let tags: string[] = []; try { const cacheNamespace = 'datasource-docker-tags'; const cacheKey = `${registry}:${repository}`; - const cachedResult = await renovateCache.get(cacheNamespace, cacheKey); + const cachedResult = await renovateCache.get<string[]>( + cacheNamespace, + cacheKey + ); // istanbul ignore if if (cachedResult) { return cachedResult; @@ -287,7 +293,16 @@ async function getTags(registry, repository) { } let page = 1; do { - const res = await got(url, { json: true, headers }); + interface DockerTagResult { + body: { + tags: string[]; + }; + headers: { + link: string; + }; + } + + const res: DockerTagResult = await got(url, { json: true, headers }); tags = tags.concat(res.body.tags); const linkHeader = parseLinkHeader(res.headers.link); url = @@ -359,11 +374,18 @@ async function getTags(registry, repository) { */ // istanbul ignore next -async function getLabels(registry, repository, tag) { +async function getLabels( + registry: string, + repository: string, + tag: string +): Promise<Record<string, string>> { logger.debug(`getLabels(${registry}, ${repository}, ${tag})`); const cacheNamespace = 'datasource-docker-labels'; const cacheKey = `${registry}:${repository}:${tag}`; - const cachedResult = await renovateCache.get(cacheNamespace, cacheKey); + const cachedResult = await renovateCache.get<Record<string, string>>( + cacheNamespace, + cacheKey + ); // istanbul ignore if if (cachedResult) { return cachedResult; @@ -397,7 +419,7 @@ async function getLabels(registry, repository, tag) { ); return {}; } - let labels = {}; + let labels: Record<string, string> = {}; const configDigest = manifest.config.digest; const headers = await getAuthHeaders(registry, repository); if (!headers) { @@ -490,9 +512,11 @@ async function getLabels(registry, repository, tag) { * - '8.1.0-alpine' is the tag * * This function will filter only tags that contain a semver version - * @param {{lookupName :string, registryUrls?: string[] }} args */ -async function getPkgReleases({ lookupName, registryUrls }) { +export async function getPkgReleases({ + lookupName, + registryUrls, +}: PkgReleaseConfig): Promise<ReleaseResult> { const { registry, repository } = getRegistryRepository( lookupName, registryUrls @@ -502,7 +526,7 @@ async function getPkgReleases({ lookupName, registryUrls }) { return null; } const releases = tags.map(version => ({ version })); - const ret = { + const ret: ReleaseResult = { dockerRegistry: registry, dockerRepository: repository, releases, diff --git a/lib/datasource/git-tags/index.js b/lib/datasource/git-tags/index.ts similarity index 70% rename from lib/datasource/git-tags/index.js rename to lib/datasource/git-tags/index.ts index 223e356c28b1580031206e9dfe8a0a5ed8b117af..85ac2d11ab13692448e92b54770806f25267c2c6 100644 --- a/lib/datasource/git-tags/index.js +++ b/lib/datasource/git-tags/index.ts @@ -1,17 +1,23 @@ -const simpleGit = require('simple-git/promise'); -const semver = require('../../versioning/semver'); +import simpleGit from 'simple-git/promise'; +import * as semver from '../../versioning/semver'; +import { logger } from '../../logger'; +import { ReleaseResult, PkgReleaseConfig } from '../common'; const cacheNamespace = 'git-tags'; const cacheMinutes = 10; -const { logger } = require('../../logger'); // git will prompt for known hosts or passwords, unless we activate BatchMode process.env.GIT_SSH_COMMAND = 'ssh -o BatchMode=yes'; -async function getPkgReleases({ lookupName }) { +export async function getPkgReleases({ + lookupName, +}: PkgReleaseConfig): Promise<ReleaseResult> { const git = simpleGit(); try { - const cachedResult = await renovateCache.get(cacheNamespace, lookupName); + const cachedResult = await renovateCache.get<ReleaseResult>( + cacheNamespace, + lookupName + ); /* istanbul ignore next line */ if (cachedResult) return cachedResult; @@ -27,7 +33,7 @@ async function getPkgReleases({ lookupName }) { .split('\n') .filter(tag => semver.isVersion(tag)); const sourceUrl = lookupName.replace(/\.git$/, '').replace(/\/$/, ''); - const result = { + const result: ReleaseResult = { sourceUrl, releases: tags.map(tag => ({ version: semver.isValid(tag), @@ -42,7 +48,3 @@ async function getPkgReleases({ lookupName }) { } return null; } - -module.exports = { - getPkgReleases, -}; diff --git a/lib/datasource/github/index.js b/lib/datasource/github/index.ts similarity index 77% rename from lib/datasource/github/index.js rename to lib/datasource/github/index.ts index 24cb23c13d57823638dae2a11c535e71f5ada650..cd66110c61677847d527de97f415730229fdafed 100644 --- a/lib/datasource/github/index.js +++ b/lib/datasource/github/index.ts @@ -1,13 +1,16 @@ import { api } from '../../platform/github/gh-got-wrapper'; - -const { logger } = require('../../logger'); -const got = require('../../util/got'); +import { + ReleaseResult, + PkgReleaseConfig, + Preset, + DigestConfig, +} from '../common'; +import { logger } from '../../logger'; +import got from '../../util/got'; const ghGot = api.get; -export { getPreset, getDigest, getPkgReleases }; - -async function fetchJSONFile(repo, fileName) { +async function fetchJSONFile(repo: string, fileName: string): Promise<Preset> { const url = `https://api.github.com/repos/${repo}/contents/${fileName}`; const opts = { headers: { @@ -18,7 +21,7 @@ async function fetchJSONFile(repo, fileName) { json: true, hostType: 'github', }; - let res; + let res: { body: { content: string } }; try { res = await got(url, opts); } catch (err) { @@ -40,7 +43,10 @@ async function fetchJSONFile(repo, fileName) { } } -async function getPreset(pkgName, presetName = 'default') { +export async function getPreset( + pkgName: string, + presetName = 'default' +): Promise<Preset> { if (presetName === 'default') { try { const defaultJson = await fetchJSONFile(pkgName, 'default.json'); @@ -60,20 +66,12 @@ async function getPreset(pkgName, presetName = 'default') { } const cacheNamespace = 'datasource-github'; -function getCacheKey(repo, type) { +function getCacheKey(repo: string, type: string) { return `${repo}:${type}`; } -/* - * github.getDigest - * - * The `newValue` supplied here should be a valid tag for the docker image. - * - * This function will simply return the latest commit hash for the configured repository. - */ - -async function getTagCommit(githubRepo, tag) { - const cachedResult = await renovateCache.get( +async function getTagCommit(githubRepo: string, tag: string): Promise<string> { + const cachedResult = await renovateCache.get<string>( cacheNamespace, getCacheKey(githubRepo, `tag-${tag}`) ); @@ -81,7 +79,7 @@ async function getTagCommit(githubRepo, tag) { if (cachedResult) { return cachedResult; } - let digest; + let digest: string; try { const url = `https://api.github.com/repos/${githubRepo}/git/refs/tags/${tag}`; const res = (await ghGot(url)).body.object; @@ -111,7 +109,17 @@ async function getTagCommit(githubRepo, tag) { return digest; } -async function getDigest({ lookupName: githubRepo }, newValue) { +/** + * github.getDigest + * + * The `newValue` supplied here should be a valid tag for the docker image. + * + * This function will simply return the latest commit hash for the configured repository. + */ +export async function getDigest( + { lookupName: githubRepo }: Partial<DigestConfig>, + newValue?: string +): Promise<string> { if (newValue && newValue.length) { return getTagCommit(githubRepo, newValue); } @@ -123,7 +131,7 @@ async function getDigest({ lookupName: githubRepo }, newValue) { if (cachedResult) { return cachedResult; } - let digest; + let digest: string; try { const url = `https://api.github.com/repos/${githubRepo}/commits?per_page=1`; digest = (await ghGot(url)).body[0].sha; @@ -146,7 +154,7 @@ async function getDigest({ lookupName: githubRepo }, newValue) { return digest; } -/* +/** * github.getPkgReleases * * This function can be used to fetch releases with a customisable version scheme (e.g. semver) and with either tags or releases. @@ -156,10 +164,12 @@ async function getDigest({ lookupName: githubRepo }, newValue) { * - Sanitize the versions if desired (e.g. strip out leading 'v') * - Return a dependency object containing sourceUrl string and releases array */ - -async function getPkgReleases({ lookupName: repo, lookupType }) { - let versions; - const cachedResult = await renovateCache.get( +export async function getPkgReleases({ + lookupName: repo, + lookupType, +}: PkgReleaseConfig): Promise<ReleaseResult> { + let versions: string[]; + const cachedResult = await renovateCache.get<ReleaseResult>( cacheNamespace, getCacheKey(repo, lookupType || 'tags') ); @@ -170,13 +180,21 @@ async function getPkgReleases({ lookupName: repo, lookupType }) { try { if (lookupType === 'releases') { const url = `https://api.github.com/repos/${repo}/releases?per_page=100`; - versions = (await ghGot(url, { paginate: true })).body.map( - o => o.tag_name - ); + type GitHubRelease = { + tag_name: string; + }[]; + + versions = (await ghGot<GitHubRelease>(url, { + paginate: true, + })).body.map(o => o.tag_name); } else { // tag const url = `https://api.github.com/repos/${repo}/tags?per_page=100`; - versions = (await ghGot(url, { + type GitHubTag = { + name: string; + }[]; + + versions = (await ghGot<GitHubTag>(url, { paginate: true, })).body.map(o => o.name); } @@ -186,8 +204,9 @@ async function getPkgReleases({ lookupName: repo, lookupType }) { if (!versions) { return null; } - const dependency = { + const dependency: ReleaseResult = { sourceUrl: 'https://github.com/' + repo, + releases: null, }; dependency.releases = versions.map(version => ({ version, diff --git a/lib/datasource/gitlab/index.js b/lib/datasource/gitlab/index.ts similarity index 69% rename from lib/datasource/gitlab/index.js rename to lib/datasource/gitlab/index.ts index a4a016934a04f4e50b4469c4dc472320845a9d6f..d309275c4f89c0e32ad27a4057f92326427cb9ac 100644 --- a/lib/datasource/gitlab/index.js +++ b/lib/datasource/gitlab/index.ts @@ -1,21 +1,25 @@ import is from '@sindresorhus/is'; +import { api } from '../../platform/gitlab/gl-got-wrapper'; +import { logger } from '../../logger'; +import { PkgReleaseConfig, ReleaseResult, Preset } from '../common'; -const glGot = require('../../platform/gitlab/gl-got-wrapper').api.get; -const { logger } = require('../../logger'); - -export { getPreset, getPkgReleases }; +const glGot = api.get; const GitLabApiUrl = 'https://gitlab.com/api/v4/projects'; -async function getPreset(pkgName, presetName = 'default') { +export async function getPreset( + pkgName: string, + presetName = 'default' +): Promise<Preset> { if (presetName !== 'default') { + // TODO: proper error contructor throw new Error( { pkgName, presetName }, // @ts-ignore 'Sub-preset names are not supported with Gitlab datasource' ); } - let res; + let res: string; try { const urlEncodedPkgName = encodeURIComponent(pkgName); const defautlBranchName = await getDefaultBranchName(urlEncodedPkgName); @@ -38,22 +42,22 @@ async function getPreset(pkgName, presetName = 'default') { } const cacheNamespace = 'datasource-gitlab'; -function getCacheKey(depHost, repo, lookupType) { +function getCacheKey(depHost: string, repo: string, lookupType: string) { const type = lookupType || 'tags'; return `${depHost}:${repo}:${type}`; } -/** - * - * @param {{registryUrls? : string[], lookupName:string, lookupType:string}} param0 - */ -async function getPkgReleases({ registryUrls, lookupName: repo, lookupType }) { +export async function getPkgReleases({ + registryUrls, + lookupName: repo, + lookupType, +}: PkgReleaseConfig): Promise<ReleaseResult> { // Use registryUrls if present, otherwise default to publid gitlab.com const depHost = is.nonEmptyArray(registryUrls) ? registryUrls[0].replace(/\/$/, '') : 'https://gitlab.com'; - let versions; - const cachedResult = await renovateCache.get( + let versions: string[]; + const cachedResult = await renovateCache.get<ReleaseResult>( cacheNamespace, getCacheKey(depHost, repo, lookupType) ); @@ -67,13 +71,21 @@ async function getPkgReleases({ registryUrls, lookupName: repo, lookupType }) { try { if (lookupType === 'releases') { const url = `${depHost}/api/v4/projects/${urlEncodedRepo}/releases?per_page=100`; - versions = (await glGot(url, { paginate: true })).body.map( - o => o.tag_name - ); + type GlRelease = { + tag_name: string; + }[]; + + versions = (await glGot<GlRelease>(url, { + paginate: true, + })).body.map(o => o.tag_name); } else { // tag const url = `${depHost}/api/v4/projects/${urlEncodedRepo}/repository/tags?per_page=100`; - versions = (await glGot(url, { + type GlTag = { + name: string; + }[]; + + versions = (await glGot<GlTag>(url, { paginate: true, })).body.map(o => o.name); } @@ -87,8 +99,9 @@ async function getPkgReleases({ registryUrls, lookupName: repo, lookupType }) { return null; } - const dependency = { + const dependency: ReleaseResult = { sourceUrl: `${depHost}/${repo}`, + releases: null, }; dependency.releases = versions.map(version => ({ version, @@ -105,9 +118,14 @@ async function getPkgReleases({ registryUrls, lookupName: repo, lookupType }) { return dependency; } -async function getDefaultBranchName(urlEncodedPkgName) { +async function getDefaultBranchName(urlEncodedPkgName: string) { const branchesUrl = `${GitLabApiUrl}/${urlEncodedPkgName}/repository/branches`; - const res = await glGot(branchesUrl); + type GlBranch = { + default: boolean; + name: string; + }[]; + + const res = await glGot<GlBranch>(branchesUrl); const branches = res.body; let defautlBranchName = 'master'; for (const branch of branches) { diff --git a/lib/datasource/go/index.js b/lib/datasource/go/index.ts similarity index 83% rename from lib/datasource/go/index.js rename to lib/datasource/go/index.ts index e44d1aab7a5429d997843b88672cbee9bb35a5db..f1963f09f505ab471a25ac42a3b52b118e688f89 100644 --- a/lib/datasource/go/index.js +++ b/lib/datasource/go/index.ts @@ -1,13 +1,14 @@ -const { logger } = require('../../logger'); -const got = require('../../util/got'); -const github = require('../github'); +import { logger } from '../../logger'; +import got from '../../util/got'; +import * as github from '../github'; +import { DigestConfig, PkgReleaseConfig, ReleaseResult } from '../common'; -module.exports = { - getPkgReleases, - getDigest, -}; +interface DataSource { + datasource: string; + lookupName: string; +} -async function getDatasource(name) { +async function getDatasource(name: string): Promise<DataSource> { if (name.startsWith('gopkg.in/')) { const [pkg] = name.replace('gopkg.in/', '').split('.'); if (pkg.includes('/')) { @@ -59,7 +60,7 @@ async function getDatasource(name) { } } -/* +/** * go.getPkgReleases * * This datasource resolves a go module URL into its source repository @@ -69,12 +70,12 @@ async function getDatasource(name) { * - Determine the source URL for the module * - Call the respective getPkgReleases in github to retrieve the tags */ - -async function getPkgReleases({ lookupName }) { +export async function getPkgReleases({ + lookupName, +}: Partial<PkgReleaseConfig>): Promise<ReleaseResult> { logger.trace(`go.getPkgReleases(${lookupName})`); const source = await getDatasource(lookupName); if (source && source.datasource === 'github') { - // @ts-ignore const res = await github.getPkgReleases(source); if (res && res.releases) { res.releases = res.releases.filter( @@ -86,7 +87,7 @@ async function getPkgReleases({ lookupName }) { return null; } -/* +/** * go.getDigest * * This datasource resolves a go module URL into its source repository @@ -96,8 +97,10 @@ async function getPkgReleases({ lookupName }) { * - Determine the source URL for the module * - Call the respective getDigest in github to retrieve the commit hash */ - -async function getDigest({ lookupName }, value) { +export async function getDigest( + { lookupName }: Partial<DigestConfig>, + value?: string +): Promise<string> { const source = await getDatasource(lookupName); if (source && source.datasource === 'github') { // ignore v0.0.0- pseudo versions that are used Go Modules - look up default branch instead diff --git a/lib/datasource/gradle-version/index.js b/lib/datasource/gradle-version/index.ts similarity index 63% rename from lib/datasource/gradle-version/index.js rename to lib/datasource/gradle-version/index.ts index ae6fc021c1c3e618224d45d5ada6807be7cef87b..6adaa7eb9df3f8c54c1c457577be84c9ca949676 100644 --- a/lib/datasource/gradle-version/index.js +++ b/lib/datasource/gradle-version/index.ts @@ -1,16 +1,26 @@ -const { coerce } = require('semver'); -const { logger } = require('../../logger'); -const got = require('../../util/got'); - -module.exports = { - getPkgReleases, -}; +import { coerce } from 'semver'; +import { logger } from '../../logger'; +import got from '../../util/got'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; const GradleVersionsServiceUrl = 'https://services.gradle.org/versions/all'; -async function getPkgReleases() { +interface GradleRelease { + body: { + snapshot?: boolean; + nightly?: boolean; + rcFor?: string; + version: string; + downloadUrl?: string; + checksumUrl?: string; + }[]; +} + +export async function getPkgReleases( + _config: PkgReleaseConfig +): Promise<ReleaseResult> { try { - const response = await got(GradleVersionsServiceUrl, { + const response: GradleRelease = await got(GradleVersionsServiceUrl, { json: true, }); const releases = response.body @@ -25,7 +35,7 @@ async function getPkgReleases() { downloadUrl: release.downloadUrl, checksumUrl: release.checksumUrl, })); - const gradle = { + const gradle: ReleaseResult = { releases, homepage: 'https://gradle.org', sourceUrl: 'https://github.com/gradle/gradle', diff --git a/lib/datasource/hex/index.js b/lib/datasource/hex/index.ts similarity index 72% rename from lib/datasource/hex/index.js rename to lib/datasource/hex/index.ts index 3db55774d3017a48a7cd06ed5d06d5391fdf582c..3364512cd9c2c46057cebb30facc51c3ed040e5a 100644 --- a/lib/datasource/hex/index.js +++ b/lib/datasource/hex/index.ts @@ -1,9 +1,6 @@ -const { logger } = require('../../logger'); -const got = require('../../util/got'); - -module.exports = { - getPkgReleases, -}; +import { logger } from '../../logger'; +import got from '../../util/got'; +import { ReleaseResult, PkgReleaseConfig } from '../common'; function getHostOpts() { return { @@ -12,11 +9,20 @@ function getHostOpts() { }; } -async function getPkgReleases({ lookupName }) { +interface HexRelease { + html_url: string; + meta?: { links?: Record<string, string> }; + name?: string; + releases?: { version: string }[]; +} + +export async function getPkgReleases({ + lookupName, +}: Partial<PkgReleaseConfig>): Promise<ReleaseResult> { const hexUrl = `https://hex.pm/api/packages/${lookupName}`; try { const opts = getHostOpts(); - const res = (await got(hexUrl, { + const res: HexRelease = (await got(hexUrl, { json: true, ...opts, })).body; @@ -24,7 +30,7 @@ async function getPkgReleases({ lookupName }) { logger.warn({ lookupName }, `Received invalid hex package data`); return null; } - const result = { + const result: ReleaseResult = { releases: [], }; if (res.releases) { diff --git a/lib/datasource/index.js b/lib/datasource/index.ts similarity index 56% rename from lib/datasource/index.js rename to lib/datasource/index.ts index b244dc11f4d24cdbaba27a7f9321351b7c59c038..c677ca1a37ff9aa29d2214e3ac9d740c7e70646a 100644 --- a/lib/datasource/index.js +++ b/lib/datasource/index.ts @@ -1,28 +1,37 @@ -const { logger } = require('../logger'); -const { addMetaData } = require('./metadata'); -const versioning = require('../versioning'); +import { logger } from '../logger'; +import { addMetaData } from './metadata'; +import * as versioning from '../versioning'; -const cargo = require('./cargo'); -const dart = require('./dart'); -const docker = require('./docker'); -const hex = require('./hex'); -const github = require('./github'); -const gitlab = require('./gitlab'); -const gitTags = require('./git-tags'); -const go = require('./go'); -const gradleVersion = require('./gradle-version'); -const maven = require('./maven'); -const npm = require('./npm'); -const nuget = require('./nuget'); -const orb = require('./orb'); -const packagist = require('./packagist'); -const pypi = require('./pypi'); -const rubygems = require('./rubygems'); -const rubyVersion = require('./ruby-version'); -const sbt = require('./sbt'); -const terraform = require('./terraform'); +import * as cargo from './cargo'; +import * as dart from './dart'; +import * as docker from './docker'; +import * as hex from './hex'; +import * as github from './github'; +import * as gitlab from './gitlab'; +import * as gitTags from './git-tags'; +import * as go from './go'; +import * as gradleVersion from './gradle-version'; +import * as maven from './maven'; +import * as npm from './npm'; +import * as nuget from './nuget'; +import * as orb from './orb'; +import * as packagist from './packagist'; +import * as pypi from './pypi'; +import * as rubygems from './rubygems'; +import * as rubyVersion from './ruby-version'; +import * as sbt from './sbt'; +import * as terraform from './terraform'; +import { + Datasource, + PkgReleaseConfig, + Release, + ReleaseResult, + DigestConfig, +} from './common'; -const datasources = { +export * from './common'; + +const datasources: Record<string, Datasource> = { cargo, dart, docker, @@ -46,7 +55,7 @@ const datasources = { const cacheNamespace = 'datasource-releases'; -async function getPkgReleases(config) { +export async function getPkgReleases(config: PkgReleaseConfig) { const res = await getRawReleases({ ...config, lookupName: config.lookupName || config.depName, @@ -59,7 +68,7 @@ async function getPkgReleases(config) { // Filter by version scheme const version = versioning.get(versionScheme); // Return a sorted list of valid Versions - function sortReleases(release1, release2) { + function sortReleases(release1: Release, release2: Release) { return version.sortVersions(release1.version, release2.version); } if (res.releases) { @@ -70,7 +79,7 @@ async function getPkgReleases(config) { return res; } -function getRawReleases(config) { +function getRawReleases(config: PkgReleaseConfig): Promise<ReleaseResult> { const cacheKey = cacheNamespace + config.datasource + @@ -84,7 +93,7 @@ function getRawReleases(config) { return global.repoCache[cacheKey]; } -async function fetchReleases(config) { +async function fetchReleases(config: PkgReleaseConfig): Promise<ReleaseResult> { const { datasource } = config; if (!datasource) { logger.warn('No datasource found'); @@ -98,11 +107,11 @@ async function fetchReleases(config) { return dep; } -function supportsDigests(config) { +export function supportsDigests(config: DigestConfig) { return !!datasources[config.datasource].getDigest; } -function getDigest(config, value) { +export function getDigest(config: DigestConfig, value?: string) { const lookupName = config.lookupName || config.depName; const { registryUrls } = config; return datasources[config.datasource].getDigest( @@ -110,9 +119,3 @@ function getDigest(config, value) { value ); } - -module.exports = { - getPkgReleases, - supportsDigests, - getDigest, -}; diff --git a/lib/datasource/maven/index.js b/lib/datasource/maven/index.ts similarity index 78% rename from lib/datasource/maven/index.js rename to lib/datasource/maven/index.ts index 732f9fbd4694a22bc1c678db72685fceb0532ec6..455546f922118cc0cf1317d8a8d6aff6f9fab2c0 100644 --- a/lib/datasource/maven/index.js +++ b/lib/datasource/maven/index.ts @@ -1,23 +1,18 @@ import is from '@sindresorhus/is'; - -const url = require('url'); -const fs = require('fs-extra'); -const { XmlDocument } = require('xmldoc'); -const { logger } = require('../../logger'); - -const { compare } = require('../../versioning/maven/compare'); -const { containsPlaceholder } = require('../../manager/maven/extract'); -const { downloadHttpProtocol } = require('./util'); - -export { getPkgReleases }; - -/** - * - * @param {{lookupName:string, registryUrls?: string[]}} args - */ -// eslint-disable-next-line no-unused-vars -async function getPkgReleases({ lookupName, registryUrls }) { - const versions = []; +import url from 'url'; +import fs from 'fs-extra'; +import { XmlDocument } from 'xmldoc'; +import { logger } from '../../logger'; +import { compare } from '../../versioning/maven/compare'; +import { containsPlaceholder } from '../../manager/maven/extract'; +import { downloadHttpProtocol } from './util'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; + +export async function getPkgReleases({ + lookupName, + registryUrls, +}: PkgReleaseConfig): Promise<ReleaseResult> { + const versions: string[] = []; const dependency = getDependencyParts(lookupName); if (!is.nonEmptyArray(registryUrls)) { logger.warn(`No repositories defined for ${dependency.display}`); @@ -84,13 +79,24 @@ function getDependencyParts(lookupName) { }; } -async function downloadMavenXml(dependency, repoUrl, dependencyFilePath) { +interface MavenDependency { + display: string; + group?: string; + name?: string; + dependencyUrl: string; +} + +async function downloadMavenXml( + dependency: MavenDependency, + repoUrl: string, + dependencyFilePath: string +) { const pkgUrl = new url.URL( `${dependency.dependencyUrl}/${dependencyFilePath}`, repoUrl ); - let rawContent; + let rawContent: string; switch (pkgUrl.protocol) { case 'file:': rawContent = await downloadFileProtocol(pkgUrl); @@ -122,14 +128,14 @@ async function downloadMavenXml(dependency, repoUrl, dependencyFilePath) { } } -function extractVersions(metadata) { +function extractVersions(metadata: XmlDocument) { const versions = metadata.descendantWithPath('versioning.versions'); const elements = versions && versions.childrenNamed('version'); if (!elements) return []; return elements.map(el => el.val); } -async function downloadFileProtocol(pkgUrl) { +async function downloadFileProtocol(pkgUrl: url.URL) { const pkgPath = pkgUrl.toString().replace('file://', ''); if (!(await fs.exists(pkgPath))) { return null; @@ -137,15 +143,19 @@ async function downloadFileProtocol(pkgUrl) { return fs.readFile(pkgPath, 'utf8'); } -function getLatestVersion(versions) { +function getLatestVersion(versions: string[]) { if (versions.length === 0) return null; return versions.reduce((latestVersion, version) => compare(version, latestVersion) === 1 ? version : latestVersion ); } -async function getDependencyInfo(dependency, repoUrl, version) { - const result = {}; +async function getDependencyInfo( + dependency: MavenDependency, + repoUrl: string, + version: string +) { + const result: Partial<ReleaseResult> = {}; const path = `${version}/${dependency.name}-${version}.pom`; const pomContent = await downloadMavenXml(dependency, repoUrl, path); diff --git a/lib/datasource/maven/util.js b/lib/datasource/maven/util.ts similarity index 70% rename from lib/datasource/maven/util.js rename to lib/datasource/maven/util.ts index 4c89618ddd6e112129b4f5e35799f7f80417509f..9b1b1b8e76966a255bfcdfe93c28bffb3b33bc8e 100644 --- a/lib/datasource/maven/util.js +++ b/lib/datasource/maven/util.ts @@ -1,20 +1,14 @@ -const got = require('../../util/got'); -const { logger } = require('../../logger'); +import url from 'url'; +import got from '../../util/got'; +import { logger } from '../../logger'; -module.exports = { - downloadHttpProtocol, -}; - -/** - * @param {import('url').URL | string} pkgUrl - */ -function isMavenCentral(pkgUrl) { +function isMavenCentral(pkgUrl: url.URL | string) { return ( (typeof pkgUrl === 'string' ? pkgUrl : pkgUrl.host) === 'central.maven.org' ); } -function isTemporalError(err) { +function isTemporalError(err: { code: string; statusCode: number }) { return ( err.code === 'ECONNRESET' || err.statusCode === 429 || @@ -22,24 +16,27 @@ function isTemporalError(err) { ); } -function isHostError(err) { +function isHostError(err: { code: string }) { return err.code === 'ETIMEDOUT'; } -function isNotFoundError(err) { +function isNotFoundError(err: { code: string; statusCode: number }) { return err.code === 'ENOTFOUND' || err.statusCode === 404; } -function isPermissionsIssue(err) { +function isPermissionsIssue(err: { statusCode: number }) { return err.statusCode === 401 || err.statusCode === 403; } -function isConnectionError(err) { +function isConnectionError(err: { code: string }) { return err.code === 'ECONNREFUSED'; } -async function downloadHttpProtocol(pkgUrl, hostType = 'maven') { - let raw; +export async function downloadHttpProtocol( + pkgUrl: url.URL | string, + hostType = 'maven' +) { + let raw: { body: string }; try { raw = await got(pkgUrl, { hostType }); } catch (err) { diff --git a/lib/datasource/metadata.js b/lib/datasource/metadata.ts similarity index 95% rename from lib/datasource/metadata.js rename to lib/datasource/metadata.ts index 885d4b0f1eb82f36b9d28aada502c1f91d4759d4..4f451957d47356291e45de1f39c49494940e767b 100644 --- a/lib/datasource/metadata.js +++ b/lib/datasource/metadata.ts @@ -1,8 +1,6 @@ import is from '@sindresorhus/is'; - -const parse = require('github-url-from-git'); - -export { addMetaData }; +import parse from 'github-url-from-git'; +import { ReleaseResult } from './common'; // Use this object to define changelog URLs for packages // Only necessary when the changelog data cannot be found in the package's source repository @@ -65,7 +63,11 @@ const manualSourceUrls = { }; /* eslint-disable no-param-reassign */ -function addMetaData(dep, datasource, lookupName) { +export function addMetaData( + dep?: ReleaseResult, + datasource?: string, + lookupName?: string +) { if (!dep) { return; } diff --git a/lib/datasource/npm/get.js b/lib/datasource/npm/get.ts similarity index 83% rename from lib/datasource/npm/get.js rename to lib/datasource/npm/get.ts index a3c5f77733cc196c997100c075bd7043dd538911..7291a848218a05829b91acee21f92ee1deb06a0a 100644 --- a/lib/datasource/npm/get.js +++ b/lib/datasource/npm/get.ts @@ -1,34 +1,46 @@ -const moment = require('moment'); -const url = require('url'); -const getRegistryUrl = require('registry-auth-token/registry-url'); -const registryAuthToken = require('registry-auth-token'); -const parse = require('github-url-from-git'); -const { isBase64 } = require('validator'); -const { logger } = require('../../logger'); - -const got = require('../../util/got'); -const hostRules = require('../../util/host-rules'); -const { maskToken } = require('../../util/mask'); -const { getNpmrc } = require('./npmrc'); - -module.exports = { - getDependency, - resetCache, - resetMemCache, -}; +import moment from 'moment'; +import url from 'url'; +import getRegistryUrl from 'registry-auth-token/registry-url'; +import registryAuthToken from 'registry-auth-token'; +import parse from 'github-url-from-git'; +import { isBase64 } from 'validator'; +import { OutgoingHttpHeaders } from 'http'; +import { logger } from '../../logger'; +import got from '../../util/got'; +import * as hostRules from '../../util/host-rules'; +import { maskToken } from '../../util/mask'; +import { getNpmrc } from './npmrc'; +import { Release, ReleaseResult } from '../common'; let memcache = {}; -function resetMemCache() { +export function resetMemCache() { logger.debug('resetMemCache()'); memcache = {}; } -function resetCache() { +export function resetCache() { resetMemCache(); } -async function getDependency(name) { +export interface NpmRelease extends Release { + canBeUnpublished?: boolean; + gitRef?: string; +} +export interface NpmDependency extends ReleaseResult { + releases: NpmRelease[]; + deprecationSource?: string; + name: string; + homepage: string; + latestVersion: string; + sourceUrl: string; + versions: Record<string, any>; + 'dist-tags': string[]; + 'renovate-config': any; + sourceDirectory?: string; +} + +export async function getDependency(name: string): Promise<NpmDependency> { logger.trace(`npm.getDependency(${name})`); // This is our datastore cache and is cleared at the end of each repo, i.e. we never requery/revalidate during a "run" @@ -38,7 +50,7 @@ async function getDependency(name) { } const scope = name.split('/')[0]; - let regUrl; + let regUrl: string; const npmrc = getNpmrc(); try { regUrl = getRegistryUrl(scope, npmrc); @@ -51,12 +63,15 @@ async function getDependency(name) { ); // Now check the persistent cache const cacheNamespace = 'datasource-npm'; - const cachedResult = await renovateCache.get(cacheNamespace, pkgUrl); + const cachedResult = await renovateCache.get<NpmDependency>( + cacheNamespace, + pkgUrl + ); if (cachedResult) { return cachedResult; } const authInfo = registryAuthToken(regUrl, { npmrc }); - const headers = {}; + const headers: OutgoingHttpHeaders = {}; if (authInfo && authInfo.type && authInfo.token) { // istanbul ignore if @@ -125,7 +140,7 @@ async function getDependency(name) { res.homepage = res.homepage || latestVersion.homepage; // Determine repository URL - let sourceUrl; + let sourceUrl: string; if (res.repository && res.repository.url) { const extraBaseUrls = []; @@ -155,12 +170,13 @@ async function getDependency(name) { delete res.homepage; } // Simplify response before caching and returning - const dep = { + const dep: NpmDependency = { name: res.name, homepage: res.homepage, latestVersion: res['dist-tags'].latest, sourceUrl, versions: {}, + releases: null, 'dist-tags': res['dist-tags'], 'renovate-config': latestVersion['renovate-config'], }; @@ -172,7 +188,7 @@ async function getDependency(name) { dep.deprecationSource = 'npm'; } dep.releases = Object.keys(res.versions).map(version => { - const release = { + const release: NpmRelease = { version, gitRef: res.versions[version].gitHead, }; diff --git a/lib/datasource/npm/index.js b/lib/datasource/npm/index.js deleted file mode 100644 index 5485934deb3e4c1477a16768aaa681ca34debd8b..0000000000000000000000000000000000000000 --- a/lib/datasource/npm/index.js +++ /dev/null @@ -1,12 +0,0 @@ -const { resetMemCache, resetCache } = require('./get'); -const { getPreset } = require('./presets'); -const { getPkgReleases } = require('./releases'); -const { setNpmrc } = require('./npmrc'); - -module.exports = { - setNpmrc, - getPreset, - getPkgReleases, - resetMemCache, - resetCache, -}; diff --git a/lib/datasource/npm/index.ts b/lib/datasource/npm/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..c4fc281955210e20437ed86cc8667f73d788798f --- /dev/null +++ b/lib/datasource/npm/index.ts @@ -0,0 +1,4 @@ +export { resetMemCache, resetCache } from './get'; +export { getPreset } from './presets'; +export { getPkgReleases } from './releases'; +export { setNpmrc } from './npmrc'; diff --git a/lib/datasource/npm/npmrc.js b/lib/datasource/npm/npmrc.ts similarity index 84% rename from lib/datasource/npm/npmrc.js rename to lib/datasource/npm/npmrc.ts index d9093a8a0cf98ba87745b4f4dcc3a08ba79d0e61..7f6fa8e26fa6aeee19909439d8b561188b94e860 100644 --- a/lib/datasource/npm/npmrc.js +++ b/lib/datasource/npm/npmrc.ts @@ -1,19 +1,16 @@ import is from '@sindresorhus/is'; +import ini from 'ini'; +import { isBase64 } from 'validator'; +import { logger } from '../../logger'; -const ini = require('ini'); -const { isBase64 } = require('validator'); -const { logger } = require('../../logger'); +let npmrc: Record<string, any> = null; +let npmrcRaw: string; -let npmrc = null; -let npmrcRaw; - -export { getNpmrc, setNpmrc }; - -function getNpmrc() { +export function getNpmrc() { return npmrc; } -function setNpmrc(input) { +export function setNpmrc(input?: string) { if (input) { if (input === npmrcRaw) { return; @@ -60,7 +57,7 @@ function setNpmrc(input) { } } -function envReplace(value, env = process.env) { +function envReplace(value: any, env = process.env) { // istanbul ignore if if (!is.string(value)) { return value; diff --git a/lib/datasource/npm/presets.js b/lib/datasource/npm/presets.ts similarity index 76% rename from lib/datasource/npm/presets.js rename to lib/datasource/npm/presets.ts index b7137f3e0331cefdf5f3f62d575dc8203de65a04..dbe911b329fd2d94d5d77e165aa5733df6faed5f 100644 --- a/lib/datasource/npm/presets.js +++ b/lib/datasource/npm/presets.ts @@ -1,10 +1,11 @@ import { logger } from '../../logger'; +import { getDependency } from './get'; +import { Preset } from '../common'; -const { getDependency } = require('./get'); - -export { getPreset }; - -async function getPreset(pkgName, presetName = 'default') { +export async function getPreset( + pkgName: string, + presetName = 'default' +): Promise<Preset> { const dep = await getDependency(pkgName); if (!dep) { throw new Error('dep not found'); diff --git a/lib/datasource/npm/releases.js b/lib/datasource/npm/releases.js deleted file mode 100644 index f2c96a675627edc201340df756beec0fd1be3d75..0000000000000000000000000000000000000000 --- a/lib/datasource/npm/releases.js +++ /dev/null @@ -1,23 +0,0 @@ -const { getDependency } = require('./get'); -const { setNpmrc } = require('./npmrc'); - -module.exports = { - getPkgReleases, -}; - -/** - * - * @param {{lookupName: string, npmrc?: string}} args - */ -async function getPkgReleases({ lookupName, npmrc }) { - if (npmrc) { - setNpmrc(npmrc); - } - const res = await getDependency(lookupName); - if (res) { - res.tags = res['dist-tags']; - delete res['dist-tags']; - delete res['renovate-config']; - } - return res; -} diff --git a/lib/datasource/npm/releases.ts b/lib/datasource/npm/releases.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2d887d46c61d2179250781d545234add8ac843e --- /dev/null +++ b/lib/datasource/npm/releases.ts @@ -0,0 +1,19 @@ +import { getDependency } from './get'; +import { setNpmrc } from './npmrc'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; + +export async function getPkgReleases({ + lookupName, + npmrc, +}: PkgReleaseConfig): Promise<ReleaseResult> { + if (npmrc) { + setNpmrc(npmrc); + } + const res: ReleaseResult = await getDependency(lookupName); + if (res) { + res.tags = res['dist-tags']; + delete res['dist-tags']; + delete res['renovate-config']; + } + return res; +} diff --git a/lib/datasource/nuget/index.js b/lib/datasource/nuget/index.ts similarity index 71% rename from lib/datasource/nuget/index.js rename to lib/datasource/nuget/index.ts index b4399c564ced0045c5ba9fe61e45927764e69431..56a1c108ec82baf858e867a621d70b8f0b730b2f 100644 --- a/lib/datasource/nuget/index.js +++ b/lib/datasource/nuget/index.ts @@ -1,15 +1,15 @@ -const urlApi = require('url'); -const { logger } = require('../../logger'); -const v2 = require('./v2'); -const v3 = require('./v3'); +import urlApi from 'url'; +import { logger } from '../../logger'; +import * as v2 from './v2'; +import * as v3 from './v3'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; -module.exports = { - getPkgReleases, -}; - -async function getPkgReleases({ lookupName, registryUrls }) { +export async function getPkgReleases({ + lookupName, + registryUrls, +}: PkgReleaseConfig): Promise<ReleaseResult> { logger.trace(`nuget.getPkgReleases(${lookupName})`); - let dep = null; + let dep: ReleaseResult = null; for (const feed of registryUrls || [v3.getDefaultFeed()]) { const feedVersion = detectFeedVersion(feed); if (feedVersion === 2) { @@ -33,7 +33,7 @@ async function getPkgReleases({ lookupName, registryUrls }) { return dep; } -function detectFeedVersion(url) { +function detectFeedVersion(url: string) { try { const parsecUrl = urlApi.parse(url); // Official client does it in the same way diff --git a/lib/datasource/nuget/v2.js b/lib/datasource/nuget/v2.ts similarity index 80% rename from lib/datasource/nuget/v2.js rename to lib/datasource/nuget/v2.ts index d18d0f366a3c17d5a5db90fcb0f5a4cdec6180fd..0297b8e4c3e305213c15529bb2cb559f91b2d727 100644 --- a/lib/datasource/nuget/v2.js +++ b/lib/datasource/nuget/v2.ts @@ -1,15 +1,16 @@ -const parse = require('github-url-from-git'); -const { XmlDocument } = require('xmldoc'); -const { logger } = require('../../logger'); -const got = require('../../util/got'); +import parse from 'github-url-from-git'; +import { XmlDocument, XmlElement } from 'xmldoc'; +import { logger } from '../../logger'; +import got from '../../util/got'; +import { ReleaseResult } from '../common'; -module.exports = { - getPkgReleases, -}; - -async function getPkgReleases(feedUrl, pkgName) { - const dep = { +export async function getPkgReleases( + feedUrl: string, + pkgName: string +): Promise<ReleaseResult> { + const dep: ReleaseResult = { pkgName, + releases: null, }; try { dep.releases = []; @@ -64,6 +65,6 @@ async function getPkgReleases(feedUrl, pkgName) { } } -function getPkgProp(pkgInfo, propName) { +function getPkgProp(pkgInfo: XmlElement, propName: string) { return pkgInfo.childNamed('m:properties').childNamed(`d:${propName}`).val; } diff --git a/lib/datasource/nuget/v3.js b/lib/datasource/nuget/v3.ts similarity index 85% rename from lib/datasource/nuget/v3.js rename to lib/datasource/nuget/v3.ts index 18965f52fa768662930fca4dfe260182bf7b022f..06c3b5b88e5c240e7790a77d2b0de69cf2af53ed 100644 --- a/lib/datasource/nuget/v3.js +++ b/lib/datasource/nuget/v3.ts @@ -1,28 +1,26 @@ -const parse = require('github-url-from-git'); -const semver = require('semver'); -const { XmlDocument } = require('xmldoc'); -const { logger } = require('../../logger'); -const got = require('../../util/got'); - -module.exports = { - getQueryUrl, - getPkgReleases, - getDefaultFeed, -}; +import parse from 'github-url-from-git'; +import * as semver from 'semver'; +import { XmlDocument } from 'xmldoc'; +import { logger } from '../../logger'; +import got from '../../util/got'; +import { ReleaseResult } from '../common'; // https://api.nuget.org/v3/index.json is a default official nuget feed const defaultNugetFeed = 'https://api.nuget.org/v3/index.json'; const cacheNamespace = 'datasource-nuget'; -function getDefaultFeed() { +export function getDefaultFeed() { return defaultNugetFeed; } -async function getQueryUrl(url) { +export async function getQueryUrl(url: string): Promise<string> { // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource const resourceType = 'SearchQueryService'; const cacheKey = `${url}:${resourceType}`; - const cachedResult = await renovateCache.get(cacheNamespace, cacheKey); + const cachedResult = await renovateCache.get<string>( + cacheNamespace, + cacheKey + ); // istanbul ignore if if (cachedResult) { @@ -61,14 +59,19 @@ async function getQueryUrl(url) { } } -async function getPkgReleases(registryUrl, feedUrl, pkgName) { +export async function getPkgReleases( + registryUrl: string, + feedUrl: string, + pkgName: string +): Promise<ReleaseResult> { let queryUrl = `${feedUrl}?q=${pkgName}`; if (registryUrl.toLowerCase() === defaultNugetFeed.toLowerCase()) { queryUrl = queryUrl.replace('q=', 'q=PackageId:'); queryUrl += '&semVerLevel=2.0.0&prerelease=true'; } - const dep = { + const dep: ReleaseResult = { pkgName, + releases: null, }; try { const pkgUrlListRaw = await got(queryUrl, { @@ -100,7 +103,7 @@ async function getPkgReleases(registryUrl, feedUrl, pkgName) { .map(release => semver.valid(release.version)) .filter(Boolean) .filter(version => !semver.prerelease(version)); - let lastVersion; + let lastVersion: string; // istanbul ignore else if (sanitizedVersions.length) { // Use the last stable version we found @@ -111,7 +114,7 @@ async function getPkgReleases(registryUrl, feedUrl, pkgName) { } if (registryUrl.toLowerCase() === defaultNugetFeed.toLowerCase()) { const nugetOrgApi = `https://api.nuget.org/v3-flatcontainer/${pkgName.toLowerCase()}/${lastVersion}/${pkgName.toLowerCase()}.nuspec`; - let metaresult; + let metaresult: { body: string }; try { metaresult = await got(nugetOrgApi, { hostType: 'nuget' }); } catch (err) /* istanbul ignore next */ { diff --git a/lib/datasource/orb/index.js b/lib/datasource/orb/index.ts similarity index 70% rename from lib/datasource/orb/index.js rename to lib/datasource/orb/index.ts index 0c912d501f603f1801f40a9ab579134caa41214a..61b399be1c8faa06275531bd0dfcf09d6842e5c8 100644 --- a/lib/datasource/orb/index.js +++ b/lib/datasource/orb/index.ts @@ -1,21 +1,29 @@ -const { logger } = require('../../logger'); -const got = require('../../util/got'); +import { logger } from '../../logger'; +import got from '../../util/got'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; -module.exports = { - getPkgReleases, -}; +interface OrbRelease { + homeUrl?: string; + versions: { + version: string; + }[]; +} -/* +/** * orb.getPkgReleases * * This function will fetch an orb from CircleCI and return all semver versions. */ - -async function getPkgReleases({ lookupName }) { +export async function getPkgReleases({ + lookupName, +}: PkgReleaseConfig): Promise<ReleaseResult> { logger.debug({ lookupName }, 'orb.getPkgReleases()'); const cacheNamespace = 'orb'; const cacheKey = lookupName; - const cachedResult = await renovateCache.get(cacheNamespace, cacheKey); + const cachedResult = await renovateCache.get<ReleaseResult>( + cacheNamespace, + cacheKey + ); // istanbul ignore if if (cachedResult) { return cachedResult; @@ -26,7 +34,7 @@ async function getPkgReleases({ lookupName }) { variables: {}, }; try { - const res = (await got.post(url, { + const res: OrbRelease = (await got.post(url, { body, json: true, retry: 5, @@ -36,17 +44,18 @@ async function getPkgReleases({ lookupName }) { return null; } // Simplify response before caching and returning - const dep = { + const dep: ReleaseResult = { name: lookupName, versions: {}, + releases: null, }; if (res.homeUrl && res.homeUrl.length) { dep.homepage = res.homeUrl; } dep.homepage = dep.homepage || `https://circleci.com/orbs/registry/orb/${lookupName}`; - dep.releases = res.versions.map(v => v.version); - dep.releases = dep.releases.map(version => ({ + const releases = res.versions.map(v => v.version); + dep.releases = releases.map(version => ({ version, })); logger.trace({ dep }, 'dep'); diff --git a/lib/datasource/packagist/index.js b/lib/datasource/packagist/index.ts similarity index 76% rename from lib/datasource/packagist/index.js rename to lib/datasource/packagist/index.ts index 8adeb74eb952cf0250ac2cca759fd0b42df73ac4..019323ed29e0bb51a31aa5eff8f9392a9a491420 100644 --- a/lib/datasource/packagist/index.js +++ b/lib/datasource/packagist/index.ts @@ -1,18 +1,17 @@ import is from '@sindresorhus/is'; -const URL = require('url'); -const delay = require('delay'); -const parse = require('github-url-from-git'); -const pAll = require('p-all'); -const { logger } = require('../../logger'); +import URL from 'url'; +import delay from 'delay'; +import parse from 'github-url-from-git'; +import pAll from 'p-all'; +import { logger } from '../../logger'; -const got = require('../../util/got'); -const hostRules = require('../../util/host-rules'); +import got from '../../util/got'; +import * as hostRules from '../../util/host-rules'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; -export { getPkgReleases }; - -function getHostOpts(url) { - const opts = { +function getHostOpts(url: string) { + const opts: any = { json: true, }; const { username, password } = hostRules.find({ hostType: 'packagist', url }); @@ -22,12 +21,30 @@ function getHostOpts(url) { return opts; } -async function getRegistryMeta(regUrl) { +interface PackageMeta { + includes?: Record<string, { sha256: string }>; + packages: Record<string, RegistryFile>; + 'provider-includes': Record<string, { sha256: string }>; + 'providers-url'?: string; +} + +interface RegistryFile { + key: string; + sha256: string; +} +interface RegistryMeta { + files?: RegistryFile[]; + providersUrl?: string; + includesFiles?: RegistryFile[]; + packages?: Record<string, RegistryFile>; +} + +async function getRegistryMeta(regUrl: string) { try { const url = URL.resolve(regUrl.replace(/\/?$/, '/'), 'packages.json'); const opts = getHostOpts(url); - const res = (await got(url, opts)).body; - const meta = {}; + const res: PackageMeta = (await got(url, opts)).body; + const meta: RegistryMeta = {}; meta.packages = res.packages; if (res.includes) { meta.includesFiles = []; @@ -73,7 +90,15 @@ async function getRegistryMeta(regUrl) { } } -async function getPackagistFile(regUrl, file) { +interface PackagistFile { + providers: Record<string, RegistryFile>; + packages?: Record<string, RegistryFile>; +} + +async function getPackagistFile( + regUrl: string, + file: RegistryFile +): Promise<PackagistFile> { const { key, sha256 } = file; const fileName = key.replace('%hash%', sha256); const opts = getHostOpts(regUrl); @@ -99,8 +124,8 @@ async function getPackagistFile(regUrl, file) { return res; } -function extractDepReleases(versions) { - const dep = {}; +function extractDepReleases(versions: RegistryFile): ReleaseResult { + const dep: ReleaseResult = { releases: null }; // istanbul ignore if if (!versions) { dep.releases = []; @@ -121,7 +146,15 @@ function extractDepReleases(versions) { return dep; } -async function getAllPackages(regUrl) { +interface AllPackages { + packages: Record<string, RegistryFile>; + providersUrl: string; + providerPackages: Record<string, string>; + + includesPackages: Record<string, ReleaseResult>; +} + +async function getAllPackages(regUrl: string): Promise<AllPackages> { let repoCacheResult = global.repoCache[`packagist-${regUrl}`]; // istanbul ignore if if (repoCacheResult) { @@ -138,7 +171,7 @@ async function getAllPackages(regUrl) { return null; } const { packages, providersUrl, files, includesFiles } = registryMeta; - const providerPackages = {}; + const providerPackages: Record<string, string> = {}; if (files) { const queue = files.map(file => () => getPackagistFile(regUrl, file)); const resolvedFiles = await pAll(queue, { concurrency: 5 }); @@ -148,7 +181,7 @@ async function getAllPackages(regUrl) { } } } - const includesPackages = {}; + const includesPackages: Record<string, ReleaseResult> = {}; if (includesFiles) { for (const file of includesFiles) { const res = await getPackagistFile(regUrl, file); @@ -161,7 +194,7 @@ async function getAllPackages(regUrl) { } } } - const allPackages = { + const allPackages: AllPackages = { packages, providersUrl, providerPackages, @@ -171,14 +204,17 @@ async function getAllPackages(regUrl) { return allPackages; } -async function packagistOrgLookup(name) { +async function packagistOrgLookup(name: string) { const cacheNamespace = 'datasource-packagist-org'; - const cachedResult = await renovateCache.get(cacheNamespace, name); + const cachedResult = await renovateCache.get<ReleaseResult>( + cacheNamespace, + name + ); // istanbul ignore if if (cachedResult) { return cachedResult; } - let dep = null; + let dep: ReleaseResult = null; const regUrl = 'https://packagist.org'; const pkgUrl = URL.resolve(regUrl, `/p/${name}.json`); const res = (await got(pkgUrl, { @@ -195,7 +231,7 @@ async function packagistOrgLookup(name) { return dep; } -async function packageLookup(regUrl, name) { +async function packageLookup(regUrl: string, name: string) { try { if (regUrl === 'https://packagist.org') { const packagistResult = await packagistOrgLookup(name); @@ -251,10 +287,13 @@ async function packageLookup(regUrl, name) { } } -async function getPkgReleases({ lookupName, registryUrls }) { +export async function getPkgReleases({ + lookupName, + registryUrls, +}: PkgReleaseConfig): Promise<ReleaseResult> { logger.trace(`getPkgReleases(${lookupName})`); - let res; + let res: ReleaseResult; const registries = is.nonEmptyArray(registryUrls) ? registryUrls : ['https://packagist.org']; diff --git a/lib/datasource/pypi/index.js b/lib/datasource/pypi/index.ts similarity index 73% rename from lib/datasource/pypi/index.js rename to lib/datasource/pypi/index.ts index 825824e3d081c72355ad6958472c91c8f19ca6f4..865332ab486b0892558b8d349fcee0ca5e13bc52 100644 --- a/lib/datasource/pypi/index.js +++ b/lib/datasource/pypi/index.ts @@ -1,18 +1,19 @@ import is from '@sindresorhus/is'; +import url from 'url'; +import { parse } from 'node-html-parser'; +import { logger } from '../../logger'; +import { matches } from '../../versioning/pep440'; +import got from '../../util/got'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; -const url = require('url'); -const { parse } = require('node-html-parser'); -const { logger } = require('../../logger'); -const { matches } = require('../../versioning/pep440'); -const got = require('../../util/got'); - -export { getPkgReleases }; - -function normalizeName(input) { +function normalizeName(input: string) { return input.toLowerCase().replace(/(-|\.)/g, '_'); } -function compatibleVersions(releases, compatibility) { +function compatibleVersions( + releases: Record<string, { requires_python?: boolean }[]>, + compatibility: Record<string, string> +) { const versions = Object.keys(releases); if (!(compatibility && compatibility.python)) { return versions; @@ -27,11 +28,11 @@ function compatibleVersions(releases, compatibility) { ); } -/** - * - * @param {{compatibility:any, lookupName:string, registryUrls?: string[] }} args - */ -async function getPkgReleases({ compatibility, lookupName, registryUrls }) { +export async function getPkgReleases({ + compatibility, + lookupName, + registryUrls, +}: PkgReleaseConfig): Promise<ReleaseResult> { let hostUrls = ['https://pypi.org/pypi/']; if (is.nonEmptyArray(registryUrls)) { hostUrls = registryUrls; @@ -41,7 +42,7 @@ async function getPkgReleases({ compatibility, lookupName, registryUrls }) { } for (let hostUrl of hostUrls) { hostUrl += hostUrl.endsWith('/') ? '' : '/'; - let dep; + let dep: ReleaseResult; if (hostUrl.endsWith('/simple/')) { dep = await getSimpleDependency(lookupName, hostUrl); } else { @@ -54,10 +55,14 @@ async function getPkgReleases({ compatibility, lookupName, registryUrls }) { return null; } -async function getDependency(depName, hostUrl, compatibility) { +async function getDependency( + depName: string, + hostUrl: string, + compatibility: Record<string, string> +) { const lookupUrl = url.resolve(hostUrl, `${depName}/json`); try { - const dependency = {}; + const dependency: ReleaseResult = { releases: null }; const rep = await got(url.parse(lookupUrl), { json: true, hostType: 'pypi', @@ -103,11 +108,14 @@ async function getDependency(depName, hostUrl, compatibility) { } } -async function getSimpleDependency(depName, hostUrl) { +async function getSimpleDependency( + depName: string, + hostUrl: string +): Promise<ReleaseResult> { const lookupUrl = url.resolve(hostUrl, `${depName}`); try { - const dependency = {}; - const response = await got(url.parse(lookupUrl), { + const dependency: ReleaseResult = { releases: null }; + const response: { body: string } = await got(url.parse(lookupUrl), { json: false, hostType: 'pypi', }); @@ -116,11 +124,10 @@ async function getSimpleDependency(depName, hostUrl) { logger.debug({ dependency: depName }, 'pip package not found'); return null; } - const root = parse(dep); - // @ts-ignore + const root: HTMLElement = parse(dep) as any; const links = root.querySelectorAll('a'); - const versions = new Set(); - for (const link of links) { + const versions = new Set<string>(); + for (const link of Array.from(links)) { const result = extractVersionFromLinkText(link.text, depName); if (result) { versions.add(result); @@ -141,7 +148,7 @@ async function getSimpleDependency(depName, hostUrl) { } } -function extractVersionFromLinkText(text, depName) { +function extractVersionFromLinkText(text: string, depName: string) { const prefix = `${depName}-`; const suffix = '.tar.gz'; if (!(text.startsWith(prefix) && text.endsWith(suffix))) { diff --git a/lib/datasource/ruby-version/index.js b/lib/datasource/ruby-version/index.ts similarity index 73% rename from lib/datasource/ruby-version/index.js rename to lib/datasource/ruby-version/index.ts index cd2507bbb98feb50a3c13f4122805dec7006a5e9..4f0768f74943ba9fe6dd290375491212380ea1c6 100644 --- a/lib/datasource/ruby-version/index.js +++ b/lib/datasource/ruby-version/index.ts @@ -1,25 +1,27 @@ -const { parse } = require('node-html-parser'); -const { logger } = require('../../logger'); +import { parse } from 'node-html-parser'; +import { logger } from '../../logger'; -const got = require('../../util/got'); -const { isVersion } = require('../../versioning/ruby'); - -module.exports = { - getPkgReleases, -}; +import got from '../../util/got'; +import { isVersion } from '../../versioning/ruby'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; const rubyVersionsUrl = 'https://www.ruby-lang.org/en/downloads/releases/'; -async function getPkgReleases() { +export async function getPkgReleases( + _config?: PkgReleaseConfig +): Promise<ReleaseResult> { // First check the persistent cache const cacheNamespace = 'datasource-ruby-version'; - const cachedResult = await renovateCache.get(cacheNamespace, 'all'); + const cachedResult = await renovateCache.get<ReleaseResult>( + cacheNamespace, + 'all' + ); // istanbul ignore if if (cachedResult) { return cachedResult; } try { - const res = { + const res: ReleaseResult = { homepage: 'https://www.ruby-lang.org', sourceUrl: 'https://github.com/ruby/ruby', releases: [], @@ -29,7 +31,7 @@ async function getPkgReleases() { // @ts-ignore const rows = root.querySelector('.release-list').querySelectorAll('tr'); for (const row of rows) { - const columns = Array.from( + const columns: string[] = Array.from( row.querySelectorAll('td').map(td => td.innerHTML) ); if (columns.length) { diff --git a/lib/datasource/rubygems/errors.js b/lib/datasource/rubygems/errors.ts similarity index 93% rename from lib/datasource/rubygems/errors.js rename to lib/datasource/rubygems/errors.ts index 4583bee07080d96c9d1084789d90310f4135baac..7c9b7971d88e09a43fa339e9aaf60c39388f9ddb 100644 --- a/lib/datasource/rubygems/errors.js +++ b/lib/datasource/rubygems/errors.ts @@ -7,7 +7,7 @@ const REQUEST_TIMEOUT = 408; const TOO_MANY_REQUEST = 429; const SERVICE_UNAVAILABLE = 503; -module.exports = { +export { UNAUTHORIZED, FORBIDDEN, NOT_FOUND, diff --git a/lib/datasource/rubygems/get-rubygems-org.js b/lib/datasource/rubygems/get-rubygems-org.ts similarity index 83% rename from lib/datasource/rubygems/get-rubygems-org.js rename to lib/datasource/rubygems/get-rubygems-org.ts index 96e2cb0072569622d7aa46a0ac4600af48ac068d..096dc47c4e5611172eb15f6e7641f1613441e35c 100644 --- a/lib/datasource/rubygems/get-rubygems-org.js +++ b/lib/datasource/rubygems/get-rubygems-org.ts @@ -1,12 +1,9 @@ -const got = require('../../util/got'); -const { logger } = require('../../logger'); - -module.exports = { - getRubygemsOrgDependency, -}; +import got from '../../util/got'; +import { logger } from '../../logger'; +import { ReleaseResult } from '../common'; let lastSync = new Date('2000-01-01'); -let packageReleases = Object.create(null); // Because we might need a "constructor" key +let packageReleases: Record<string, string[]> = Object.create(null); // Because we might need a "constructor" key let contentLength = 0; async function updateRubyGemsVersions() { @@ -17,7 +14,7 @@ async function updateRubyGemsVersions() { range: `bytes=${contentLength}-`, }, }; - let newLines; + let newLines: string; try { logger.debug('Rubygems: Fetching rubygems.org versions'); newLines = (await got(url, options)).body; @@ -33,10 +30,10 @@ async function updateRubyGemsVersions() { return; } - function processLine(line) { - let split; - let pkg; - let versions; + function processLine(line: string) { + let split: string[]; + let pkg: string; + let versions: string; try { const l = line.trim(); if (!l.length || l.startsWith('created_at:') || l === '---') { @@ -87,13 +84,15 @@ async function syncVersions() { } } -async function getRubygemsOrgDependency(lookupName) { +export async function getRubygemsOrgDependency( + lookupName: string +): Promise<ReleaseResult> { logger.debug(`getRubygemsOrgDependency(${lookupName})`); await syncVersions(); if (!packageReleases[lookupName]) { return null; } - const dep = { + const dep: ReleaseResult = { name: lookupName, releases: packageReleases[lookupName].map(version => ({ version })), }; diff --git a/lib/datasource/rubygems/get.js b/lib/datasource/rubygems/get.ts similarity index 85% rename from lib/datasource/rubygems/get.js rename to lib/datasource/rubygems/get.ts index c51b2d6fb3697435ebb34e3849f2af044f6113e7..ce43de4e4caa2a44bef4b12d545aa5a75416427a 100644 --- a/lib/datasource/rubygems/get.js +++ b/lib/datasource/rubygems/get.ts @@ -1,8 +1,9 @@ -const { logger } = require('../../logger'); -const got = require('../../util/got'); -const { maskToken } = require('../../util/mask'); -const retriable = require('./retriable'); -const { UNAUTHORIZED, FORBIDDEN, NOT_FOUND } = require('./errors'); +import { logger } from '../../logger'; +import got from '../../util/got'; +import { maskToken } from '../../util/mask'; +import retriable from './retriable'; +import { UNAUTHORIZED, FORBIDDEN, NOT_FOUND } from './errors'; +import { ReleaseResult } from '../common'; const INFO_PATH = '/api/v1/gems'; const VERSIONS_PATH = '/api/v1/versions'; @@ -50,7 +51,10 @@ const fetch = async ({ dependency, registry, path }) => { return response.body; }; -const getDependency = async ({ dependency, registry }) => { +export const getDependency = async ({ + dependency, + registry, +}): Promise<ReleaseResult> => { try { const info = await fetch({ dependency, registry, path: INFO_PATH }); if (!info) { @@ -95,7 +99,3 @@ const getDependency = async ({ dependency, registry }) => { return processError({ err, registry, dependency }); } }; - -module.exports = { - getDependency, -}; diff --git a/lib/datasource/rubygems/index.js b/lib/datasource/rubygems/index.js deleted file mode 100644 index a2e4f69f7e97dfafd4133f51159f0d7262889e44..0000000000000000000000000000000000000000 --- a/lib/datasource/rubygems/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const { getPkgReleases } = require('./releases'); - -module.exports = { - getPkgReleases, -}; diff --git a/lib/datasource/rubygems/index.ts b/lib/datasource/rubygems/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..d55467325c9d0463aad8addd43f97e1dad5f9703 --- /dev/null +++ b/lib/datasource/rubygems/index.ts @@ -0,0 +1 @@ +export { getPkgReleases } from './releases'; diff --git a/lib/datasource/rubygems/releases.js b/lib/datasource/rubygems/releases.ts similarity index 56% rename from lib/datasource/rubygems/releases.js rename to lib/datasource/rubygems/releases.ts index f7c8f1cf8905b735999bac45b29d9b562e192e47..34596c224b4ab25096714b6c620aeffe8f5d3c72 100644 --- a/lib/datasource/rubygems/releases.js +++ b/lib/datasource/rubygems/releases.ts @@ -1,14 +1,16 @@ import is from '@sindresorhus/is'; +import { getDependency } from './get'; +import { getRubygemsOrgDependency } from './get-rubygems-org'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; -const { getDependency } = require('./get'); -const { getRubygemsOrgDependency } = require('./get-rubygems-org'); - -/** @param {{lookupName:string, registryUrls?: string[]}} opt */ -async function getPkgReleases({ lookupName, registryUrls }) { +export async function getPkgReleases({ + lookupName, + registryUrls, +}: PkgReleaseConfig): Promise<ReleaseResult> { const registries = is.nonEmptyArray(registryUrls) ? registryUrls : []; for (const registry of registries) { - let pkg; + let pkg: ReleaseResult; if (registry.endsWith('rubygems.org')) { pkg = await getRubygemsOrgDependency(lookupName); } else { @@ -21,5 +23,3 @@ async function getPkgReleases({ lookupName, registryUrls }) { return null; } - -export { getPkgReleases }; diff --git a/lib/datasource/rubygems/retriable.js b/lib/datasource/rubygems/retriable.ts similarity index 64% rename from lib/datasource/rubygems/retriable.js rename to lib/datasource/rubygems/retriable.ts index 791b9cda724af3a24e80a1e8b6ce929ce0196cb1..4a55692ef7bd53139a084bb6ba75819b797928f6 100644 --- a/lib/datasource/rubygems/retriable.js +++ b/lib/datasource/rubygems/retriable.ts @@ -1,11 +1,12 @@ -const { logger } = require('../../logger'); -const { +import got from 'got'; +import { logger } from '../../logger'; +import { UNAUTHORIZED, FORBIDDEN, REQUEST_TIMEOUT, TOO_MANY_REQUEST, SERVICE_UNAVAILABLE, -} = require('./errors'); +} from './errors'; const RETRY_AFTER = 600; const NUMBER_OF_RETRIES = 5; @@ -13,13 +14,14 @@ const NUMBER_OF_RETRIES = 5; const getDelayStep = () => parseInt(process.env.RENOVATE_RUBYGEMS_RETRY_DELAY_STEP || '1000', 10); -const toMs = value => value * getDelayStep(); -const getBannedDelay = retryAfter => +const toMs = (value: number) => value * getDelayStep(); +const getBannedDelay = (retryAfter: string) => (parseInt(retryAfter, 10) || RETRY_AFTER) + 1; -const getDefaultDelay = count => (NUMBER_OF_RETRIES * getDelayStep()) / count; +const getDefaultDelay = (count: number) => + (NUMBER_OF_RETRIES * getDelayStep()) / count; -const getDelayMessage = delay => `Retry in ${delay} seconds.`; -const getErrorMessage = status => { +const getDelayMessage = (delay: any) => `Retry in ${delay} seconds.`; +const getErrorMessage = (status: number) => { // istanbul ignore next switch (status) { case UNAUTHORIZED: @@ -35,7 +37,13 @@ const getErrorMessage = status => { } }; -module.exports = (numberOfRetries = NUMBER_OF_RETRIES) => (_, err) => { +// TODO: workaround because got does not export HTTPError, should be moved to `lib/util/got` +export type HTTPError = InstanceType<got.GotInstance['HTTPError']>; + +export default (numberOfRetries = NUMBER_OF_RETRIES): got.RetryFunction => ( + _?: number, + err?: Partial<HTTPError> +) => { if (numberOfRetries === 0) { return 0; } diff --git a/lib/datasource/sbt/index.js b/lib/datasource/sbt/index.ts similarity index 81% rename from lib/datasource/sbt/index.js rename to lib/datasource/sbt/index.ts index 9f8d442dd6dab701beb1fcf6bba5e52f1fe6cd78..9456fd1e6b09d81a25d9ecf399e342ad88351c31 100644 --- a/lib/datasource/sbt/index.js +++ b/lib/datasource/sbt/index.ts @@ -1,9 +1,12 @@ -const { compare } = require('../../versioning/maven/compare'); -const { downloadHttpProtocol } = require('../maven/util'); -const { parseIndexDir, SBT_PLUGINS_REPO } = require('./util'); -const { logger } = require('../../logger'); +import { compare } from '../../versioning/maven/compare'; +import { downloadHttpProtocol } from '../maven/util'; +import { parseIndexDir, SBT_PLUGINS_REPO } from './util'; +import { logger } from '../../logger'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; -async function getPkgReleases(config) { +export async function getPkgReleases( + config: PkgReleaseConfig +): Promise<ReleaseResult> { const { lookupName, depType } = config; const registryUrls = @@ -17,7 +20,7 @@ async function getPkgReleases(config) { const [artifact, scalaVersion] = artifactIdSplit; const repoRoots = registryUrls.map(x => x.replace(/\/?$/, '')); - const searchRoots = []; + const searchRoots: string[] = []; repoRoots.forEach(repoRoot => { // Optimize lookup order if (depType === 'plugin') { @@ -56,12 +59,17 @@ async function getPkgReleases(config) { return null; } -async function resolvePluginReleases(rootUrl, artifact, scalaVersion) { +async function resolvePluginReleases( + rootUrl: string, + artifact: string, + scalaVersion: string +) { const searchRoot = `${rootUrl}/${artifact}`; - const parse = content => parseIndexDir(content, x => !/^\.+$/.test(x)); + const parse = (content: string) => + parseIndexDir(content, x => !/^\.+$/.test(x)); const indexContent = await downloadHttpProtocol(searchRoot, 'sbt'); if (indexContent) { - const releases = []; + const releases: string[] = []; const scalaVersionItems = parse(indexContent); const scalaVersions = scalaVersionItems.map(x => x.replace(/^scala_/, '')); const searchVersions = @@ -91,11 +99,15 @@ async function resolvePluginReleases(rootUrl, artifact, scalaVersion) { return resolvePackageReleases(rootUrl, artifact, scalaVersion); } -async function resolvePackageReleases(searchRoot, artifact, scalaVersion) { +async function resolvePackageReleases( + searchRoot: string, + artifact: string, + scalaVersion: string +): Promise<string[]> { const indexContent = await downloadHttpProtocol(searchRoot, 'sbt'); if (indexContent) { - const releases = []; - const parseSubdirs = content => + const releases: string[] = []; + const parseSubdirs = (content: string) => parseIndexDir(content, x => { if (x === artifact) return true; if (x.indexOf(`${artifact}_native`) === 0) return false; @@ -110,7 +122,7 @@ async function resolvePackageReleases(searchRoot, artifact, scalaVersion) { ) { searchSubdirs = [`${artifact}_${scalaVersion}`]; } - const parseReleases = content => + const parseReleases = (content: string) => parseIndexDir(content, x => !/^\.+$/.test(x)); for (const searchSubdir of searchSubdirs) { const content = await downloadHttpProtocol( @@ -127,7 +139,3 @@ async function resolvePackageReleases(searchRoot, artifact, scalaVersion) { return null; } - -module.exports = { - getPkgReleases, -}; diff --git a/lib/datasource/sbt/util.js b/lib/datasource/sbt/util.js deleted file mode 100644 index 8fbdb9d9d732dccbee7c32be64908b3ae99a818d..0000000000000000000000000000000000000000 --- a/lib/datasource/sbt/util.js +++ /dev/null @@ -1,11 +0,0 @@ -const SBT_PLUGINS_REPO = 'https://dl.bintray.com/sbt/sbt-plugin-releases'; - -function parseIndexDir(content, filterFn = x => !/^\.+/.test(x)) { - const unfiltered = content.match(/(?<=href=['"])[^'"]*(?=\/['"])/g) || []; - return unfiltered.filter(filterFn); -} - -module.exports = { - parseIndexDir, - SBT_PLUGINS_REPO, -}; diff --git a/lib/datasource/sbt/util.ts b/lib/datasource/sbt/util.ts new file mode 100644 index 0000000000000000000000000000000000000000..5a402d0baa8d69337706c17c5f2a3ac56e8ae5c9 --- /dev/null +++ b/lib/datasource/sbt/util.ts @@ -0,0 +1,10 @@ +export const SBT_PLUGINS_REPO = + 'https://dl.bintray.com/sbt/sbt-plugin-releases'; + +export function parseIndexDir( + content: string, + filterFn = (x: string) => !/^\.+/.test(x) +) { + const unfiltered = content.match(/(?<=href=['"])[^'"]*(?=\/['"])/g) || []; + return unfiltered.filter(filterFn); +} diff --git a/lib/datasource/terraform/index.js b/lib/datasource/terraform/index.ts similarity index 75% rename from lib/datasource/terraform/index.js rename to lib/datasource/terraform/index.ts index 949f035c34667861be4abb9582216893eebabdef..ff884aab5d39f294a0757fc1821efb2ebc3dd823 100644 --- a/lib/datasource/terraform/index.js +++ b/lib/datasource/terraform/index.ts @@ -1,14 +1,11 @@ import is from '@sindresorhus/is'; +import parse from 'github-url-from-git'; +import { logger } from '../../logger'; +import got from '../../util/got'; +import { PkgReleaseConfig, ReleaseResult } from '../common'; -const parse = require('github-url-from-git'); -const { logger } = require('../../logger'); - -const got = require('../../util/got'); - -export { getPkgReleases }; - -function getRegistryRepository(lookupName, registryUrls) { - let registry; +function getRegistryRepository(lookupName: string, registryUrls: string[]) { + let registry: string; const split = lookupName.split('/'); if (split.length > 3 && split[0].includes('.')) { [registry] = split; @@ -28,15 +25,25 @@ function getRegistryRepository(lookupName, registryUrls) { }; } -/* +interface TerraformRelease { + namespace: string; + name: string; + provider: string; + source?: string; + versions: string[]; +} + +/** * terraform.getPkgReleases * * This function will fetch a package from the specified Terraform registry and return all semver versions. * - `sourceUrl` is supported of "source" field is set * - `homepage` is set to the Terraform registry's page if it's on the official main registry */ - -async function getPkgReleases({ lookupName, registryUrls }) { +export async function getPkgReleases({ + lookupName, + registryUrls, +}: PkgReleaseConfig): Promise<ReleaseResult> { const { registry, repository } = getRegistryRepository( lookupName, registryUrls @@ -44,13 +51,16 @@ async function getPkgReleases({ lookupName, registryUrls }) { logger.debug({ registry, repository }, 'terraform.getDependencies()'); const cacheNamespace = 'terraform'; const pkgUrl = `${registry}/v1/modules/${repository}`; - const cachedResult = await renovateCache.get(cacheNamespace, pkgUrl); + const cachedResult = await renovateCache.get<ReleaseResult>( + cacheNamespace, + pkgUrl + ); // istanbul ignore if if (cachedResult) { return cachedResult; } try { - const res = (await got(pkgUrl, { + const res: TerraformRelease = (await got(pkgUrl, { json: true, hostType: 'terraform', })).body; @@ -60,9 +70,10 @@ async function getPkgReleases({ lookupName, registryUrls }) { return null; } // Simplify response before caching and returning - const dep = { + const dep: ReleaseResult = { name: repository, versions: {}, + releases: null, }; if (res.source) { dep.sourceUrl = parse(res.source); diff --git a/package.json b/package.json index 8f4113ee3b15cec67344a392cb35fc9251cb7446..f299beda225413425ac9ae752dd8eb8474c0eccb 100644 --- a/package.json +++ b/package.json @@ -167,15 +167,19 @@ "@types/convert-hrtime": "2.0.0", "@types/fs-extra": "8.0.0", "@types/got": "9.6.2", + "@types/ini": "1.3.30", "@types/jest": "24.0.15", "@types/js-yaml": "3.12.1", "@types/lodash": "4.14.136", "@types/luxon": "1.15.2", + "@types/nock": "10.0.3", "@types/node": "11.13.18", "@types/parse-link-header": "1.0.0", + "@types/registry-auth-token": "3.3.0", "@types/semver": "6.0.1", "@types/shelljs": "0.8.5", "@types/tmp": "0.1.0", + "@types/validator": "10.11.2", "@types/xmldoc": "1.1.4", "@typescript-eslint/eslint-plugin": "1.12.0", "@typescript-eslint/parser": "1.12.0", diff --git a/test/config/index.spec.js b/test/config/index.spec.js index 5b86396fa40bb83352cf99328d52657a59537f3f..1d24ce3ce473635bd07d94955d333d056131cb72 100644 --- a/test/config/index.spec.js +++ b/test/config/index.spec.js @@ -5,6 +5,8 @@ const defaultConfig = require('../../lib/config/defaults').getConfig(); const npm = require('../../lib/datasource/npm'); const presetDefaults = require('./npm/_fixtures/renovate-config-default.json'); +jest.mock('../../lib/datasource/npm'); + npm.getPkgReleases = jest.fn(() => ({ 'renovate-config': presetDefaults.versions[presetDefaults['dist-tags'].latest][ diff --git a/test/config/presets.spec.js b/test/config/presets.spec.js index d26792c668489ac5eff766e120d1450e94b55f92..93956e03e2b03467cff59a72b5bf1dd547622f35 100644 --- a/test/config/presets.spec.js +++ b/test/config/presets.spec.js @@ -6,6 +6,8 @@ const presetGroup = require('./npm/_fixtures/renovate-config-group.json'); const presetMonorepo = require('./npm/_fixtures/renovate-config-monorepo.json'); const presetIkatyang = require('./npm/_fixtures/renovate-config-ikatyang.json'); +jest.mock('../../lib/datasource/npm'); + npm.getPreset = jest.fn((dep, presetName) => { if (dep === 'renovate-config-default') { return presetDefaults.versions[presetDefaults['dist-tags'].latest][ diff --git a/test/datasource/__snapshots__/cargo.spec.js.snap b/test/datasource/__snapshots__/cargo.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/cargo.spec.js.snap rename to test/datasource/__snapshots__/cargo.spec.ts.snap diff --git a/test/datasource/__snapshots__/dart.spec.js.snap b/test/datasource/__snapshots__/dart.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/dart.spec.js.snap rename to test/datasource/__snapshots__/dart.spec.ts.snap diff --git a/test/datasource/__snapshots__/docker.spec.js.snap b/test/datasource/__snapshots__/docker.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/docker.spec.js.snap rename to test/datasource/__snapshots__/docker.spec.ts.snap diff --git a/test/datasource/__snapshots__/github.spec.js.snap b/test/datasource/__snapshots__/github.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/github.spec.js.snap rename to test/datasource/__snapshots__/github.spec.ts.snap diff --git a/test/datasource/__snapshots__/gitlab.spec.js.snap b/test/datasource/__snapshots__/gitlab.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/gitlab.spec.js.snap rename to test/datasource/__snapshots__/gitlab.spec.ts.snap diff --git a/test/datasource/__snapshots__/go.spec.js.snap b/test/datasource/__snapshots__/go.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/go.spec.js.snap rename to test/datasource/__snapshots__/go.spec.ts.snap diff --git a/test/datasource/__snapshots__/gradle-version.spec.js.snap b/test/datasource/__snapshots__/gradle-version.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/gradle-version.spec.js.snap rename to test/datasource/__snapshots__/gradle-version.spec.ts.snap diff --git a/test/datasource/__snapshots__/hex.spec.js.snap b/test/datasource/__snapshots__/hex.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/hex.spec.js.snap rename to test/datasource/__snapshots__/hex.spec.ts.snap diff --git a/test/datasource/__snapshots__/index.spec.js.snap b/test/datasource/__snapshots__/index.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/index.spec.js.snap rename to test/datasource/__snapshots__/index.spec.ts.snap diff --git a/test/datasource/__snapshots__/metadata.spec.js.snap b/test/datasource/__snapshots__/metadata.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/metadata.spec.js.snap rename to test/datasource/__snapshots__/metadata.spec.ts.snap diff --git a/test/datasource/__snapshots__/nuget.spec.js.snap b/test/datasource/__snapshots__/nuget.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/nuget.spec.js.snap rename to test/datasource/__snapshots__/nuget.spec.ts.snap diff --git a/test/datasource/__snapshots__/orb.spec.js.snap b/test/datasource/__snapshots__/orb.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/orb.spec.js.snap rename to test/datasource/__snapshots__/orb.spec.ts.snap diff --git a/test/datasource/__snapshots__/packagist.spec.js.snap b/test/datasource/__snapshots__/packagist.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/packagist.spec.js.snap rename to test/datasource/__snapshots__/packagist.spec.ts.snap diff --git a/test/datasource/__snapshots__/pypi.spec.js.snap b/test/datasource/__snapshots__/pypi.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/pypi.spec.js.snap rename to test/datasource/__snapshots__/pypi.spec.ts.snap diff --git a/test/datasource/__snapshots__/ruby-version.spec.js.snap b/test/datasource/__snapshots__/ruby-version.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/ruby-version.spec.js.snap rename to test/datasource/__snapshots__/ruby-version.spec.ts.snap diff --git a/test/datasource/__snapshots__/terraform.spec.js.snap b/test/datasource/__snapshots__/terraform.spec.ts.snap similarity index 100% rename from test/datasource/__snapshots__/terraform.spec.js.snap rename to test/datasource/__snapshots__/terraform.spec.ts.snap diff --git a/test/datasource/cargo.spec.js b/test/datasource/cargo.spec.ts similarity index 95% rename from test/datasource/cargo.spec.js rename to test/datasource/cargo.spec.ts index 165217b1032e55e012584a28d391f180c6ad4d61..4c8d93b0e3339ac9263d52b52b46beb08fc0228d 100644 --- a/test/datasource/cargo.spec.js +++ b/test/datasource/cargo.spec.ts @@ -1,7 +1,9 @@ -const fs = require('fs'); +import fs from 'fs'; -const got = require('../../lib/util/got'); -const { getPkgReleases } = require('../../lib/datasource/cargo'); +import _got from '../../lib/util/got'; +import { getPkgReleases } from '../../lib/datasource/cargo'; + +const got: any = _got; const res1 = fs.readFileSync('test/datasource/cargo/_fixtures/libc', 'utf8'); const res2 = fs.readFileSync( diff --git a/test/datasource/dart.spec.js b/test/datasource/dart.spec.ts similarity index 92% rename from test/datasource/dart.spec.js rename to test/datasource/dart.spec.ts index 37a73f825a91e0e48c6470dc4d5f41292f80e24f..e8d828b7aa53465f437b58f80911310c9e00de30 100644 --- a/test/datasource/dart.spec.js +++ b/test/datasource/dart.spec.ts @@ -1,8 +1,10 @@ -const fs = require('fs'); -const got = require('../../lib/util/got'); -const { getPkgReleases } = require('../../lib/datasource/dart'); +import fs from 'fs'; +import _got from '../../lib/util/got'; +import { getPkgReleases } from '../../lib/datasource/dart'; -const body = JSON.parse( +const got = _got; + +const body: any = JSON.parse( fs.readFileSync( 'test/datasource/dart/_fixtures/shared_preferences.json', 'utf8' diff --git a/test/datasource/docker.spec.js b/test/datasource/docker.spec.ts similarity index 97% rename from test/datasource/docker.spec.js rename to test/datasource/docker.spec.ts index 87a815f7e7f17b5f006521fbf3a1a5b5f93478ed..a3e752b57d28d27ee9ae861c775f4ed82a16f9b7 100644 --- a/test/datasource/docker.spec.js +++ b/test/datasource/docker.spec.ts @@ -1,8 +1,10 @@ -const got = require('../../lib/util/got'); -const docker = require('../../lib/datasource/docker'); -const { getPkgReleases } = require('../../lib/datasource'); -/** @type any */ -const hostRules = require('../../lib/util/host-rules'); +import _got from '../../lib/util/got'; +import * as docker from '../../lib/datasource/docker'; +import { getPkgReleases } from '../../lib/datasource'; +import * as _hostRules from '../../lib/util/host-rules'; + +const got: any = _got; +const hostRules: any = _hostRules; jest.mock('../../lib/util/got'); jest.mock('../../lib/util/host-rules'); diff --git a/test/datasource/git-tags.spec.js b/test/datasource/git-tags.spec.ts similarity index 90% rename from test/datasource/git-tags.spec.js rename to test/datasource/git-tags.spec.ts index 9288c35b6509c14d35ac4ed939707f2a6d41d28e..7825d7490822106428402387cfdf023479f27a69 100644 --- a/test/datasource/git-tags.spec.js +++ b/test/datasource/git-tags.spec.ts @@ -1,8 +1,8 @@ -/** @type any */ -const simpleGit = require('simple-git/promise'); -const { getPkgReleases } = require('../../lib/datasource/git-tags'); +import _simpleGit from 'simple-git/promise'; +import { getPkgReleases } from '../../lib/datasource/git-tags'; jest.mock('simple-git/promise.js'); +const simpleGit: any = _simpleGit; // const lookupName = 'vapor'; const lookupName = 'https://github.com/example/example.git'; diff --git a/test/datasource/github.spec.js b/test/datasource/github.spec.ts similarity index 95% rename from test/datasource/github.spec.js rename to test/datasource/github.spec.ts index 7a98c36064cd93c7d685f22b441fb466d7bd03ae..e467751d86c2a76a33da3a49cc6f77ce8d36625f 100644 --- a/test/datasource/github.spec.js +++ b/test/datasource/github.spec.ts @@ -1,16 +1,15 @@ import { api } from '../../lib/platform/github/gh-got-wrapper'; -const datasource = require('../../lib/datasource'); -const github = require('../../lib/datasource/github'); -const got = require('../../lib/util/got'); -const hostRules = require('../../lib/util/host-rules'); +import * as datasource from '../../lib/datasource'; +import * as github from '../../lib/datasource/github'; +import got from '../../lib/util/got'; +import * as hostRules from '../../lib/util/host-rules'; jest.mock('../../lib/platform/github/gh-got-wrapper'); jest.mock('../../lib/util/got'); jest.mock('../../lib/util/host-rules'); -/** @type any */ -const ghGot = api.get; +const ghGot: any = api.get; describe('datasource/github', () => { beforeEach(() => global.renovateCache.rmAll()); diff --git a/test/datasource/gitlab.spec.js b/test/datasource/gitlab.spec.ts similarity index 92% rename from test/datasource/gitlab.spec.js rename to test/datasource/gitlab.spec.ts index 7b7c26dcf1ad1cf6c27acb5b7852ee04aa6cb656..2f088dff5e102026a749e7308df8ce721c87c89c 100644 --- a/test/datasource/gitlab.spec.js +++ b/test/datasource/gitlab.spec.ts @@ -1,11 +1,12 @@ -const datasource = require('../../lib/datasource'); -const gitlab = require('../../lib/datasource/gitlab'); -/** @type any */ -const glGot = require('../../lib/platform/gitlab/gl-got-wrapper').api.get; +import * as datasource from '../../lib/datasource'; +import * as gitlab from '../../lib/datasource/gitlab'; +import { api } from '../../lib/platform/gitlab/gl-got-wrapper'; jest.mock('../../lib/platform/gitlab/gl-got-wrapper'); jest.mock('../../lib/util/got'); +const glGot: any = api.get; + describe('datasource/gitlab', () => { beforeEach(() => { global.repoCache = {}; diff --git a/test/datasource/go.spec.js b/test/datasource/go.spec.ts similarity index 95% rename from test/datasource/go.spec.js rename to test/datasource/go.spec.ts index 94795d723631610b7a0452999f216ac8f1bbc52d..2dd6762abf9217df857326a9cfbeee0433199cf8 100644 --- a/test/datasource/go.spec.js +++ b/test/datasource/go.spec.ts @@ -1,11 +1,13 @@ -const got = require('../../lib/util/got'); -/** @type any */ -const github = require('../../lib/datasource/github'); -const go = require('../../lib/datasource/go'); +import _got from '../../lib/util/got'; +import * as _github from '../../lib/datasource/github'; +import * as go from '../../lib/datasource/go'; jest.mock('../../lib/util/got'); jest.mock('../../lib/datasource/github'); +const got: any = _got; +const github: any = _github; + const res1 = `<!DOCTYPE html> <html> <head> diff --git a/test/datasource/gradle-version.spec.js b/test/datasource/gradle-version.spec.ts similarity index 86% rename from test/datasource/gradle-version.spec.js rename to test/datasource/gradle-version.spec.ts index 44206c1af66345e4bdaa6ea29371004fd1972c8a..f30ed7c7ce48e8292eee5e21fd0afdfd28873ad4 100644 --- a/test/datasource/gradle-version.spec.js +++ b/test/datasource/gradle-version.spec.ts @@ -1,15 +1,16 @@ -const fs = require('fs'); -const got = require('../../lib/util/got'); -const datasource = require('../../lib/datasource'); +import fs from 'fs'; +import _got from '../../lib/util/got'; +import * as datasource from '../../lib/datasource'; jest.mock('../../lib/util/got'); -/** @type any */ -const allResponse = fs.readFileSync( +const got: any = _got; + +const allResponse: any = fs.readFileSync( 'test/datasource/gradle-wrapper/_fixtures/all.json' ); -let config = {}; +let config: datasource.PkgReleaseConfig = {}; describe('datasource/gradle', () => { describe('getPkgReleases', () => { diff --git a/test/datasource/hex.spec.js b/test/datasource/hex.spec.ts similarity index 91% rename from test/datasource/hex.spec.js rename to test/datasource/hex.spec.ts index 7559bb2604362accad5f9d7a82d90f13f0adcb98..cb5aacc3a7a5cd190007902e66cdc92ed84abf38 100644 --- a/test/datasource/hex.spec.js +++ b/test/datasource/hex.spec.ts @@ -1,8 +1,10 @@ -const fs = require('fs'); -const got = require('../../lib/util/got'); -/** @type any */ -const hostRules = require('../../lib/util/host-rules'); -const { getPkgReleases } = require('../../lib/datasource/hex'); +import fs from 'fs'; +import _got from '../../lib/util/got'; +import * as _hostRules from '../../lib/util/host-rules'; +import { getPkgReleases } from '../../lib/datasource/hex'; + +const got: any = _got; +const hostRules: any = _hostRules; let res1 = fs.readFileSync( 'test/datasource/hex/_fixtures/certifi.json', diff --git a/test/datasource/index.spec.js b/test/datasource/index.spec.ts similarity index 93% rename from test/datasource/index.spec.js rename to test/datasource/index.spec.ts index a3cf872d54327948a3bffb743b4a68049d050f80..870db99448169d2f18fb5326b95df3724cc0c489 100644 --- a/test/datasource/index.spec.js +++ b/test/datasource/index.spec.ts @@ -1,10 +1,11 @@ -const datasource = require('../../lib/datasource'); -/** @type any */ -const npmDatasource = require('../../lib/datasource/npm'); +import * as datasource from '../../lib/datasource'; +import * as _npm from '../../lib/datasource/npm'; jest.mock('../../lib/datasource/docker'); jest.mock('../../lib/datasource/npm'); +const npmDatasource: any = _npm; + describe('datasource/index', () => { it('returns if digests are supported', async () => { expect(await datasource.supportsDigests({ datasource: 'github' })).toBe( diff --git a/test/datasource/maven.spec.js b/test/datasource/maven.spec.ts similarity index 98% rename from test/datasource/maven.spec.js rename to test/datasource/maven.spec.ts index e5fa68071f6821eb929b4c3985bfb51b54f95c60..3d84c79897e9700b8ca2459707108ee1184e5401 100644 --- a/test/datasource/maven.spec.js +++ b/test/datasource/maven.spec.ts @@ -1,7 +1,6 @@ -const nock = require('nock'); -const fs = require('fs'); - -const datasource = require('../../lib/datasource'); +import nock from 'nock'; +import fs from 'fs'; +import * as datasource from '../../lib/datasource'; const MYSQL_VERSIONS = [ '6.0.5', diff --git a/test/datasource/metadata.spec.js b/test/datasource/metadata.spec.ts similarity index 97% rename from test/datasource/metadata.spec.js rename to test/datasource/metadata.spec.ts index 2d8ddaf16a92e97c900c7ab5e22e5e7c21906e49..52967c58ccafa8de7c62cfc7c67ad80129067afa 100644 --- a/test/datasource/metadata.spec.js +++ b/test/datasource/metadata.spec.ts @@ -1,4 +1,4 @@ -const { addMetaData } = require('../../lib/datasource/metadata'); +import { addMetaData } from '../../lib/datasource/metadata'; describe('datasource/metadata', () => { it('Should do nothing if dep is not specified', () => { diff --git a/test/datasource/npm/__snapshots__/index.spec.js.snap b/test/datasource/npm/__snapshots__/index.spec.ts.snap similarity index 100% rename from test/datasource/npm/__snapshots__/index.spec.js.snap rename to test/datasource/npm/__snapshots__/index.spec.ts.snap diff --git a/test/datasource/npm/index.spec.js b/test/datasource/npm/index.spec.ts similarity index 95% rename from test/datasource/npm/index.spec.js rename to test/datasource/npm/index.spec.ts index d0d7ebf3a1c8b1b4ebb950fa098ca140f6509908..47c0f7a7c84c2becb2c4fffb0f058d4f8451f333 100644 --- a/test/datasource/npm/index.spec.js +++ b/test/datasource/npm/index.spec.ts @@ -1,15 +1,21 @@ -const registryAuthToken = require('registry-auth-token'); -const nock = require('nock'); -const moment = require('moment'); -const npm = require('../../../lib/datasource/npm'); +import _registryAuthToken from 'registry-auth-token'; +import nock from 'nock'; +import moment from 'moment'; +import * as npm from '../../../lib/datasource/npm'; jest.mock('registry-auth-token'); jest.mock('delay'); -let npmResponse; +const registryAuthToken: any = _registryAuthToken; +let npmResponse: any; -function getRelease(dependency, version) { - return dependency.releases.find(release => release.version === version); +function getRelease( + dependency: { releases: { version: string; canBeUnpublished?: boolean }[] }, + version: string +) { + return dependency.releases.find( + (release: { version: string }) => release.version === version + ); } describe('api/npm', () => { @@ -166,7 +172,7 @@ describe('api/npm', () => { nock('https://registry.npmjs.org') .get('/foobar') .reply(200, presetPackage); - const res = await npm.getPreset('foobar', 'default'); + const res = await npm.getPreset('foobar'); expect(res).toMatchSnapshot(); }); it('should parse repo url', async () => { diff --git a/test/datasource/nuget.spec.js b/test/datasource/nuget.spec.ts similarity index 98% rename from test/datasource/nuget.spec.js rename to test/datasource/nuget.spec.ts index f50944eee8947450c54527a628b8030943f0021b..efca574cca48b3f6586cee81429a34cd06e57bb2 100644 --- a/test/datasource/nuget.spec.js +++ b/test/datasource/nuget.spec.ts @@ -1,6 +1,6 @@ -const fs = require('fs'); -const got = require('../../lib/util/got'); -const datasource = require('../../lib/datasource'); +import fs from 'fs'; +import got from '../../lib/util/got'; +import * as datasource from '../../lib/datasource'; jest.mock('../../lib/util/got'); jest.mock('../../lib/util/host-rules'); diff --git a/test/datasource/orb.spec.js b/test/datasource/orb.spec.ts similarity index 96% rename from test/datasource/orb.spec.js rename to test/datasource/orb.spec.ts index 18cc716f030eba36a575db786e50471c07772913..4db9ad0bf93cb1ba348a386e09fe77d8210c226f 100644 --- a/test/datasource/orb.spec.js +++ b/test/datasource/orb.spec.ts @@ -1,8 +1,10 @@ -const got = require('../../lib/util/got'); -const datasource = require('../../lib/datasource'); +import _got from '../../lib/util/got'; +import * as datasource from '../../lib/datasource'; jest.mock('../../lib/util/got'); +const got: any = _got; + const orbData = { data: { orb: { diff --git a/test/datasource/packagist.spec.js b/test/datasource/packagist.spec.ts similarity index 94% rename from test/datasource/packagist.spec.js rename to test/datasource/packagist.spec.ts index 33012d34b352738eb391d6e1105172dad772af65..bd1e968aae11afc152262b040d437b87d7b2e09e 100644 --- a/test/datasource/packagist.spec.js +++ b/test/datasource/packagist.spec.ts @@ -1,27 +1,27 @@ -const fs = require('fs'); -const got = require('../../lib/util/got'); -const datasource = require('../../lib/datasource'); -const hostRules = require('../../lib/util/host-rules'); +import fs from 'fs'; +import _got from '../../lib/util/got'; +import * as datasource from '../../lib/datasource'; +import * as _hostRules from '../../lib/util/host-rules'; jest.mock('../../lib/util/got'); jest.mock('../../lib/util/host-rules'); -/** @type any */ -const includesJson = fs.readFileSync( +const got = _got; +const hostRules = _hostRules; + +const includesJson: any = fs.readFileSync( 'test/datasource/packagist/_fixtures/includes.json' ); -/** @type any */ -const beytJson = fs.readFileSync( +const beytJson: any = fs.readFileSync( 'test/datasource/packagist/_fixtures/1beyt.json' ); -/** @type any */ -const mailchimpJson = fs.readFileSync( +const mailchimpJson: any = fs.readFileSync( 'test/datasource/packagist/_fixtures/mailchimp-api.json' ); describe('datasource/packagist', () => { describe('getPkgReleases', () => { - let config; + let config: datasource.PkgReleaseConfig; beforeEach(() => { jest.resetAllMocks(); hostRules.find = jest.fn(input => input); diff --git a/test/datasource/pypi.spec.js b/test/datasource/pypi.spec.ts similarity index 97% rename from test/datasource/pypi.spec.js rename to test/datasource/pypi.spec.ts index dbb8f1e6642719c4cf3f46768c0af4dd537ecb6f..9c360672797a30e54d0ac3bf161a57b62984203e 100644 --- a/test/datasource/pypi.spec.js +++ b/test/datasource/pypi.spec.ts @@ -1,11 +1,10 @@ -const fs = require('fs'); -const got = require('../../lib/util/got'); -const datasource = require('../../lib/datasource'); +import fs from 'fs'; +import got from '../../lib/util/got'; +import * as datasource from '../../lib/datasource'; jest.mock('../../lib/util/got'); -/** @type any */ -const res1 = fs.readFileSync( +const res1: any = fs.readFileSync( 'test/datasource/pypi/_fixtures/azure-cli-monitor.json' ); const htmlResponse = fs.readFileSync( diff --git a/test/datasource/ruby-version.spec.js b/test/datasource/ruby-version.spec.ts similarity index 85% rename from test/datasource/ruby-version.spec.js rename to test/datasource/ruby-version.spec.ts index fee67efab3c99f756b2a0421d43845c39cd07e99..c4235f0e21309f09626e6190d8d9fc3af9f7be23 100644 --- a/test/datasource/ruby-version.spec.js +++ b/test/datasource/ruby-version.spec.ts @@ -1,9 +1,11 @@ -const fs = require('fs'); -const got = require('../../lib/util/got'); -const { getPkgReleases } = require('../../lib/datasource/ruby-version'); +import fs from 'fs'; +import _got from '../../lib/util/got'; +import { getPkgReleases } from '../../lib/datasource/ruby-version'; jest.mock('../../lib/util/got'); +const got: any = _got; + const rubyReleasesHtml = fs.readFileSync( 'test/datasource/ruby-version/_fixtures/releases.html', 'utf8' diff --git a/test/datasource/rubygems/__snapshots__/index.spec.js.snap b/test/datasource/rubygems/__snapshots__/index.spec.ts.snap similarity index 100% rename from test/datasource/rubygems/__snapshots__/index.spec.js.snap rename to test/datasource/rubygems/__snapshots__/index.spec.ts.snap diff --git a/test/datasource/rubygems/index.spec.js b/test/datasource/rubygems/index.spec.ts similarity index 93% rename from test/datasource/rubygems/index.spec.js rename to test/datasource/rubygems/index.spec.ts index 9e61afc139c444f5a35671851b61d2ed6dac2414..ceea2878168efc77f97a0364bbea6d6547ac43ee 100644 --- a/test/datasource/rubygems/index.spec.js +++ b/test/datasource/rubygems/index.spec.ts @@ -1,7 +1,7 @@ -const got = require('../../../lib/util/got'); -const railsInfo = require('./_fixtures/rails/info.json'); -const railsVersions = require('./_fixtures/rails/versions.json'); -const rubygems = require('../../../lib/datasource/rubygems/index.js'); +import got from '../../../lib/util/got'; +import railsInfo from './_fixtures/rails/info.json'; +import railsVersions from './_fixtures/rails/versions.json'; +import * as rubygems from '../../../lib/datasource/rubygems'; const rubygemsOrgVersions = `created_at: 2017-03-27T04:38:13+00:00 --- diff --git a/test/datasource/rubygems/retriable.spec.js b/test/datasource/rubygems/retriable.spec.ts similarity index 81% rename from test/datasource/rubygems/retriable.spec.js rename to test/datasource/rubygems/retriable.spec.ts index 27cc770a8f55ad0ccf8bfd752ff39845a652f97d..463fe41477ff5b1f5b832877b07747c6cf1c5216 100644 --- a/test/datasource/rubygems/retriable.spec.js +++ b/test/datasource/rubygems/retriable.spec.ts @@ -1,4 +1,4 @@ -const retriable = require('../../../lib/datasource/rubygems/retriable.js'); +import retriable from '../../../lib/datasource/rubygems/retriable'; describe('datasource/rubygems/retriable', () => { const { RENOVATE_RUBYGEMS_RETRY_DELAY_STEP } = process.env; @@ -8,21 +8,21 @@ describe('datasource/rubygems/retriable', () => { }); it('returns 0 when numberOfRetries equals 0', () => { - expect(retriable(0)()).toEqual(0); + expect(retriable(0)(null, null)).toEqual(0); }); it('returns retry after header + 1 second if request is banned', () => { expect( retriable(1)(null, { statusCode: 429, - headers: { 'retry-after': 5 }, + headers: { 'retry-after': '5' }, }) ).toEqual(6); expect( retriable(1)(null, { statusCode: 503, - headers: { 'retry-after': 9 }, + headers: { 'retry-after': '9' }, }) ).toEqual(10); }); diff --git a/test/datasource/sbt/__snapshots__/index.spec.js.snap b/test/datasource/sbt/__snapshots__/index.spec.ts.snap similarity index 100% rename from test/datasource/sbt/__snapshots__/index.spec.js.snap rename to test/datasource/sbt/__snapshots__/index.spec.ts.snap diff --git a/test/datasource/sbt/index.spec.js b/test/datasource/sbt/index.spec.ts similarity index 95% rename from test/datasource/sbt/index.spec.js rename to test/datasource/sbt/index.spec.ts index df354dd29d7fe3e984f70dafbc46b965a3a78cdd..913a4167b323f8c8e79b70ec3f38e3dfd6518a0e 100644 --- a/test/datasource/sbt/index.spec.js +++ b/test/datasource/sbt/index.spec.ts @@ -1,14 +1,12 @@ -const path = require('path'); -const fs = require('fs'); -const nock = require('nock'); - -const { getPkgReleases } = require('../../../lib/datasource/sbt'); - -const { DEFAULT_MAVEN_REPO } = require('../../../lib/manager/maven/extract'); -const { +import path from 'path'; +import fs from 'fs'; +import nock from 'nock'; +import { getPkgReleases } from '../../../lib/datasource/sbt'; +import { DEFAULT_MAVEN_REPO } from '../../../lib/manager/maven/extract'; +import { parseIndexDir, SBT_PLUGINS_REPO, -} = require('../../../lib/datasource/sbt/util'); +} from '../../../lib/datasource/sbt/util'; const mavenIndexHtml = fs.readFileSync( path.resolve(__dirname, `./_fixtures/maven-index.html`), diff --git a/test/datasource/terraform.spec.js b/test/datasource/terraform.spec.ts similarity index 92% rename from test/datasource/terraform.spec.js rename to test/datasource/terraform.spec.ts index 247cd121b70120d96ad6880c385d374797bbe9d4..7cb4611edd35f5b4e8904ce281c5e9043b2ac00d 100644 --- a/test/datasource/terraform.spec.js +++ b/test/datasource/terraform.spec.ts @@ -1,10 +1,10 @@ -const fs = require('fs'); -const got = require('../../lib/util/got'); -const datasource = require('../../lib/datasource'); +import fs from 'fs'; +import got from '../../lib/util/got'; +import * as datasource from '../../lib/datasource'; jest.mock('../../lib/util/got'); -/** @type any */ -const consulData = fs.readFileSync( + +const consulData: any = fs.readFileSync( 'test/datasource/terraform/_fixtures/registry-consul.json' ); diff --git a/yarn.lock b/yarn.lock index b9f252e7ccc80e3c98a6bcf5d61d0ecc4ed46544..c5bbeb120b418ec3254e18a0f17d276d547dd06a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1145,6 +1145,11 @@ "@types/tough-cookie" "*" form-data "^2.5.0" +"@types/ini@1.3.30": + version "1.3.30" + resolved "https://registry.yarnpkg.com/@types/ini/-/ini-1.3.30.tgz#d1485459c9fad84e937414b832a2adb649eab379" + integrity sha512-2+iF8zPSbpU83UKE+PNd4r/MhwNAdyGpk3H+VMgEH3EhjFZq1kouLgRoZrmIcmoGX97xFvqdS44DkICR5Nz3tQ== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -1197,6 +1202,13 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/nock@10.0.3": + version "10.0.3" + resolved "https://registry.yarnpkg.com/@types/nock/-/nock-10.0.3.tgz#dab1d18ffbccfbf2db811dab9584304eeb6e1c4c" + integrity sha512-OthuN+2FuzfZO3yONJ/QVjKmLEuRagS9TV9lEId+WHL9KhftYG+/2z+pxlr0UgVVXSpVD8woie/3fzQn8ft/Ow== + dependencies: + "@types/node" "*" + "@types/node@*": version "12.6.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.2.tgz#a5ccec6abb6060d5f20d256fb03ed743e9774999" @@ -1217,6 +1229,11 @@ resolved "https://registry.yarnpkg.com/@types/parse-link-header/-/parse-link-header-1.0.0.tgz#69f059e40a0fa93dc2e095d4142395ae6adc5d7a" integrity sha512-fCA3btjE7QFeRLfcD0Sjg+6/CnmC66HpMBoRfRzd2raTaWMJV21CCZ0LO8MOqf8onl5n0EPfjq4zDhbyX8SVwA== +"@types/registry-auth-token@3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@types/registry-auth-token/-/registry-auth-token-3.3.0.tgz#bfb57ed386d84749c982ec20c804ac119382b285" + integrity sha512-HEnnGNRFbVXwqLV1xzQTY4zElLEn85mHAXm9LbAut0+gQI6LafAhW0qmCLuBcm5QtekXQWXFGchi0ZjTdX6Upw== + "@types/retry@^0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" @@ -1250,6 +1267,11 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d" integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg== +"@types/validator@10.11.2": + version "10.11.2" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-10.11.2.tgz#48b60ca2cca927081f37a1ad1de3e25d04abc9f0" + integrity sha512-k/ju1RsdP5ACFUWebqsyEy0avP5uNJCs2p3pmTHzOZdd4gMSAJTq7iUEHFY3tt3emBrPTm6oGvfZ4SzcqOgLPQ== + "@types/xmldoc@1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@types/xmldoc/-/xmldoc-1.1.4.tgz#5867d4e29739719c633bf16413c5a4a4c1c3c802"