mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Upgrade to latest node-fetch (#6046)
* Upgrade to latest node-fetch - Introduce injection tokens for retriving the implementation of node-fetch via await import() calls - Add webpack file for compiling node-fetch to electron-renderer single file format Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update lock file Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add type packages which were removed for some reason Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add more dev @types deps that weren't added last time Signed-off-by: Sebastian Malton <sebastian@malton.name> * Simpify by using webpack to create a commonjs package Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix build for integration tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix unit tests on CI not having all deps Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Revert accidental timeout change Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace manually specifying nodeJS externals with preset Signed-off-by: Sebastian Malton <sebastian@malton.name> Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
6d9a76835c
commit
86ac417cab
@ -12,6 +12,7 @@ module.exports = {
|
|||||||
"**/static/**/*",
|
"**/static/**/*",
|
||||||
"**/site/**/*",
|
"**/site/**/*",
|
||||||
"extensions/*/*.tgz",
|
"extensions/*/*.tgz",
|
||||||
|
"build/webpack/**/*",
|
||||||
],
|
],
|
||||||
settings: {
|
settings: {
|
||||||
react: {
|
react: {
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,3 +17,4 @@ types/extension-renderer-api.d.ts
|
|||||||
extensions/*/dist
|
extensions/*/dist
|
||||||
docs/extensions/api
|
docs/extensions/api
|
||||||
site/
|
site/
|
||||||
|
build/webpack/
|
||||||
|
|||||||
2
Makefile
2
Makefile
@ -44,7 +44,7 @@ tag-release:
|
|||||||
scripts/tag-release.sh $(CMD_ARGS)
|
scripts/tag-release.sh $(CMD_ARGS)
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: binaries/client
|
test: node_modules binaries/client
|
||||||
yarn run jest $(or $(CMD_ARGS), "src")
|
yarn run jest $(or $(CMD_ARGS), "src")
|
||||||
|
|
||||||
.PHONY: integration
|
.PHONY: integration
|
||||||
|
|||||||
@ -8,15 +8,19 @@ import { open } from "fs/promises";
|
|||||||
import type { WriteStream } from "fs-extra";
|
import type { WriteStream } from "fs-extra";
|
||||||
import { constants, ensureDir, unlink } from "fs-extra";
|
import { constants, ensureDir, unlink } from "fs-extra";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fetch from "node-fetch";
|
import type * as FetchModule from "node-fetch";
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
import { pipeline as _pipeline, Transform, Writable } from "stream";
|
import { pipeline as _pipeline, Transform, Writable } from "stream";
|
||||||
import type { SingleBar } from "cli-progress";
|
import type { SingleBar } from "cli-progress";
|
||||||
import { MultiBar } from "cli-progress";
|
import { MultiBar } from "cli-progress";
|
||||||
import { extract } from "tar-stream";
|
import { extract } from "tar-stream";
|
||||||
import gunzip from "gunzip-maybe";
|
import gunzip from "gunzip-maybe";
|
||||||
import { getBinaryName, normalizedPlatform } from "../src/common/vars";
|
import { getBinaryName } from "../src/common/vars";
|
||||||
import { isErrnoException } from "../src/common/utils";
|
import { isErrnoException, setTimeoutFor } from "../src/common/utils";
|
||||||
|
|
||||||
|
type Response = FetchModule.Response;
|
||||||
|
type RequestInfo = FetchModule.RequestInfo;
|
||||||
|
type RequestInit = FetchModule.RequestInit;
|
||||||
|
|
||||||
const pipeline = promisify(_pipeline);
|
const pipeline = promisify(_pipeline);
|
||||||
|
|
||||||
@ -29,6 +33,10 @@ interface BinaryDownloaderArgs {
|
|||||||
readonly baseDir: string;
|
readonly baseDir: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface BinaryDownloaderDependencies {
|
||||||
|
fetch: (url: RequestInfo, init?: RequestInit) => Promise<Response>;
|
||||||
|
}
|
||||||
|
|
||||||
abstract class BinaryDownloader {
|
abstract class BinaryDownloader {
|
||||||
protected abstract readonly url: string;
|
protected abstract readonly url: string;
|
||||||
protected readonly bar: SingleBar;
|
protected readonly bar: SingleBar;
|
||||||
@ -38,7 +46,7 @@ abstract class BinaryDownloader {
|
|||||||
return [file];
|
return [file];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(public readonly args: BinaryDownloaderArgs, multiBar: MultiBar) {
|
constructor(protected readonly dependencies: BinaryDownloaderDependencies, public readonly args: BinaryDownloaderArgs, multiBar: MultiBar) {
|
||||||
this.bar = multiBar.create(1, 0, args);
|
this.bar = multiBar.create(1, 0, args);
|
||||||
this.target = path.join(args.baseDir, args.platform, args.fileArch, args.binaryName);
|
this.target = path.join(args.baseDir, args.platform, args.fileArch, args.binaryName);
|
||||||
}
|
}
|
||||||
@ -49,8 +57,10 @@ abstract class BinaryDownloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const stream = await fetch(this.url, {
|
|
||||||
timeout: 15 * 60 * 1000, // 15min
|
setTimeoutFor(controller, 15 * 60 * 1000);
|
||||||
|
|
||||||
|
const stream = await this.dependencies.fetch(this.url, {
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
});
|
});
|
||||||
const total = Number(stream.headers.get("content-length"));
|
const total = Number(stream.headers.get("content-length"));
|
||||||
@ -72,6 +82,10 @@ abstract class BinaryDownloader {
|
|||||||
*/
|
*/
|
||||||
const handle = fileHandle = await open(this.target, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
|
const handle = fileHandle = await open(this.target, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
|
||||||
|
|
||||||
|
if (!stream.body) {
|
||||||
|
throw new Error("no body on stream");
|
||||||
|
}
|
||||||
|
|
||||||
await pipeline(
|
await pipeline(
|
||||||
stream.body,
|
stream.body,
|
||||||
new Transform({
|
new Transform({
|
||||||
@ -108,10 +122,10 @@ abstract class BinaryDownloader {
|
|||||||
class LensK8sProxyDownloader extends BinaryDownloader {
|
class LensK8sProxyDownloader extends BinaryDownloader {
|
||||||
protected readonly url: string;
|
protected readonly url: string;
|
||||||
|
|
||||||
constructor(args: Omit<BinaryDownloaderArgs, "binaryName">, bar: MultiBar) {
|
constructor(deps: BinaryDownloaderDependencies, args: Omit<BinaryDownloaderArgs, "binaryName">, bar: MultiBar) {
|
||||||
const binaryName = getBinaryName("lens-k8s-proxy", { forPlatform: args.platform });
|
const binaryName = getBinaryName("lens-k8s-proxy", { forPlatform: args.platform });
|
||||||
|
|
||||||
super({ ...args, binaryName }, bar);
|
super(deps, { ...args, binaryName }, bar);
|
||||||
this.url = `https://github.com/lensapp/lens-k8s-proxy/releases/download/v${args.version}/lens-k8s-proxy-${args.platform}-${args.downloadArch}`;
|
this.url = `https://github.com/lensapp/lens-k8s-proxy/releases/download/v${args.version}/lens-k8s-proxy-${args.platform}-${args.downloadArch}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,10 +133,10 @@ class LensK8sProxyDownloader extends BinaryDownloader {
|
|||||||
class KubectlDownloader extends BinaryDownloader {
|
class KubectlDownloader extends BinaryDownloader {
|
||||||
protected readonly url: string;
|
protected readonly url: string;
|
||||||
|
|
||||||
constructor(args: Omit<BinaryDownloaderArgs, "binaryName">, bar: MultiBar) {
|
constructor(deps: BinaryDownloaderDependencies, args: Omit<BinaryDownloaderArgs, "binaryName">, bar: MultiBar) {
|
||||||
const binaryName = getBinaryName("kubectl", { forPlatform: args.platform });
|
const binaryName = getBinaryName("kubectl", { forPlatform: args.platform });
|
||||||
|
|
||||||
super({ ...args, binaryName }, bar);
|
super(deps, { ...args, binaryName }, bar);
|
||||||
this.url = `https://storage.googleapis.com/kubernetes-release/release/v${args.version}/bin/${args.platform}/${args.downloadArch}/${binaryName}`;
|
this.url = `https://storage.googleapis.com/kubernetes-release/release/v${args.version}/bin/${args.platform}/${args.downloadArch}/${binaryName}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,10 +144,10 @@ class KubectlDownloader extends BinaryDownloader {
|
|||||||
class HelmDownloader extends BinaryDownloader {
|
class HelmDownloader extends BinaryDownloader {
|
||||||
protected readonly url: string;
|
protected readonly url: string;
|
||||||
|
|
||||||
constructor(args: Omit<BinaryDownloaderArgs, "binaryName">, bar: MultiBar) {
|
constructor(deps: BinaryDownloaderDependencies, args: Omit<BinaryDownloaderArgs, "binaryName">, bar: MultiBar) {
|
||||||
const binaryName = getBinaryName("helm", { forPlatform: args.platform });
|
const binaryName = getBinaryName("helm", { forPlatform: args.platform });
|
||||||
|
|
||||||
super({ ...args, binaryName }, bar);
|
super(deps, { ...args, binaryName }, bar);
|
||||||
this.url = `https://get.helm.sh/helm-v${args.version}-${args.platform}-${args.downloadArch}.tar.gz`;
|
this.url = `https://get.helm.sh/helm-v${args.version}-${args.platform}-${args.downloadArch}.tar.gz`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +174,24 @@ class HelmDownloader extends BinaryDownloader {
|
|||||||
|
|
||||||
type SupportedPlatform = "darwin" | "linux" | "windows";
|
type SupportedPlatform = "darwin" | "linux" | "windows";
|
||||||
|
|
||||||
|
const importFetchModule = new Function('return import("node-fetch")') as () => Promise<typeof FetchModule>;
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
|
const deps: BinaryDownloaderDependencies = {
|
||||||
|
fetch: (await importFetchModule()).default,
|
||||||
|
};
|
||||||
|
const normalizedPlatform = (() => {
|
||||||
|
switch (process.platform) {
|
||||||
|
case "darwin":
|
||||||
|
return "darwin";
|
||||||
|
case "linux":
|
||||||
|
return "linux";
|
||||||
|
case "win32":
|
||||||
|
return "windows";
|
||||||
|
default:
|
||||||
|
throw new Error(`platform=${process.platform} is unsupported`);
|
||||||
|
}
|
||||||
|
})();
|
||||||
const multiBar = new MultiBar({
|
const multiBar = new MultiBar({
|
||||||
align: "left",
|
align: "left",
|
||||||
clearOnComplete: false,
|
clearOnComplete: false,
|
||||||
@ -171,21 +202,21 @@ async function main() {
|
|||||||
});
|
});
|
||||||
const baseDir = path.join(__dirname, "..", "binaries", "client");
|
const baseDir = path.join(__dirname, "..", "binaries", "client");
|
||||||
const downloaders: BinaryDownloader[] = [
|
const downloaders: BinaryDownloader[] = [
|
||||||
new LensK8sProxyDownloader({
|
new LensK8sProxyDownloader(deps, {
|
||||||
version: packageInfo.config.k8sProxyVersion,
|
version: packageInfo.config.k8sProxyVersion,
|
||||||
platform: normalizedPlatform,
|
platform: normalizedPlatform,
|
||||||
downloadArch: "amd64",
|
downloadArch: "amd64",
|
||||||
fileArch: "x64",
|
fileArch: "x64",
|
||||||
baseDir,
|
baseDir,
|
||||||
}, multiBar),
|
}, multiBar),
|
||||||
new KubectlDownloader({
|
new KubectlDownloader(deps, {
|
||||||
version: packageInfo.config.bundledKubectlVersion,
|
version: packageInfo.config.bundledKubectlVersion,
|
||||||
platform: normalizedPlatform,
|
platform: normalizedPlatform,
|
||||||
downloadArch: "amd64",
|
downloadArch: "amd64",
|
||||||
fileArch: "x64",
|
fileArch: "x64",
|
||||||
baseDir,
|
baseDir,
|
||||||
}, multiBar),
|
}, multiBar),
|
||||||
new HelmDownloader({
|
new HelmDownloader(deps, {
|
||||||
version: packageInfo.config.bundledHelmVersion,
|
version: packageInfo.config.bundledHelmVersion,
|
||||||
platform: normalizedPlatform,
|
platform: normalizedPlatform,
|
||||||
downloadArch: "amd64",
|
downloadArch: "amd64",
|
||||||
@ -196,21 +227,21 @@ async function main() {
|
|||||||
|
|
||||||
if (normalizedPlatform !== "windows") {
|
if (normalizedPlatform !== "windows") {
|
||||||
downloaders.push(
|
downloaders.push(
|
||||||
new LensK8sProxyDownloader({
|
new LensK8sProxyDownloader(deps, {
|
||||||
version: packageInfo.config.k8sProxyVersion,
|
version: packageInfo.config.k8sProxyVersion,
|
||||||
platform: normalizedPlatform,
|
platform: normalizedPlatform,
|
||||||
downloadArch: "arm64",
|
downloadArch: "arm64",
|
||||||
fileArch: "arm64",
|
fileArch: "arm64",
|
||||||
baseDir,
|
baseDir,
|
||||||
}, multiBar),
|
}, multiBar),
|
||||||
new KubectlDownloader({
|
new KubectlDownloader(deps, {
|
||||||
version: packageInfo.config.bundledKubectlVersion,
|
version: packageInfo.config.bundledKubectlVersion,
|
||||||
platform: normalizedPlatform,
|
platform: normalizedPlatform,
|
||||||
downloadArch: "arm64",
|
downloadArch: "arm64",
|
||||||
fileArch: "arm64",
|
fileArch: "arm64",
|
||||||
baseDir,
|
baseDir,
|
||||||
}, multiBar),
|
}, multiBar),
|
||||||
new HelmDownloader({
|
new HelmDownloader(deps, {
|
||||||
version: packageInfo.config.bundledHelmVersion,
|
version: packageInfo.config.bundledHelmVersion,
|
||||||
platform: normalizedPlatform,
|
platform: normalizedPlatform,
|
||||||
downloadArch: "arm64",
|
downloadArch: "arm64",
|
||||||
|
|||||||
@ -26,6 +26,8 @@
|
|||||||
"compile:main": "yarn run webpack --config webpack/main.ts",
|
"compile:main": "yarn run webpack --config webpack/main.ts",
|
||||||
"compile:renderer": "yarn run webpack --config webpack/renderer.ts",
|
"compile:renderer": "yarn run webpack --config webpack/renderer.ts",
|
||||||
"compile:extension-types": "yarn run webpack --config webpack/extensions.ts",
|
"compile:extension-types": "yarn run webpack --config webpack/extensions.ts",
|
||||||
|
"compile:node-fetch": "yarn run webpack --config ./webpack/node-fetch.ts",
|
||||||
|
"postinstall": "yarn run compile:node-fetch",
|
||||||
"npm:fix-package-version": "yarn run ts-node build/set_npm_version.ts",
|
"npm:fix-package-version": "yarn run ts-node build/set_npm_version.ts",
|
||||||
"build:linux": "yarn run compile && electron-builder --linux --dir",
|
"build:linux": "yarn run compile && electron-builder --linux --dir",
|
||||||
"build:mac": "yarn run compile && electron-builder --mac --dir",
|
"build:mac": "yarn run compile && electron-builder --mac --dir",
|
||||||
@ -262,7 +264,7 @@
|
|||||||
"moment-timezone": "^0.5.38",
|
"moment-timezone": "^0.5.38",
|
||||||
"monaco-editor": "^0.29.1",
|
"monaco-editor": "^0.29.1",
|
||||||
"monaco-editor-webpack-plugin": "^5.0.0",
|
"monaco-editor-webpack-plugin": "^5.0.0",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^3.2.10",
|
||||||
"node-pty": "0.10.1",
|
"node-pty": "0.10.1",
|
||||||
"npm": "^8.19.3",
|
"npm": "^8.19.3",
|
||||||
"p-limit": "^3.1.0",
|
"p-limit": "^3.1.0",
|
||||||
@ -332,9 +334,7 @@
|
|||||||
"@types/memorystream": "^0.3.0",
|
"@types/memorystream": "^0.3.0",
|
||||||
"@types/mini-css-extract-plugin": "^2.4.0",
|
"@types/mini-css-extract-plugin": "^2.4.0",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/node": "^16.18.3",
|
"@types/node": "^16.18.2",
|
||||||
"@types/node-fetch": "^2.6.2",
|
|
||||||
"@types/npm": "^2.0.32",
|
|
||||||
"@types/proper-lockfile": "^4.1.2",
|
"@types/proper-lockfile": "^4.1.2",
|
||||||
"@types/randomcolor": "^0.5.6",
|
"@types/randomcolor": "^0.5.6",
|
||||||
"@types/react": "^17.0.45",
|
"@types/react": "^17.0.45",
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import type { RequestInit, Response } from "node-fetch";
|
import type { RequestInit, Response } from "node-fetch";
|
||||||
import type { JsonValue } from "type-fest";
|
|
||||||
import type { AsyncResult } from "../utils/async-result";
|
import type { AsyncResult } from "../utils/async-result";
|
||||||
import fetchInjectable from "./fetch.injectable";
|
import fetchInjectable from "./fetch.injectable";
|
||||||
|
|
||||||
@ -12,7 +11,7 @@ export interface DownloadJsonOptions {
|
|||||||
signal?: AbortSignal | null | undefined;
|
signal?: AbortSignal | null | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DownloadJson = (url: string, opts?: DownloadJsonOptions) => Promise<AsyncResult<JsonValue, string>>;
|
export type DownloadJson = (url: string, opts?: DownloadJsonOptions) => Promise<AsyncResult<unknown, string>>;
|
||||||
|
|
||||||
const downloadJsonInjectable = getInjectable({
|
const downloadJsonInjectable = getInjectable({
|
||||||
id: "download-json",
|
id: "download-json",
|
||||||
|
|||||||
@ -3,9 +3,7 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getGlobalOverride } from "../test-utils/get-global-override";
|
import { getGlobalOverrideForFunction } from "../test-utils/get-global-override-for-function";
|
||||||
import fetchInjectable from "./fetch.injectable";
|
import fetchInjectable from "./fetch.injectable";
|
||||||
|
|
||||||
export default getGlobalOverride(fetchInjectable, () => () => {
|
export default getGlobalOverrideForFunction(fetchInjectable);
|
||||||
throw new Error("tried to fetch a resource without override in test");
|
|
||||||
});
|
|
||||||
|
|||||||
@ -3,8 +3,12 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import fetch from "node-fetch";
|
import type * as FetchModule from "node-fetch";
|
||||||
import type { RequestInit, Response } from "node-fetch";
|
|
||||||
|
const { NodeFetch: { default: fetch }} = require("../../../build/webpack/node-fetch.bundle") as { NodeFetch: typeof FetchModule };
|
||||||
|
|
||||||
|
type Response = FetchModule.Response;
|
||||||
|
type RequestInit = FetchModule.RequestInit;
|
||||||
|
|
||||||
export type Fetch = (url: string, init?: RequestInit) => Promise<Response>;
|
export type Fetch = (url: string, init?: RequestInit) => Promise<Response>;
|
||||||
|
|
||||||
|
|||||||
@ -15,20 +15,76 @@ import type { Fetch } from "../../fetch/fetch.injectable";
|
|||||||
import fetchInjectable from "../../fetch/fetch.injectable";
|
import fetchInjectable from "../../fetch/fetch.injectable";
|
||||||
import type { CreateKubeApiForRemoteCluster } from "../create-kube-api-for-remote-cluster.injectable";
|
import type { CreateKubeApiForRemoteCluster } from "../create-kube-api-for-remote-cluster.injectable";
|
||||||
import createKubeApiForRemoteClusterInjectable from "../create-kube-api-for-remote-cluster.injectable";
|
import createKubeApiForRemoteClusterInjectable from "../create-kube-api-for-remote-cluster.injectable";
|
||||||
import { Response } from "node-fetch";
|
|
||||||
import type { AsyncFnMock } from "@async-fn/jest";
|
import type { AsyncFnMock } from "@async-fn/jest";
|
||||||
import asyncFn from "@async-fn/jest";
|
import asyncFn from "@async-fn/jest";
|
||||||
import { flushPromises } from "../../test-utils/flush-promises";
|
import { flushPromises } from "../../test-utils/flush-promises";
|
||||||
import createKubeJsonApiInjectable from "../create-kube-json-api.injectable";
|
import createKubeJsonApiInjectable from "../create-kube-json-api.injectable";
|
||||||
import type { IKubeWatchEvent } from "../kube-watch-event";
|
import type { IKubeWatchEvent } from "../kube-watch-event";
|
||||||
import type { KubeJsonApiDataFor } from "../kube-object";
|
import type { KubeJsonApiDataFor } from "../kube-object";
|
||||||
|
import type { Response, Headers as NodeFetchHeaders } from "node-fetch";
|
||||||
import AbortController from "abort-controller";
|
import AbortController from "abort-controller";
|
||||||
|
|
||||||
|
const createMockResponseFromString = (url: string, data: string, statusCode = 200) => {
|
||||||
|
const res: jest.Mocked<Response> = {
|
||||||
|
buffer: jest.fn(async () => { throw new Error("buffer() is not supported"); }),
|
||||||
|
clone: jest.fn(() => res),
|
||||||
|
arrayBuffer: jest.fn(async () => { throw new Error("arrayBuffer() is not supported"); }),
|
||||||
|
blob: jest.fn(async () => { throw new Error("blob() is not supported"); }),
|
||||||
|
body: new PassThrough(),
|
||||||
|
bodyUsed: false,
|
||||||
|
headers: new Headers() as NodeFetchHeaders,
|
||||||
|
json: jest.fn(async () => JSON.parse(await res.text())),
|
||||||
|
ok: 200 <= statusCode && statusCode < 300,
|
||||||
|
redirected: 300 <= statusCode && statusCode < 400,
|
||||||
|
size: data.length,
|
||||||
|
status: statusCode,
|
||||||
|
statusText: "some-text",
|
||||||
|
text: jest.fn(async () => data),
|
||||||
|
type: "basic",
|
||||||
|
url,
|
||||||
|
formData: jest.fn(async () => { throw new Error("formData() is not supported"); }),
|
||||||
|
};
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createMockResponseFromStream = (url: string, stream: NodeJS.ReadableStream, statusCode = 200) => {
|
||||||
|
const res: jest.Mocked<Response> = {
|
||||||
|
buffer: jest.fn(async () => { throw new Error("buffer() is not supported"); }),
|
||||||
|
clone: jest.fn(() => res),
|
||||||
|
arrayBuffer: jest.fn(async () => { throw new Error("arrayBuffer() is not supported"); }),
|
||||||
|
blob: jest.fn(async () => { throw new Error("blob() is not supported"); }),
|
||||||
|
body: stream,
|
||||||
|
bodyUsed: false,
|
||||||
|
headers: new Headers() as NodeFetchHeaders,
|
||||||
|
json: jest.fn(async () => JSON.parse(await res.text())),
|
||||||
|
ok: 200 <= statusCode && statusCode < 300,
|
||||||
|
redirected: 300 <= statusCode && statusCode < 400,
|
||||||
|
size: 10,
|
||||||
|
status: statusCode,
|
||||||
|
statusText: "some-text",
|
||||||
|
text: jest.fn(() => {
|
||||||
|
const chunks: Buffer[] = [];
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
||||||
|
stream.on("error", (err) => reject(err));
|
||||||
|
stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
type: "basic",
|
||||||
|
url,
|
||||||
|
formData: jest.fn(async () => { throw new Error("formData() is not supported"); }),
|
||||||
|
};
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
describe("createKubeApiForRemoteCluster", () => {
|
describe("createKubeApiForRemoteCluster", () => {
|
||||||
let createKubeApiForRemoteCluster: CreateKubeApiForRemoteCluster;
|
let createKubeApiForRemoteCluster: CreateKubeApiForRemoteCluster;
|
||||||
let fetchMock: AsyncFnMock<Fetch>;
|
let fetchMock: AsyncFnMock<Fetch>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
|
||||||
fetchMock = asyncFn();
|
fetchMock = asyncFn();
|
||||||
@ -94,7 +150,7 @@ describe("createKubeApiForRemoteCluster", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["https://127.0.0.1:6443/api/v1/pods"],
|
["https://127.0.0.1:6443/api/v1/pods"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("https://127.0.0.1:6443/api/v1/pods", JSON.stringify({
|
||||||
kind: "PodList",
|
kind: "PodList",
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
metadata:{
|
metadata:{
|
||||||
@ -118,7 +174,7 @@ describe("KubeApi", () => {
|
|||||||
let registerApiSpy: jest.SpiedFunction<ApiManager["registerApi"]>;
|
let registerApiSpy: jest.SpiedFunction<ApiManager["registerApi"]>;
|
||||||
let fetchMock: AsyncFnMock<Fetch>;
|
let fetchMock: AsyncFnMock<Fetch>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
|
||||||
fetchMock = asyncFn();
|
fetchMock = asyncFn();
|
||||||
@ -172,7 +228,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1"],
|
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1", JSON.stringify({
|
||||||
resources: [{
|
resources: [{
|
||||||
name: "ingresses",
|
name: "ingresses",
|
||||||
}],
|
}],
|
||||||
@ -196,7 +252,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io"],
|
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io", JSON.stringify({
|
||||||
preferredVersion: {
|
preferredVersion: {
|
||||||
version: "v1",
|
version: "v1",
|
||||||
},
|
},
|
||||||
@ -234,7 +290,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo"],
|
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo"],
|
||||||
new Response(JSON.stringify({})),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo", JSON.stringify({})),
|
||||||
);
|
);
|
||||||
result = await getCall;
|
result = await getCall;
|
||||||
});
|
});
|
||||||
@ -274,7 +330,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1"],
|
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1"],
|
||||||
new Response(JSON.stringify({})),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||||
);
|
);
|
||||||
result = await getCall;
|
result = await getCall;
|
||||||
});
|
});
|
||||||
@ -292,7 +348,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo"],
|
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo", JSON.stringify({
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
kind: "Ingress",
|
kind: "Ingress",
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -341,7 +397,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1"],
|
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1"],
|
||||||
new Response(JSON.stringify({})),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||||
);
|
);
|
||||||
result = await getCall;
|
result = await getCall;
|
||||||
});
|
});
|
||||||
@ -359,7 +415,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1"],
|
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1", JSON.stringify({
|
||||||
resources: [],
|
resources: [],
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
@ -381,7 +437,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1"],
|
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1", JSON.stringify({
|
||||||
resources: [{
|
resources: [{
|
||||||
name: "ingresses",
|
name: "ingresses",
|
||||||
}],
|
}],
|
||||||
@ -405,7 +461,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/extensions"],
|
["http://127.0.0.1:9999/api-kube/apis/extensions"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions", JSON.stringify({
|
||||||
preferredVersion: {
|
preferredVersion: {
|
||||||
version: "v1beta1",
|
version: "v1beta1",
|
||||||
},
|
},
|
||||||
@ -443,7 +499,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo"],
|
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo"],
|
||||||
new Response(JSON.stringify({})),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({})),
|
||||||
);
|
);
|
||||||
result = await getCall;
|
result = await getCall;
|
||||||
});
|
});
|
||||||
@ -483,7 +539,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1"],
|
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1"],
|
||||||
new Response(JSON.stringify({})),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||||
);
|
);
|
||||||
result = await getCall;
|
result = await getCall;
|
||||||
});
|
});
|
||||||
@ -501,7 +557,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo"],
|
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({
|
||||||
apiVersion: "v1beta1",
|
apiVersion: "v1beta1",
|
||||||
kind: "Ingress",
|
kind: "Ingress",
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -550,7 +606,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1"],
|
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1"],
|
||||||
new Response(JSON.stringify({})),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||||
);
|
);
|
||||||
result = await getCall;
|
result = await getCall;
|
||||||
});
|
});
|
||||||
@ -604,7 +660,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
kind: "Deployment",
|
kind: "Deployment",
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -657,7 +713,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
kind: "Deployment",
|
kind: "Deployment",
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -710,7 +766,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
kind: "Deployment",
|
kind: "Deployment",
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -768,7 +824,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
fetchMock.resolveSpecific(
|
fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background"],
|
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background"],
|
||||||
new Response("{}"),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background", "{}"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -804,7 +860,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
fetchMock.resolveSpecific(
|
fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background"],
|
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background"],
|
||||||
new Response("{}"),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background", "{}"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -840,7 +896,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
fetchMock.resolveSpecific(
|
fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background"],
|
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background"],
|
||||||
new Response("{}"),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background", "{}"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -886,7 +942,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
fetchMock.resolveSpecific(
|
fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background"],
|
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background"],
|
||||||
new Response("{}"),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background", "{}"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -922,7 +978,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
fetchMock.resolveSpecific(
|
fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background"],
|
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background"],
|
||||||
new Response("{}"),
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background", "{}"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -995,7 +1051,7 @@ describe("KubeApi", () => {
|
|||||||
|
|
||||||
return isMatch;
|
return isMatch;
|
||||||
},
|
},
|
||||||
new Response(stream),
|
createMockResponseFromStream("http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=", stream),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1091,7 +1147,7 @@ describe("KubeApi", () => {
|
|||||||
|
|
||||||
return isMatch;
|
return isMatch;
|
||||||
},
|
},
|
||||||
new Response(stream),
|
createMockResponseFromStream("http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=", stream),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1186,7 +1242,7 @@ describe("KubeApi", () => {
|
|||||||
|
|
||||||
return isMatch;
|
return isMatch;
|
||||||
},
|
},
|
||||||
new Response(stream),
|
createMockResponseFromStream("http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60", stream),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1350,7 +1406,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods"],
|
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods", JSON.stringify({
|
||||||
kind: "Pod",
|
kind: "Pod",
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -1462,7 +1518,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar"],
|
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar", JSON.stringify({
|
||||||
kind: "Pod",
|
kind: "Pod",
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -1530,7 +1586,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/pods"],
|
["http://127.0.0.1:9999/api-kube/api/v1/pods"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/pods", JSON.stringify({
|
||||||
kind: "PodList",
|
kind: "PodList",
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
metadata: {},
|
metadata: {},
|
||||||
@ -1572,7 +1628,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/pods"],
|
["http://127.0.0.1:9999/api-kube/api/v1/pods"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/pods", JSON.stringify({
|
||||||
kind: "PodList",
|
kind: "PodList",
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
metadata: {},
|
metadata: {},
|
||||||
@ -1614,7 +1670,7 @@ describe("KubeApi", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fetchMock.resolveSpecific(
|
await fetchMock.resolveSpecific(
|
||||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods"],
|
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods"],
|
||||||
new Response(JSON.stringify({
|
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods", JSON.stringify({
|
||||||
kind: "PodList",
|
kind: "PodList",
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
metadata: {},
|
metadata: {},
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import byline from "byline";
|
|||||||
import type { IKubeWatchEvent } from "./kube-watch-event";
|
import type { IKubeWatchEvent } from "./kube-watch-event";
|
||||||
import type { KubeJsonApiData, KubeJsonApi } from "./kube-json-api";
|
import type { KubeJsonApiData, KubeJsonApi } from "./kube-json-api";
|
||||||
import type { Disposer } from "../utils";
|
import type { Disposer } from "../utils";
|
||||||
import { isDefined, noop, WrappedAbortController } from "../utils";
|
import { setTimeoutFor, isDefined, noop, WrappedAbortController } from "../utils";
|
||||||
import type { RequestInit, Response } from "node-fetch";
|
import type { RequestInit, Response } from "node-fetch";
|
||||||
import type { Patch } from "rfc6902";
|
import type { Patch } from "rfc6902";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
@ -643,11 +643,12 @@ export class KubeApi<
|
|||||||
clearTimeout(timedRetry);
|
clearTimeout(timedRetry);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setTimeoutFor(abortController, 600 * 1000);
|
||||||
|
|
||||||
const requestParams = timeout ? { query: { timeoutSeconds: timeout }} : {};
|
const requestParams = timeout ? { query: { timeoutSeconds: timeout }} : {};
|
||||||
const watchUrl = this.getWatchUrl(namespace);
|
const watchUrl = this.getWatchUrl(namespace);
|
||||||
const responsePromise = this.request.getResponse(watchUrl, requestParams, {
|
const responsePromise = this.request.getResponse(watchUrl, requestParams, {
|
||||||
signal: abortController.signal,
|
signal: abortController.signal,
|
||||||
timeout: 600_000,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(`[KUBE-API] watch (${watchId}) ${retry === true ? "retried" : "started"} ${watchUrl}`);
|
logger.info(`[KUBE-API] watch (${watchId}) ${retry === true ? "retried" : "started"} ${watchUrl}`);
|
||||||
@ -686,7 +687,19 @@ export class KubeApi<
|
|||||||
}, timeout * 1000 * 1.1);
|
}, timeout * 1000 * 1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
["end", "close", "error"].forEach((eventName) => {
|
if (!response.body) {
|
||||||
|
logger.error(`[KUBE-API]: watch (${watchId}) did not return a body`);
|
||||||
|
requestRetried = true;
|
||||||
|
|
||||||
|
clearTimeout(timedRetry);
|
||||||
|
timedRetry = setTimeout(() => { // we did not get any kubernetes errors so let's retry
|
||||||
|
this.watch({ ...opts, namespace, callback, watchId, retry: true });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const eventName of ["end", "close", "error"]) {
|
||||||
response.body.on(eventName, () => {
|
response.body.on(eventName, () => {
|
||||||
// We only retry if we haven't retried, haven't aborted and haven't received k8s error
|
// We only retry if we haven't retried, haven't aborted and haven't received k8s error
|
||||||
// kubernetes errors (=errorReceived set) should be handled in a callback
|
// kubernetes errors (=errorReceived set) should be handled in a callback
|
||||||
@ -703,7 +716,7 @@ export class KubeApi<
|
|||||||
this.watch({ ...opts, namespace, callback, watchId, retry: true });
|
this.watch({ ...opts, namespace, callback, watchId, retry: true });
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
byline(response.body).on("data", (line) => {
|
byline(response.body).on("data", (line) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -473,7 +473,6 @@ export abstract class KubeObjectStore<
|
|||||||
callback,
|
callback,
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: upgrade node-fetch once we are starting to use ES modules
|
|
||||||
const signal = abortController.signal;
|
const signal = abortController.signal;
|
||||||
|
|
||||||
const callback: KubeApiWatchCallback<D> = (data, error) => {
|
const callback: KubeApiWatchCallback<D> = (data, error) => {
|
||||||
|
|||||||
@ -18,3 +18,9 @@ export class WrappedAbortController extends AbortController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setTimeoutFor(controller: AbortController, timeout: number): void {
|
||||||
|
const handle = setTimeout(() => controller.abort(), timeout);
|
||||||
|
|
||||||
|
controller.signal.addEventListener("abort", () => clearTimeout(handle));
|
||||||
|
}
|
||||||
|
|||||||
@ -11,9 +11,9 @@ const lensResourcesDirInjectable = getInjectable({
|
|||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const isProduction = di.inject(isProductionInjectable);
|
const isProduction = di.inject(isProductionInjectable);
|
||||||
|
|
||||||
return !isProduction
|
return isProduction
|
||||||
? process.cwd()
|
? process.resourcesPath
|
||||||
: process.resourcesPath;
|
: process.cwd();
|
||||||
},
|
},
|
||||||
|
|
||||||
causesSideEffects: true,
|
causesSideEffects: true,
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { LensApiRequest, Route } from "../router/route";
|
import type { LensApiRequest, Route } from "../router/route";
|
||||||
import staticFileRouteInjectable from "../routes/static-file-route.injectable";
|
import staticFileRouteInjectable from "../routes/files/static-file-route.injectable";
|
||||||
import { getDiForUnitTesting } from "../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../getDiForUnitTesting";
|
||||||
|
|
||||||
jest.mock("electron", () => ({
|
jest.mock("electron", () => ({
|
||||||
|
|||||||
33
src/main/routes/files/development.injectable.ts
Normal file
33
src/main/routes/files/development.injectable.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import httpProxy from "http-proxy";
|
||||||
|
import { webpackDevServerPort } from "../../../../webpack/vars";
|
||||||
|
import { publicPath } from "../../../common/vars";
|
||||||
|
import appNameInjectable from "../../../common/vars/app-name.injectable";
|
||||||
|
import type { LensApiRequest, RouteResponse } from "../../router/route";
|
||||||
|
|
||||||
|
const devStaticFileRouteHandlerInjectable = getInjectable({
|
||||||
|
id: "dev-static-file-route-handler",
|
||||||
|
instantiate: (di) => {
|
||||||
|
const proxy = httpProxy.createProxy();
|
||||||
|
const appName = di.inject(appNameInjectable);
|
||||||
|
const proxyTarget = `http://127.0.0.1:${webpackDevServerPort}`;
|
||||||
|
|
||||||
|
return async ({ raw: { req, res }}: LensApiRequest<"/{path*}">): Promise<RouteResponse<Buffer>> => {
|
||||||
|
if (req.url === "/" || !req.url) {
|
||||||
|
req.url = `${publicPath}/${appName}.html`;
|
||||||
|
} else if (!req.url.startsWith("/build/")) {
|
||||||
|
return { statusCode: 404 };
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.web(req, res, { target: proxyTarget });
|
||||||
|
|
||||||
|
return { proxy };
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default devStaticFileRouteHandlerInjectable;
|
||||||
61
src/main/routes/files/production.injectable.ts
Normal file
61
src/main/routes/files/production.injectable.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import readFileBufferInjectable from "../../../common/fs/read-file-buffer.injectable";
|
||||||
|
import joinPathsInjectable from "../../../common/path/join-paths.injectable";
|
||||||
|
import staticFilesDirectoryInjectable from "../../../common/vars/static-files-directory.injectable";
|
||||||
|
import appNameInjectable from "../../../common/vars/app-name.injectable";
|
||||||
|
import type { LensApiRequest } from "../../router/route";
|
||||||
|
import path from "path";
|
||||||
|
import type { SupportedFileExtension } from "../../router/router-content-types";
|
||||||
|
import { contentTypes } from "../../router/router-content-types";
|
||||||
|
import loggerInjectable from "../../../common/logger.injectable";
|
||||||
|
import { publicPath } from "../../../common/vars";
|
||||||
|
|
||||||
|
const prodStaticFileRouteHandlerInjectable = getInjectable({
|
||||||
|
id: "prod-static-file-route-handler",
|
||||||
|
instantiate: (di) => {
|
||||||
|
const readFileBuffer = di.inject(readFileBufferInjectable);
|
||||||
|
const joinPaths = di.inject(joinPathsInjectable);
|
||||||
|
const staticFilesDirectory = di.inject(staticFilesDirectoryInjectable);
|
||||||
|
const appName = di.inject(appNameInjectable);
|
||||||
|
const logger = di.inject(loggerInjectable);
|
||||||
|
|
||||||
|
return async ({ params }: LensApiRequest<"/{path*}">) => {
|
||||||
|
let filePath = params.path;
|
||||||
|
|
||||||
|
|
||||||
|
for (let retryCount = 0; retryCount < 5; retryCount += 1) {
|
||||||
|
const assetFilePath = joinPaths(staticFilesDirectory, filePath);
|
||||||
|
|
||||||
|
if (!assetFilePath.startsWith(staticFilesDirectory)) {
|
||||||
|
return { statusCode: 404 };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fileExtension = path
|
||||||
|
.extname(assetFilePath)
|
||||||
|
.slice(1) as SupportedFileExtension;
|
||||||
|
|
||||||
|
const contentType = contentTypes[fileExtension] || contentTypes.txt;
|
||||||
|
|
||||||
|
return { response: await readFileBuffer(assetFilePath), contentType };
|
||||||
|
} catch (err) {
|
||||||
|
if (retryCount > 5) {
|
||||||
|
logger.error("handleStaticFile:", String(err));
|
||||||
|
|
||||||
|
return { statusCode: 404 };
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath = `${publicPath}/${appName}.html`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { statusCode: 404 };
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default prodStaticFileRouteHandlerInjectable;
|
||||||
28
src/main/routes/files/static-file-route.injectable.ts
Normal file
28
src/main/routes/files/static-file-route.injectable.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getRouteInjectable } from "../../router/router.injectable";
|
||||||
|
import isDevelopmentInjectable from "../../../common/vars/is-development.injectable";
|
||||||
|
import { route } from "../../router/route";
|
||||||
|
import prodStaticFileRouteHandlerInjectable from "./production.injectable";
|
||||||
|
import devStaticFileRouteHandlerInjectable from "./development.injectable";
|
||||||
|
|
||||||
|
const staticFileRouteInjectable = getRouteInjectable({
|
||||||
|
id: "static-file-route",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const isDevelopment = di.inject(isDevelopmentInjectable);
|
||||||
|
|
||||||
|
return route({
|
||||||
|
method: "get",
|
||||||
|
path: `/{path*}`,
|
||||||
|
})(
|
||||||
|
isDevelopment
|
||||||
|
? di.inject(devStaticFileRouteHandlerInjectable)
|
||||||
|
: di.inject(prodStaticFileRouteHandlerInjectable),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default staticFileRouteInjectable;
|
||||||
@ -1,126 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
import type { SupportedFileExtension } from "../router/router-content-types";
|
|
||||||
import { contentTypes } from "../router/router-content-types";
|
|
||||||
import logger from "../logger";
|
|
||||||
import { getRouteInjectable } from "../router/router.injectable";
|
|
||||||
import { publicPath } from "../../common/vars";
|
|
||||||
import path from "path";
|
|
||||||
import isDevelopmentInjectable from "../../common/vars/is-development.injectable";
|
|
||||||
import httpProxy from "http-proxy";
|
|
||||||
import readFileBufferInjectable from "../../common/fs/read-file-buffer.injectable";
|
|
||||||
import type { JoinPaths } from "../../common/path/join-paths.injectable";
|
|
||||||
import joinPathsInjectable from "../../common/path/join-paths.injectable";
|
|
||||||
import { webpackDevServerPort } from "../../../webpack/vars";
|
|
||||||
import type { LensApiRequest, RouteResponse } from "../router/route";
|
|
||||||
import { route } from "../router/route";
|
|
||||||
import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable";
|
|
||||||
import appNameInjectable from "../../common/vars/app-name.injectable";
|
|
||||||
import type { GetAbsolutePath } from "../../common/path/get-absolute-path.injectable";
|
|
||||||
import getAbsolutePathInjectable from "../../common/path/get-absolute-path.injectable";
|
|
||||||
|
|
||||||
interface ProductionDependencies {
|
|
||||||
readFileBuffer: (path: string) => Promise<Buffer>;
|
|
||||||
joinPaths: JoinPaths;
|
|
||||||
getAbsolutePath: GetAbsolutePath;
|
|
||||||
staticFilesDirectory: string;
|
|
||||||
appName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleStaticFileInProduction = ({
|
|
||||||
readFileBuffer,
|
|
||||||
getAbsolutePath,
|
|
||||||
joinPaths,
|
|
||||||
staticFilesDirectory,
|
|
||||||
appName,
|
|
||||||
}: ProductionDependencies) => (
|
|
||||||
async ({ params }: LensApiRequest<"/{path*}">): Promise<RouteResponse<Buffer>> => {
|
|
||||||
let filePath = params.path;
|
|
||||||
|
|
||||||
for (let retryCount = 0; retryCount < 5; retryCount += 1) {
|
|
||||||
const asset = joinPaths(staticFilesDirectory, filePath);
|
|
||||||
const normalizedFilePath = getAbsolutePath(asset);
|
|
||||||
|
|
||||||
if (!normalizedFilePath.startsWith(staticFilesDirectory)) {
|
|
||||||
return { statusCode: 404 };
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const fileExtension = path
|
|
||||||
.extname(asset)
|
|
||||||
.slice(1) as SupportedFileExtension;
|
|
||||||
|
|
||||||
const contentType = contentTypes[fileExtension] || contentTypes.txt;
|
|
||||||
|
|
||||||
return { response: await readFileBuffer(asset), contentType };
|
|
||||||
} catch (err) {
|
|
||||||
if (retryCount > 5) {
|
|
||||||
logger.error("handleStaticFile:", String(err));
|
|
||||||
|
|
||||||
return { statusCode: 404 };
|
|
||||||
}
|
|
||||||
|
|
||||||
filePath = `${publicPath}/${appName}.html`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { statusCode: 404 };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
interface DevelopmentDependencies {
|
|
||||||
proxy: httpProxy;
|
|
||||||
appName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleStaticFileInDevelopment = ({
|
|
||||||
proxy,
|
|
||||||
appName,
|
|
||||||
}: DevelopmentDependencies) => (
|
|
||||||
({ raw: { req, res }}: LensApiRequest<"/{path*}">): RouteResponse<Buffer> => {
|
|
||||||
if (req.url === "/" || !req.url?.startsWith("/build/")) {
|
|
||||||
req.url = `${publicPath}/${appName}.html`;
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy.web(req, res, {
|
|
||||||
target: `http://127.0.0.1:${webpackDevServerPort}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
return { proxy };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const staticFileRouteInjectable = getRouteInjectable({
|
|
||||||
id: "static-file-route",
|
|
||||||
|
|
||||||
instantiate: (di) => {
|
|
||||||
const isDevelopment = di.inject(isDevelopmentInjectable);
|
|
||||||
const readFileBuffer = di.inject(readFileBufferInjectable);
|
|
||||||
const joinPaths = di.inject(joinPathsInjectable);
|
|
||||||
const getAbsolutePath = di.inject(getAbsolutePathInjectable);
|
|
||||||
const staticFilesDirectory = di.inject(staticFilesDirectoryInjectable);
|
|
||||||
const appName = di.inject(appNameInjectable);
|
|
||||||
|
|
||||||
return route({
|
|
||||||
method: "get",
|
|
||||||
path: `/{path*}`,
|
|
||||||
})(
|
|
||||||
isDevelopment
|
|
||||||
? handleStaticFileInDevelopment({
|
|
||||||
proxy: httpProxy.createProxy(),
|
|
||||||
appName,
|
|
||||||
})
|
|
||||||
: handleStaticFileInProduction({
|
|
||||||
readFileBuffer,
|
|
||||||
joinPaths,
|
|
||||||
staticFilesDirectory,
|
|
||||||
appName,
|
|
||||||
getAbsolutePath,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default staticFileRouteInjectable;
|
|
||||||
31
webpack/node-fetch.ts
Normal file
31
webpack/node-fetch.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
entry: "./node_modules/node-fetch/src/index.js",
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, "..", "build", "webpack"),
|
||||||
|
filename: "node-fetch.bundle.js",
|
||||||
|
library: {
|
||||||
|
name: "NodeFetch",
|
||||||
|
type: "commonjs",
|
||||||
|
},
|
||||||
|
clean: true,
|
||||||
|
asyncChunks: false, // This is required so that only one file is created
|
||||||
|
},
|
||||||
|
mode: "production",
|
||||||
|
target: "electron-renderer",
|
||||||
|
optimization: {
|
||||||
|
concatenateModules: true,
|
||||||
|
minimize: true,
|
||||||
|
},
|
||||||
|
externalsPresets: {
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: [".js"],
|
||||||
|
},
|
||||||
|
};
|
||||||
75
yarn.lock
75
yarn.lock
@ -2221,31 +2221,16 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
|
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
|
||||||
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
|
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
|
||||||
|
|
||||||
"@types/node-fetch@^2.6.2":
|
|
||||||
version "2.6.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da"
|
|
||||||
integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
form-data "^3.0.0"
|
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "17.0.24"
|
version "17.0.24"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.24.tgz#20ba1bf69c1b4ab405c7a01e950c4f446b05029f"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.24.tgz#20ba1bf69c1b4ab405c7a01e950c4f446b05029f"
|
||||||
integrity sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==
|
integrity sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==
|
||||||
|
|
||||||
"@types/node@^16.11.26", "@types/node@^16.18.3":
|
"@types/node@^16.11.26", "@types/node@^16.18.2":
|
||||||
version "16.18.3"
|
version "16.18.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.3.tgz#d7f7ba828ad9e540270f01ce00d391c54e6e0abc"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.3.tgz#d7f7ba828ad9e540270f01ce00d391c54e6e0abc"
|
||||||
integrity sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==
|
integrity sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==
|
||||||
|
|
||||||
"@types/npm@^2.0.32":
|
|
||||||
version "2.0.32"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/npm/-/npm-2.0.32.tgz#036682075b9c2116b510fe24b52a5b932e3a99d5"
|
|
||||||
integrity sha512-9Lg4woNVzJCtac0lET91H65lbO+8YXfk0nmlmoPGhHXMdaVEDloH6zOPIYMy2n39z/aCXXQR0nax66EDekAyIQ==
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
|
|
||||||
"@types/parse-json@^4.0.0":
|
"@types/parse-json@^4.0.0":
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||||
@ -4552,6 +4537,11 @@ dashdash@^1.12.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
|
data-uri-to-buffer@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b"
|
||||||
|
integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==
|
||||||
|
|
||||||
data-urls@^2.0.0:
|
data-urls@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
|
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
|
||||||
@ -5899,6 +5889,14 @@ fecha@^4.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
|
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
|
||||||
integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
|
integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
|
||||||
|
|
||||||
|
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
|
||||||
|
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
|
||||||
|
dependencies:
|
||||||
|
node-domexception "^1.0.0"
|
||||||
|
web-streams-polyfill "^3.0.3"
|
||||||
|
|
||||||
figures@^3.0.0:
|
figures@^3.0.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
|
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
|
||||||
@ -6127,6 +6125,13 @@ form-data@~2.3.2:
|
|||||||
combined-stream "^1.0.6"
|
combined-stream "^1.0.6"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
|
formdata-polyfill@^4.0.10:
|
||||||
|
version "4.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
|
||||||
|
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
|
||||||
|
dependencies:
|
||||||
|
fetch-blob "^3.1.2"
|
||||||
|
|
||||||
forwarded@0.2.0:
|
forwarded@0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||||
@ -9104,12 +9109,19 @@ node-addon-api@^5.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.0.0.tgz#7d7e6f9ef89043befdb20c1989c905ebde18c501"
|
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.0.0.tgz#7d7e6f9ef89043befdb20c1989c905ebde18c501"
|
||||||
integrity sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==
|
integrity sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==
|
||||||
|
|
||||||
node-fetch@^2.6.7:
|
node-domexception@^1.0.0:
|
||||||
version "2.6.7"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
|
||||||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
|
||||||
|
|
||||||
|
node-fetch@^3.2.10:
|
||||||
|
version "3.2.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.10.tgz#e8347f94b54ae18b57c9c049ef641cef398a85c8"
|
||||||
|
integrity sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==
|
||||||
dependencies:
|
dependencies:
|
||||||
whatwg-url "^5.0.0"
|
data-uri-to-buffer "^4.0.0"
|
||||||
|
fetch-blob "^3.1.4"
|
||||||
|
formdata-polyfill "^4.0.10"
|
||||||
|
|
||||||
node-forge@^0.10.0:
|
node-forge@^0.10.0:
|
||||||
version "0.10.0"
|
version "0.10.0"
|
||||||
@ -12069,11 +12081,6 @@ tr46@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.1"
|
punycode "^2.1.1"
|
||||||
|
|
||||||
tr46@~0.0.3:
|
|
||||||
version "0.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
|
||||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
|
||||||
|
|
||||||
traverse-chain@~0.1.0:
|
traverse-chain@~0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1"
|
resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1"
|
||||||
@ -12601,10 +12608,10 @@ wcwidth@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
defaults "^1.0.3"
|
defaults "^1.0.3"
|
||||||
|
|
||||||
webidl-conversions@^3.0.0:
|
web-streams-polyfill@^3.0.3:
|
||||||
version "3.0.1"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
|
||||||
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
|
||||||
|
|
||||||
webidl-conversions@^5.0.0:
|
webidl-conversions@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
@ -12795,14 +12802,6 @@ whatwg-url@^11.0.0:
|
|||||||
tr46 "^3.0.0"
|
tr46 "^3.0.0"
|
||||||
webidl-conversions "^7.0.0"
|
webidl-conversions "^7.0.0"
|
||||||
|
|
||||||
whatwg-url@^5.0.0:
|
|
||||||
version "5.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
|
||||||
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
|
|
||||||
dependencies:
|
|
||||||
tr46 "~0.0.3"
|
|
||||||
webidl-conversions "^3.0.0"
|
|
||||||
|
|
||||||
whatwg-url@^8.0.0, whatwg-url@^8.5.0:
|
whatwg-url@^8.0.0, whatwg-url@^8.5.0:
|
||||||
version "8.7.0"
|
version "8.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
|
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user