From aecdb222ac3ee54b3f900cc890df20b454e7934c Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 15 Feb 2022 14:33:46 -0500 Subject: [PATCH] Remove request and request-promise-native in favour of got Signed-off-by: Sebastian Malton --- build/download_kubectl.ts | 36 +++++---- package.json | 3 +- src/common/request.ts | 34 --------- src/common/utils/app-version.ts | 15 ++-- src/common/utils/downloadFile.ts | 10 ++- src/main/__test__/cluster.test.ts | 1 - .../base-cluster-detector.ts | 15 ++-- .../cluster-detectors/detector-registry.ts | 50 +++++++------ src/main/helm/helm-repo-manager.ts | 75 +++++++------------ src/main/k8s-request.ts | 34 +++++---- src/main/kubectl/kubectl.ts | 20 ++++- src/main/lens-binary.ts | 23 +++--- .../+preferences/add-helm-repo-dialog.tsx | 2 +- .../components/+preferences/helm-charts.tsx | 13 +++- yarn.lock | 44 ++++------- 15 files changed, 176 insertions(+), 199 deletions(-) delete mode 100644 src/common/request.ts diff --git a/build/download_kubectl.ts b/build/download_kubectl.ts index 8e85ac0c9804..ed970a9dcc53 100644 --- a/build/download_kubectl.ts +++ b/build/download_kubectl.ts @@ -4,19 +4,18 @@ */ import packageInfo from "../package.json"; import fs from "fs"; -import request from "request"; import md5File from "md5-file"; -import requestPromise from "request-promise-native"; import { ensureDir, pathExists } from "fs-extra"; import path from "path"; import { noop } from "lodash"; import { isLinux, isMac } from "../src/common/vars"; +import got from "got"; class KubectlDownloader { - public kubectlVersion: string; - protected url: string; - protected path: string; - protected dirname: string; + public readonly kubectlVersion: string; + protected readonly url: string; + protected readonly path: string; + protected readonly dirname: string; constructor(clusterVersion: string, platform: string, arch: string, target: string) { this.kubectlVersion = clusterVersion; @@ -28,14 +27,14 @@ class KubectlDownloader { } protected async urlEtag() { - const response = await requestPromise({ - method: "HEAD", - uri: this.url, - resolveWithFullResponse: true, - }).catch(console.error); - - if (response.headers["etag"]) { - return response.headers["etag"].replace(/"/g, ""); + try { + const response = await got.head(this.url); + + if (response.headers["etag"]) { + return response.headers["etag"].replace(/"/g, ""); + } + } catch (error) { + console.error(error); } return ""; @@ -71,11 +70,10 @@ class KubectlDownloader { const file = fs.createWriteStream(this.path); console.log(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`); - const requestOpts: request.UriOptions & request.CoreOptions = { - uri: this.url, - gzip: true, - }; - const stream = request(requestOpts); + const stream = got.stream({ + url: this.url, + decompress: true, + }); stream.on("complete", () => { console.log("kubectl binary download finished"); diff --git a/package.json b/package.json index 64cfed725f72..7eb47a27b23e 100644 --- a/package.json +++ b/package.json @@ -216,6 +216,7 @@ "got": "^11.8.3", "grapheme-splitter": "^1.0.4", "handlebars": "^4.7.7", + "hpagent": "^0.1.2", "http-proxy": "^1.18.1", "immer": "^9.0.6", "joi": "^17.5.0", @@ -246,8 +247,6 @@ "react-router": "^5.2.0", "react-virtualized-auto-sizer": "^1.0.6", "readable-stream": "^3.6.0", - "request": "^2.88.2", - "request-promise-native": "^1.0.9", "rfc6902": "^4.0.2", "semver": "^7.3.2", "shell-env": "^3.0.1", diff --git a/src/common/request.ts b/src/common/request.ts deleted file mode 100644 index 331b257f4de4..000000000000 --- a/src/common/request.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import request from "request"; -import requestPromise from "request-promise-native"; -import { UserStore } from "./user-store"; - -// todo: get rid of "request" (deprecated) -// https://github.com/lensapp/lens/issues/459 - -function getDefaultRequestOpts(): Partial { - const { httpsProxy, allowUntrustedCAs } = UserStore.getInstance(); - - return { - proxy: httpsProxy || undefined, - rejectUnauthorized: !allowUntrustedCAs, - }; -} - -/** - * @deprecated - */ -export function customRequest(opts: request.Options) { - return request.defaults(getDefaultRequestOpts())(opts); -} - -/** - * @deprecated - */ -export function customRequestPromise(opts: requestPromise.Options) { - return requestPromise.defaults(getDefaultRequestOpts())(opts); -} diff --git a/src/common/utils/app-version.ts b/src/common/utils/app-version.ts index 28882e092b03..200023ec946b 100644 --- a/src/common/utils/app-version.ts +++ b/src/common/utils/app-version.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import requestPromise from "request-promise-native"; +import got from "got"; import packageInfo from "../../../package.json"; export function getAppVersion(): string { @@ -14,13 +14,14 @@ export function getBundledKubectlVersion(): string { return packageInfo.config.bundledKubectlVersion; } +interface AppVersion { + version: string; +} + export async function getAppVersionFromProxyServer(proxyPort: number): Promise { - const response = await requestPromise({ - method: "GET", - uri: `http://127.0.0.1:${proxyPort}/version`, - resolveWithFullResponse: true, - proxy: undefined, + const { body } = await got(`http://localhost:${proxyPort}/version`, { + responseType: "json", }); - return JSON.parse(response.body).version; + return body.version; } diff --git a/src/common/utils/downloadFile.ts b/src/common/utils/downloadFile.ts index 3ff60470d311..c74ea0d15f74 100644 --- a/src/common/utils/downloadFile.ts +++ b/src/common/utils/downloadFile.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import request from "request"; +import got from "got"; export interface DownloadFileOptions { url: string; @@ -19,7 +19,11 @@ export interface DownloadFileTicket { export function downloadFile({ url, timeout, gzip = true }: DownloadFileOptions): DownloadFileTicket { const fileChunks: Buffer[] = []; - const req = request(url, { gzip, timeout }); + const req = got.stream({ + url, + timeout, + decompress: gzip, + }); const promise: Promise = new Promise((resolve, reject) => { req.on("data", (chunk: Buffer) => { fileChunks.push(chunk); @@ -36,7 +40,7 @@ export function downloadFile({ url, timeout, gzip = true }: DownloadFileOptions) url, promise, cancel() { - req.abort(); + req.destroy(); }, }; } diff --git a/src/main/__test__/cluster.test.ts b/src/main/__test__/cluster.test.ts index 4fa5f5cdd3bd..0faf108be1bd 100644 --- a/src/main/__test__/cluster.test.ts +++ b/src/main/__test__/cluster.test.ts @@ -30,7 +30,6 @@ jest.mock("winston", () => ({ jest.mock("../../common/ipc"); jest.mock("request"); -jest.mock("request-promise-native"); import { Console } from "console"; import mockFs from "mock-fs"; diff --git a/src/main/cluster-detectors/base-cluster-detector.ts b/src/main/cluster-detectors/base-cluster-detector.ts index 6fd8fc483988..763bf07dcdff 100644 --- a/src/main/cluster-detectors/base-cluster-detector.ts +++ b/src/main/cluster-detectors/base-cluster-detector.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { RequestPromiseOptions } from "request-promise-native"; import type { Cluster } from "../../common/cluster/cluster"; +import type { OptionsOfJSONResponseBody } from "got"; import { k8sRequest } from "../k8s-request"; export type ClusterDetectionResult = { @@ -12,17 +12,14 @@ export type ClusterDetectionResult = { accuracy: number }; -export class BaseClusterDetector { - key: string; +export abstract class BaseClusterDetector { + abstract key: string; - constructor(public cluster: Cluster) { - } + constructor(public cluster: Cluster) {} - detect(): Promise { - return null; - } + abstract detect(): Promise; - protected async k8sRequest(path: string, options: RequestPromiseOptions = {}): Promise { + protected async k8sRequest(path: string, options: OptionsOfJSONResponseBody = {}): Promise { return k8sRequest(this.cluster, path, options); } } diff --git a/src/main/cluster-detectors/detector-registry.ts b/src/main/cluster-detectors/detector-registry.ts index e2741c13535c..cdd0eab4ceef 100644 --- a/src/main/cluster-detectors/detector-registry.ts +++ b/src/main/cluster-detectors/detector-registry.ts @@ -5,43 +5,51 @@ import { observable } from "mobx"; import type { ClusterMetadata } from "../../common/cluster-types"; -import { Singleton } from "../../common/utils"; +import { iter, Singleton } from "../../common/utils"; import type { Cluster } from "../../common/cluster/cluster"; import type { BaseClusterDetector, ClusterDetectionResult } from "./base-cluster-detector"; +export type ClusterDetectionConstructor = new (cluster: Cluster) => BaseClusterDetector; + export class DetectorRegistry extends Singleton { - registry = observable.array([], { deep: false }); + private registry = observable.array([], { deep: false }); - add(detectorClass: typeof BaseClusterDetector): this { + add(detectorClass: ClusterDetectionConstructor): this { this.registry.push(detectorClass); return this; } async detectForCluster(cluster: Cluster): Promise { - const results: { [key: string]: ClusterDetectionResult } = {}; + const results = new Map(); + const detections = this.registry.map(async DetectorClass => { + const detector = new DetectorClass(cluster); - for (const detectorClass of this.registry) { - const detector = new detectorClass(cluster); + return [detector.key, await detector.detect()] as const; + }); + for (const detection of detections) { try { - const data = await detector.detect(); - - if (!data) continue; - const existingValue = results[detector.key]; - - if (existingValue && existingValue.accuracy > data.accuracy) continue; // previous value exists and is more accurate - results[detector.key] = data; - } catch (e) { - // detector raised error, do nothing + const [key, data] = await detection; + + if ( + data && ( + !results.has(key) + || results.get(key).accuracy <= data.accuracy + ) + ) { + results.set(key, data); + } + } catch { + // ignore errors } } - const metadata: ClusterMetadata = {}; - - for (const [key, result] of Object.entries(results)) { - metadata[key] = result.value; - } - return metadata; + return Object.fromEntries( + iter.map( + results.entries(), + ([key, { value }]) => [key, value], + ), + ); } } diff --git a/src/main/helm/helm-repo-manager.ts b/src/main/helm/helm-repo-manager.ts index 9ca2ae05d279..ea8bb2c8eb01 100644 --- a/src/main/helm/helm-repo-manager.ts +++ b/src/main/helm/helm-repo-manager.ts @@ -8,10 +8,9 @@ import { BaseEncodingOptions, readFile } from "fs-extra"; import { promiseExecFile } from "../../common/utils/promise-exec"; import { helmCli } from "./helm-cli"; import { Singleton } from "../../common/utils/singleton"; -import { customRequestPromise } from "../../common/request"; -import orderBy from "lodash/orderBy"; import logger from "../logger"; import type { ExecFileOptions } from "child_process"; +import { iter } from "../../common/utils"; export type HelmEnv = Record & { HELM_REPOSITORY_CACHE?: string; @@ -46,47 +45,42 @@ async function execHelm(args: string[], options?: BaseEncodingOptions & ExecFile } } +/** + * A Regex for matching strings of the form = where key MUST NOT + * include a '=' + */ +const envVarMatcher = /^((?[^=]*)=(?.*))$/; + export class HelmRepoManager extends Singleton { - protected repos: HelmRepo[]; - protected helmEnv: HelmEnv; - protected initialized: boolean; - - public static async loadAvailableRepos(): Promise { - const res = await customRequestPromise({ - uri: "https://github.com/lensapp/artifact-hub-repositories/releases/download/latest/repositories.json", - json: true, - resolveWithFullResponse: true, - timeout: 10000, - }); - - return orderBy(res.body, repo => repo.name); - } + protected helmEnv: HelmEnv | null = null; - private async init() { + private async ensureInitialized() { helmCli.setLogger(logger); await helmCli.ensureBinary(); - if (!this.initialized) { + if (!this.helmEnv) { this.helmEnv = await HelmRepoManager.parseHelmEnv(); - await HelmRepoManager.update(); - this.initialized = true; + + try { + await HelmRepoManager.update(); + } catch (error) { + logger.warn(`[HELM-REPO-MANAGER]: failed to update helm repos`, error); + } } } - protected static async parseHelmEnv() { + protected static async parseHelmEnv(): Promise { const output = await execHelm(["env"]); - const lines = output.split(/\r?\n/); // split by new line feed - const env: HelmEnv = {}; - - lines.forEach((line: string) => { - const [key, value] = line.split("="); - if (key && value) { - env[key] = value.replace(/"/g, ""); // strip quotas - } - }); - - return env; + return Object.fromEntries( + iter.map( + iter.filterMap( + output.split(/\r?\n/), + line => line.match(envVarMatcher), + ), + ({ groups: { key, value }}) => [key, JSON.parse(value)], + ), + ); } public async repo(name: string): Promise { @@ -114,9 +108,7 @@ export class HelmRepoManager extends Singleton { public async repositories(): Promise { try { - if (!this.initialized) { - await this.init(); - } + await this.ensureInitialized(); const { repositories } = await this.readConfig(); @@ -144,18 +136,7 @@ export class HelmRepoManager extends Singleton { ]); } - public static async addRepo({ name, url }: HelmRepo) { - logger.info(`[HELM]: adding repo "${name}" from ${url}`); - - return execHelm([ - "repo", - "add", - name, - url, - ]); - } - - public static async addCustomRepo({ name, url, insecureSkipTlsVerify, username, password, caFile, keyFile, certFile }: HelmRepo) { + public static async addRepo({ name, url, insecureSkipTlsVerify, username, password, caFile, keyFile, certFile }: HelmRepo) { logger.info(`[HELM]: adding repo ${name} from ${url}`); const args = [ "repo", diff --git a/src/main/k8s-request.ts b/src/main/k8s-request.ts index 43002f0b4776..8b80b46fa0f0 100644 --- a/src/main/k8s-request.ts +++ b/src/main/k8s-request.ts @@ -3,32 +3,40 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import request, { RequestPromiseOptions } from "request-promise-native"; import { apiKubePrefix } from "../common/vars"; import type { IMetricsReqParams } from "../common/k8s-api/endpoints/metrics.api"; import { LensProxy } from "./lens-proxy"; import type { Cluster } from "../common/cluster/cluster"; +import got, { OptionsOfJSONResponseBody } from "got"; -export async function k8sRequest(cluster: Cluster, path: string, options: RequestPromiseOptions = {}): Promise { - const kubeProxyUrl = `http://localhost:${LensProxy.getInstance().port}${apiKubePrefix}`; +function getKubeProxyUrl() { + return `http://localhost:${LensProxy.getInstance().port}${apiKubePrefix}`; +} + +export async function k8sRequest(cluster: Cluster, path: string, options: OptionsOfJSONResponseBody = {}): Promise { + const kubeProxyUrl = getKubeProxyUrl(); - options.headers ??= {}; - options.json ??= true; options.timeout ??= 30000; + options.headers ??= {}; options.headers.Host = `${cluster.id}.${new URL(kubeProxyUrl).host}`; // required in ClusterManager.getClusterForRequest() + options.responseType = "json"; - return request(kubeProxyUrl + path, options); + const { body } = await got(kubeProxyUrl + path, options); + + return body; } export async function getMetrics(cluster: Cluster, prometheusPath: string, queryParams: IMetricsReqParams & { query: string }): Promise { const prometheusPrefix = cluster.preferences.prometheus?.prefix || ""; - const metricsPath = `/api/v1/namespaces/${prometheusPath}/proxy${prometheusPrefix}/api/v1/query_range`; - - return k8sRequest(cluster, metricsPath, { - timeout: 0, - resolveWithFullResponse: false, - json: true, - method: "POST", + const kubeProxyUrl = getKubeProxyUrl(); + const url = `${kubeProxyUrl}/api/v1/namespaces/${prometheusPath}/proxy${prometheusPrefix}/api/v1/query_range`; + const { body } = await got.post(url, { form: queryParams, + headers: { + Host: `${cluster.id}.${new URL(kubeProxyUrl).host}`, + }, + responseType: "json", }); + + return body; } diff --git a/src/main/kubectl/kubectl.ts b/src/main/kubectl/kubectl.ts index 6469f6e7befd..2fb410b81fba 100644 --- a/src/main/kubectl/kubectl.ts +++ b/src/main/kubectl/kubectl.ts @@ -14,7 +14,8 @@ import { getBundledKubectlVersion } from "../../common/utils/app-version"; import { isDevelopment, isWindows, isTestEnv } from "../../common/vars"; import { SemVer } from "semver"; import { defaultPackageMirror, packageMirrors } from "../../common/user-store/preferences-helpers"; -import got from "got/dist/source"; +import got, { Agents } from "got"; +import { HttpsProxyAgent } from "hpagent"; import { promisify } from "util"; import stream from "stream"; import { noop } from "lodash/fp"; @@ -68,6 +69,8 @@ interface Dependencies { downloadBinariesPath?: string downloadKubectlBinaries: boolean downloadMirror: string + httpsProxy?: string; + allowUntrustedCAs?: boolean; }; } @@ -297,7 +300,20 @@ export class Kubectl { logger.info(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`); - const downloadStream = got.stream({ url: this.url, decompress: true }); + const { httpsProxy, allowUntrustedCAs } = this.dependencies.userStore; + const agent: Agents | false = httpsProxy + ? { + https: new HttpsProxyAgent({ + proxy: httpsProxy, + }), + } + : false; + const downloadStream = got.stream({ + url: this.url, + decompress: true, + rejectUnauthorized: !allowUntrustedCAs, + agent, + }); const fileWriteStream = fs.createWriteStream(this.path, { mode: 0o755 }); const pipeline = promisify(stream.pipeline); diff --git a/src/main/lens-binary.ts b/src/main/lens-binary.ts index 2b8b5c27d313..4153c7e8ab9b 100644 --- a/src/main/lens-binary.ts +++ b/src/main/lens-binary.ts @@ -5,18 +5,23 @@ import path from "path"; import fs from "fs"; -import request from "request"; import { ensureDir, pathExists } from "fs-extra"; import * as tar from "tar"; import { isWindows } from "../common/vars"; import type winston from "winston"; +import got, { Options } from "got"; +import type { Merge } from "type-fest"; + +type GotStreamOptions = Merge; export type LensBinaryOpts = { version: string; baseDir: string; originalBinaryName: string; newBinaryName?: string; - requestOpts?: request.Options; + requestOpts?: GotStreamOptions; }; export class LensBinary { @@ -31,7 +36,7 @@ export class LensBinary { protected platformName: string; protected arch: string; protected originalBinaryName: string; - protected requestOpts: request.Options; + protected requestOpts: GotStreamOptions; protected logger: Console | winston.Logger; constructor(opts: LensBinaryOpts) { @@ -40,7 +45,7 @@ export class LensBinary { this.originalBinaryName = opts.originalBinaryName; this.binaryName = opts.newBinaryName || opts.originalBinaryName; this.binaryVersion = opts.version; - this.requestOpts = opts.requestOpts; + this.requestOpts = opts.requestOpts || {}; this.logger = console; let arch = null; @@ -160,6 +165,7 @@ export class LensBinary { } protected async downloadBinary() { + const binaryPath = this.tarPath || this.getBinaryPath(); await ensureDir(this.getBinaryDir(), 0o755); @@ -168,12 +174,11 @@ export class LensBinary { const url = this.getUrl(); this.logger.info(`Downloading ${this.originalBinaryName} ${this.binaryVersion} from ${url} to ${binaryPath}`); - const requestOpts: request.UriOptions & request.CoreOptions = { - uri: url, - gzip: true, + + const stream = got.stream(url, { + decompress: true, ...this.requestOpts, - }; - const stream = request(requestOpts); + }); stream.on("complete", () => { this.logger.info(`Download of ${this.originalBinaryName} finished`); diff --git a/src/renderer/components/+preferences/add-helm-repo-dialog.tsx b/src/renderer/components/+preferences/add-helm-repo-dialog.tsx index 249046e6b134..175033e97542 100644 --- a/src/renderer/components/+preferences/add-helm-repo-dialog.tsx +++ b/src/renderer/components/+preferences/add-helm-repo-dialog.tsx @@ -91,7 +91,7 @@ export class AddHelmRepoDialog extends React.Component { async addCustomRepo() { try { - await HelmRepoManager.addCustomRepo(this.helmRepo); + await HelmRepoManager.addRepo(this.helmRepo); Notifications.ok(<>Helm repository {this.helmRepo.name} has added); this.props.onAddRepo(); this.close(); diff --git a/src/renderer/components/+preferences/helm-charts.tsx b/src/renderer/components/+preferences/helm-charts.tsx index 5bd8fb387a6d..d1da210bc423 100644 --- a/src/renderer/components/+preferences/helm-charts.tsx +++ b/src/renderer/components/+preferences/helm-charts.tsx @@ -18,6 +18,17 @@ import { observer } from "mobx-react"; import { RemovableItem } from "./removable-item"; import { Notice } from "../+extensions/notice"; import { Spinner } from "../spinner"; +import got from "got"; +import { orderBy } from "lodash"; + +async function loadAvailableHelmRepos(): Promise { + const { body } = await got.get("https://github.com/lensapp/artifact-hub-repositories/releases/download/latest/repositories.json", { + timeout: 10_000, + responseType: "json", + }); + + return orderBy(body, repo => repo.name); +} @observer export class HelmCharts extends React.Component { @@ -47,7 +58,7 @@ export class HelmCharts extends React.Component { try { if (!this.repos.length) { - this.repos = await HelmRepoManager.loadAvailableRepos(); + this.repos = await loadAvailableHelmRepos(); } const repos = await HelmRepoManager.getInstance().repositories(); // via helm-cli diff --git a/yarn.lock b/yarn.lock index 4682cf7f9836..8382fc976bb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6664,6 +6664,11 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" +hpagent@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-0.1.2.tgz#cab39c66d4df2d4377dbd212295d878deb9bdaa9" + integrity sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ== + html-encoding-sniffer@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" @@ -8753,7 +8758,7 @@ lodash.without@~4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@4.x, lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: +lodash@4.x, lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -11389,22 +11394,6 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -request-promise-core@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" - integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== - dependencies: - lodash "^4.17.19" - -request-promise-native@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" - integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== - dependencies: - request-promise-core "1.1.4" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" @@ -12320,11 +12309,6 @@ static-extend@^0.1.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= - stream-buffers@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-3.0.2.tgz#5249005a8d5c2d00b3a32e6e0a6ea209dc4f3521" @@ -12937,14 +12921,6 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@^2.3.3, tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - tough-cookie@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" @@ -12954,6 +12930,14 @@ tough-cookie@^4.0.0: punycode "^2.1.1" universalify "^0.1.2" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"