From bdd13554ff4cbfb26a0a8a7781c3fac0380d5ce4 Mon Sep 17 00:00:00 2001 From: Shane McLaughlin Date: Mon, 5 Dec 2022 09:05:21 -0600 Subject: [PATCH] feat: remove qq and parallelize build/pack/promote (#1035) * feat: remove qq and parallelize build/promote * chore: reformat pjson * refactor: remove redundant objects * refactor: pr feedback * feat: publishes debian packages with qq * test: integration tests in parallel * test: restore debian integration tests * chore: remove ds_store * chore: ignore dsStore * chore: ignore dist * Update src/commands/upload/deb.ts Co-authored-by: Rodrigo Espinosa de los Monteros <1084688+RodEsp@users.noreply.github.com> * fix: cwd on pretarball * refactor: pr feedback * test: integration test for tarball promote * test: revert unnecessary trims * perf: optional xz hashes in parallel * chore: fix pjson format * refactor: remove unused conditional * fix: osslsign command requires "sign" Co-authored-by: Rodrigo Espinosa de los Monteros <1084688+RodEsp@users.noreply.github.com> --- .gitignore | 3 + .idea/codeStyles/Project.xml | 43 ++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/git_toolbox_prj.xml | 15 + .idea/inspectionProfiles/Project_Default.xml | 7 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/oclif.iml | 15 + .idea/vcs.xml | 6 + .idea/workspace.xml | 443 +++++++++++++++ .vscode/launch.json | 15 + package.json | 10 +- src/aws.ts | 4 +- src/commands/pack/deb.ts | 80 ++- src/commands/pack/macos.ts | 44 +- src/commands/pack/tarballs.ts | 3 - src/commands/pack/win.ts | 96 ++-- src/commands/promote.ts | 208 ++++---- src/commands/upload/deb.ts | 43 +- src/commands/upload/macos.ts | 8 +- src/commands/upload/tarballs.ts | 43 +- src/commands/upload/win.ts | 11 +- src/log.ts | 4 +- src/tarballs/bin.ts | 16 +- src/tarballs/build.ts | 112 ++-- src/tarballs/config.ts | 15 +- src/tarballs/node.ts | 56 +- src/util.ts | 22 + test/helpers/helper.ts | 6 +- test/integration/deb.test.ts | 34 +- test/integration/macos.test.ts | 23 +- test/integration/publish.test.ts | 125 +++-- test/integration/win.test.ts | 26 +- test/release.key | 38 +- tsconfig.json | 1 + yarn.lock | 534 +++++++------------ 36 files changed, 1310 insertions(+), 816 deletions(-) create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/git_toolbox_prj.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/oclif.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 .vscode/launch.json diff --git a/.gitignore b/.gitignore index 20218a0e5..6865c2117 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ /coverage /coverage.lcov /lib +/dist /node_modules /tmp +/test/tmp package-lock.json +**/.DS_Store diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 000000000..111a1245c --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 000000000..79ee123c2 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 000000000..b3820067b --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000..9c6941105 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 000000000..cd8ed3153 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..8ffa5adac --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/oclif.iml b/.idea/oclif.iml new file mode 100644 index 000000000..6e7c09c28 --- /dev/null +++ b/.idea/oclif.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..94a25f7f4 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 000000000..644481d05 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,443 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1664999434977 + + + 1665082218003 + + + 1668639620057 + + + 1668640672677 + + + 1668640821949 + + + 1668642998652 + + + 1668643102478 + + + 1668647675346 + + + 1668661654334 + + + 1668662793744 + + + 1668663159217 + + + 1668663288888 + + + 1668663369743 + + + 1668663500625 + + + 1668663814751 + + + 1668664081202 + + + 1668664133748 + + + 1668664212337 + + + 1668664274146 + + + 1668666490346 + + + 1668666646768 + + + 1668666755135 + + + 1668666843191 + + + 1668667210157 + + + 1668667339021 + + + 1668702333835 + + + 1668704681310 + + + 1668704765883 + + + 1668705008413 + + + 1668705294119 + + + 1669103492888 + + + 1669103711213 + + + 1669103740471 + + + 1669759721082 + + + 1669762371219 + + + 1669762464672 + + + 1669763109200 + + + 1669766764674 + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..fab6ce13e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "attach", + "name": "Attach", + "port": 9229, + "skipFiles": ["/**"] + } + ] +} diff --git a/package.json b/package.json index 218efa3b0..4ebd97255 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,9 @@ "find-yarn-workspace-root": "^2.0.0", "fs-extra": "^8.1", "github-slugger": "^1.5.0", + "got": "^11", "lodash": "^4.17.21", "normalize-package-data": "^3.0.3", - "qqjs": "^0.3.11", "semver": "^7.3.8", "tslib": "^2.3.1", "yeoman-environment": "^3.11.1", @@ -62,12 +62,10 @@ "typescript": "4.5.5" }, "resolutions": { - "colors": "1.4.0", - "@oclif/core": "^1.16.1" + "colors": "1.4.0" }, "overrides": { - "colors": "1.4.0", - "@oclif/core": "^1.16.1" + "colors": "1.4.0" }, "engines": { "node": ">=12.0.0" @@ -103,7 +101,7 @@ "debounce": 60 }, "node": { - "version": "12.12.0" + "version": "16.13.2" }, "s3": { "bucket": "dfc-data-production", diff --git a/src/aws.ts b/src/aws.ts index 1016b0f14..f3926b5f6 100644 --- a/src/aws.ts +++ b/src/aws.ts @@ -1,9 +1,9 @@ import * as CloudFront from 'aws-sdk/clients/cloudfront' import * as S3 from 'aws-sdk/clients/s3' import * as fs from 'fs-extra' -import * as qq from 'qqjs' import {debug as Debug, log} from './log' +import {prettifyPaths} from './util' const debug = Debug.new('aws') @@ -65,7 +65,7 @@ export default { get s3() { return { uploadFile: (local: string, options: S3.Types.PutObjectRequest) => new Promise((resolve, reject) => { - log('s3:uploadFile', qq.prettifyPaths(local), `s3://${options.Bucket}/${options.Key}`) + log('s3:uploadFile', prettifyPaths(local), `s3://${options.Bucket}/${options.Key}`) options.Body = fs.createReadStream(local) aws.s3.upload(options, err => { if (err) reject(err) diff --git a/src/commands/pack/deb.ts b/src/commands/pack/deb.ts index 34c386024..dd7001e61 100644 --- a/src/commands/pack/deb.ts +++ b/src/commands/pack/deb.ts @@ -1,11 +1,14 @@ import {Command, Flags} from '@oclif/core' import {Interfaces} from '@oclif/core' - +import * as fs from 'fs-extra' import * as _ from 'lodash' -import * as qq from 'qqjs' - +import * as path from 'path' import * as Tarballs from '../../tarballs' import {templateShortKey, debVersion, debArch} from '../../upload-util' +import {exec as execSync} from 'child_process' +import {promisify} from 'node:util' + +const exec = promisify(execSync) const scripts = { /* eslint-disable no-useless-escape */ @@ -59,45 +62,64 @@ export default class PackDeb extends Command { const {flags} = await this.parse(PackDeb) const buildConfig = await Tarballs.buildConfig(flags.root) const {config} = buildConfig - await Tarballs.build(buildConfig, {platform: 'linux', pack: false, tarball: flags.tarball}) + await Tarballs.build(buildConfig, {platform: 'linux', pack: false, tarball: flags.tarball, parallel: true}) const dist = buildConfig.dist('deb') - await qq.emptyDir(dist) + await fs.emptyDir(dist) const build = async (arch: Interfaces.ArchTypes) => { + this.log(`building debian / ${arch}`) const target: { platform: 'linux'; arch: Interfaces.ArchTypes} = {platform: 'linux', arch} const versionedDebBase = templateShortKey('deb', {bin: config.bin, versionShaRevision: debVersion(buildConfig), arch: debArch(arch) as any}) - const workspace = qq.join(buildConfig.tmp, 'apt', versionedDebBase.replace('.deb', '.apt')) - await qq.rm(workspace) - await qq.mkdirp([workspace, 'DEBIAN']) - await qq.mkdirp([workspace, 'usr/bin']) - await qq.mkdirp([workspace, 'usr/lib']) - await qq.mv(buildConfig.workspace(target), [workspace, 'usr/lib', config.dirname]) - await qq.write([workspace, 'usr/lib', config.dirname, 'bin', config.bin], scripts.bin(config)) - await qq.write([workspace, 'DEBIAN/control'], scripts.control(buildConfig, debArch(arch))) - await qq.chmod([workspace, 'usr/lib', config.dirname, 'bin', config.bin], 0o755) - await qq.x(`ln -s "../lib/${config.dirname}/bin/${config.bin}" "${workspace}/usr/bin/${config.bin}"`) - await qq.x(`sudo chown -R root "${workspace}"`) - await qq.x(`sudo chgrp -R root "${workspace}"`) - await qq.x(`dpkg --build "${workspace}" "${qq.join(dist, versionedDebBase)}"`) + const workspace = path.join(buildConfig.tmp, 'apt', versionedDebBase.replace('.deb', '.apt')) + await fs.remove(workspace) + await Promise.all([ + fs.promises.mkdir(path.join(workspace, 'DEBIAN'), {recursive: true}), + fs.promises.mkdir(path.join(workspace, 'usr', 'bin'), {recursive: true}), + ]) + await fs.copy(buildConfig.workspace(target), path.join(workspace, 'usr', 'lib', config.dirname)) + await Promise.all([ + // usr/lib/oclif/bin/oclif (the executable) + fs.promises.writeFile(path.join(workspace, 'usr', 'lib', config.dirname, 'bin', config.bin), scripts.bin(config), {mode: 0o755}), + fs.promises.writeFile(path.join(workspace, 'DEBIAN', 'control'), scripts.control(buildConfig, debArch(arch))), + ]) + // symlink usr/bin/oclif points to usr/lib/oclif/bin/oclif + await exec(`ln -s "${path.join('..', 'lib', config.dirname, 'bin', config.bin)}" "${config.bin}"`, {cwd: path.join(workspace, 'usr', 'bin')}) + await exec(`sudo chown -R root "${workspace}"`) + await exec(`sudo chgrp -R root "${workspace}"`) + await exec(`dpkg --build "${workspace}" "${path.join(dist, versionedDebBase)}"`) + this.log(`finished building debian / ${arch}`) } const arches = _.uniq(buildConfig.targets .filter(t => t.platform === 'linux') .map(t => t.arch)) - // eslint-disable-next-line no-await-in-loop - for (const a of arches) await build(a) + await Promise.all(arches.map(a => build(a))) + + await exec('apt-ftparchive packages . > Packages', {cwd: dist}) + this.log('debian packages created') + await Promise.all([ + exec('gzip -c Packages > Packages.gz', {cwd: dist}), + exec('bzip2 -k Packages', {cwd: dist}), + exec('xz -k Packages', {cwd: dist}), + packForFTP(buildConfig, config, dist), + ]) + + this.log('debian packages archived') - await qq.x('apt-ftparchive packages . > Packages', {cwd: dist}) - await qq.x('gzip -c Packages > Packages.gz', {cwd: dist}) - await qq.x('bzip2 -k Packages', {cwd: dist}) - await qq.x('xz -k Packages', {cwd: dist}) - const ftparchive = qq.join(buildConfig.tmp, 'apt', 'apt-ftparchive.conf') - await qq.write(ftparchive, scripts.ftparchive(config)) - await qq.x(`apt-ftparchive -c "${ftparchive}" release . > Release`, {cwd: dist}) const gpgKey = config.scopedEnvVar('DEB_KEY') if (gpgKey) { - await qq.x(`gpg --digest-algo SHA512 --clearsign -u ${gpgKey} -o InRelease Release`, {cwd: dist}) - await qq.x(`gpg --digest-algo SHA512 -abs -u ${gpgKey} -o Release.gpg Release`, {cwd: dist}) + this.log('adding gpg signatures to Release') + await exec(`gpg --digest-algo SHA512 --clearsign -u ${gpgKey} -o InRelease Release`, {cwd: dist}) + await exec(`gpg --digest-algo SHA512 -abs -u ${gpgKey} -o Release.gpg Release`, {cwd: dist}) } + + this.log('debian packing complete') } } +async function packForFTP(buildConfig: Tarballs.BuildConfig, config: Interfaces.Config, dist: string) { + const ftparchive = path.join(buildConfig.tmp, 'apt', 'apt-ftparchive.conf') + await fs.promises.mkdir(path.basename(ftparchive), {recursive: true}) + await fs.writeFile(ftparchive, scripts.ftparchive(config)) + await exec(`apt-ftparchive -c "${ftparchive}" release . > Release`, {cwd: dist}) +} + diff --git a/src/commands/pack/macos.ts b/src/commands/pack/macos.ts index 29f9e4714..975c321e4 100644 --- a/src/commands/pack/macos.ts +++ b/src/commands/pack/macos.ts @@ -1,14 +1,16 @@ import * as path from 'path' import * as _ from 'lodash' -import * as qq from 'qqjs' - +import * as fs from 'fs-extra' import {Command, Flags} from '@oclif/core' import {Interfaces} from '@oclif/core' import * as Tarballs from '../../tarballs' import {templateShortKey} from '../../upload-util' +import {exec as execSync} from 'child_process' +import {promisify} from 'node:util' +const exec = promisify(execSync) type OclifConfig = { macos?: { identifier?: string; @@ -77,7 +79,7 @@ while [ "$1" != "-y" ]; do done echo "Application uninstalling process started" -# remove link to shorcut file +# remove link to shortcut file find "/usr/local/bin/" -name "${config.bin}" | xargs rm ${additionalCLI ? `find "/usr/local/bin/" -name "${additionalCLI}" | xargs rm` : ''} if [ $? -eq 0 ] @@ -156,30 +158,33 @@ the CLI should already exist in a directory named after the CLI that is the root if (!c.macos.identifier) this.error('package.json must have oclif.macos.identifier set') const macos = c.macos const packageIdentifier = macos.identifier - await Tarballs.build(buildConfig, {platform: 'darwin', pack: false, tarball: flags.tarball}) - const scriptsDir = qq.join(buildConfig.tmp, 'macos/scripts') - await qq.emptyDir(buildConfig.dist('macos')) - const noBundleConfigurationPath = qq.join(buildConfig.tmp, 'macos/no-bundle.plist') + await Tarballs.build(buildConfig, {platform: 'darwin', pack: false, tarball: flags.tarball, parallel: true}) + const scriptsDir = path.join(buildConfig.tmp, 'macos/scripts') + await fs.emptyDir(buildConfig.dist('macos')) + const noBundleConfigurationPath = path.join(buildConfig.tmp, 'macos', 'no-bundle.plist') const build = async (arch: Interfaces.ArchTypes) => { const templateKey = templateShortKey('macos', {bin: config.bin, version: config.version, sha: buildConfig.gitSha, arch}) const dist = buildConfig.dist(`macos/${templateKey}`) const rootDir = buildConfig.workspace({platform: 'darwin', arch}) const writeNoBundleConfiguration = async () => { - await qq.write(noBundleConfigurationPath, noBundleConfiguration) - await qq.chmod(noBundleConfigurationPath, 0o755) + await fs.mkdir(path.dirname(noBundleConfigurationPath), {recursive: true}) + await fs.writeFile(noBundleConfigurationPath, noBundleConfiguration, {mode: 0o755}) } + const writeScript = async (script: 'preinstall' | 'postinstall' | 'uninstall') => { - const path = script === 'uninstall' ? [rootDir, 'bin'] : [scriptsDir] - path.push(script) - await qq.write(path, scripts[script](config, flags['additional-cli'])) - await qq.chmod(path, 0o755) + const scriptLocation = script === 'uninstall' ? [rootDir, 'bin'] : [scriptsDir] + scriptLocation.push(script) + await fs.mkdir(path.dirname(path.join(...scriptLocation)), {recursive: true}) + await fs.writeFile(path.join(...scriptLocation), scripts[script](config, flags['additional-cli']), {mode: 0o755}) } - await writeNoBundleConfiguration(); - await writeScript('preinstall') - await writeScript('postinstall') - await writeScript('uninstall') + await Promise.all([ + writeNoBundleConfiguration(), + writeScript('preinstall'), + writeScript('postinstall'), + writeScript('uninstall'), + ]) /* eslint-disable array-element-newline */ const args = [ '--root', rootDir, @@ -195,13 +200,12 @@ the CLI should already exist in a directory named after the CLI that is the root } else this.debug('Skipping macOS pkg signing') if (process.env.OSX_KEYCHAIN) args.push('--keychain', process.env.OSX_KEYCHAIN) args.push(dist) - await qq.x('pkgbuild', args as string[]) + await exec(`pkgbuild ${args.join(' ')}`) } const arches = _.uniq(buildConfig.targets .filter(t => t.platform === 'darwin') .map(t => t.arch)) - // eslint-disable-next-line no-await-in-loop - for (const a of arches) await build(a) + await Promise.all(arches.map(a => build(a))) } } diff --git a/src/commands/pack/tarballs.ts b/src/commands/pack/tarballs.ts index a8374ae8d..8121615c5 100644 --- a/src/commands/pack/tarballs.ts +++ b/src/commands/pack/tarballs.ts @@ -1,5 +1,4 @@ import {Command, Flags} from '@oclif/core' -import * as qq from 'qqjs' import * as Tarballs from '../../tarballs' @@ -18,7 +17,6 @@ This can be used to create oclif CLIs that use the system node or that come prel } async run(): Promise { - const prevCwd = qq.cwd() if (process.platform === 'win32') throw new Error('pack does not function on windows') const {flags} = await this.parse(PackTarballs) const buildConfig = await Tarballs.buildConfig(flags.root, {xz: flags.xz, targets: flags?.targets?.split(',')}) @@ -30,6 +28,5 @@ This can be used to create oclif CLIs that use the system node or that come prel tarball: flags.tarball, parallel: flags.parallel, }) - qq.cd(prevCwd) } } diff --git a/src/commands/pack/win.ts b/src/commands/pack/win.ts index 3f5e21df9..23b403291 100644 --- a/src/commands/pack/win.ts +++ b/src/commands/pack/win.ts @@ -1,10 +1,13 @@ import {Command, Flags} from '@oclif/core' import {Interfaces} from '@oclif/core' - -import * as qq from 'qqjs' - +import * as path from 'path' +import * as fs from 'fs-extra' import * as Tarballs from '../../tarballs' import {templateShortKey} from '../../upload-util' +import {exec as execSync} from 'child_process' +import {promisify} from 'node:util' + +const exec = promisify(execSync) const scripts = { /* eslint-disable no-useless-escape */ @@ -226,63 +229,40 @@ the CLI should already exist in a directory named after the CLI that is the root const {flags} = await this.parse(PackWin) const buildConfig = await Tarballs.buildConfig(flags.root) const {config} = buildConfig - await Tarballs.build(buildConfig, {platform: 'win32', pack: false, tarball: flags.tarball}) + await Tarballs.build(buildConfig, {platform: 'win32', pack: false, tarball: flags.tarball, parallel: true}) const arches = buildConfig.targets.filter(t => t.platform === 'win32').map(t => t.arch) - for (const arch of arches) { - const installerBase = qq.join(buildConfig.tmp, `windows-${arch}-installer`) - // eslint-disable-next-line no-await-in-loop - await qq.write([installerBase, `bin/${config.bin}.cmd`], scripts.cmd(config)) - // eslint-disable-next-line no-await-in-loop - await qq.write([installerBase, `bin/${config.bin}`], scripts.sh(config)) - - if (flags['additional-cli']) { - await qq.write([installerBase, `bin/${flags['additional-cli']}.cmd`], scripts.cmd(config, flags['additional-cli'])) // eslint-disable-line no-await-in-loop - await qq.write([installerBase, `bin/${flags['additional-cli']}`], scripts.sh({bin: flags['additional-cli']} as Interfaces.Config)) // eslint-disable-line no-await-in-loop - } - - // eslint-disable-next-line no-await-in-loop - await qq.write([installerBase, `${config.bin}.nsi`], scripts.nsis(config, arch)) - // eslint-disable-next-line no-await-in-loop - await qq.mv(buildConfig.workspace({platform: 'win32', arch}), [installerBase, 'client']) - // eslint-disable-next-line no-await-in-loop - await qq.x(`makensis ${installerBase}/${config.bin}.nsi | grep -v "\\[compress\\]" | grep -v "^File: Descending to"`) + await Promise.all(arches.map(async arch => { + const installerBase = path.join(buildConfig.tmp, `windows-${arch}-installer`) + await fs.promises.rm(installerBase, {recursive: true, force: true}) + await fs.promises.mkdir(path.join(installerBase, 'bin'), {recursive: true}) + + await Promise.all([ + fs.writeFile(path.join(installerBase, 'bin', `${config.bin}.cmd`), scripts.cmd(config)), + fs.writeFile(path.join(installerBase, 'bin', `${config.bin}`), scripts.sh(config)), + fs.writeFile(path.join(installerBase, `${config.bin}.nsi`), scripts.nsis(config, arch)), + ].concat(flags['additional-cli'] ? [ + fs.writeFile(path.join(installerBase, 'bin', `${flags['additional-cli']}.cmd`), scripts.cmd(config, flags['additional-cli'])), + fs.writeFile(path.join(installerBase, 'bin', `${flags['additional-cli']}`), scripts.sh({bin: flags['additional-cli']} as Interfaces.Config)), + ] : [])) + + await fs.move(buildConfig.workspace({platform: 'win32', arch}), path.join(installerBase, 'client')) + await exec(`makensis ${installerBase}/${config.bin}.nsi | grep -v "\\[compress\\]" | grep -v "^File: Descending to"`) const templateKey = templateShortKey('win32', {bin: config.bin, version: config.version, sha: buildConfig.gitSha, arch}) const o = buildConfig.dist(`win32/${templateKey}`) - // eslint-disable-next-line no-await-in-loop - await qq.mv([installerBase, 'installer.exe'], o) + await fs.move(path.join(installerBase, 'installer.exe'), o) const windows = (config.pjson.oclif as any).windows as {name: string; keypath: string; homepage?: string} if (windows && windows.name && windows.keypath) { - const buildLocationUnsigned = o.replace(`${arch}.exe`, `${arch}-unsigned.exe`) - // eslint-disable-next-line no-await-in-loop - await qq.mv(o, buildLocationUnsigned) - - const pass = config.scopedEnvVar('WINDOWS_SIGNING_PASS') - if (!pass) { - throw new Error(`${config.scopedEnvVarKey('WINDOWS_SIGNING_PASS')} not set in the environment`) - } - - /* eslint-disable array-element-newline */ - const args = [ - '-pkcs12', windows.keypath, - '-pass', pass, - '-n', windows.name, - '-i', windows.homepage || config.pjson.homepage, - '-h', 'sha512', - '-in', buildLocationUnsigned, - '-out', o, - ] - // eslint-disable-next-line no-await-in-loop - await qq.x('osslsigncode', args) + await signWindows(o, arch, config, windows) } else this.debug('Skipping windows exe signing') this.log(`built ${o}`) - } + })) } private async checkForNSIS() { try { - await qq.x('makensis', {stdio: [0, null, 2]}) + await exec('makensis') } catch (error: any) { if (error.code === 1) return if (error.code === 127) this.error('install makensis') @@ -290,3 +270,25 @@ the CLI should already exist in a directory named after the CLI that is the root } } } +async function signWindows(o: string, arch: string, config: Interfaces.Config, windows: { name: string; keypath: string; homepage?: string | undefined }) { + const buildLocationUnsigned = o.replace(`${arch}.exe`, `${arch}-unsigned.exe`) + await fs.move(o, buildLocationUnsigned) + + const pass = config.scopedEnvVar('WINDOWS_SIGNING_PASS') + if (!pass) { + throw new Error(`${config.scopedEnvVarKey('WINDOWS_SIGNING_PASS')} not set in the environment`) + } + + /* eslint-disable array-element-newline */ + const args = [ + '-pkcs12', windows.keypath, + '-pass', pass, + '-n', `"${windows.name}"`, + '-i', windows.homepage || config.pjson.homepage, + '-h', 'sha512', + '-in', buildLocationUnsigned, + '-out', o, + ] + await exec(`osslsigncode sign ${args}.join(' ')`) +} + diff --git a/src/commands/promote.ts b/src/commands/promote.ts index 5cbca59c2..7a5ca4035 100644 --- a/src/commands/promote.ts +++ b/src/commands/promote.ts @@ -28,23 +28,28 @@ export default class Promote extends Command { async run(): Promise { const {flags} = await this.parse(Promote) - const maxAge = `max-age=${flags['max-age']}` const buildConfig = await Tarballs.buildConfig(flags.root, {targets: flags?.targets?.split(',')}) const {s3Config, config} = buildConfig const indexDefaults = { version: flags.version, s3Config, - maxAge, + maxAge: `max-age=${flags['max-age']}`, } if (!s3Config.bucket) this.error('Cannot determine S3 bucket for promotion') - + const awsDefaults = { + Bucket: s3Config.bucket, + ACL: s3Config.acl ?? 'public-read', + MetadataDirective: 'REPLACE', + CacheControl: indexDefaults.maxAge, + } const cloudBucketCommitKey = (shortKey: string) => path.join(s3Config.bucket!, commitAWSDir(flags.version, flags.sha, s3Config), shortKey) const cloudChannelKey = (shortKey: string) => path.join(channelAWSDir(flags.channel, s3Config), shortKey) // copy tarballs manifests if (buildConfig.targets.length > 0) this.log(`Promoting buildmanifests & unversioned tarballs to ${flags.channel}`) - for (const target of buildConfig.targets) { + + const promoteManifest = async (target: typeof buildConfig.targets[number]) => { const manifest = templateShortKey('manifest', { arch: target.arch, bin: config.bin, @@ -52,21 +57,18 @@ export default class Promote extends Command { sha: flags.sha, version: flags.version, }) - const copySource = cloudBucketCommitKey(manifest) // strip version & sha so update/scripts can point to a static channel manifest const unversionedManifest = manifest.replace(`-v${flags.version}-${flags.sha}`, '') - const key = cloudChannelKey(unversionedManifest) - // eslint-disable-next-line no-await-in-loop await aws.s3.copyObject( { - Bucket: s3Config.bucket, - ACL: s3Config.acl || 'public-read', - CopySource: copySource, - Key: key, - CacheControl: maxAge, - MetadataDirective: 'REPLACE', + ...awsDefaults, + CopySource: cloudBucketCommitKey(manifest), + Key: cloudChannelKey(unversionedManifest), }, ) + } + + const promoteGzTarballs = async (target: typeof buildConfig.targets[number]) => { const versionedTarGzName = templateShortKey('versioned', '.tar.gz', { arch: target.arch, bin: config.bin, @@ -78,129 +80,127 @@ export default class Promote extends Command { // strip version & sha so update/scripts can point to a static channel tarball const unversionedTarGzName = versionedTarGzName.replace(`-v${flags.version}-${flags.sha}`, '') const unversionedTarGzKey = cloudChannelKey(unversionedTarGzName) - // eslint-disable-next-line no-await-in-loop - await aws.s3.copyObject( + await Promise.all([aws.s3.copyObject( { - Bucket: s3Config.bucket, - ACL: s3Config.acl || 'public-read', + ...awsDefaults, CopySource: versionedTarGzKey, Key: unversionedTarGzKey, - CacheControl: maxAge, - MetadataDirective: 'REPLACE', }, - ) + )].concat(flags.indexes ? [appendToIndex({...indexDefaults, originalUrl: versionedTarGzKey, filename: unversionedTarGzName})] : [])) + } - // eslint-disable-next-line no-await-in-loop - if (flags.indexes) await appendToIndex({...indexDefaults, originalUrl: versionedTarGzKey, filename: unversionedTarGzName}) - - if (flags.xz) { - const versionedTarXzName = templateShortKey('versioned', '.tar.xz', { - arch: target.arch, - bin: config.bin, - platform: target.platform, - sha: flags.sha, - version: flags.version, - }) - const versionedTarXzKey = cloudBucketCommitKey(versionedTarXzName) - // strip version & sha so update/scripts can point to a static channel tarball - const unversionedTarXzName = versionedTarXzName.replace(`-v${flags.version}-${flags.sha}`, '') - const unversionedTarXzKey = cloudChannelKey(unversionedTarXzName) - // eslint-disable-next-line no-await-in-loop - await aws.s3.copyObject( - { - Bucket: s3Config.bucket, - ACL: s3Config.acl || 'public-read', - CopySource: versionedTarXzKey, - Key: unversionedTarXzKey, - CacheControl: maxAge, - MetadataDirective: 'REPLACE', - }, - ) - // eslint-disable-next-line no-await-in-loop - if (flags.indexes) await appendToIndex({...indexDefaults, originalUrl: versionedTarXzKey, filename: unversionedTarXzName}) - } + const promoteXzTarballs = async (target: typeof buildConfig.targets[number]) => { + const versionedTarXzName = templateShortKey('versioned', '.tar.xz', { + arch: target.arch, + bin: config.bin, + platform: target.platform, + sha: flags.sha, + version: flags.version, + }) + const versionedTarXzKey = cloudBucketCommitKey(versionedTarXzName) + // strip version & sha so update/scripts can point to a static channel tarball + const unversionedTarXzName = versionedTarXzName.replace(`-v${flags.version}-${flags.sha}`, '') + const unversionedTarXzKey = cloudChannelKey(unversionedTarXzName) + await Promise.all([aws.s3.copyObject( + { + ...awsDefaults, + CopySource: versionedTarXzKey, + Key: unversionedTarXzKey, + }, + )].concat(flags.indexes ? [appendToIndex({...indexDefaults, originalUrl: versionedTarXzKey, filename: unversionedTarXzName})] : [])) } - // copy darwin pkg - if (flags.macos) { + const promoteMacInstallers = async () => { this.log(`Promoting macos pkgs to ${flags.channel}`) const arches = _.uniq(buildConfig.targets.filter(t => t.platform === 'darwin').map(t => t.arch)) - for (const arch of arches) { + await Promise.all(arches.map(async arch => { const darwinPkg = templateShortKey('macos', {bin: config.bin, version: flags.version, sha: flags.sha, arch}) const darwinCopySource = cloudBucketCommitKey(darwinPkg) // strip version & sha so scripts can point to a static channel pkg const unversionedPkg = darwinPkg.replace(`-v${flags.version}-${flags.sha}`, '') - const darwinKey = cloudChannelKey(unversionedPkg) - // eslint-disable-next-line no-await-in-loop - await aws.s3.copyObject( + await Promise.all([aws.s3.copyObject( { - Bucket: s3Config.bucket, - ACL: s3Config.acl || 'public-read', + ...awsDefaults, CopySource: darwinCopySource, - Key: darwinKey, - CacheControl: maxAge, - MetadataDirective: 'REPLACE', + Key: cloudChannelKey(unversionedPkg), + }, - ) - // eslint-disable-next-line no-await-in-loop - if (flags.indexes) await appendToIndex({...indexDefaults, originalUrl: darwinCopySource, filename: unversionedPkg}) - } + )].concat(flags.indexes ? [appendToIndex({...indexDefaults, originalUrl: darwinCopySource, filename: unversionedPkg})] : [])) + })) } - // copy win exe - if (flags.win) { + const promoteWindowsInstallers = async () => { + // copy win exe this.log(`Promoting windows exe to ${flags.channel}`) - const archs = buildConfig.targets.filter(t => t.platform === 'win32').map(t => t.arch) - for (const arch of archs) { + const arches = buildConfig.targets.filter(t => t.platform === 'win32').map(t => t.arch) + await Promise.all(arches.map(async arch => { const winPkg = templateShortKey('win32', {bin: config.bin, version: flags.version, sha: flags.sha, arch}) const winCopySource = cloudBucketCommitKey(winPkg) // strip version & sha so scripts can point to a static channel exe const unversionedExe = winPkg.replace(`-v${flags.version}-${flags.sha}`, '') - const winKey = cloudChannelKey(unversionedExe) - // eslint-disable-next-line no-await-in-loop - await aws.s3.copyObject( + await Promise.all([aws.s3.copyObject( { - Bucket: s3Config.bucket, - ACL: s3Config.acl || 'public-read', + ...awsDefaults, CopySource: winCopySource, - Key: winKey, - CacheControl: maxAge, + Key: cloudChannelKey(unversionedExe), }, - ) - // eslint-disable-next-line no-await-in-loop - if (flags.indexes) await appendToIndex({...indexDefaults, originalUrl: winCopySource, filename: unversionedExe}) + )].concat(flags.indexes ? [appendToIndex({...indexDefaults, originalUrl: winCopySource, filename: unversionedExe})] : [])) CliUx.ux.action.stop('successfully') - } + })) } - // copy debian artifacts - const debArtifacts = [ - templateShortKey('deb', {bin: config.bin, versionShaRevision: debVersion(buildConfig), arch: 'amd64' as any}), - templateShortKey('deb', {bin: config.bin, versionShaRevision: debVersion(buildConfig), arch: 'i386' as any}), - 'Packages.gz', - 'Packages.xz', - 'Packages.bz2', - 'Release', - 'InRelease', - 'Release.gpg', - ] - if (flags.deb) { + const promoteDebianAptPackages = async () => { + // copy debian artifacts + const debArtifacts = [ + templateShortKey('deb', {bin: config.bin, versionShaRevision: debVersion(buildConfig), arch: 'amd64' as any}), + templateShortKey('deb', {bin: config.bin, versionShaRevision: debVersion(buildConfig), arch: 'i386' as any}), + 'Packages.gz', + 'Packages.xz', + 'Packages.bz2', + 'Release', + 'InRelease', + 'Release.gpg', + ] this.log(`Promoting debian artifacts to ${flags.channel}`) - for (const artifact of debArtifacts) { + await Promise.all(debArtifacts.flatMap(artifact => { const debCopySource = cloudBucketCommitKey(`apt/${artifact}`) const debKey = cloudChannelKey(`apt/${artifact}`) - // eslint-disable-next-line no-await-in-loop - await aws.s3.copyObject( - { - Bucket: s3Config.bucket, - ACL: s3Config.acl || 'public-read', - CopySource: debCopySource, - Key: debKey, - CacheControl: maxAge, - MetadataDirective: 'REPLACE', - }, - ) - } + // apt expects ../apt/dists/versionName/[artifacts] but oclif wants varsions/sha/apt/[artifacts] + // see https://github.com/oclif/oclif/issues/347 for the AWS-redirect that solves this + // this workaround puts the code in both places that the redirect was doing + // with this, the docs are correct. The copies are all done in parallel so it shouldn't be too costly. + const workaroundKey = cloudChannelKey(`apt/./${artifact}`) + return [ + aws.s3.copyObject( + { + ...awsDefaults, + CopySource: debCopySource, + Key: debKey, + }, + ), + aws.s3.copyObject( + { + ...awsDefaults, + CopySource: debCopySource, + Key: workaroundKey, + }, + ), + ] + }), + + ) } + + await Promise.all(buildConfig.targets.flatMap(target => [ + // always promote the manifest and gz + promoteManifest(target), + promoteGzTarballs(target), + ]) + // optionally promote other artifacts depending on the specified flags + .concat(flags.xz ? buildConfig.targets.map(target => promoteXzTarballs(target)) : []) + .concat(flags.macos ? [promoteMacInstallers()] : []) + .concat(flags.win ? [promoteWindowsInstallers()] : []) + .concat(flags.deb ? [promoteDebianAptPackages()] : []), + ) } } diff --git a/src/commands/upload/deb.ts b/src/commands/upload/deb.ts index e36e24561..888a1015e 100644 --- a/src/commands/upload/deb.ts +++ b/src/commands/upload/deb.ts @@ -1,6 +1,6 @@ import {Command, Flags} from '@oclif/core' -import * as qq from 'qqjs' - +import * as fs from 'fs' +import * as path from 'path' import aws from '../../aws' import {log} from '../../log' import * as Tarballs from '../../tarballs' @@ -17,13 +17,13 @@ export default class UploadDeb extends Command { const {flags} = await this.parse(UploadDeb) const buildConfig = await Tarballs.buildConfig(flags.root) const {s3Config, config} = buildConfig - const dist = (f: string) => buildConfig.dist(qq.join('deb', f)) + const dist = (f: string) => buildConfig.dist(path.join('deb', f)) const S3Options = { Bucket: s3Config.bucket!, ACL: s3Config.acl || 'public-read', } - if (!await qq.exists(dist('Release'))) this.error('Cannot find debian artifacts', { + if (!fs.existsSync(dist('Release'))) this.error('Cannot find debian artifacts', { suggestions: ['Run "oclif pack deb" before uploading'], }) @@ -33,20 +33,37 @@ export default class UploadDeb extends Command { return aws.s3.uploadFile(dist(file), {...S3Options, CacheControl: 'max-age=86400', Key: cloudKey}) } + // apt expects ../apt/dists/versionName/[artifacts] but oclif wants versions/sha/apt/[artifacts] + // see https://github.com/oclif/oclif/issues/347 for the AWS-redirect that solves this + // this workaround puts the code in both places that the redirect was doing + // with this, the docs are correct. The copies are all done in parallel so it shouldn't be too costly. + const uploadWorkaround = (file: string) => { + const cloudKey = `${cloudKeyBase}/apt/./${file}` + return aws.s3.uploadFile(dist(file), {...S3Options, CacheControl: 'max-age=86400', Key: cloudKey}) + } + const uploadDeb = async (arch: 'amd64' | 'i386') => { const deb = templateShortKey('deb', {bin: config.bin, versionShaRevision: debVersion(buildConfig), arch: arch as any}) - if (await qq.exists(dist(deb))) await upload(deb) + if (fs.existsSync(dist(deb))) await Promise.all([upload(deb), uploadWorkaround(deb)]) } - await uploadDeb('amd64') - await uploadDeb('i386') - await upload('Packages.gz') - await upload('Packages.xz') - await upload('Packages.bz2') - await upload('Release') - if (await qq.exists(dist('InRelease'))) await upload('InRelease') - if (await qq.exists(dist('Release.gpg'))) await upload('Release.gpg') + log(`starting upload of deb artifacts for v${config.version}-${buildConfig.gitSha}`) + await Promise.all([ + uploadDeb('amd64'), + uploadDeb('i386'), + upload('Packages.gz'), + upload('Packages.xz'), + upload('Packages.bz2'), + upload('Release'), + uploadWorkaround('Packages.gz'), + uploadWorkaround('Packages.xz'), + uploadWorkaround('Packages.bz2'), + uploadWorkaround('Release'), + ].concat( + fs.existsSync(dist('InRelease')) ? [upload('InRelease'), uploadWorkaround('InRelease')] : [], + fs.existsSync(dist('Release.gpg')) ? [upload('Release.gpg'), uploadWorkaround('Release.gpg')] : [], + )) log(`done uploading deb artifacts for v${config.version}-${buildConfig.gitSha}`) } } diff --git a/src/commands/upload/macos.ts b/src/commands/upload/macos.ts index 170f9853b..447df59bf 100644 --- a/src/commands/upload/macos.ts +++ b/src/commands/upload/macos.ts @@ -1,6 +1,5 @@ import * as _ from 'lodash' -import * as qq from 'qqjs' - +import * as fs from 'fs' import {Command, Flags, Interfaces} from '@oclif/core' import aws from '../../aws' @@ -31,7 +30,7 @@ export default class UploadMacos extends Command { const cloudKey = `${cloudKeyBase}/${templateKey}` const localPkg = dist(`macos/${templateKey}`) - if (await qq.exists(localPkg)) await aws.s3.uploadFile(localPkg, {...S3Options, CacheControl: 'max-age=86400', Key: cloudKey}) + if (fs.existsSync(localPkg)) await aws.s3.uploadFile(localPkg, {...S3Options, CacheControl: 'max-age=86400', Key: cloudKey}) else this.error('Cannot find macOS pkg', { suggestions: ['Run "oclif pack macos" before uploading'], }) @@ -40,8 +39,7 @@ export default class UploadMacos extends Command { const arches = _.uniq(buildConfig.targets .filter(t => t.platform === 'darwin') .map(t => t.arch)) - // eslint-disable-next-line no-await-in-loop - for (const a of arches) await upload(a) + await Promise.all(arches.map(a => upload(a))) log(`done uploading macos pkgs for v${config.version}-${buildConfig.gitSha}`) } diff --git a/src/commands/upload/tarballs.ts b/src/commands/upload/tarballs.ts index 0fb79cdf6..44add7afa 100644 --- a/src/commands/upload/tarballs.ts +++ b/src/commands/upload/tarballs.ts @@ -1,7 +1,6 @@ import {Command, Flags} from '@oclif/core' import {Interfaces} from '@oclif/core' -import * as qq from 'qqjs' - +import * as fs from 'fs' import aws from '../../aws' import {log} from '../../log' import * as Tarballs from '../../tarballs' @@ -28,8 +27,7 @@ export default class UploadTarballs extends Command { // fail early if targets are not built for (const target of buildConfig.targets) { const tarball = dist(templateShortKey('versioned', {ext: '.tar.gz', bin: config.bin, version: config.version, sha: buildConfig.gitSha, ...target})) - // eslint-disable-next-line no-await-in-loop - if (!await qq.exists(tarball)) this.error(`Cannot find a tarball ${tarball} for ${target.platform}-${target.arch}`, { + if (!fs.existsSync(tarball)) this.error(`Cannot find a tarball ${tarball} for ${target.platform}-${target.arch}`, { suggestions: [`Run "oclif pack --target ${target.platform}-${target.arch}" before uploading`], }) } @@ -40,26 +38,7 @@ export default class UploadTarballs extends Command { } const uploadTarball = async (options?: { platform: Interfaces.PlatformTypes; arch: Interfaces.ArchTypes}) => { - const TarballS3Options = {...S3Options, CacheControl: 'max-age=604800'} - const releaseTarballs = async (ext: '.tar.gz' | '.tar.xz') => { - const localKey = templateShortKey('versioned', ext, { - // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain - arch: options?.arch!, - bin: config.bin, - // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain - platform: options?.platform!, - sha: buildConfig.gitSha, - version: config.version, - }) - const cloudKey = `${commitAWSDir(config.version, buildConfig.gitSha, s3Config)}/${localKey}` - await aws.s3.uploadFile(dist(localKey), {...TarballS3Options, ContentType: 'application/gzip', Key: cloudKey}) - } - - await releaseTarballs('.tar.gz') - if (xz) await releaseTarballs('.tar.xz') - - const ManifestS3Options = {...S3Options, CacheControl: 'max-age=86400', ContentType: 'application/json'} - const manifest = templateShortKey('manifest', { + const shortKeyInputs = { // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain arch: options?.arch!, bin: config.bin, @@ -67,14 +46,22 @@ export default class UploadTarballs extends Command { platform: options?.platform!, sha: buildConfig.gitSha, version: config.version, - }) + } + + const releaseTarballs = async (ext: '.tar.gz' | '.tar.xz') => { + const localKey = templateShortKey('versioned', ext, shortKeyInputs) + const cloudKey = `${commitAWSDir(config.version, buildConfig.gitSha, s3Config)}/${localKey}` + await aws.s3.uploadFile(dist(localKey), {...S3Options, CacheControl: 'max-age=604800', ContentType: 'application/gzip', Key: cloudKey}) + } + + const manifest = templateShortKey('manifest', shortKeyInputs) const cloudKey = `${commitAWSDir(config.version, buildConfig.gitSha, s3Config)}/${manifest}` - await aws.s3.uploadFile(dist(manifest), {...ManifestS3Options, Key: cloudKey}) + + await Promise.all([releaseTarballs('.tar.gz'), aws.s3.uploadFile(dist(manifest), {...S3Options, CacheControl: 'max-age=86400', ContentType: 'application/json', Key: cloudKey})].concat(xz ? [releaseTarballs('.tar.xz')] : [])) } if (buildConfig.targets.length > 0) log('uploading targets') - // eslint-disable-next-line no-await-in-loop - for (const target of buildConfig.targets) await uploadTarball(target) + await Promise.all(buildConfig.targets.map(t => uploadTarball(t))) log(`done uploading tarballs & manifests for v${config.version}-${buildConfig.gitSha}`) } } diff --git a/src/commands/upload/win.ts b/src/commands/upload/win.ts index 96eb5c9b7..db1c972b0 100644 --- a/src/commands/upload/win.ts +++ b/src/commands/upload/win.ts @@ -1,6 +1,5 @@ import {Command, Flags} from '@oclif/core' -import * as qq from 'qqjs' - +import * as fs from 'fs' import aws from '../../aws' import {log} from '../../log' import * as Tarballs from '../../tarballs' @@ -27,8 +26,7 @@ export default class UploadWin extends Command { for (const arch of archs) { const templateKey = templateShortKey('win32', {bin: config.bin, version: config.version, sha: buildConfig.gitSha, arch}) const localKey = dist(`win32/${templateKey}`) - // eslint-disable-next-line no-await-in-loop - if (!await qq.exists(localKey)) this.error(`Cannot find Windows exe for ${arch}`, { + if (!fs.existsSync(localKey)) this.error(`Cannot find Windows exe for ${arch}`, { suggestions: ['Run "oclif pack win" before uploading'], }) } @@ -38,11 +36,10 @@ export default class UploadWin extends Command { const templateKey = templateShortKey('win32', {bin: config.bin, version: config.version, sha: buildConfig.gitSha, arch}) const localExe = dist(`win32/${templateKey}`) const cloudKey = `${cloudKeyBase}/${templateKey}` - if (await qq.exists(localExe)) await aws.s3.uploadFile(localExe, {...S3Options, CacheControl: 'max-age=86400', Key: cloudKey}) + if (fs.existsSync(localExe)) await aws.s3.uploadFile(localExe, {...S3Options, CacheControl: 'max-age=86400', Key: cloudKey}) } - await uploadWin('x64') - await uploadWin('x86') + await Promise.all([uploadWin('x64'), uploadWin('x86')]) log(`done uploading windows executables for v${config.version}-${buildConfig.gitSha}`) } diff --git a/src/log.ts b/src/log.ts index 4f0d42813..c91368663 100644 --- a/src/log.ts +++ b/src/log.ts @@ -1,11 +1,11 @@ import {CliUx} from '@oclif/core' -import * as qq from 'qqjs' import * as util from 'util' +import {prettifyPaths} from './util' export const debug = require('debug')('oclif') debug.new = (name: string) => require('debug')(`oclif:${name}`) export function log(format: string, ...args: any[]): void { - args = args.map((arg: any) => qq.prettifyPaths(arg)) + args = args.map((arg: any) => prettifyPaths(arg)) debug.enabled ? debug(format, ...args) : CliUx.ux.log(`oclif: ${util.format(format, ...args)}`) } diff --git a/src/tarballs/bin.ts b/src/tarballs/bin.ts index 161af87fd..e772d2484 100644 --- a/src/tarballs/bin.ts +++ b/src/tarballs/bin.ts @@ -1,7 +1,7 @@ /* eslint-disable no-useless-escape */ import {Interfaces} from '@oclif/core' - -import * as qq from 'qqjs' +import * as fs from 'fs' +import * as path from 'path' export async function writeBinScripts({config, baseWorkspace, nodeVersion}: {config: Interfaces.Config ; baseWorkspace: string; nodeVersion: string;}): Promise { @@ -10,7 +10,7 @@ export async function writeBinScripts({config, baseWorkspace, nodeVersion}: {con const clientHomeEnvVar = config.scopedEnvVarKey('OCLIF_CLIENT_HOME') const writeWin32 = async () => { const {bin} = config - await qq.write([baseWorkspace, 'bin', `${config.bin}.cmd`], `@echo off + await fs.promises.writeFile(path.join(baseWorkspace, 'bin', `${config.bin}.cmd`), `@echo off setlocal enableextensions if not "%${redirectedEnvVar}%"=="1" if exist "%LOCALAPPDATA%\\${bin}\\client\\bin\\${bin}.cmd" ( @@ -37,8 +37,8 @@ if exist "%~dp0..\\bin\\node.exe" ( } const writeUnix = async () => { - const bin = qq.join([baseWorkspace, 'bin', config.bin]) - await qq.write(bin, `#!/usr/bin/env bash + const bin = path.join(baseWorkspace, 'bin', config.bin) + await fs.promises.writeFile(bin, `#!/usr/bin/env bash set -e echoerr() { echo "$@" 1>&2; } @@ -83,10 +83,8 @@ else fi "\$NODE" "\$DIR/run" "\$@" fi -`) - await qq.chmod(bin, 0o755) +`, {mode: 0o755}) } - await writeWin32() - await writeUnix() + await Promise.all([writeWin32(), writeUnix()]) } diff --git a/src/tarballs/build.ts b/src/tarballs/build.ts index 8be13ddb1..f3c150a30 100644 --- a/src/tarballs/build.ts +++ b/src/tarballs/build.ts @@ -1,24 +1,25 @@ import {Interfaces} from '@oclif/core' import * as findYarnWorkspaceRoot from 'find-yarn-workspace-root' -import * as path from 'path' -import * as qq from 'qqjs' - import {log} from '../log' - +import * as path from 'path' +import * as fs from 'fs-extra' import {writeBinScripts} from './bin' import {BuildConfig} from './config' import {fetchNodeBinary} from './node' import {commitAWSDir, templateShortKey} from '../upload-util' +import {prettifyPaths, hash} from '../util' +import {exec as execSync} from 'child_process' +import {promisify} from 'node:util' + +const exec = promisify(execSync) const pack = async (from: string, to: string) => { - const prevCwd = qq.cwd() - qq.cd(path.dirname(from)) - await qq.mkdirp(path.dirname(to)) - log(`packing tarball from ${qq.prettifyPaths(from)} to ${qq.prettifyPaths(to)}`) - await (to.endsWith('gz') ? - qq.x('tar', ['czf', to, path.basename(from)]) : - qq.x(`tar c "${path.basename(from)}" | xz > "${to}"`)) - qq.cd(prevCwd) + const cwd = path.dirname(from) + await fs.promises.mkdir(path.dirname(to), {recursive: true}) + log(`packing tarball from ${prettifyPaths(path.dirname(from))} to ${prettifyPaths(to)}`); + (to.endsWith('gz') ? + await exec(`tar czf ${to} ${(path.basename(from))}`, {cwd}) : + await exec(`tar cfJ ${to} ${(path.basename(from))}`, {cwd})) } export async function build(c: BuildConfig, options: { @@ -28,67 +29,67 @@ export async function build(c: BuildConfig, options: { parallel?: boolean; } = {}): Promise { const {xz, config} = c - const prevCwd = qq.cwd() const packCLI = async () => { - const stdout = await qq.x.stdout('npm', ['pack', '--unsafe-perm'], {cwd: c.root}) - return path.join(c.root, stdout.split('\n').pop()!) + const {stdout} = await exec('npm pack --unsafe-perm', {cwd: c.root}) + return path.join(c.root, stdout.trim().split('\n').pop()!) } const extractCLI = async (tarball: string) => { - await qq.emptyDir(c.workspace()) - await qq.mv(tarball, c.workspace()) - tarball = path.basename(tarball) - tarball = qq.join([c.workspace(), tarball]) - qq.cd(c.workspace()) - await qq.x(`tar -xzf "${tarball}"`) - // eslint-disable-next-line no-await-in-loop - for (const f of await qq.ls('package', {fullpath: true})) await qq.mv(f, '.') - await qq.rm('package', tarball, 'bin/run.cmd') + await fs.emptyDir(c.workspace()) + const tarballNewLocation = path.join(c.workspace(), path.basename(tarball)) + await fs.move(tarball, tarballNewLocation) + await exec(`tar -xzf "${tarballNewLocation}"`, {cwd: c.workspace()}) + + await Promise.all( + (await fs.promises.readdir(path.join(c.workspace(), 'package'), {withFileTypes: true})) + .map(i => fs.move(path.join(c.workspace(), 'package', i.name), path.join(c.workspace(), i.name))), + ) + + await Promise.all([ + fs.promises.rm(path.join(c.workspace(), 'package'), {recursive: true}), + fs.promises.rm(path.join(c.workspace(), path.basename(tarball)), {recursive: true}), + fs.remove(path.join(c.workspace(), 'bin', 'run.cmd')), + ]) } const updatePJSON = async () => { - qq.cd(c.workspace()) - const pjson = await qq.readJSON('package.json') + const pjsonPath = path.join(c.workspace(), 'package.json') + const pjson = await fs.readJSON(pjsonPath) pjson.version = config.version pjson.oclif.update = pjson.oclif.update || {} pjson.oclif.update.s3 = pjson.oclif.update.s3 || {} pjson.oclif.update.s3.bucket = c.s3Config.bucket - await qq.writeJSON('package.json', pjson) + await fs.writeJSON(pjsonPath, pjson) } const addDependencies = async () => { - qq.cd(c.workspace()) const yarnRoot = findYarnWorkspaceRoot(c.root) || c.root - const yarn = await qq.exists([yarnRoot, 'yarn.lock']) - if (yarn) { - await qq.cp([yarnRoot, 'yarn.lock'], '.') + if (fs.existsSync(path.join(yarnRoot, 'yarn.lock'))) { + await fs.copy(path.join(yarnRoot, 'yarn.lock'), path.join(c.workspace(), 'yarn.lock')) - const yarnVersion = (await qq.x.stdout('yarn', ['-v'])).charAt(0) + const yarnVersion = (await exec('yarn', ['-v'])).stdout.charAt(0) if (yarnVersion === '1') { - await qq.x('yarn --no-progress --production --non-interactive') + await exec('yarn --no-progress --production --non-interactive', {cwd: c.workspace()}) } else { - await qq.x('yarn workspaces focus --production') + await exec('yarn workspaces focus --production', {cwd: c.workspace()}) } } else { - let lockpath = qq.join(c.root, 'package-lock.json') - if (!await qq.exists(lockpath)) { - lockpath = qq.join(c.root, 'npm-shrinkwrap.json') - } - - await qq.cp(lockpath, '.') - await qq.x('npm install --production') + const lockpath = fs.existsSync(path.join(c.root, 'package-lock.json')) ? + path.join(c.root, 'package-lock.json') : + path.join(c.root, 'npm-shrinkwrap.json') + await fs.copy(lockpath, path.join(c.workspace(), path.basename(lockpath))) + await exec('npm install --production', {cwd: c.workspace()}) } } const pretarball = async () => { - qq.cd(c.workspace()) - const pjson = await qq.readJSON('package.json') + const pjson = await fs.readJSON(path.join(c.workspace(), 'package.json')) const yarnRoot = findYarnWorkspaceRoot(c.root) || c.root - const yarn = await qq.exists([yarnRoot, 'yarn.lock']) + const yarn = fs.existsSync(path.join(yarnRoot, 'yarn.lock')) if (pjson.scripts.pretarball) { yarn ? - await qq.x('yarn run pretarball') : - await qq.x('npm run pretarball', {}) + await exec('yarn run pretarball', {cwd: c.workspace()}) : + await exec('npm run pretarball', {cwd: c.workspace()}) } } @@ -112,14 +113,14 @@ export async function build(c: BuildConfig, options: { const base = path.basename(gzLocalKey) log(`building target ${base}`) log('copying workspace', c.workspace(), workspace) - await qq.rm(workspace) - await qq.cp(c.workspace(), workspace) + await fs.emptyDir(workspace) + await fs.copy(c.workspace(), workspace) await fetchNodeBinary({ nodeVersion: c.nodeVersion, output: path.join(workspace, 'bin', 'node'), platform: target.platform, arch: target.arch, - tmp: qq.join(config.root, 'tmp'), + tmp: path.join(config.root, 'tmp'), }) if (options.pack === false) return if (options.parallel) { @@ -138,6 +139,8 @@ export async function build(c: BuildConfig, options: { const gzCloudKey = `${commitAWSDir(config.version, c.gitSha, c.updateConfig.s3)}/${gzLocalKey}` const xzCloudKey = `${commitAWSDir(config.version, c.gitSha, c.updateConfig.s3)}/${xzLocalKey}` + const [sha256gz, sha256xz] = await Promise.all([hash('sha256', c.dist(gzLocalKey))].concat(xz ? [hash('sha256', c.dist(xzLocalKey))] : [])) + const manifest: Interfaces.S3Manifest = { rollout: rollout === false ? undefined : rollout, version: config.version, @@ -145,8 +148,8 @@ export async function build(c: BuildConfig, options: { baseDir: templateShortKey('baseDir', target, {bin: c.config.bin}), gz: config.s3Url(gzCloudKey), xz: xz ? config.s3Url(xzCloudKey) : undefined, - sha256gz: await qq.hash('sha256', c.dist(gzLocalKey)), - sha256xz: xz ? await qq.hash('sha256', c.dist(xzLocalKey)) : undefined, + sha256gz, + sha256xz, node: { compatible: config.pjson.engines.node, recommended: c.nodeVersion, @@ -159,7 +162,7 @@ export async function build(c: BuildConfig, options: { sha: c.gitSha, version: config.version, })) - await qq.writeJSON(manifestFilepath, manifest) + await fs.writeJSON(manifestFilepath, manifest) } log(`gathering workspace for ${config.bin} to ${c.workspace()}`) @@ -178,7 +181,8 @@ export async function build(c: BuildConfig, options: { // eslint-disable-next-line no-await-in-loop await buildTarget(target) } - } - qq.cd(prevCwd) + log(`finished building ${targetsToBuild.length} targets sequentially`) + } } + diff --git a/src/tarballs/config.ts b/src/tarballs/config.ts index 942fcdb7c..c58188102 100644 --- a/src/tarballs/config.ts +++ b/src/tarballs/config.ts @@ -1,12 +1,15 @@ import {CliUx, Interfaces, Config} from '@oclif/core' import * as path from 'path' -import * as qq from 'qqjs' import * as semver from 'semver' +import * as fs from 'fs-extra' import {compact} from '../util' import {templateShortKey} from '../upload-util' +import {exec as execSync} from 'child_process' +import {promisify} from 'node:util' +const exec = promisify(execSync) export const TARGETS = [ 'linux-x64', 'linux-arm', @@ -32,13 +35,13 @@ export interface BuildConfig { export async function gitSha(cwd: string, options: {short?: boolean} = {}): Promise { const args = options.short ? ['rev-parse', '--short', 'HEAD'] : ['rev-parse', 'HEAD'] - return qq.x.stdout('git', args, {cwd}) + return (await exec(`git ${args.join(' ')}`, {cwd})).stdout.trim() } async function Tmp(config: Interfaces.Config, ) { const tmp = path.join(config.root, 'tmp') - await qq.mkdirp(tmp) + await fs.promises.mkdir(tmp, {recursive: true}) return tmp } @@ -75,9 +78,9 @@ export async function buildConfig(root: string, options: {xz?: boolean; targets? s3Config: updateConfig.s3, nodeVersion, workspace(target) { - const base = qq.join(config.root, 'tmp') - if (target && target.platform) return qq.join(base, [target.platform, target.arch].join('-'), templateShortKey('baseDir', {bin: config.bin})) - return qq.join(base, templateShortKey('baseDir', {bin: config.bin})) + const base = path.join(config.root, 'tmp') + if (target && target.platform) return path.join(base, [target.platform, target.arch].join('-'), templateShortKey('baseDir', {bin: config.bin})) + return path.join(base, templateShortKey('baseDir', {bin: config.bin})) }, targets, } diff --git a/src/tarballs/node.ts b/src/tarballs/node.ts index be4b577cd..527ca9762 100644 --- a/src/tarballs/node.ts +++ b/src/tarballs/node.ts @@ -1,8 +1,14 @@ import {Errors, Interfaces} from '@oclif/core' import * as path from 'path' -import * as qq from 'qqjs' - +import * as fs from 'fs-extra' +import {pipeline as pipelineSync} from 'node:stream' import {log} from '../log' +import {exec as execSync} from 'node:child_process' +import {promisify} from 'node:util' +import got from 'got' +const pipeline = promisify(pipelineSync) + +const exec = promisify(execSync) type Options = { nodeVersion: string; @@ -14,7 +20,7 @@ type Options = { async function checkFor7Zip() { try { - await qq.x('7z', {stdio: [0, null, 2]}) + await exec('7z') } catch (error: any) { if (error.code === 127) Errors.error('install 7-zip to package windows tarball') else throw error @@ -39,38 +45,52 @@ export async function fetchNodeBinary({nodeVersion, output, platform, arch, tmp} const download = async () => { log(`downloading ${nodeBase}`) + await Promise.all([ + fs.ensureDir(path.join(tmp, 'cache', nodeVersion)), + fs.ensureDir(path.join(tmp, 'node')), + ]) const shasums = path.join(tmp, 'cache', nodeVersion, 'SHASUMS256.txt.asc') - if (!await qq.exists(shasums)) { - await qq.download(`https://nodejs.org/dist/v${nodeVersion}/SHASUMS256.txt.asc`, shasums) + if (!fs.existsSync(shasums)) { + await pipeline( + got.stream(`https://nodejs.org/dist/v${nodeVersion}/SHASUMS256.txt.asc`), + fs.createWriteStream(shasums), + ) } const basedir = path.dirname(tarball) - await qq.mkdirp(basedir) - await qq.download(url, tarball) - if (platform !== 'win32') await qq.x(`grep "${path.basename(tarball)}" "${shasums}" | shasum -a 256 -c -`, {cwd: basedir}) + await fs.promises.mkdir(basedir, {recursive: true}) + await pipeline( + got.stream(url), + fs.createWriteStream(tarball), + ) + if (platform !== 'win32') await exec(`grep "${path.basename(tarball)}" "${shasums}" | shasum -a 256 -c -`, {cwd: basedir}) } const extract = async () => { log(`extracting ${nodeBase}`) const nodeTmp = path.join(tmp, 'node') - await qq.mkdirp(nodeTmp) - await qq.mkdirp(path.dirname(cache)) + await fs.promises.mkdir(nodeTmp, {recursive: true}) + await fs.promises.mkdir(path.dirname(cache), {recursive: true}) + if (platform === 'win32') { - await qq.x(`7z x -bd -y "${tarball}"`, {cwd: nodeTmp}) - await qq.mv([nodeTmp, nodeBase, 'node.exe'], cache) + await exec(`7z x -bd -y "${tarball}"`, {cwd: nodeTmp}) + await fs.move(path.join(nodeTmp, nodeBase, 'node.exe'), path.join(cache, 'node.exe')) } else { - await qq.x(`tar -C "${tmp}/node" -xJf "${tarball}"`) - await qq.mv([nodeTmp, nodeBase, 'bin/node'], cache) + await exec(`tar -C "${tmp}/node" -xJf "${tarball}"`) + await fs.move(path.join(nodeTmp, nodeBase, 'bin', 'node'), path.join(cache, 'node')) } } - if (await qq.exists(cache)) { - await qq.cp(cache, output) - } else { + if (!fs.existsSync(cache)) { await download() await extract() - await qq.cp(cache, output) } + await fs.copy(path.join(cache, getFilename(platform)), output) + return output } + +const getFilename = (platform: string): string => { + return platform === 'win32' ? 'node.exe' : 'node' +} diff --git a/src/util.ts b/src/util.ts index c9435ecac..d6e3f3392 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,4 +1,8 @@ import _ = require('lodash') +import * as os from 'os' +import * as crypto from 'node:crypto' +import {log} from './log' +import * as fs from 'fs-extra' export function castArray(input?: T | T[]): T[] { if (input === undefined) return [] @@ -69,3 +73,21 @@ export const sortVersionsObjectByKeysDesc = (input: VersionsObject): VersionsObj return result } + +const homeRegexp = new RegExp(`\\B${os.homedir().replace('/', '\\/')}`, 'g') +const curRegexp = new RegExp(`\\B${process.cwd()}`, 'g') + +export const prettifyPaths = (input: string): string => + (input ?? '').toString().replace(curRegexp, '.').replace(homeRegexp, '~') + +export const hash = async (algo: string, fp: string | string[]):Promise => { + const f = Array.isArray(fp) ? fp.join('') : fp + log('hash', algo, f) + return new Promise((resolve, reject) => { + const hashInProgress = crypto.createHash(algo) + const stream = fs.createReadStream(f) + stream.on('error', err => reject(err)) + stream.on('data', chunk => hashInProgress.update(chunk)) + stream.on('end', () => resolve(hashInProgress.digest('hex'))) + }) +} diff --git a/test/helpers/helper.ts b/test/helpers/helper.ts index ab9924c49..6e9116121 100644 --- a/test/helpers/helper.ts +++ b/test/helpers/helper.ts @@ -1,16 +1,16 @@ -import * as qq from 'qqjs' import {expect} from '@oclif/test' import {gitSha} from '../../src/tarballs' import * as shelljs from 'shelljs' import * as S3 from 'aws-sdk/clients/s3' import aws from '../../src/aws' +import * as fs from 'fs' export const oclifTestingVersionsURI = 'media/salesforce-cli/oclif-testing/versions' export const oclifTestingChannelsURI = 'media/salesforce-cli/oclif-testing/channels' export const developerSalesforceCom = 'developer.salesforce.com' export const findDistFileSha = async (cwd: string, platform: string, filter: (f: string) => boolean): Promise => { - const distFiles = await qq.ls(`${cwd}/dist/${platform}/`) + const distFiles = await fs.promises.readdir(`${cwd}/dist/${platform}/`) const pkg = distFiles.find(element => filter(element)) as string expect(pkg).to.be.ok return [pkg, await gitSha(process.cwd(), {short: true})] @@ -19,7 +19,7 @@ export const findDistFileSha = async (cwd: string, platform: string, filter: (f: export function gitShaSync(cwd: string, options: {short?: boolean} = {}): string { const args = options.short ? ['rev-parse', '--short', 'HEAD'] : ['rev-parse', 'HEAD'] const r = shelljs.exec(`git ${args.join(' ')}`, {cwd}) - return r.stdout + return r.stdout.trim() } export async function deleteFolder(bucket: string, folder: string): Promise<(string | undefined)[]> { diff --git a/test/integration/deb.test.ts b/test/integration/deb.test.ts index 47e805281..371e4c876 100644 --- a/test/integration/deb.test.ts +++ b/test/integration/deb.test.ts @@ -1,8 +1,12 @@ import {expect, test} from '@oclif/test' -import * as qq from 'qqjs' import {deleteFolder, developerSalesforceCom} from '../helpers/helper' import {gitSha} from '../../src/tarballs' +import * as fs from 'fs-extra' +import * as path from 'path' +import {exec as execSync} from 'child_process' +import {promisify} from 'node:util' +const exec = promisify(execSync) const pjson = require('../../package.json') const pjsonPath = require.resolve('../../package.json') const originalVersion = pjson.version @@ -11,10 +15,10 @@ const target = [process.platform, process.arch].join('-') const onlyLinux = process.platform === 'linux' ? test : test.skip() const testRun = `test-${Math.random().toString().split('.')[1].slice(0, 4)}` -// 2022-01 - this test requires linux with apt-ftparchive installed. Current CircleCi images do not have that util installed - skipping test -describe.skip('publish:deb', () => { +describe('publish:deb', () => { let bucket: string let basePrefix: string + const root = path.join(__dirname, '../tmp/test/publish') beforeEach(async () => { pjson.version = `${pjson.version}-${testRun}` @@ -22,16 +26,13 @@ describe.skip('publish:deb', () => { bucket = pjson.oclif.update.s3.bucket basePrefix = pjson.oclif.update.s3.folder await deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`) - await qq.writeJSON(pjsonPath, pjson) - const root = qq.join(__dirname, '../tmp/test/publish') - await qq.emptyDir(root) - qq.cd(root) + await fs.writeJSON(pjsonPath, pjson) + await fs.emptyDir(root) }) afterEach(async () => { await deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`) - qq.cd([__dirname, '..']) pjson.version = originalVersion - await qq.writeJSON(pjsonPath, pjson) + await fs.writeJSON(pjsonPath, pjson) }) onlyLinux @@ -39,13 +40,12 @@ describe.skip('publish:deb', () => { .command(['upload:deb']) .it('publishes valid releases', async () => { const sha = await gitSha(process.cwd(), {short: true}) - qq.cd([__dirname, '..', '..']) - await qq.x('cat test/release.key | apt-key add -') - await qq.x(`echo "deb https://${developerSalesforceCom}/apt ./" > /etc/apt/sources.list.d/oclif-dev.list`) - await qq.x('apt-get update') - await qq.x('apt-get install -y oclif-dev') - await qq.x('oclif --version') - const stdout = await qq.x.stdout('oclif', ['--version']) - expect(stdout).to.contain(`oclif/${pjson.version}.${sha} ${target} node-v${pjson.oclif.update.node.version}`) + await exec('cat test/release.key | sudo apt-key add -') + await exec(`sudo sh -c 'echo "deb https://${developerSalesforceCom}/${basePrefix}/versions/${pjson.version}/${sha}/apt/ /" > /etc/apt/sources.list.d/oclif.list'`) + await exec('sudo apt-get update') + await exec('sudo apt-get install -y oclif') + await exec('oclif --version') + const {stdout} = await exec('oclif --version') + expect(stdout).to.contain(`oclif/${pjson.version} ${target} node-v${pjson.oclif.update.node.version}`) }) }) diff --git a/test/integration/macos.test.ts b/test/integration/macos.test.ts index 5728a2052..8e8550d6f 100644 --- a/test/integration/macos.test.ts +++ b/test/integration/macos.test.ts @@ -1,7 +1,12 @@ import {test} from '@oclif/test' -import * as qq from 'qqjs' import {findDistFileSha, developerSalesforceCom, deleteFolder} from '../helpers/helper' +import * as fs from 'fs-extra' +import * as path from 'path' +import {promisify} from 'node:util' +import {pipeline as pipelineSync} from 'node:stream' +import got from 'got' +const pipeline = promisify(pipelineSync) const pjson = require('../../package.json') const pjsonPath = require.resolve('../../package.json') const originalVersion = pjson.version @@ -15,22 +20,21 @@ describe('publish:macos', () => { let sha: string let bucket: string let basePrefix: string + const root = path.join(__dirname, '../tmp/test/publish') + beforeEach(async () => { pjson.version = `${pjson.version}-${testRun}` pjson.oclif.update.node.version = process.versions.node bucket = pjson.oclif.update.s3.bucket basePrefix = pjson.oclif.update.s3.folder await deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`) - await qq.writeJSON(pjsonPath, pjson) - const root = qq.join(__dirname, '../tmp/test/publish') - await qq.emptyDir(root) - qq.cd(root) + await fs.writeJSON(pjsonPath, pjson) + await fs.emptyDir(root) }) afterEach(async () => { await deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`) - qq.cd([__dirname, '..']) pjson.version = originalVersion - await qq.writeJSON(pjsonPath, pjson) + await fs.writeJSON(pjsonPath, pjson) }) onlyMacos @@ -40,6 +44,9 @@ describe('publish:macos', () => { }) .command(['upload:macos']) .it('publishes valid releases', async () => { - await qq.download(`https://${developerSalesforceCom}/${basePrefix}/versions/${pjson.version}/${sha}/${pkg}`) + await pipeline( + got.stream(`https://${developerSalesforceCom}/${basePrefix}/versions/${pjson.version}/${sha}/${pkg}`), + fs.createWriteStream(pkg), + ) }) }) diff --git a/test/integration/publish.test.ts b/test/integration/publish.test.ts index 4eb016fdf..0416fda42 100644 --- a/test/integration/publish.test.ts +++ b/test/integration/publish.test.ts @@ -1,13 +1,22 @@ import {expect, test} from '@oclif/test' -import * as qq from 'qqjs' +import {join} from 'path' +import * as fs from 'fs-extra' +import {promisify} from 'node:util' +import {pipeline as pipelineSync} from 'node:stream' +import got from 'got' +import {exec as execSync} from 'child_process' +import {hash} from '../../src/util' +const exec = promisify(execSync) + +const pipeline = promisify(pipelineSync) import aws from '../../src/aws' -import {gitSha} from '../../src/tarballs' import { developerSalesforceCom, - // gitShaSync, + gitShaSync, deleteFolder, } from '../helpers/helper' +import {Interfaces} from '@oclif/core' const pjson = require('../../package.json') const pjsonPath = require.resolve('../../package.json') @@ -15,70 +24,70 @@ const originalVersion = pjson.version const target = [process.platform, process.arch].join('-') const skipIfWindows = process.platform === 'win32' ? test.skip() : test const testRun = `test-${Math.random().toString().split('.')[1].slice(0, 4)}` -// const s3UploadedFiles: string[] = [] +const cwd = process.cwd() +pjson.version = `${pjson.version}-${testRun}` +pjson.oclif.update.node.version = process.versions.node +const bucket = pjson.oclif.update.s3.bucket +const basePrefix = pjson.oclif.update.s3.folder +const root = join(__dirname, '../tmp/test/publish') +const sha = gitShaSync(cwd, {short: true}) + +const manifest = async (path: string, nodeVersion: string) => { + const list = await aws.s3.listObjects({Bucket: bucket, Prefix: `${basePrefix}/${path}`}) + const manifestFile = list.Contents?.map(listObject => listObject.Key).find(f => f!.includes(target) && f!.endsWith('-buildmanifest')) + if (!manifestFile) { + throw new Error(`could not find a buildmanifest file for target ${target}`) + } + + const manifest = await got(`https://${developerSalesforceCom}/${manifestFile}`).json() + const test = async (url: string, expectedSha: string, nodeVersion: string) => { + const xz = url.endsWith('.tar.xz') + const ext = xz ? '.tar.xz' : '.tar.gz' + await pipeline( + got.stream(url), + fs.createWriteStream(join(root, `oclif${ext}`)), + ) + const receivedSha = await hash('sha256', join(root, `oclif${ext}`)) + expect(receivedSha).to.equal(expectedSha) + if (xz) { + await exec('tar xJf oclif.tar.xz', {cwd: root}) + } else { + await exec('tar xzf oclif.tar.gz', {cwd: root}) + } + + const {stdout} = await exec('./oclif/bin/oclif --version', {cwd: root}) + expect(stdout).to.contain(`oclif/${pjson.version} ${target} node-v${nodeVersion}`) + await fs.promises.rm(join(root, 'oclif'), {recursive: true}) + } + + await test(manifest.gz, manifest.sha256gz, nodeVersion) + await test(manifest.xz!, manifest.sha256xz!, nodeVersion) +} + +const folderCleanup = async () => Promise.all([ + deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`), + deleteFolder(bucket, `${basePrefix}/channels/${pjson.version}/`), +]) describe('upload tarballs', async () => { - const cwd = process.cwd() - let sha: string - let bucket: string - let basePrefix: string beforeEach(async () => { - sha = await gitSha(process.cwd(), {short: true}) - pjson.version = `${pjson.version}-${testRun}` - pjson.oclif.update.node.version = process.versions.node - bucket = pjson.oclif.update.s3.bucket - basePrefix = pjson.oclif.update.s3.folder - await deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`) - await qq.writeJSON(pjsonPath, pjson) - const root = qq.join(__dirname, '../tmp/test/publish') - await qq.emptyDir(root) - qq.cd(root) + await folderCleanup() + await fs.writeJSON(pjsonPath, pjson) + await fs.emptyDir(root) }) afterEach(async () => { - await deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`) - qq.cd([__dirname, '..']) + await folderCleanup() pjson.version = originalVersion - await qq.writeJSON(pjsonPath, pjson) + await fs.writeJSON(pjsonPath, pjson) }) skipIfWindows - .command(['pack:tarballs']) - .do(async () => { - sha = await gitSha(cwd, {short: true}) - }) - .command(['upload:tarballs']) - // .command(['promote', '--channel', 'stable', '-t', 'darwin-x64', '--sha', gitShaSync(process.cwd(), {short: true}), '--version', pjson.version]) - .it('promotes valid releases', async () => { - const manifest = async (path: string, nodeVersion: string) => { - const list = await aws.s3.listObjects({Bucket: bucket, Prefix: `${basePrefix}/${path}`}) - const manifestFile = list.Contents?.map(listObject => listObject.Key).find(f => f!.includes(target) && f!.endsWith('-buildmanifest')) - if (!manifestFile) { - throw new Error(`could not find a buildmanifest file for target ${target}`) - } - - const manifest = await qq.readJSON(`https://${developerSalesforceCom}/${manifestFile}`) - const test = async (url: string, expectedSha: string, nodeVersion: string) => { - const xz = url.endsWith('.tar.xz') - const ext = xz ? '.tar.xz' : '.tar.gz' - await qq.download(url, `oclif${ext}`) - const receivedSha = await qq.hash('sha256', `oclif${ext}`) - expect(receivedSha).to.equal(expectedSha) - if (xz) { - await qq.x('tar xJf oclif.tar.xz') - } else { - await qq.x('tar xzf oclif.tar.gz') - } - - const stdout = await qq.x.stdout('./oclif/bin/oclif', ['--version']) - expect(stdout).to.contain(`oclif/${pjson.version} ${target} node-v${nodeVersion}`) - await qq.rm('oclif') - } - - await test(manifest.gz, manifest.sha256gz, nodeVersion) - await test(manifest.xz, manifest.sha256xz, nodeVersion) - } - + .command(['pack:tarballs', '--parallel', '--xz']) + .command(['upload:tarballs', '--xz']) + .command(['promote', '--channel', pjson.version, '--sha', sha, '--version', pjson.version]) + .it('checks uploads for version and channel', async () => { await manifest(`versions/${pjson.version}/${sha}`, pjson.oclif.update.node.version) - // await testPromote('stable') + await manifest(`channels/${pjson.version}`, pjson.oclif.update.node.version) }) }) + diff --git a/test/integration/win.test.ts b/test/integration/win.test.ts index 309a8988b..a202b5630 100644 --- a/test/integration/win.test.ts +++ b/test/integration/win.test.ts @@ -1,7 +1,13 @@ import {expect, test} from '@oclif/test' -import * as qq from 'qqjs' import {deleteFolder, developerSalesforceCom, findDistFileSha, oclifTestingVersionsURI} from '../helpers/helper' import {gitSha} from '../../src/tarballs' +import * as path from 'path' +import * as fs from 'fs-extra' +import {promisify} from 'node:util' +import {pipeline as pipelineSync} from 'node:stream' +import got from 'got' + +const pipeline = promisify(pipelineSync) const pjson = require('../../package.json') const pjsonPath = require.resolve('../../package.json') @@ -15,7 +21,7 @@ describe('publish:win', () => { let sha: string let bucket: string let basePrefix: string - const cwd = process.cwd() + const root = path.join(__dirname, '../tmp/test/publish') beforeEach(async () => { sha = await gitSha(process.cwd(), {short: true}) @@ -24,27 +30,27 @@ describe('publish:win', () => { bucket = pjson.oclif.update.s3.bucket basePrefix = pjson.oclif.update.s3.folder await deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`) - await qq.writeJSON(pjsonPath, pjson) - const root = qq.join(__dirname, '../tmp/test/publish') - await qq.emptyDir(root) - qq.cd(root) + await fs.writeJSON(pjsonPath, pjson) + await fs.emptyDir(root) }) afterEach(async () => { await deleteFolder(bucket, `${basePrefix}/versions/${pjson.version}/`) - qq.cd([__dirname, '..']) pjson.version = originalVersion - await qq.writeJSON(pjsonPath, pjson) + await fs.writeJSON(pjsonPath, pjson) }) skipIfWindows .command(['pack:win']) .command(['upload:win']) .do(async () => { - [pkg, sha] = await findDistFileSha(cwd, 'win32', f => f.endsWith('x64.exe')) + [pkg, sha] = await findDistFileSha(process.cwd(), 'win32', f => f.endsWith('x64.exe')) expect(pkg).to.be.ok expect(sha).to.be.ok }) .it('publishes valid releases', async () => { - await qq.download(`https://${developerSalesforceCom}/${oclifTestingVersionsURI}/${pjson.version}/${sha}/${pkg}`) + await pipeline( + got.stream(`https://${developerSalesforceCom}/${oclifTestingVersionsURI}/${pjson.version}/${sha}/${pkg}`), + fs.createWriteStream(pkg), + ) }) }) diff --git a/test/release.key b/test/release.key index 0d7b2dde3..cd5ad72c3 100644 --- a/test/release.key +++ b/test/release.key @@ -1,30 +1,14 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -mQENBFrMe8gBCADUuDPKDBwneHVs1lUQ4losjkwH5siY9Y2/w2fUqUhiwssuFVBb -aOLzffEMYtdc+rW9zUSBaftovzpnDKgI/bleIxDC/5VdkC4FuxPQYPXfV4gIrTT1 -r7JoPMm9mwHxKMga4QmOFPeIHS+fZ11KMawANA2zvtv0CMrLTBRvHdGkbdO2u7XL -Plp++G6ifFuTLy9DQcRaFUwa2vBuM5Uxxaf6TIlnQndFSib9BHRCFp6cXNJU0VNI -RvD4O9BxioFMuhy+jWKR4tM65Btx7H9ydhqkS0PKMMi4BJOfeCRgBJ7g/tl3uXnH -VwIUb2qsOZ7+jCen7d36nrsZkOSWqhMtBqnBABEBAAG0CW9jbGlmLWRldokBTgQT -AQgAOBYhBFkKfMcUiWgcatzwkzXMdhxCULWABQJazHvIAhsDBQsJCAcCBhUICQoL -AgQWAgMBAh4BAheAAAoJEDXMdhxCULWASjUIAJqvLYuhuO+bLP7F2a5a5lGktG65 -G/U4qjfUo5GasiZsM8RjYfzx8WxSMvrvhH8BobAbr0swtPLfFpl64YZpQpS1M1ES -JxrCiXWHqPV7X3SQkBRZBJn8oG7p18Bjt5xXzcmM5H1uUwDEyF1d6uuokVI0Lk5u -a6fZukKRfOocoVL55Krv1Ted0R0oBvxqQnmVOyly9YUZD3PfF26EZgDek/+X4QWy -qsWJHtGDSHqJkuUv0PrvRhzNmaFs9KX0a/VfaVrvnXzjIW5A/34SsO+OYtDX0nQE -qsA/s+SC+uFr+9YYpVR+E+SizjM1LcP+pWMZ1Add5X/UK6O0dd165FPzg2K5AQ0E -Wsx7yAEIAM3aJIrrRM5NUAaYfes9NX+pk9WQDFywqFRa6/LZ+Baap6Qo67T3C+ib -pcLv6Gj7/wChNX3D9OrRdaNlV8ePfQftJmI2oGJ5ybCgEzRB4ynt782x/+Md/CHm -U8+B12wzWwCSPEPPjijbeHICiW0swhzGY3zt7UDSCiIgGfz8D6espbdnlnrxmnSu -Q6JTONVkmovBBVg3GDTfa07qlgfxRDYHVm0EL18WvkIHqZHASm96uNKdfEMI2C9e -EHV56t2SNW4nJlBXHmI5Tqit5idMR5pyGcJ616g8Y3DghYuikaq0a2edpOQpDDmo -uh9WulS6nHyQxbC73OS2ViPjEB11XHsAEQEAAYkBNgQYAQgAIBYhBFkKfMcUiWgc -atzwkzXMdhxCULWABQJazHvIAhsMAAoJEDXMdhxCULWA1dgIALCwfa+hD7vEmKJG -DRJwrRoynRHerugC+Ntz53VdzfeQuyLwPBN2qT6UawVqGbXLyOfA2egGuKhqqQQl -x/c8aa5LGPEbVAZOCL9Q+nVaaPdUNAV3UdBPP2DWZSzVKvvCBBliUoa7gLgwnC3e -x4G0y02qKndt97H9holbFa6UtGRiEXo+GfVPDCe0B33M6hCnDrvqKC8NwQPI9ZSy -uLBjwbwTovafoZbhoPfHKS5defa3JQ3dHqGBg+GJUeyK/t0vUoMm8MM/LTuRXb5O -SFraQVYholUUPMe5VT0dXAhibxXpcSTf82bl0iuqQndB+E0eq1gu+98D7CWzDDS7 -uUAn/24= -=5Z6m +mDMEY4LSlhYJKwYBBAHaRw8BAQdAcWzX/BFDWIYdO21295BkIIgSv1DVU5BrWZqh +dO+IfxW0Km9jbGlmTnV0IDxzaGFuZS5tY2xhdWdobGluQHNhbGVzZm9yY2UuY29t +PoiaBBMWCgBCFiEEBb22FA4VvCU68lYnnP+iV+KTQ6EFAmOC0pYCGwMFCQPCZwAF +CwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJEJz/olfik0Oh/58A/iKQkXKA +Ls/J/WTNw7xzQT+cuzpDl9Su+YB7fBKorfPvAQDebD3cEuQDOcTfawJ8YPV+lHC9 +qummkpzq5qjSfC5RCrg4BGOC0pYSCisGAQQBl1UBBQEBB0Cwvmg1G4NL80ftEOUo +U3J6Bd+9Xb5GxXNIizylmWHQEwMBCAeIfgQYFgoAJhYhBAW9thQOFbwlOvJWJ5z/ +olfik0OhBQJjgtKWAhsMBQkDwmcAAAoJEJz/olfik0Oh6zAA/1NEUZRBiIfS95Jl +it6tz+pgXwt7uKJtE3GnI+xtxLYjAQDkX/dwKAn2qVeLfoluzbZ421TiV1lMK6p5 +PziLHQbABA== +=Yt3s -----END PGP PUBLIC KEY BLOCK----- diff --git a/tsconfig.json b/tsconfig.json index 6c9a4b111..c1b47e0bd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ "./src" ], "strict": true, + "lib": ["ES2019"], "target": "es2017" }, "include": [ diff --git a/yarn.lock b/yarn.lock index 40bdc7c72..cbd090e01 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,14 +2,14 @@ # yarn lockfile v1 -"@babel/code-frame@7.12.11", "@babel/code-frame@^7.0.0": +"@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.16.0": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0": version "7.16.0" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== @@ -152,11 +152,6 @@ dependencies: "@babel/types" "^7.16.0" -"@babel/helper-validator-identifier@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" - integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== - "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": version "7.15.7" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" @@ -176,16 +171,7 @@ "@babel/traverse" "^7.16.3" "@babel/types" "^7.16.0" -"@babel/highlight@^7.10.4": - version "7.13.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" - integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== - dependencies: - "@babel/helper-validator-identifier" "^7.12.11" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.16.0": +"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.0": version "7.16.0" resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== @@ -506,7 +492,7 @@ is-wsl "^2.1.1" tslib "^2.0.0" -"@oclif/core@^1.16.1", "@oclif/core@^1.20.0", "@oclif/core@^1.20.4": +"@oclif/core@^1.20.0", "@oclif/core@^1.20.4": version "1.20.4" resolved "https://registry.yarnpkg.com/@oclif/core/-/core-1.20.4.tgz#7378b52e1f1b502e383ffb07f95dffc9fd8588ff" integrity sha512-giug32M4YhSYNYKQwE1L57/+k5gp1+Bq3/0vKNQmzAY1tizFGhvBJc6GIRZasHjU+xtZLutQvrVrJo7chX3hxg== @@ -571,16 +557,7 @@ resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91" integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw== -"@oclif/parser@^3.8.0": - version "3.8.4" - resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.4.tgz#1a90fc770a42792e574fb896325618aebbe8c9e4" - integrity sha512-cyP1at3l42kQHZtqDS3KfTeyMvxITGwXwH1qk9ktBYvqgMp5h4vHT+cOD74ld3RqJUOZY/+Zi9lb4Tbza3BtuA== - dependencies: - "@oclif/linewrap" "^1.0.0" - chalk "^2.4.2" - tslib "^1.9.3" - -"@oclif/parser@^3.8.6": +"@oclif/parser@^3.8.0", "@oclif/parser@^3.8.6": version "3.8.6" resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.6.tgz#d5a108af9c708a051cc6b1d27d47359d75f41236" integrity sha512-tXb0NKgSgNxmf6baN6naK+CCwOueaFk93FG9u202U7mTBHUKsioOUlw1SG/iPi9aJM3WE4pHLXmty59pci0OEw== @@ -752,6 +729,18 @@ dependencies: "@octokit/openapi-types" "^11.2.0" +"@sindresorhus/is@^4.0.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + +"@szmarczak/http-timer@^4.0.5": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -777,6 +766,16 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== +"@types/cacheable-request@^6.0.1": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "^3.1.4" + "@types/node" "*" + "@types/responselike" "^1.0.0" + "@types/chai@*", "@types/chai@^4.3.4": version "4.3.4" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" @@ -821,7 +820,7 @@ dependencies: "@types/node" "*" -"@types/glob@*", "@types/glob@^7.1.1": +"@types/glob@*": version "7.1.1" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== @@ -830,6 +829,11 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/http-cache-semantics@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + "@types/inquirer@*": version "7.3.1" resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-7.3.1.tgz#1f231224e7df11ccfaf4cf9acbcc3b935fea292d" @@ -838,16 +842,18 @@ "@types/through" "*" rxjs "^6.4.0" -"@types/json-schema@*": - version "7.0.6" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" - integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== - -"@types/json-schema@^7.0.7": +"@types/json-schema@*", "@types/json-schema@^7.0.7": version "7.0.9" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + dependencies: + "@types/node" "*" + "@types/lodash.template@^4.5.0": version "4.5.0" resolved "https://registry.yarnpkg.com/@types/lodash.template/-/lodash.template-4.5.0.tgz#277654af717ed37ce2687c69f8f221c550276b7a" @@ -917,6 +923,13 @@ dependencies: read-pkg "*" +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + "@types/semver@^7.3.13": version "7.3.13" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" @@ -952,15 +965,7 @@ dependencies: "@types/node" "*" -"@types/vinyl@*": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/vinyl/-/vinyl-2.0.4.tgz#9a7a8071c8d14d3a95d41ebe7135babe4ad5995a" - integrity sha512-2o6a2ixaVI2EbwBPg1QYLGQoHK56p/8X/sGfKbFC8N6sY9lfjsMf/GprtkQkSya0D4uRiutRZ2BWj7k3JvLsAQ== - dependencies: - "@types/expect" "^1.20.4" - "@types/node" "*" - -"@types/vinyl@^2.0.4": +"@types/vinyl@*", "@types/vinyl@^2.0.4": version "2.0.6" resolved "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz#b2d134603557a7c3d2b5d3dc23863ea2b5eb29b0" integrity sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g== @@ -1379,13 +1384,6 @@ binaryextensions@^4.15.0, binaryextensions@^4.16.0: resolved "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.18.0.tgz#22aeada2d14de062c60e8ca59a504a5636a76ceb" integrity sha512-PQu3Kyv9dM4FnwB7XGj1+HucW+ShvJzJqjuw1JkKVs1mWdwOKVcRjOi+pV9X52A0tNvrPCsPkbFFQb+wE1EAXw== -bl@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.1.tgz#1cbb439299609e419b5a74d7fce2f8b37d8e5c6f" - integrity sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ== - dependencies: - readable-stream "^3.0.1" - bl@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -1477,6 +1475,24 @@ cacache@^15.0.3, cacache@^15.0.5, cacache@^15.2.0: tar "^6.0.2" unique-filename "^1.1.1" +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-request@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1623,11 +1639,6 @@ chokidar@3.5.3: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== - chownr@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -1743,6 +1754,13 @@ clone-buffer@^1.0.0: resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + clone-stats@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" @@ -2149,6 +2167,13 @@ decamelize@^4.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + deep-eql@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.2.tgz#270ceb902f87724077e6f6449aed81463f42fc1c" @@ -2173,6 +2198,11 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" +defer-to-connect@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -2274,7 +2304,7 @@ encoding@^0.1.12: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -2497,12 +2527,7 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint-visitor-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" - integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== - -eslint-visitor-keys@^2.1.0: +eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== @@ -2586,12 +2611,7 @@ estraverse@^4.1.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= -estraverse@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" - integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== - -estraverse@^5.2.0: +estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== @@ -2727,7 +2747,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.0.3, fast-glob@^3.2.9: +fast-glob@^3.2.9: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== @@ -2885,20 +2905,6 @@ from@~0: resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - -fs-extra@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" - integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^7.0.0, fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -3057,9 +3063,9 @@ get-stream@^4.0.0: pump "^3.0.0" get-stream@^5.0.0, get-stream@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" @@ -3129,7 +3135,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob@7.2.0, glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@7.2.0, glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.0" resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -3146,34 +3152,13 @@ globals@^11.1.0: resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.6.0: - version "13.6.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.6.0.tgz#d77138e53738567bb96a3916ff6f6b487af20ef7" - integrity sha512-YFKCX0SiPg7l5oKYCJ2zZGxcXprVXHcSnVuvzrT3oSENQonVLqM5pf9fN5dLGZGyCjhw8TN8Btwe/jKnZ0pjvQ== - dependencies: - type-fest "^0.20.2" - -globals@^13.9.0: +globals@^13.6.0, globals@^13.9.0: version "13.12.0" resolved "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== dependencies: type-fest "^0.20.2" -globby@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" - integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - globby@^11.0.1, globby@^11.0.3, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -3186,12 +3171,24 @@ globby@^11.0.1, globby@^11.0.3, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== - -graceful-fs@^4.1.5, graceful-fs@^4.2.6: +got@^11: + version "11.8.5" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046" + integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + +graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.6: version "4.2.9" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== @@ -3306,12 +3303,12 @@ hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" -http-cache-semantics@^4.1.0: +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== -http-call@^5.1.2, http-call@^5.2.2, http-call@^5.2.4: +http-call@^5.2.2, http-call@^5.2.4: version "5.3.0" resolved "https://registry.yarnpkg.com/http-call/-/http-call-5.3.0.tgz#4ded815b13f423de176eb0942d69c43b25b148db" integrity sha512-ahwimsC23ICE4kPl9xTBjKB4inbRaeLyZeRunC/1Jy/Z6X8tv22MEAjK+KBOMSVLaqXPTTmd8638waVIKLGx2w== @@ -3332,6 +3329,14 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -3446,16 +3451,11 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - ini@^1.3.2: version "1.3.7" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" @@ -3651,12 +3651,7 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.0.0.tgz#7fd1a7f1b69e160cde9181d2313f445c68aa2679" - integrity sha512-EYisGhpgSCwspmIuRHGjROWTon2Xp8Z7U03Wubk/bTL5TTRC5R1rGVgyjzBrk9+ULdH6cRD06KRcw/xfqhVYKQ== - -is-plain-obj@^2.1.0: +is-plain-obj@^2.0.0, is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== @@ -3666,11 +3661,6 @@ is-plain-object@^5.0.0: resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -3679,12 +3669,7 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-retry-allowed@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= - -is-retry-allowed@^1.1.0: +is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== @@ -3834,6 +3819,11 @@ jsesc@^2.5.1: resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -3907,6 +3897,13 @@ just-diff@^5.0.1: resolved "https://registry.npmjs.org/just-diff/-/just-diff-5.0.1.tgz#db8fe1cfeea1156f2374bfb289826dca28e7e390" integrity sha512-X00TokkRIDotUIf3EV4xUm6ELc/IkqhS/vPSHdWnsM5y0HoNMfEqrazizI7g78lpHvnRSRt/PFfKtRqJCOGIuQ== +keyv@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" + integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== + dependencies: + json-buffer "3.0.1" + kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -3946,16 +3943,6 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -load-json-file@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1" - integrity sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ== - dependencies: - graceful-fs "^4.1.15" - parse-json "^5.0.0" - strip-bom "^4.0.0" - type-fest "^0.6.0" - load-yaml-file@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.2.0.tgz#af854edaf2bea89346c07549122753c07372f64d" @@ -4064,6 +4051,11 @@ loupe@^2.3.1: dependencies: get-func-name "^2.0.0" +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -4209,20 +4201,12 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -micromatch@^4.0.4: +micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== @@ -4235,6 +4219,16 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + min-indent@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -4271,11 +4265,6 @@ minimist-options@^3.0.1: arrify "^1.0.1" is-plain-obj "^1.1.0" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -4352,13 +4341,6 @@ mkdirp-infer-owner@^2.0.0: infer-owner "^1.0.4" mkdirp "^1.0.3" -mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -4543,6 +4525,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + npm-bundled@^1.1.1: version "1.1.2" resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" @@ -4697,14 +4684,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -4750,6 +4730,11 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -4762,14 +4747,7 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" - integrity sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g== - dependencies: - p-try "^2.0.0" - -p-limit@^2.2.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== @@ -5010,17 +4988,7 @@ picocolors@^1.0.0: resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - -picomatch@^2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" - integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== - -picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -5097,12 +5065,7 @@ proc-log@^1.0.0: resolved "https://registry.npmjs.org/proc-log/-/proc-log-1.0.0.tgz#0d927307401f69ed79341e83a0b2c9a13395eb77" integrity sha512-aCk8AO51s+4JyuYGg3Q/a6gnrlDO09NpVWePtjp7xwphcoQ04x5WAfCyugcsbLooWcMJ87CLkD4+604IckEdhg== -process-nextick-args@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== - -process-nextick-args@~2.0.0: +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== @@ -5170,25 +5133,6 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qqjs@^0.3.11: - version "0.3.11" - resolved "https://registry.yarnpkg.com/qqjs/-/qqjs-0.3.11.tgz#795b9f7d00807d75c391b1241b5be3077143d9ea" - integrity sha512-pB2X5AduTl78J+xRSxQiEmga1jQV0j43jOPs/MTgTLApGFEOn6NgdE2dEjp7nvDtjkIOZbvFIojAiYUx6ep3zg== - dependencies: - chalk "^2.4.1" - debug "^4.1.1" - execa "^0.10.0" - fs-extra "^6.0.1" - get-stream "^5.1.0" - glob "^7.1.2" - globby "^10.0.1" - http-call "^5.1.2" - load-json-file "^6.2.0" - pkg-dir "^4.2.0" - tar-fs "^2.0.0" - tmp "^0.1.0" - write-json-file "^4.1.1" - querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -5204,6 +5148,11 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + ramda@^0.27.1: version "0.27.1" resolved "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" @@ -5282,7 +5231,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -readable-stream@3, readable-stream@^3.0.1, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@3, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -5378,16 +5327,11 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^3.0.0: +regexpp@^3.0.0, regexpp@^3.1.0: version "3.2.0" resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -5420,6 +5364,11 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== +resolve-alpn@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -5433,6 +5382,13 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1: is-core-module "^2.2.0" path-parse "^1.0.6" +responselike@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== + dependencies: + lowercase-keys "^2.0.0" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -5451,13 +5407,6 @@ reusify@^1.0.0: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -5465,14 +5414,7 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -run-async@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - -run-async@^2.4.0: +run-async@^2.0.0, run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== @@ -5496,12 +5438,7 @@ rxjs@^7.0.0, rxjs@^7.2.0: dependencies: tslib "^2.1.0" -safe-buffer@^5.0.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5605,16 +5542,7 @@ shell-quote@^1.7.3: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== -shelljs@^0.8.3: - version "0.8.4" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" - integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -shelljs@^0.8.5: +shelljs@^0.8.3, shelljs@^0.8.5: version "0.8.5" resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== @@ -5640,12 +5568,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -signal-exit@^3.0.3: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.6" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== @@ -5686,21 +5609,7 @@ socks@^2.6.1: ip "^1.1.5" smart-buffer "^4.1.0" -sort-keys@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-3.0.0.tgz#fa751737e3da363ef80632d4fd78e324d661fe9a" - integrity sha512-77XUKMiZN5LvQXZ9sgWfJza19AvYIDwaDGwGiULM+B5XYru8Z90Oh06JvqDlJczvjjYvssrV0aK1GI6+YXvn5A== - dependencies: - is-plain-obj "^2.0.0" - -sort-keys@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.1.0.tgz#727edc12fee49ce482848db07369ec44e0f3e9f2" - integrity sha512-/sRdxzkkPFUYiCrTr/2t+104nDc9AgDmEpeVYuvOWYQe3Djk1GWO6lVw3Vx2jfh1SsR0eehhd1nvFYlzt5e99w== - dependencies: - is-plain-obj "^2.0.0" - -sort-keys@^4.2.0: +sort-keys@^4.0.0, sort-keys@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz#6b7638cee42c506fff8c1cecde7376d21315be18" integrity sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg== @@ -5931,11 +5840,6 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -6031,27 +5935,6 @@ taketalk@^1.0.0: get-stdin "^4.0.1" minimist "^1.1.0" -tar-fs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" - integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA== - dependencies: - chownr "^1.1.1" - mkdirp "^0.5.1" - pump "^3.0.0" - tar-stream "^2.0.0" - -tar-stream@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3" - integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw== - dependencies: - bl "^3.0.0" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - tar@^6.0.2, tar@^6.1.0, tar@^6.1.2: version "6.1.11" resolved "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" @@ -6119,13 +6002,6 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tmp@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" - integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== - dependencies: - rimraf "^2.6.3" - tmp@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" @@ -6565,17 +6441,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.1.tgz#558328352e673b5bb192cf86500d60b230667d4b" - integrity sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -write-file-atomic@^3.0.3: +write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== @@ -6597,18 +6463,6 @@ write-json-file@*: sort-keys "^4.0.0" write-file-atomic "^3.0.0" -write-json-file@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-4.2.0.tgz#85a853ef1c28feb206bd56c2903fe19a6803c7ac" - integrity sha512-PUmPZDcQZRO+w69pGGepxt5r8USK3KTDy5758dOAEzDaL5a6gbe5EPkyOfo28DRT/cruPRiMaAy9XZnDHHoBjQ== - dependencies: - detect-indent "^6.0.0" - graceful-fs "^4.1.15" - is-plain-obj "^2.0.0" - make-dir "^3.0.0" - sort-keys "^3.0.0" - write-file-atomic "^3.0.0" - xml2js@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"