mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into download-all-pod-logs
This commit is contained in:
commit
363f6997e2
4
.github/workflows/check-docs.yml
vendored
4
.github/workflows/check-docs.yml
vendored
@ -23,8 +23,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate Extensions API Reference using typedocs
|
- name: Generate Extensions API Reference using typedocs
|
||||||
run: |
|
run: |
|
||||||
yarn install
|
yarn install
|
||||||
yarn typedocs-extensions-api
|
yarn typedocs-extensions-api
|
||||||
|
|
||||||
- name: Verify that the markdown is valid
|
- name: Verify that the markdown is valid
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
2
.github/workflows/electronegativity.yml
vendored
2
.github/workflows/electronegativity.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
|||||||
- uses: doyensec/electronegativity-action@v1.1
|
- uses: doyensec/electronegativity-action@v1.1
|
||||||
with:
|
with:
|
||||||
input: src/
|
input: src/
|
||||||
electron-version: "15.5.7"
|
electron-version: "19.0.4"
|
||||||
severity: medium
|
severity: medium
|
||||||
|
|
||||||
- name: Upload sarif
|
- name: Upload sarif
|
||||||
|
|||||||
8
.github/workflows/mkdocs-manual.yml
vendored
8
.github/workflows/mkdocs-manual.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Set up Python 3.7
|
- name: Set up Python 3.7
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: '3.x'
|
python-version: "3.x"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
@ -28,7 +28,7 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: '${{ github.event.inputs.version }}'
|
ref: "${{ github.event.inputs.version }}"
|
||||||
|
|
||||||
- name: Using Node.js ${{ matrix.node-version }}
|
- name: Using Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
@ -43,8 +43,8 @@ jobs:
|
|||||||
- name: Checkout master branch from lens
|
- name: Checkout master branch from lens
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
path: 'master'
|
path: "master"
|
||||||
ref: 'master'
|
ref: "master"
|
||||||
|
|
||||||
- name: Bring in latest mkdocs.yml from master
|
- name: Bring in latest mkdocs.yml from master
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
4
.github/workflows/publish-release-npm.yml
vendored
4
.github/workflows/publish-release-npm.yml
vendored
@ -23,11 +23,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate NPM package
|
- name: Generate NPM package
|
||||||
run: |
|
run: |
|
||||||
make build-npm
|
make build-npm
|
||||||
|
|
||||||
- name: publish new release
|
- name: publish new release
|
||||||
if: contains(github.ref, 'refs/tags/v')
|
if: contains(github.ref, 'refs/tags/v')
|
||||||
run: |
|
run: |
|
||||||
make publish-npm
|
make publish-npm
|
||||||
env:
|
env:
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|||||||
4
.yarnrc
4
.yarnrc
@ -1,3 +1,3 @@
|
|||||||
disturl "https://atom.io/download/electron"
|
disturl "https://electronjs.org/headers"
|
||||||
target "15.5.0"
|
target "19.0.4"
|
||||||
runtime "electron"
|
runtime "electron"
|
||||||
|
|||||||
@ -13,7 +13,6 @@ 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 AbortController from "abort-controller";
|
|
||||||
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, normalizedPlatform } from "../src/common/vars";
|
||||||
|
|||||||
@ -55,7 +55,7 @@ Some of the most-important fields include:
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://github.com/lensapp/lens-extension-samples",
|
"homepage": "https://github.com/lensapp/lens-extension-samples",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.18.12",
|
"node": "^16.14.2",
|
||||||
"lens": "5.4"
|
"lens": "5.4"
|
||||||
},
|
},
|
||||||
"main": "dist/main.js",
|
"main": "dist/main.js",
|
||||||
@ -72,7 +72,7 @@ Some of the most-important fields include:
|
|||||||
"ts-loader": "^8.0.4",
|
"ts-loader": "^8.0.4",
|
||||||
"typescript": "^4.5.5",
|
"typescript": "^4.5.5",
|
||||||
"@types/react": "^17.0.44",
|
"@types/react": "^17.0.44",
|
||||||
"@types/node": "^14.18.12",
|
"@types/node": "^16.14.2",
|
||||||
"webpack": "^4.44.2",
|
"webpack": "^4.44.2",
|
||||||
"webpack-cli": "^3.3.11"
|
"webpack-cli": "^3.3.11"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -222,7 +222,6 @@
|
|||||||
"@sentry/integrations": "^6.19.3",
|
"@sentry/integrations": "^6.19.3",
|
||||||
"@side/jest-runtime": "^1.0.1",
|
"@side/jest-runtime": "^1.0.1",
|
||||||
"@types/circular-dependency-plugin": "5.0.5",
|
"@types/circular-dependency-plugin": "5.0.5",
|
||||||
"abort-controller": "^3.0.0",
|
|
||||||
"auto-bind": "^4.0.0",
|
"auto-bind": "^4.0.0",
|
||||||
"await-lock": "^2.2.2",
|
"await-lock": "^2.2.2",
|
||||||
"byline": "^5.0.0",
|
"byline": "^5.0.0",
|
||||||
@ -369,7 +368,7 @@
|
|||||||
"css-loader": "^6.7.1",
|
"css-loader": "^6.7.1",
|
||||||
"deepdash": "^5.3.9",
|
"deepdash": "^5.3.9",
|
||||||
"dompurify": "^2.3.10",
|
"dompurify": "^2.3.10",
|
||||||
"electron": "^15.5.7",
|
"electron": "^19.0.4",
|
||||||
"electron-builder": "^23.3.3",
|
"electron-builder": "^23.3.3",
|
||||||
"electron-notarize": "^0.3.0",
|
"electron-notarize": "^0.3.0",
|
||||||
"esbuild": "^0.14.53",
|
"esbuild": "^0.14.53",
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
|
|||||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||||
import loggerInjectable from "../../common/logger.injectable";
|
import loggerInjectable from "../../common/logger.injectable";
|
||||||
import type { Logger } from "../../common/logger";
|
import type { Logger } from "../../common/logger";
|
||||||
|
import getRandomIdInjectable from "../../common/utils/get-random-id.injectable";
|
||||||
|
|
||||||
describe("clicking tray menu item originating from extension", () => {
|
describe("clicking tray menu item originating from extension", () => {
|
||||||
let applicationBuilder: ApplicationBuilder;
|
let applicationBuilder: ApplicationBuilder;
|
||||||
@ -20,6 +21,7 @@ describe("clicking tray menu item originating from extension", () => {
|
|||||||
logErrorMock = jest.fn();
|
logErrorMock = jest.fn();
|
||||||
|
|
||||||
mainDi.override(loggerInjectable, () => ({ error: logErrorMock }) as unknown as Logger);
|
mainDi.override(loggerInjectable, () => ({ error: logErrorMock }) as unknown as Logger);
|
||||||
|
mainDi.override(getRandomIdInjectable, () => () => "some-random-id");
|
||||||
});
|
});
|
||||||
|
|
||||||
await applicationBuilder.render();
|
await applicationBuilder.render();
|
||||||
@ -42,7 +44,7 @@ describe("clicking tray menu item originating from extension", () => {
|
|||||||
|
|
||||||
it("when item is clicked, triggers the click handler", () => {
|
it("when item is clicked, triggers the click handler", () => {
|
||||||
applicationBuilder.tray.click(
|
applicationBuilder.tray.click(
|
||||||
"some-label-tray-menu-item-for-extension-some-extension-id",
|
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(clickMock).toHaveBeenCalled();
|
expect(clickMock).toHaveBeenCalled();
|
||||||
@ -55,13 +57,13 @@ describe("clicking tray menu item originating from extension", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
applicationBuilder.tray.click(
|
applicationBuilder.tray.click(
|
||||||
"some-label-tray-menu-item-for-extension-some-extension-id",
|
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("logs the error", () => {
|
it("logs the error", () => {
|
||||||
expect(logErrorMock).toHaveBeenCalledWith(
|
expect(logErrorMock).toHaveBeenCalledWith(
|
||||||
'[TRAY]: Clicking of tray item "some-label" from extension "some-extension-id" failed.',
|
'[TRAY]: Clicking of tray item "some-random-id" from extension "some-extension-id" failed.',
|
||||||
expect.any(Error),
|
expect.any(Error),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -72,13 +74,13 @@ describe("clicking tray menu item originating from extension", () => {
|
|||||||
clickMock.mockImplementation(() => Promise.reject("some-rejection"));
|
clickMock.mockImplementation(() => Promise.reject("some-rejection"));
|
||||||
|
|
||||||
applicationBuilder.tray.click(
|
applicationBuilder.tray.click(
|
||||||
"some-label-tray-menu-item-for-extension-some-extension-id",
|
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("logs the error", () => {
|
it("logs the error", () => {
|
||||||
expect(logErrorMock).toHaveBeenCalledWith(
|
expect(logErrorMock).toHaveBeenCalledWith(
|
||||||
'[TRAY]: Clicking of tray item "some-label" from extension "some-extension-id" failed.',
|
'[TRAY]: Clicking of tray item "some-random-id" from extension "some-extension-id" failed.',
|
||||||
"some-rejection",
|
"some-rejection",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -92,7 +94,7 @@ describe("clicking tray menu item originating from extension", () => {
|
|||||||
it("does not have the tray menu item from extension", () => {
|
it("does not have the tray menu item from extension", () => {
|
||||||
expect(
|
expect(
|
||||||
applicationBuilder.tray.get(
|
applicationBuilder.tray.get(
|
||||||
"some-label-tray-menu-item-for-extension-some-extension-id",
|
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||||
),
|
),
|
||||||
).toBeNull();
|
).toBeNull();
|
||||||
});
|
});
|
||||||
@ -103,7 +105,7 @@ describe("clicking tray menu item originating from extension", () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
applicationBuilder.tray.get(
|
applicationBuilder.tray.get(
|
||||||
"some-label-tray-menu-item-for-extension-some-extension-id",
|
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||||
),
|
),
|
||||||
).not.toBeNull();
|
).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -13,6 +13,7 @@ describe("preferences: extension adding tray items", () => {
|
|||||||
let builder: ApplicationBuilder;
|
let builder: ApplicationBuilder;
|
||||||
let someObservableForVisibility: IObservableValue<boolean>;
|
let someObservableForVisibility: IObservableValue<boolean>;
|
||||||
let someObservableForEnabled: IObservableValue<boolean>;
|
let someObservableForEnabled: IObservableValue<boolean>;
|
||||||
|
let someObservableLabel: IObservableValue<string>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
builder = getApplicationBuilder();
|
builder = getApplicationBuilder();
|
||||||
@ -25,6 +26,7 @@ describe("preferences: extension adding tray items", () => {
|
|||||||
|
|
||||||
someObservableForVisibility = observable.box(false);
|
someObservableForVisibility = observable.box(false);
|
||||||
someObservableForEnabled = observable.box(false);
|
someObservableForEnabled = observable.box(false);
|
||||||
|
someObservableLabel = observable.box("Some label");
|
||||||
|
|
||||||
const testExtension = getExtensionFake({
|
const testExtension = getExtensionFake({
|
||||||
id: "some-extension-id",
|
id: "some-extension-id",
|
||||||
@ -33,38 +35,51 @@ describe("preferences: extension adding tray items", () => {
|
|||||||
mainOptions: {
|
mainOptions: {
|
||||||
trayMenus: [
|
trayMenus: [
|
||||||
{
|
{
|
||||||
|
id: "some-controlled-visibility",
|
||||||
label: "some-controlled-visibility",
|
label: "some-controlled-visibility",
|
||||||
click: () => {},
|
click: () => {},
|
||||||
visible: computed(() => someObservableForVisibility.get()),
|
visible: computed(() => someObservableForVisibility.get()),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
id: "some-uncontrolled-visibility",
|
||||||
label: "some-uncontrolled-visibility",
|
label: "some-uncontrolled-visibility",
|
||||||
click: () => {},
|
click: () => {},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
id: "some-controlled-enabled",
|
||||||
label: "some-controlled-enabled",
|
label: "some-controlled-enabled",
|
||||||
click: () => {},
|
click: () => {},
|
||||||
enabled: computed(() => someObservableForEnabled.get()),
|
enabled: computed(() => someObservableForEnabled.get()),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
id: "some-uncontrolled-enabled",
|
||||||
label: "some-uncontrolled-enabled",
|
label: "some-uncontrolled-enabled",
|
||||||
click: () => {},
|
click: () => {},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
id: "some-statically-enabled",
|
||||||
label: "some-statically-enabled",
|
label: "some-statically-enabled",
|
||||||
click: () => {},
|
click: () => {},
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
id: "some-statically-disabled",
|
||||||
label: "some-statically-disabled",
|
label: "some-statically-disabled",
|
||||||
click: () => {},
|
click: () => {},
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: "some-item-with-controlled-label",
|
||||||
|
label: computed(() => someObservableLabel.get()),
|
||||||
|
click: () => {},
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -72,6 +87,37 @@ describe("preferences: extension adding tray items", () => {
|
|||||||
builder.extensions.enable(testExtension);
|
builder.extensions.enable(testExtension);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("given controlled label", () => {
|
||||||
|
it("has the label", () => {
|
||||||
|
const item = builder.tray.get(
|
||||||
|
"some-item-with-controlled-label-tray-menu-item-for-extension-some-extension",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(item?.label).toBe("Some label");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when label changes, updates the label", () => {
|
||||||
|
runInAction(() => {
|
||||||
|
someObservableLabel.set("Some new label");
|
||||||
|
});
|
||||||
|
|
||||||
|
const item = builder.tray.get(
|
||||||
|
"some-item-with-controlled-label-tray-menu-item-for-extension-some-extension",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(item?.label).toBe("Some new label");
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given item is statically disabled, item is disabled", () => {
|
||||||
|
const item = builder.tray.get(
|
||||||
|
"some-statically-disabled-tray-menu-item-for-extension-some-extension",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(item?.enabled).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it("shows item which doesn't control the visibility", () => {
|
it("shows item which doesn't control the visibility", () => {
|
||||||
expect(
|
expect(
|
||||||
builder.tray.get(
|
builder.tray.get(
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
import { forRemoteCluster, KubeApi } from "../kube-api";
|
import { forRemoteCluster, KubeApi } from "../kube-api";
|
||||||
import { KubeJsonApi } from "../kube-json-api";
|
import { KubeJsonApi } from "../kube-json-api";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import AbortController from "abort-controller";
|
|
||||||
import { delay } from "../../utils/delay";
|
import { delay } from "../../utils/delay";
|
||||||
import { PassThrough } from "stream";
|
import { PassThrough } from "stream";
|
||||||
import { ApiManager } from "../api-manager";
|
import { ApiManager } from "../api-manager";
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import { KubeJsonApi } from "./kube-json-api";
|
|||||||
import type { Disposer } from "../utils";
|
import type { Disposer } from "../utils";
|
||||||
import { isDefined, noop, WrappedAbortController } from "../utils";
|
import { isDefined, noop, WrappedAbortController } from "../utils";
|
||||||
import type { RequestInit } from "node-fetch";
|
import type { RequestInit } from "node-fetch";
|
||||||
import type AbortController from "abort-controller";
|
|
||||||
import type { AgentOptions } from "https";
|
import type { AgentOptions } from "https";
|
||||||
import { Agent } from "https";
|
import { Agent } from "https";
|
||||||
import type { Patch } from "rfc6902";
|
import type { Patch } from "rfc6902";
|
||||||
@ -29,6 +28,9 @@ import logger from "../logger";
|
|||||||
import { Environments, getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
import { Environments, getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||||
import autoRegistrationEmitterInjectable from "./api-manager/auto-registration-emitter.injectable";
|
import autoRegistrationEmitterInjectable from "./api-manager/auto-registration-emitter.injectable";
|
||||||
|
|
||||||
|
// TODO: upgrade node-fetch once we are starting to use ES modules
|
||||||
|
type LegacyAbortSignal = NonNullable<RequestInit["signal"]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The options used for creating a `KubeApi`
|
* The options used for creating a `KubeApi`
|
||||||
*/
|
*/
|
||||||
@ -717,7 +719,7 @@ export class KubeApi<
|
|||||||
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 as LegacyAbortSignal,
|
||||||
timeout: 600_000,
|
timeout: 600_000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -15,13 +15,15 @@ import { ItemStore } from "../item.store";
|
|||||||
import type { KubeApiQueryParams, KubeApi, KubeApiWatchCallback } from "./kube-api";
|
import type { KubeApiQueryParams, KubeApi, KubeApiWatchCallback } from "./kube-api";
|
||||||
import { parseKubeApi } from "./kube-api-parse";
|
import { parseKubeApi } from "./kube-api-parse";
|
||||||
import type { RequestInit } from "node-fetch";
|
import type { RequestInit } from "node-fetch";
|
||||||
import AbortController from "abort-controller";
|
|
||||||
import type { Patch } from "rfc6902";
|
import type { Patch } from "rfc6902";
|
||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import type { PartialDeep } from "type-fest";
|
import type { PartialDeep } from "type-fest";
|
||||||
import { entries } from "../utils/objects";
|
import { entries } from "../utils/objects";
|
||||||
|
|
||||||
|
// TODO: upgrade node-fetch once we are starting to use ES modules
|
||||||
|
type LegacyAbortSignal = NonNullable<RequestInit["signal"]>;
|
||||||
|
|
||||||
export type OnLoadFailure = (error: unknown) => void;
|
export type OnLoadFailure = (error: unknown) => void;
|
||||||
|
|
||||||
export interface KubeObjectStoreLoadingParams {
|
export interface KubeObjectStoreLoadingParams {
|
||||||
@ -477,7 +479,8 @@ export abstract class KubeObjectStore<
|
|||||||
callback,
|
callback,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { signal } = abortController;
|
// TODO: upgrade node-fetch once we are starting to use ES modules
|
||||||
|
const signal = abortController.signal as LegacyAbortSignal;
|
||||||
|
|
||||||
const callback: KubeApiWatchCallback<D> = (data, error) => {
|
const callback: KubeApiWatchCallback<D> = (data, error) => {
|
||||||
if (!this.isLoaded || error?.type === "aborted") return;
|
if (!this.isLoaded || error?.type === "aborted") return;
|
||||||
|
|||||||
@ -4,6 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
import type { Injectable } from "@ogre-tools/injectable";
|
import type { Injectable } from "@ogre-tools/injectable";
|
||||||
|
|
||||||
|
export interface GlobalOverride {
|
||||||
|
injectable: Injectable<any, any, any>;
|
||||||
|
overridingInstantiate: any;
|
||||||
|
}
|
||||||
|
|
||||||
export const getGlobalOverride = <T extends Injectable<any, any, any>>(
|
export const getGlobalOverride = <T extends Injectable<any, any, any>>(
|
||||||
injectable: T,
|
injectable: T,
|
||||||
overridingInstantiate: T["instantiate"],
|
overridingInstantiate: T["instantiate"],
|
||||||
|
|||||||
@ -2,10 +2,13 @@
|
|||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
* 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 AbortController from "abort-controller";
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is like an `AbortController` but will also abort if the parent aborts,
|
||||||
|
* but won't make the parent abort if this aborts (single direction)
|
||||||
|
*/
|
||||||
export class WrappedAbortController extends AbortController {
|
export class WrappedAbortController extends AbortController {
|
||||||
constructor(parent?: AbortController) {
|
constructor(parent?: AbortController | undefined) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
parent?.signal.addEventListener("abort", () => {
|
parent?.signal.addEventListener("abort", () => {
|
||||||
|
|||||||
@ -3,8 +3,6 @@
|
|||||||
* 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 type { AbortController } from "abort-controller";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a promise that will be resolved after at least `timeout` ms have
|
* Return a promise that will be resolved after at least `timeout` ms have
|
||||||
* passed. If `failFast` is provided then the promise is also resolved if it has
|
* passed. If `failFast` is provided then the promise is also resolved if it has
|
||||||
|
|||||||
@ -3,8 +3,6 @@
|
|||||||
* 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 type { AbortSignal } from "abort-controller";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new promise that will be rejected when the signal rejects.
|
* Creates a new promise that will be rejected when the signal rejects.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import configurePackages from "./common/configure-packages";
|
|||||||
import { configure } from "mobx";
|
import { configure } from "mobx";
|
||||||
import { setImmediate } from "timers";
|
import { setImmediate } from "timers";
|
||||||
import { TextEncoder, TextDecoder as TextDecoderNode } from "util";
|
import { TextEncoder, TextDecoder as TextDecoderNode } from "util";
|
||||||
|
import glob from "glob";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
// setup default configuration for external npm-packages
|
// setup default configuration for external npm-packages
|
||||||
configurePackages();
|
configurePackages();
|
||||||
@ -45,3 +47,13 @@ global.ResizeObserver = class {
|
|||||||
|
|
||||||
jest.mock("./renderer/components/monaco-editor/monaco-editor");
|
jest.mock("./renderer/components/monaco-editor/monaco-editor");
|
||||||
jest.mock("./renderer/components/tooltip/withTooltip");
|
jest.mock("./renderer/components/tooltip/withTooltip");
|
||||||
|
|
||||||
|
const getInjectables = (environment: "renderer" | "main", filePathGlob: string) =>
|
||||||
|
glob.sync(`./{common,extensions,${environment}}/**/${filePathGlob}`, {
|
||||||
|
cwd: __dirname,
|
||||||
|
}).map(x => path.resolve(__dirname, x));
|
||||||
|
|
||||||
|
(global as any).rendererInjectablePaths = getInjectables("renderer", "*.injectable.{ts,tsx}");
|
||||||
|
(global as any).rendererGlobalOverridePaths = getInjectables("renderer", "*.global-override-for-injectable.{ts,tsx}");
|
||||||
|
(global as any).mainInjectablePaths = getInjectables("main", "*.injectable.{ts,tsx}");
|
||||||
|
(global as any).mainGlobalOverridePaths = getInjectables("main", "*.global-override-for-injectable.{ts,tsx}");
|
||||||
|
|||||||
@ -11,9 +11,8 @@ import { watch } from "chokidar";
|
|||||||
import type { Stats } from "fs";
|
import type { Stats } from "fs";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import type stream from "stream";
|
|
||||||
import type { Disposer } from "../../../common/utils";
|
import type { Disposer } from "../../../common/utils";
|
||||||
import { bytesToUnits, getOrInsertWith, iter, noop } from "../../../common/utils";
|
import { disposer, bytesToUnits, getOrInsertWith, iter, noop } from "../../../common/utils";
|
||||||
import logger from "../../logger";
|
import logger from "../../logger";
|
||||||
import type { KubeConfig } from "@kubernetes/client-node";
|
import type { KubeConfig } from "@kubernetes/client-node";
|
||||||
import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers";
|
import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers";
|
||||||
@ -265,47 +264,35 @@ const diffChangedConfigFor = (dependencies: ComputeDiffDependencies) => ({ fileP
|
|||||||
return noop;
|
return noop;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace with an AbortController with fs.readFile when we upgrade to Node 16 (after it comes out)
|
const controller = new AbortController();
|
||||||
const fileReader = fs.createReadStream(filePath, {
|
const fileContentsP = fs.promises.readFile(filePath, {
|
||||||
mode: fs.constants.O_RDONLY,
|
signal: controller.signal,
|
||||||
});
|
});
|
||||||
const readStream: stream.Readable = fileReader;
|
const cleanup = disposer(
|
||||||
const decoder = new TextDecoder("utf-8", { fatal: true });
|
() => controller.abort(),
|
||||||
let fileString = "";
|
);
|
||||||
let closed = false;
|
|
||||||
|
|
||||||
const cleanup = () => {
|
fileContentsP
|
||||||
closed = true;
|
.then((fileData) => {
|
||||||
fileReader.close(); // This may not close the stream.
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
||||||
// Artificially marking end-of-stream, as if the underlying resource had
|
|
||||||
// indicated end-of-file by itself, allows the stream to close.
|
|
||||||
// This does not cancel pending read operations, and if there is such an
|
|
||||||
// operation, the process may still not be able to exit successfully
|
|
||||||
// until it finishes.
|
|
||||||
fileReader.push(null);
|
|
||||||
fileReader.read(0);
|
|
||||||
readStream.removeAllListeners();
|
|
||||||
};
|
|
||||||
|
|
||||||
readStream
|
|
||||||
.on("data", (chunk: Buffer) => {
|
|
||||||
try {
|
try {
|
||||||
fileString += decoder.decode(chunk, { stream: true });
|
const fileString = decoder.decode(fileData);
|
||||||
|
|
||||||
|
computeDiff(dependencies)(fileString, source, filePath);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn(`${logPrefix} skipping ${filePath}: ${error}`);
|
logger.warn(`${logPrefix} skipping ${filePath}: ${error}`);
|
||||||
source.clear();
|
source.clear();
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on("close", () => cleanup())
|
.catch(error => {
|
||||||
.on("error", error => {
|
if (controller.signal.aborted) {
|
||||||
cleanup();
|
return;
|
||||||
logger.warn(`${logPrefix} failed to read file: ${error}`, { filePath });
|
|
||||||
})
|
|
||||||
.on("end", () => {
|
|
||||||
if (!closed) {
|
|
||||||
computeDiff(dependencies)(fileString, source, filePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.warn(`${logPrefix} failed to read file: ${error}`, { filePath });
|
||||||
|
cleanup();
|
||||||
});
|
});
|
||||||
|
|
||||||
return cleanup;
|
return cleanup;
|
||||||
|
|||||||
@ -96,8 +96,6 @@ export class DistributionDetector extends BaseClusterDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getKubernetesVersion() {
|
public async getKubernetesVersion() {
|
||||||
if (this.cluster.version) return this.cluster.version;
|
|
||||||
|
|
||||||
const response = await this.k8sRequest("/version");
|
const response = await this.k8sRequest("/version");
|
||||||
|
|
||||||
return response.gitVersion;
|
return response.gitVersion;
|
||||||
|
|||||||
@ -3,8 +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 glob from "glob";
|
import { kebabCase, noop, chunk } from "lodash/fp";
|
||||||
import { kebabCase, memoize, noop, chunk } from "lodash/fp";
|
|
||||||
import type { DiContainer, Injectable } from "@ogre-tools/injectable";
|
import type { DiContainer, Injectable } from "@ogre-tools/injectable";
|
||||||
import { createContainer } from "@ogre-tools/injectable";
|
import { createContainer } from "@ogre-tools/injectable";
|
||||||
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||||
@ -101,6 +100,7 @@ import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
|||||||
import electronInjectable from "./utils/resolve-system-proxy/electron.injectable";
|
import electronInjectable from "./utils/resolve-system-proxy/electron.injectable";
|
||||||
import type { HotbarStore } from "../common/hotbars/store";
|
import type { HotbarStore } from "../common/hotbars/store";
|
||||||
import focusApplicationInjectable from "./electron-app/features/focus-application.injectable";
|
import focusApplicationInjectable from "./electron-app/features/focus-application.injectable";
|
||||||
|
import type { GlobalOverride } from "../common/test-utils/get-global-override";
|
||||||
|
|
||||||
export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) {
|
export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) {
|
||||||
const {
|
const {
|
||||||
@ -113,9 +113,9 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
|
|
||||||
setLegacyGlobalDiForExtensionApi(di, Environments.main);
|
setLegacyGlobalDiForExtensionApi(di, Environments.main);
|
||||||
|
|
||||||
const filePaths = getInjectableFilePaths();
|
const injectables: Injectable<any, any, any>[] = (global as any).mainInjectablePaths.map(
|
||||||
|
(filePath: string) => require(filePath).default,
|
||||||
const injectables = filePaths.map(filePath => require(filePath).default);
|
);
|
||||||
|
|
||||||
chunk(100)(injectables).forEach(chunkInjectables => {
|
chunk(100)(injectables).forEach(chunkInjectables => {
|
||||||
di.register(...chunkInjectables);
|
di.register(...chunkInjectables);
|
||||||
@ -124,10 +124,8 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
di.preventSideEffects();
|
di.preventSideEffects();
|
||||||
|
|
||||||
if (doGeneralOverrides) {
|
if (doGeneralOverrides) {
|
||||||
const globalOverrideFilePaths = getGlobalOverridePaths();
|
const globalOverrides: GlobalOverride[] = (global as any).mainGlobalOverridePaths.map(
|
||||||
|
(filePath: string) => require(filePath).default,
|
||||||
const globalOverrides = globalOverrideFilePaths.map(
|
|
||||||
(filePath) => require(filePath).default,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
globalOverrides.forEach(globalOverride => {
|
globalOverrides.forEach(globalOverride => {
|
||||||
@ -215,20 +213,6 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
return di;
|
return di;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getInjectableFilePaths = memoize(() => [
|
|
||||||
...glob.sync("./**/*.injectable.{ts,tsx}", { cwd: __dirname }),
|
|
||||||
...glob.sync("../extensions/**/*.injectable.{ts,tsx}", { cwd: __dirname }),
|
|
||||||
...glob.sync("../common/**/*.injectable.{ts,tsx}", { cwd: __dirname }),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const getGlobalOverridePaths = memoize(() =>
|
|
||||||
glob.sync(
|
|
||||||
"../{common,extensions,main}/**/*.global-override-for-injectable.{ts,tsx}",
|
|
||||||
|
|
||||||
{ cwd: __dirname },
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: Reorganize code in Runnables to get rid of requirement for override
|
// TODO: Reorganize code in Runnables to get rid of requirement for override
|
||||||
const overrideRunnablesHavingSideEffects = (di: DiContainer) => {
|
const overrideRunnablesHavingSideEffects = (di: DiContainer) => {
|
||||||
[
|
[
|
||||||
|
|||||||
@ -77,9 +77,7 @@ const createElectronWindowInjectable = getInjectable({
|
|||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
nodeIntegrationInSubFrames: true,
|
nodeIntegrationInSubFrames: true,
|
||||||
webviewTag: true,
|
|
||||||
contextIsolation: false,
|
contextIsolation: false,
|
||||||
nativeWindowOpen: false,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -89,20 +87,16 @@ const createElectronWindowInjectable = getInjectable({
|
|||||||
.on("focus", () => {
|
.on("focus", () => {
|
||||||
configuration.onFocus?.();
|
configuration.onFocus?.();
|
||||||
})
|
})
|
||||||
|
|
||||||
.on("blur", () => {
|
.on("blur", () => {
|
||||||
configuration.onBlur?.();
|
configuration.onBlur?.();
|
||||||
})
|
})
|
||||||
|
|
||||||
.on("closed", () => {
|
.on("closed", () => {
|
||||||
configuration.onClose();
|
configuration.onClose();
|
||||||
applicationWindowState.unmanage();
|
applicationWindowState.unmanage();
|
||||||
})
|
})
|
||||||
|
|
||||||
.webContents.on("dom-ready", () => {
|
.webContents.on("dom-ready", () => {
|
||||||
configuration.onDomReady?.();
|
configuration.onDomReady?.();
|
||||||
})
|
})
|
||||||
|
|
||||||
.on("did-fail-load", (_event, code, desc) => {
|
.on("did-fail-load", (_event, code, desc) => {
|
||||||
logger.error(
|
logger.error(
|
||||||
`[CREATE-ELECTRON-WINDOW]: Failed to load window "${configuration.id}"`,
|
`[CREATE-ELECTRON-WINDOW]: Failed to load window "${configuration.id}"`,
|
||||||
@ -112,52 +106,11 @@ const createElectronWindowInjectable = getInjectable({
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
||||||
.on("did-finish-load", () => {
|
.on("did-finish-load", () => {
|
||||||
logger.info(
|
logger.info(
|
||||||
`[CREATE-ELECTRON-WINDOW]: Window "${configuration.id}" loaded`,
|
`[CREATE-ELECTRON-WINDOW]: Window "${configuration.id}" loaded`,
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
||||||
.on("will-attach-webview", (event, webPreferences, params) => {
|
|
||||||
logger.debug(
|
|
||||||
`[CREATE-ELECTRON-WINDOW]: Attaching webview to window "${configuration.id}"`,
|
|
||||||
);
|
|
||||||
// Following is security recommendations because we allow webview tag (webviewTag: true)
|
|
||||||
// suggested by https://www.electronjs.org/docs/tutorial/security#11-verify-webview-options-before-creation
|
|
||||||
// and https://www.electronjs.org/docs/tutorial/security#10-do-not-use-allowpopups
|
|
||||||
|
|
||||||
if (webPreferences.preload) {
|
|
||||||
logger.warn(
|
|
||||||
"[CREATE-ELECTRON-WINDOW]: Strip away preload scripts of webview",
|
|
||||||
);
|
|
||||||
delete webPreferences.preload;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-expect-error some electron version uses webPreferences.preloadURL/webPreferences.preload
|
|
||||||
if (webPreferences.preloadURL) {
|
|
||||||
logger.warn(
|
|
||||||
"[CREATE-ELECTRON-WINDOW]: Strip away preload scripts of webview",
|
|
||||||
);
|
|
||||||
delete webPreferences.preload;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.allowpopups) {
|
|
||||||
logger.warn(
|
|
||||||
"[CREATE-ELECTRON-WINDOW]: We do not allow allowpopups props, stop webview from renderer",
|
|
||||||
);
|
|
||||||
|
|
||||||
// event.preventDefault() will destroy the guest page.
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always disable Node.js integration for all webviews
|
|
||||||
webPreferences.nodeIntegration = false;
|
|
||||||
webPreferences.nativeWindowOpen = false;
|
|
||||||
})
|
|
||||||
|
|
||||||
.setWindowOpenHandler((details) => {
|
.setWindowOpenHandler((details) => {
|
||||||
openLinkInBrowser(details.url).catch((error) => {
|
openLinkInBrowser(details.url).catch((error) => {
|
||||||
logger.error("[CREATE-ELECTRON-WINDOW]: failed to open browser", {
|
logger.error("[CREATE-ELECTRON-WINDOW]: failed to open browser", {
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
* 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 { pipeline } from "@ogre-tools/fp";
|
import { pipeline } from "@ogre-tools/fp";
|
||||||
import { kebabCase } from "lodash/fp";
|
|
||||||
import type { Injectable } from "@ogre-tools/injectable";
|
import type { Injectable } from "@ogre-tools/injectable";
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { computed } from "mobx";
|
import { computed } from "mobx";
|
||||||
@ -16,7 +15,7 @@ import { withErrorSuppression } from "../../../common/utils/with-error-suppressi
|
|||||||
import type { WithErrorLoggingFor } from "../../../common/utils/with-error-logging/with-error-logging.injectable";
|
import type { WithErrorLoggingFor } from "../../../common/utils/with-error-logging/with-error-logging.injectable";
|
||||||
import withErrorLoggingInjectable from "../../../common/utils/with-error-logging/with-error-logging.injectable";
|
import withErrorLoggingInjectable from "../../../common/utils/with-error-logging/with-error-logging.injectable";
|
||||||
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
|
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
|
||||||
import { isBoolean } from "../../../common/utils";
|
import { isBoolean, isString } from "../../../common/utils";
|
||||||
|
|
||||||
const trayMenuItemRegistratorInjectable = getInjectable({
|
const trayMenuItemRegistratorInjectable = getInjectable({
|
||||||
id: "tray-menu-item-registrator",
|
id: "tray-menu-item-registrator",
|
||||||
@ -38,7 +37,7 @@ export default trayMenuItemRegistratorInjectable;
|
|||||||
|
|
||||||
const toItemInjectablesFor = (extension: LensMainExtension, withErrorLoggingFor: WithErrorLoggingFor, getRandomId: () => string) => {
|
const toItemInjectablesFor = (extension: LensMainExtension, withErrorLoggingFor: WithErrorLoggingFor, getRandomId: () => string) => {
|
||||||
const _toItemInjectables = (parentId: string | null) => (registration: TrayMenuRegistration): Injectable<TrayMenuItem, TrayMenuItem, void>[] => {
|
const _toItemInjectables = (parentId: string | null) => (registration: TrayMenuRegistration): Injectable<TrayMenuItem, TrayMenuItem, void>[] => {
|
||||||
const trayItemId = registration.id || kebabCase(registration.label || getRandomId());
|
const trayItemId = registration.id || getRandomId();
|
||||||
const id = `${trayItemId}-tray-menu-item-for-extension-${extension.sanitizedExtensionId}`;
|
const id = `${trayItemId}-tray-menu-item-for-extension-${extension.sanitizedExtensionId}`;
|
||||||
|
|
||||||
const parentInjectable = getInjectable({
|
const parentInjectable = getInjectable({
|
||||||
@ -51,7 +50,18 @@ const toItemInjectablesFor = (extension: LensMainExtension, withErrorLoggingFor:
|
|||||||
|
|
||||||
separator: registration.type === "separator",
|
separator: registration.type === "separator",
|
||||||
|
|
||||||
label: computed(() => registration.label || ""),
|
label: computed(() => {
|
||||||
|
if (!registration.label) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isString(registration.label)) {
|
||||||
|
return registration.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
return registration.label.get();
|
||||||
|
}),
|
||||||
|
|
||||||
tooltip: registration.toolTip,
|
tooltip: registration.toolTip,
|
||||||
|
|
||||||
click: () => {
|
click: () => {
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
import type { IComputedValue } from "mobx";
|
import type { IComputedValue } from "mobx";
|
||||||
|
|
||||||
export interface TrayMenuRegistration {
|
export interface TrayMenuRegistration {
|
||||||
label?: string;
|
label?: string | IComputedValue<string>;
|
||||||
click?: (menuItem: TrayMenuRegistration) => void;
|
click?: (menuItem: TrayMenuRegistration) => void;
|
||||||
id?: string;
|
id?: string;
|
||||||
type?: "normal" | "separator" | "submenu";
|
type?: "normal" | "separator" | "submenu";
|
||||||
|
|||||||
@ -54,11 +54,10 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 0;
|
height: 3px;
|
||||||
height: $unit * 0.5;
|
transition: opacity 150ms;
|
||||||
transition: width 150ms;
|
|
||||||
background: currentColor;
|
background: currentColor;
|
||||||
color: var(--halfGray)
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
@ -76,6 +75,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: auto;
|
right: auto;
|
||||||
color: var(--line-color-active);
|
color: var(--line-color-active);
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +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 glob from "glob";
|
import { noop, chunk } from "lodash/fp";
|
||||||
import { memoize, noop, chunk } from "lodash/fp";
|
|
||||||
import type { DiContainer, Injectable } from "@ogre-tools/injectable";
|
import type { DiContainer, Injectable } from "@ogre-tools/injectable";
|
||||||
import {
|
import {
|
||||||
createContainer,
|
createContainer,
|
||||||
@ -73,6 +72,7 @@ import forceUpdateModalRootFrameComponentInjectable from "./application-update/f
|
|||||||
import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable";
|
import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable";
|
||||||
import getEntitySettingCommandsInjectable from "./components/command-palette/registered-commands/get-entity-setting-commands.injectable";
|
import getEntitySettingCommandsInjectable from "./components/command-palette/registered-commands/get-entity-setting-commands.injectable";
|
||||||
import storageSaveDelayInjectable from "./utils/create-storage/storage-save-delay.injectable";
|
import storageSaveDelayInjectable from "./utils/create-storage/storage-save-delay.injectable";
|
||||||
|
import type { GlobalOverride } from "../common/test-utils/get-global-override";
|
||||||
|
|
||||||
export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) => {
|
export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) => {
|
||||||
const {
|
const {
|
||||||
@ -85,9 +85,9 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
|
|
||||||
setLegacyGlobalDiForExtensionApi(di, Environments.renderer);
|
setLegacyGlobalDiForExtensionApi(di, Environments.renderer);
|
||||||
|
|
||||||
const filePaths = getInjectableFilePaths();
|
const injectables: Injectable<any, any, any>[] = (global as any).rendererInjectablePaths.map(
|
||||||
|
(filePath: string) => require(filePath).default,
|
||||||
const injectables = filePaths.map(filePath => require(filePath).default);
|
);
|
||||||
|
|
||||||
chunk(100)(injectables).forEach(chunkInjectables => {
|
chunk(100)(injectables).forEach(chunkInjectables => {
|
||||||
di.register(...chunkInjectables);
|
di.register(...chunkInjectables);
|
||||||
@ -96,10 +96,8 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
di.preventSideEffects();
|
di.preventSideEffects();
|
||||||
|
|
||||||
if (doGeneralOverrides) {
|
if (doGeneralOverrides) {
|
||||||
const globalOverrideFilePaths = getGlobalOverridePaths();
|
const globalOverrides: GlobalOverride[] = (global as any).rendererGlobalOverridePaths.map(
|
||||||
|
(filePath: string) => require(filePath).default,
|
||||||
const globalOverrides = globalOverrideFilePaths.map(
|
|
||||||
(filePath) => require(filePath).default,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
globalOverrides.forEach(globalOverride => {
|
globalOverrides.forEach(globalOverride => {
|
||||||
@ -232,20 +230,6 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
return di;
|
return di;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getInjectableFilePaths = memoize(() => [
|
|
||||||
...glob.sync("./**/*.injectable.{ts,tsx}", { cwd: __dirname }),
|
|
||||||
...glob.sync("../common/**/*.injectable.{ts,tsx}", { cwd: __dirname }),
|
|
||||||
...glob.sync("../extensions/**/*.injectable.{ts,tsx}", { cwd: __dirname }),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const getGlobalOverridePaths = memoize(() =>
|
|
||||||
glob.sync(
|
|
||||||
"../{common,extensions,renderer}/**/*.global-override-for-injectable.{ts,tsx}",
|
|
||||||
|
|
||||||
{ cwd: __dirname },
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
const overrideFunctionalInjectables = (di: DiContainer, injectables: Injectable<any, any, any>[]) => {
|
const overrideFunctionalInjectables = (di: DiContainer, injectables: Injectable<any, any, any>[]) => {
|
||||||
injectables.forEach(injectable => {
|
injectables.forEach(injectable => {
|
||||||
di.override(injectable, () => () => {
|
di.override(injectable, () => () => {
|
||||||
|
|||||||
@ -5,11 +5,14 @@
|
|||||||
import { comparer, reaction } from "mobx";
|
import { comparer, reaction } from "mobx";
|
||||||
import type { Disposer } from "../../common/utils";
|
import type { Disposer } from "../../common/utils";
|
||||||
import { disposer, getOrInsert, noop, WrappedAbortController } from "../../common/utils";
|
import { disposer, getOrInsert, noop, WrappedAbortController } from "../../common/utils";
|
||||||
import AbortController from "abort-controller";
|
|
||||||
import { once } from "lodash";
|
import { once } from "lodash";
|
||||||
import type { ClusterFrameContext } from "../cluster-frame-context/cluster-frame-context";
|
import type { ClusterFrameContext } from "../cluster-frame-context/cluster-frame-context";
|
||||||
import logger from "../../common/logger";
|
import logger from "../../common/logger";
|
||||||
import type { KubeObjectStoreLoadAllParams, KubeObjectStoreSubscribeParams } from "../../common/k8s-api/kube-object.store";
|
import type { KubeObjectStoreLoadAllParams, KubeObjectStoreSubscribeParams } from "../../common/k8s-api/kube-object.store";
|
||||||
|
import type { RequestInit } from "node-fetch";
|
||||||
|
|
||||||
|
// TODO: upgrade node-fetch once we are starting to use ES modules
|
||||||
|
type LegacyAbortSignal = NonNullable<RequestInit["signal"]>;
|
||||||
|
|
||||||
// Kubernetes watch-api client
|
// Kubernetes watch-api client
|
||||||
// API: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
|
// API: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
|
||||||
@ -103,7 +106,7 @@ export class KubeWatchApi {
|
|||||||
|
|
||||||
const loadThenSubscribe = async (namespaces: string[] | undefined) => {
|
const loadThenSubscribe = async (namespaces: string[] | undefined) => {
|
||||||
try {
|
try {
|
||||||
await store.loadAll({ namespaces, reqInit: { signal: childController.signal }, onLoadFailure });
|
await store.loadAll({ namespaces, reqInit: { signal: childController.signal as LegacyAbortSignal }, onLoadFailure });
|
||||||
unsubscribe.push(store.subscribe({ onLoadFailure, abortController: childController }));
|
unsubscribe.push(store.subscribe({ onLoadFailure, abortController: childController }));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!(error instanceof DOMException)) {
|
if (!(error instanceof DOMException)) {
|
||||||
|
|||||||
58
yarn.lock
58
yarn.lock
@ -481,7 +481,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
|
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
|
||||||
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
|
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
|
||||||
|
|
||||||
"@electron/get@^1.13.0":
|
"@electron/get@^1.14.1":
|
||||||
version "1.14.1"
|
version "1.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.14.1.tgz#16ba75f02dffb74c23965e72d617adc721d27f40"
|
resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.14.1.tgz#16ba75f02dffb74c23965e72d617adc721d27f40"
|
||||||
integrity sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==
|
integrity sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==
|
||||||
@ -2106,19 +2106,19 @@
|
|||||||
form-data "^3.0.0"
|
form-data "^3.0.0"
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "17.0.31"
|
version "17.0.24"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.24.tgz#20ba1bf69c1b4ab405c7a01e950c4f446b05029f"
|
||||||
integrity sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==
|
integrity sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==
|
||||||
|
|
||||||
"@types/node@^10.12.0":
|
"@types/node@^10.12.0":
|
||||||
version "10.17.60"
|
version "10.17.60"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
|
||||||
integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
|
integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
|
||||||
|
|
||||||
"@types/node@^14.6.2":
|
"@types/node@^16.11.26":
|
||||||
version "14.18.18"
|
version "16.11.34"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.18.tgz#5c9503030df484ccffcbb935ea9a9e1d6fad1a20"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.34.tgz#520224e4be4448c279ecad09639ab460cc441a50"
|
||||||
integrity sha512-B9EoJFjhqcQ9OmQrNorItO+OwEOORNn3S31WuiHvZY/dm9ajkB7AKD/8toessEtHHNL+58jofbq7hMMY9v4yig==
|
integrity sha512-UrWGDyLAlQ2Z8bNOGWTsqbP9ZcBeTYBVuTRNxXTztBy5KhWUFI3BaeDWoCP/CzV/EVGgO1NTYzv9ZytBI9GAEw==
|
||||||
|
|
||||||
"@types/node@^16.11.47":
|
"@types/node@^16.11.47":
|
||||||
version "16.11.47"
|
version "16.11.47"
|
||||||
@ -2838,14 +2838,15 @@ abbrev@1, abbrev@~1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||||
|
|
||||||
abort-controller@^3.0.0:
|
accepts@~1.3.4, accepts@~1.3.5:
|
||||||
version "3.0.0"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
||||||
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
|
integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
|
||||||
dependencies:
|
dependencies:
|
||||||
event-target-shim "^5.0.0"
|
mime-types "~2.1.24"
|
||||||
|
negotiator "0.6.2"
|
||||||
|
|
||||||
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
|
accepts@~1.3.8:
|
||||||
version "1.3.8"
|
version "1.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||||
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
||||||
@ -4483,11 +4484,16 @@ copy-concurrently@^1.0.0:
|
|||||||
rimraf "^2.5.4"
|
rimraf "^2.5.4"
|
||||||
run-queue "^1.0.0"
|
run-queue "^1.0.0"
|
||||||
|
|
||||||
core-js-pure@^3.20.2, core-js-pure@^3.8.1:
|
core-js-pure@^3.20.2:
|
||||||
version "3.22.5"
|
version "3.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.5.tgz#bdee0ed2f9b78f2862cda4338a07b13a49b6c9a9"
|
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.5.tgz#bdee0ed2f9b78f2862cda4338a07b13a49b6c9a9"
|
||||||
integrity sha512-8xo9R00iYD7TcV7OrC98GwxiUEAabVWO3dix+uyWjnYrx9fyASLlIX+f/3p5dW5qByaP2bcZ8X/T47s55et/tA==
|
integrity sha512-8xo9R00iYD7TcV7OrC98GwxiUEAabVWO3dix+uyWjnYrx9fyASLlIX+f/3p5dW5qByaP2bcZ8X/T47s55et/tA==
|
||||||
|
|
||||||
|
core-js-pure@^3.8.1:
|
||||||
|
version "3.21.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.0.tgz#819adc8dfb808205ce25b51d50591becd615db7e"
|
||||||
|
integrity sha512-VaJUunCZLnxuDbo1rNOzwbet9E1K9joiXS5+DQMPtgxd24wfsZbJZMMfQLGYMlCUvSxLfsRUUhoOR2x28mFfeg==
|
||||||
|
|
||||||
core-util-is@1.0.2:
|
core-util-is@1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
@ -5325,13 +5331,13 @@ electron-window-state@^5.0.3:
|
|||||||
jsonfile "^4.0.0"
|
jsonfile "^4.0.0"
|
||||||
mkdirp "^0.5.1"
|
mkdirp "^0.5.1"
|
||||||
|
|
||||||
electron@^15.5.7:
|
electron@^19.0.4:
|
||||||
version "15.5.7"
|
version "19.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/electron/-/electron-15.5.7.tgz#aadb0081c504f2c2d8f81ea5fd23e38881afe86a"
|
resolved "https://registry.yarnpkg.com/electron/-/electron-19.0.4.tgz#a88d5e542868c4abd7704228ec62c553605605a0"
|
||||||
integrity sha512-n4mVlxoMc4eYx07wWFWGficL+iOMz5xZEf5dBtE/wwLm0fQpYVyW4AlknMFG9F8Css0MM0JSwNMOyRg5e1vDtg==
|
integrity sha512-roRYr1VNAWIhjD9n8qZdmhROtrzsFpuZEXrjWAw+GqPbZlrUInmvFCviRDC2Lt+VBsTNRpTfPpfzXSlLL4reEw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron/get" "^1.13.0"
|
"@electron/get" "^1.14.1"
|
||||||
"@types/node" "^14.6.2"
|
"@types/node" "^16.11.26"
|
||||||
extract-zip "^1.0.3"
|
extract-zip "^1.0.3"
|
||||||
|
|
||||||
emittery@^0.10.2:
|
emittery@^0.10.2:
|
||||||
@ -5910,11 +5916,6 @@ etag@~1.8.1:
|
|||||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||||
|
|
||||||
event-target-shim@^5.0.0:
|
|
||||||
version "5.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
|
|
||||||
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
|
|
||||||
|
|
||||||
eventemitter3@^4.0.0:
|
eventemitter3@^4.0.0:
|
||||||
version "4.0.7"
|
version "4.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||||
@ -9732,6 +9733,11 @@ needle@^2.5.2:
|
|||||||
iconv-lite "^0.4.4"
|
iconv-lite "^0.4.4"
|
||||||
sax "^1.2.4"
|
sax "^1.2.4"
|
||||||
|
|
||||||
|
negotiator@0.6.2:
|
||||||
|
version "0.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||||
|
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
||||||
|
|
||||||
negotiator@0.6.3, negotiator@^0.6.2:
|
negotiator@0.6.3, negotiator@^0.6.2:
|
||||||
version "0.6.3"
|
version "0.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user