mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into app-modal-registry
This commit is contained in:
commit
136823ce18
35
.github/workflows/bump-master-version.yaml
vendored
Normal file
35
.github/workflows/bump-master-version.yaml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: Bump Version on master
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'release') }}
|
||||
steps:
|
||||
- name: Checkout Release from lens
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm i --location=global semver
|
||||
- name: Bump version to first alpha of next minor version
|
||||
run: |
|
||||
NEW_VERSION=$(cat package.json | jq .version --raw-output| xargs semver -i preminor --preid alpha)
|
||||
cat package.json | jq --arg new_version "$NEW_VERSION" '.version = $new_version' > new-package.json
|
||||
mv new-package.json package.json
|
||||
- uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
add-paths: package.json
|
||||
commit-message: Update package.json version to next preminor because of recent release
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
title: Update version to next preminor
|
||||
labels: chore
|
||||
6
.github/workflows/mkdocs-manual.yml
vendored
6
.github/workflows/mkdocs-manual.yml
vendored
@ -53,9 +53,9 @@ jobs:
|
||||
rm -fr ./docs/clusters ./docs/contributing ./docs/faq ./docs/getting-started ./docs/helm ./docs/support ./docs/supporting
|
||||
sed -i '/Protocol Handlers/d' ./mkdocs.yml
|
||||
sed -i '/IPC/d' ./mkdocs.yml
|
||||
sed -i 's#../../clusters/adding-clusters.md#https://docs.k8slens.dev/latest/clusters/adding-clusters/#g' ./docs/extensions/get-started/your-first-extension.md
|
||||
sed -i 's#clusters/adding-clusters.md#https://docs.k8slens.dev/latest/clusters/adding-clusters/#g' ./docs/README.md
|
||||
sed -i 's#../../contributing/README.md#https://docs.k8slens.dev/latest/contributing/#g' ./docs/extensions/guides/generator.md
|
||||
sed -i 's#../../clusters/adding-clusters.md#https://docs.k8slens.dev/getting-started/add-cluster/#g' ./docs/extensions/get-started/your-first-extension.md
|
||||
sed -i 's#clusters/adding-clusters.md#https://docs.k8slens.dev//getting-started/adding-clusters/#g' ./docs/README.md
|
||||
sed -i 's#../../contributing/README.md#https://docs.k8slens.dev/contributing/#g' ./docs/extensions/guides/generator.md
|
||||
|
||||
- name: git config
|
||||
run: |
|
||||
|
||||
14
.github/workflows/require-milestone.yml
vendored
Normal file
14
.github/workflows/require-milestone.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
name: Require Milestone
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize]
|
||||
jobs:
|
||||
milestone:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Require Milestone
|
||||
run: |
|
||||
exit $(gh pr view ${{ github.event.pull_request.number }} --json milestone | jq 'if .milestone == null then 1 else 0 end')
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
@ -1,3 +1,3 @@
|
||||
# Contributing to Lens
|
||||
|
||||
See [Contributing to Lens](https://docs.k8slens.dev/latest/contributing/) documentation.
|
||||
See [Contributing to Lens](https://docs.k8slens.dev/contributing/) documentation.
|
||||
|
||||
@ -19,15 +19,15 @@ Lens IDE a standalone application for MacOS, Windows and Linux operating systems
|
||||
|
||||
## Installation
|
||||
|
||||
See [Getting Started](https://docs.k8slens.dev/main/getting-started/install-lens/) page.
|
||||
See [Getting Started](https://docs.k8slens.dev/getting-started/install-lens/) page.
|
||||
|
||||
## Development
|
||||
|
||||
See [Development](https://docs.k8slens.dev/latest/contributing/development/) page.
|
||||
See [Development](https://docs.k8slens.dev/contributing/development/) page.
|
||||
|
||||
## Contributing
|
||||
|
||||
See [Contributing](https://docs.k8slens.dev/latest/contributing/) page.
|
||||
See [Contributing](https://docs.k8slens.dev/contributing/) page.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ npm run dev
|
||||
You must restart Lens for the extension to load.
|
||||
After this initial restart, reload Lens and it will automatically pick up changes any time the extension rebuilds.
|
||||
|
||||
With Lens running, either connect to an existing cluster or create a new one - refer to the latest [Lens Documentation](https://docs.k8slens.dev/main/catalog/) for details on how to add a cluster in Lens IDE.
|
||||
With Lens running, either connect to an existing cluster or create a new one - refer to the latest [Lens Documentation](https://docs.k8slens.dev/getting-started/add-cluster/) for details on how to add a cluster in Lens IDE.
|
||||
You will see the "Hello World" page in the left-side cluster menu.
|
||||
|
||||
## Develop the Extension
|
||||
|
||||
@ -46,14 +46,14 @@ Open `my-first-lens-ext/renderer.tsx` and change the value of `title` from `"Hel
|
||||
|
||||
```typescript
|
||||
clusterPageMenus = [
|
||||
{
|
||||
target: { pageId: "hello" },
|
||||
title: "Hello Lens",
|
||||
components: {
|
||||
Icon: ExampleIcon,
|
||||
}
|
||||
}
|
||||
]
|
||||
{
|
||||
target: { pageId: "hello" },
|
||||
title: "Hello Lens",
|
||||
components: {
|
||||
Icon: ExampleIcon,
|
||||
},
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
Reload Lens and you will see that the menu item text has changed to "Hello Lens".
|
||||
@ -70,6 +70,6 @@ To debug your extension, please see our instructions on [Testing Extensions](../
|
||||
To dive deeper, consider looking at [Common Capabilities](../capabilities/common-capabilities.md), [Styling](../capabilities/styling.md), or [Extension Anatomy](anatomy.md).
|
||||
|
||||
If you find problems with the Lens Extension Generator, or have feature requests, you are welcome to raise an [issue](https://github.com/lensapp/generator-lens-ext/issues).
|
||||
You can find the latest Lens contribution guidelines [here](https://docs.k8slens.dev/latest/contributing).
|
||||
You can find the latest Lens contribution guidelines [here](https://docs.k8slens.dev/contributing).
|
||||
|
||||
The Generator source code is hosted at [GitHub](https://github.com/lensapp/generator-lens-ext).
|
||||
|
||||
@ -771,7 +771,7 @@ Construct the table using the `Renderer.Component.Table` and related elements.
|
||||
|
||||
For each pod the name, age, and status are obtained using the `Renderer.K8sApi.Pod` methods.
|
||||
The table is constructed using the `Renderer.Component.Table` and related elements.
|
||||
See [Component documentation](https://docs.k8slens.dev/latest/extensions/api/modules/_renderer_api_components_/) for further details.
|
||||
See [Component documentation](https://api-docs.k8slens.dev/latest/extensions/api/modules/Renderer.Component/) for further details.
|
||||
|
||||
### `kubeObjectStatusTexts`
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
},
|
||||
},
|
||||
},
|
||||
prometheus+:: {
|
||||
kubernetesControlPlane+:: {
|
||||
serviceMonitorKubelet+: {
|
||||
spec+: {
|
||||
endpoints: std.map(function(endpoint)
|
||||
|
||||
39
package.json
39
package.json
@ -3,7 +3,7 @@
|
||||
"productName": "OpenLens",
|
||||
"description": "OpenLens - Open Source IDE for Kubernetes",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"version": "6.1.0",
|
||||
"version": "6.2.0-alpha.0",
|
||||
"main": "static/build/main.js",
|
||||
"copyright": "© 2022 OpenLens Authors",
|
||||
"license": "MIT",
|
||||
@ -246,7 +246,7 @@
|
||||
"history": "^4.10.1",
|
||||
"http-proxy": "^1.18.1",
|
||||
"immer": "^9.0.15",
|
||||
"joi": "^17.6.2",
|
||||
"joi": "^17.6.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^16.7.0",
|
||||
"lodash": "^4.17.15",
|
||||
@ -259,7 +259,7 @@
|
||||
"mobx-utils": "^6.0.4",
|
||||
"mock-fs": "^5.1.4",
|
||||
"moment": "^2.29.4",
|
||||
"moment-timezone": "^0.5.37",
|
||||
"moment-timezone": "^0.5.38",
|
||||
"monaco-editor": "^0.29.1",
|
||||
"monaco-editor-webpack-plugin": "^5.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
@ -298,10 +298,10 @@
|
||||
"@material-ui/core": "^4.12.3",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.8",
|
||||
"@sentry/types": "^6.19.7",
|
||||
"@swc/cli": "^0.1.57",
|
||||
"@swc/core": "^1.3.5",
|
||||
"@swc/core": "^1.3.9",
|
||||
"@swc/jest": "^0.2.23",
|
||||
"@testing-library/dom": "^7.31.2",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
@ -331,7 +331,7 @@
|
||||
"@types/md5-file": "^4.0.2",
|
||||
"@types/mini-css-extract-plugin": "^2.4.0",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/node": "^16.11.64",
|
||||
"@types/node": "^16.11.68",
|
||||
"@types/node-fetch": "^2.6.2",
|
||||
"@types/npm": "^2.0.32",
|
||||
"@types/proper-lockfile": "^4.1.2",
|
||||
@ -350,7 +350,7 @@
|
||||
"@types/semver": "^7.3.12",
|
||||
"@types/sharp": "^0.31.0",
|
||||
"@types/spdy": "^3.4.5",
|
||||
"@types/tar": "^6.1.2",
|
||||
"@types/tar": "^6.1.3",
|
||||
"@types/tar-stream": "^2.2.2",
|
||||
"@types/tcp-port-used": "^1.0.1",
|
||||
"@types/tempy": "^0.3.0",
|
||||
@ -361,8 +361,8 @@
|
||||
"@types/webpack-dev-server": "^4.7.2",
|
||||
"@types/webpack-env": "^1.18.0",
|
||||
"@types/webpack-node-externals": "^2.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.39.0",
|
||||
"@typescript-eslint/parser": "^5.39.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||
"@typescript-eslint/parser": "^5.40.1",
|
||||
"adr": "^1.4.3",
|
||||
"ansi_up": "^5.1.0",
|
||||
"chart.js": "^2.9.4",
|
||||
@ -374,18 +374,17 @@
|
||||
"css-loader": "^6.7.1",
|
||||
"deepdash": "^5.3.9",
|
||||
"dompurify": "^2.4.0",
|
||||
"electron": "^19.1.1",
|
||||
"electron-builder": "^23.3.3",
|
||||
"electron": "^19.1.3",
|
||||
"electron-builder": "^23.6.0",
|
||||
"electron-notarize": "^0.3.0",
|
||||
"esbuild": "^0.15.10",
|
||||
"esbuild": "^0.15.12",
|
||||
"esbuild-loader": "^2.20.0",
|
||||
"eslint": "^8.24.0",
|
||||
"eslint": "^8.25.0",
|
||||
"eslint-plugin-header": "^3.1.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-react": "7.31.8",
|
||||
"eslint-plugin-react": "7.31.10",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"flex.box": "^3.4.4",
|
||||
"fork-ts-checker-webpack-plugin": "^6.5.2",
|
||||
"gunzip-maybe": "^1.4.2",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
@ -402,8 +401,8 @@
|
||||
"node-gyp": "^8.3.0",
|
||||
"node-loader": "^2.0.0",
|
||||
"nodemon": "^2.0.20",
|
||||
"playwright": "^1.26.1",
|
||||
"postcss": "^8.4.17",
|
||||
"playwright": "^1.27.1",
|
||||
"postcss": "^8.4.18",
|
||||
"postcss-loader": "^6.2.1",
|
||||
"query-string": "^7.1.1",
|
||||
"randomcolor": "^0.6.2",
|
||||
@ -411,7 +410,7 @@
|
||||
"react-refresh": "^0.14.0",
|
||||
"react-refresh-typescript": "^2.0.7",
|
||||
"react-router-dom": "^5.3.4",
|
||||
"react-select": "^5.4.0",
|
||||
"react-select": "^5.5.4",
|
||||
"react-select-event": "^5.5.1",
|
||||
"react-table": "^7.8.0",
|
||||
"react-window": "^1.8.7",
|
||||
@ -419,13 +418,13 @@
|
||||
"sass-loader": "^12.6.0",
|
||||
"sharp": "^0.31.1",
|
||||
"style-loader": "^3.3.1",
|
||||
"tailwindcss": "^3.1.8",
|
||||
"tailwindcss": "^3.2.0",
|
||||
"tar-stream": "^2.2.0",
|
||||
"ts-loader": "^9.4.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"type-fest": "^2.14.0",
|
||||
"typed-emitter": "^1.4.0",
|
||||
"typedoc": "0.23.15",
|
||||
"typedoc": "0.23.17",
|
||||
"typedoc-plugin-markdown": "^3.13.6",
|
||||
"typescript": "^4.8.4",
|
||||
"typescript-plugin-css-modules": "^3.4.0",
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* 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 type { AppPaths } from "./app-path-injection-token";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-injection-token";
|
||||
import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token";
|
||||
|
||||
export type AppPathsChannel = RequestChannel<void, AppPaths>;
|
||||
|
||||
const appPathsChannelInjectable = getInjectable({
|
||||
id: "app-paths-channel",
|
||||
|
||||
instantiate: (): AppPathsChannel => ({
|
||||
id: "app-paths",
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default appPathsChannelInjectable;
|
||||
13
src/common/app-paths/app-paths-channel.ts
Normal file
13
src/common/app-paths/app-paths-channel.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { AppPaths } from "./app-path-injection-token";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export type AppPathsChannel = RequestChannel<void, AppPaths>;
|
||||
|
||||
export const appPathsChannel: AppPathsChannel = {
|
||||
id: "app-paths",
|
||||
};
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
export type RestartAndInstallUpdateChannel = MessageChannel<void>;
|
||||
|
||||
export const restartAndInstallUpdateChannel: RestartAndInstallUpdateChannel = {
|
||||
id: "restart-and-install-update-channel",
|
||||
};
|
||||
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* 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 type { MessageChannel } from "../../utils/channel/message-channel-injection-token";
|
||||
import { messageChannelInjectionToken } from "../../utils/channel/message-channel-injection-token";
|
||||
|
||||
export type RestartAndInstallUpdateChannel = MessageChannel;
|
||||
|
||||
const restartAndInstallUpdateChannel = getInjectable({
|
||||
id: "restart-and-install-update-channel",
|
||||
|
||||
instantiate: (): RestartAndInstallUpdateChannel => ({
|
||||
id: "restart-and-install-update-channel",
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default restartAndInstallUpdateChannel;
|
||||
@ -19,7 +19,7 @@ const selectedUpdateChannelInjectable = getInjectable({
|
||||
|
||||
instantiate: (di): SelectedUpdateChannel => {
|
||||
const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable);
|
||||
const state = observable.box<UpdateChannel>();
|
||||
const state = observable.box<UpdateChannel>(undefined, { deep: false });
|
||||
|
||||
return {
|
||||
value: computed(() => state.get() ?? defaultUpdateChannel.get()),
|
||||
|
||||
56
src/common/fetch/download-binary.injectable.ts
Normal file
56
src/common/fetch/download-binary.injectable.ts
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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 type { RequestInit, Response } from "node-fetch";
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
import fetchInjectable from "./fetch.injectable";
|
||||
|
||||
export interface DownloadBinaryOptions {
|
||||
signal?: AbortSignal | null | undefined;
|
||||
}
|
||||
|
||||
export type DownloadBinary = (url: string, opts?: DownloadBinaryOptions) => Promise<AsyncResult<Buffer, string>>;
|
||||
|
||||
const downloadBinaryInjectable = getInjectable({
|
||||
id: "download-binary",
|
||||
instantiate: (di): DownloadBinary => {
|
||||
const fetch = di.inject(fetchInjectable);
|
||||
|
||||
return async (url, opts) => {
|
||||
let result: Response;
|
||||
|
||||
try {
|
||||
// TODO: upgrade node-fetch once we switch to ESM
|
||||
result = await fetch(url, opts as RequestInit);
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
|
||||
if (result.status < 200 || 300 <= result.status) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: result.statusText,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
response: await result.buffer(),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default downloadBinaryInjectable;
|
||||
56
src/common/fetch/download-json.injectable.ts
Normal file
56
src/common/fetch/download-json.injectable.ts
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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 type { RequestInit, Response } from "node-fetch";
|
||||
import type { JsonValue } from "type-fest";
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
import fetchInjectable from "./fetch.injectable";
|
||||
|
||||
export interface DownloadJsonOptions {
|
||||
signal?: AbortSignal | null | undefined;
|
||||
}
|
||||
|
||||
export type DownloadJson = (url: string, opts?: DownloadJsonOptions) => Promise<AsyncResult<JsonValue, string>>;
|
||||
|
||||
const downloadJsonInjectable = getInjectable({
|
||||
id: "download-json",
|
||||
instantiate: (di): DownloadJson => {
|
||||
const fetch = di.inject(fetchInjectable);
|
||||
|
||||
return async (url, opts) => {
|
||||
let result: Response;
|
||||
|
||||
try {
|
||||
result = await fetch(url, opts as RequestInit);
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
|
||||
if (result.status < 200 || 300 <= result.status) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: result.statusText,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
response: await result.json(),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default downloadJsonInjectable;
|
||||
@ -3,10 +3,10 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { RequestInfo, RequestInit, Response } from "node-fetch";
|
||||
import fetch from "node-fetch";
|
||||
import type { RequestInit, Response } from "node-fetch";
|
||||
|
||||
export type Fetch = (url: RequestInfo, init?: RequestInit) => Promise<Response>;
|
||||
export type Fetch = (url: string, init?: RequestInit) => Promise<Response>;
|
||||
|
||||
const fetchInjectable = getInjectable({
|
||||
id: "fetch",
|
||||
|
||||
17
src/common/fetch/timeout-controller.ts
Normal file
17
src/common/fetch/timeout-controller.ts
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates an AbortController with an associated timeout
|
||||
* @param timeout The number of milliseconds before this controller will auto abort
|
||||
*/
|
||||
export function withTimeout(timeout: number): AbortController {
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), timeout);
|
||||
|
||||
controller.signal.addEventListener("abort", () => clearTimeout(id));
|
||||
|
||||
return controller;
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* 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 { IpcRendererNavigationEvents } from "../../renderer/navigation/events";
|
||||
import type { MessageChannel } from "../utils/channel/message-channel-injection-token";
|
||||
import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token";
|
||||
|
||||
export type AppNavigationChannel = MessageChannel<string>;
|
||||
|
||||
const appNavigationChannelInjectable = getInjectable({
|
||||
id: "app-navigation-channel",
|
||||
|
||||
instantiate: (): AppNavigationChannel => ({
|
||||
id: IpcRendererNavigationEvents.NAVIGATE_IN_APP,
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default appNavigationChannelInjectable;
|
||||
12
src/common/front-end-routing/app-navigation-channel.ts
Normal file
12
src/common/front-end-routing/app-navigation-channel.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { IpcRendererNavigationEvents } from "../../renderer/navigation/events";
|
||||
import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
export type AppNavigationChannel = MessageChannel<string>;
|
||||
|
||||
export const appNavigationChannel: AppNavigationChannel = {
|
||||
id: IpcRendererNavigationEvents.NAVIGATE_IN_APP,
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* 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 { IpcRendererNavigationEvents } from "../../renderer/navigation/events";
|
||||
import type { MessageChannel } from "../utils/channel/message-channel-injection-token";
|
||||
import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token";
|
||||
|
||||
export type ClusterFrameNavigationChannel = MessageChannel<string>;
|
||||
|
||||
const clusterFrameNavigationChannelInjectable = getInjectable({
|
||||
id: "cluster-frame-navigation-channel",
|
||||
|
||||
instantiate: (): ClusterFrameNavigationChannel => ({
|
||||
id: IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER,
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default clusterFrameNavigationChannelInjectable;
|
||||
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { IpcRendererNavigationEvents } from "../../renderer/navigation/events";
|
||||
import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
export type ClusterFrameNavigationChannel = MessageChannel<string>;
|
||||
|
||||
export const clusterFrameNavigationChannel: ClusterFrameNavigationChannel = {
|
||||
id: IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER,
|
||||
};
|
||||
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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 isAllowedResourceInjectable from "../../../../../utils/is-allowed-resource.injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
|
||||
|
||||
const leasesRouteInjectable = getInjectable({
|
||||
id: "leases",
|
||||
|
||||
instantiate: (di) => {
|
||||
const isAllowedResource = di.inject(isAllowedResourceInjectable, "leases");
|
||||
|
||||
return {
|
||||
path: "/leases",
|
||||
clusterFrame: true,
|
||||
isEnabled: isAllowedResource,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: frontEndRouteInjectionToken,
|
||||
});
|
||||
|
||||
export default leasesRouteInjectable;
|
||||
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 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 leasesRouteInjectable from "./leases-route.injectable";
|
||||
import { navigateToRouteInjectionToken } from "../../../../navigate-to-route-injection-token";
|
||||
|
||||
const navigateToLeasesInjectable = getInjectable({
|
||||
id: "navigate-to-leases",
|
||||
|
||||
instantiate: (di) => {
|
||||
const navigateToRoute = di.inject(navigateToRouteInjectionToken);
|
||||
const route = di.inject(leasesRouteInjectable);
|
||||
|
||||
return () => navigateToRoute(route);
|
||||
},
|
||||
});
|
||||
|
||||
export default navigateToLeasesInjectable;
|
||||
@ -5,22 +5,33 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ExecFileOptions } from "child_process";
|
||||
import { execFile } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
|
||||
export type ExecFile = (filePath: string, args: string[], options: ExecFileOptions) => Promise<string>;
|
||||
export interface ExecFile {
|
||||
(filePath: string, args: string[], options: ExecFileOptions): Promise<AsyncResult<string, { stderr: string; error: Error }>>;
|
||||
}
|
||||
|
||||
const execFileInjectable = getInjectable({
|
||||
id: "exec-file",
|
||||
|
||||
instantiate: (): ExecFile => {
|
||||
const asyncExecFile = promisify(execFile);
|
||||
|
||||
return async (filePath, args, options) => {
|
||||
const result = await asyncExecFile(filePath, args, options);
|
||||
|
||||
return result.stdout;
|
||||
};
|
||||
},
|
||||
instantiate: (): ExecFile => (filePath, args, options) => new Promise((resolve) => {
|
||||
execFile(filePath, args, options, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
resolve({
|
||||
callWasSuccessful: false,
|
||||
error: {
|
||||
error,
|
||||
stderr,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
callWasSuccessful: true,
|
||||
response: stdout,
|
||||
});
|
||||
}
|
||||
});
|
||||
}),
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
@ -2,22 +2,12 @@
|
||||
* 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 type { HelmRepo } from "./helm-repo";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token";
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export type AddHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<string>>;
|
||||
|
||||
const addHelmRepositoryChannelInjectable = getInjectable({
|
||||
export const addHelmRepositoryChannel: AddHelmRepositoryChannel = {
|
||||
id: "add-helm-repository-channel",
|
||||
|
||||
instantiate: (): AddHelmRepositoryChannel => ({
|
||||
id: "add-helm-repository-channel",
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default addHelmRepositoryChannelInjectable;
|
||||
};
|
||||
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* 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 type { RequestChannel } from "../utils/channel/request-channel-injection-token";
|
||||
import type { HelmRepo } from "./helm-repo";
|
||||
import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token";
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
|
||||
export type GetHelmRepositoriesChannel = RequestChannel<void, AsyncResult<HelmRepo[]>>;
|
||||
|
||||
const getActiveHelmRepositoriesChannelInjectable = getInjectable({
|
||||
id: "get-active-helm-repositories-channel",
|
||||
|
||||
instantiate: (): GetHelmRepositoriesChannel => ({
|
||||
id: "get-helm-active-list-repositories",
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default getActiveHelmRepositoriesChannelInjectable;
|
||||
13
src/common/helm/get-active-helm-repositories-channel.ts
Normal file
13
src/common/helm/get-active-helm-repositories-channel.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { HelmRepo } from "./helm-repo";
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export type GetActiveHelmRepositoriesChannel = RequestChannel<void, AsyncResult<HelmRepo[]>>;
|
||||
|
||||
export const getActiveHelmRepositoriesChannel: GetActiveHelmRepositoriesChannel = {
|
||||
id: "get-helm-active-list-repositories",
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* 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 type { HelmRepo } from "./helm-repo";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token";
|
||||
|
||||
export type RemoveHelmRepositoryChannel = RequestChannel<HelmRepo>;
|
||||
|
||||
const removeHelmRepositoryChannelInjectable = getInjectable({
|
||||
id: "remove-helm-repository-channel",
|
||||
|
||||
instantiate: (): RemoveHelmRepositoryChannel => ({
|
||||
id: "remove-helm-repository-channel",
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default removeHelmRepositoryChannelInjectable;
|
||||
13
src/common/helm/remove-helm-repository-channel.ts
Normal file
13
src/common/helm/remove-helm-repository-channel.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
|
||||
import type { HelmRepo } from "./helm-repo";
|
||||
|
||||
export type RemoveHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<string, string>>;
|
||||
|
||||
export const removeHelmRepositoryChannel: RemoveHelmRepositoryChannel = {
|
||||
id: "remove-helm-repository-channel",
|
||||
};
|
||||
@ -19,6 +19,7 @@ export * from "./events.api";
|
||||
export * from "./horizontal-pod-autoscaler.api";
|
||||
export * from "./ingress.api";
|
||||
export * from "./job.api";
|
||||
export * from "./lease.api";
|
||||
export * from "./limit-range.api";
|
||||
export * from "./namespace.api";
|
||||
export * from "./network-policy.api";
|
||||
|
||||
22
src/common/k8s-api/endpoints/lease.api.injectable.ts
Normal file
22
src/common/k8s-api/endpoints/lease.api.injectable.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { LeaseApi } from "./lease.api";
|
||||
import { kubeApiInjectionToken } from "../kube-api/kube-api-injection-token";
|
||||
|
||||
const leaseApiInjectable = getInjectable({
|
||||
id: "lease-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "leaseApi is only available in certain environments");
|
||||
|
||||
return new LeaseApi();
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default leaseApiInjectable;
|
||||
56
src/common/k8s-api/endpoints/lease.api.ts
Normal file
56
src/common/k8s-api/endpoints/lease.api.ts
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { DerivedKubeApiOptions, IgnoredKubeApiOptions } from "../kube-api";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { NamespaceScopedMetadata } from "../kube-object";
|
||||
import { KubeObject } from "../kube-object";
|
||||
|
||||
export interface LeaseSpec {
|
||||
acquireTime?: string;
|
||||
holderIdentity: string;
|
||||
leaseDurationSeconds: number;
|
||||
leaseTransitions?: number;
|
||||
renewTime: string;
|
||||
}
|
||||
|
||||
export class Lease extends KubeObject<
|
||||
NamespaceScopedMetadata,
|
||||
void,
|
||||
LeaseSpec
|
||||
> {
|
||||
static readonly kind = "Lease";
|
||||
static readonly namespaced = true;
|
||||
static readonly apiBase = "/apis/coordination.k8s.io/v1/leases";
|
||||
|
||||
getAcquireTime(): string {
|
||||
return this.spec.acquireTime || "";
|
||||
}
|
||||
|
||||
getHolderIdentity(): string {
|
||||
return this.spec.holderIdentity;
|
||||
}
|
||||
|
||||
getLeaseDurationSeconds(): number {
|
||||
return this.spec.leaseDurationSeconds;
|
||||
}
|
||||
|
||||
getLeaseTransitions(): number | undefined {
|
||||
return this.spec.leaseTransitions;
|
||||
}
|
||||
|
||||
getRenewTime(): string {
|
||||
return this.spec.renewTime;
|
||||
}
|
||||
}
|
||||
|
||||
export class LeaseApi extends KubeApi<Lease> {
|
||||
constructor(opts: DerivedKubeApiOptions & IgnoredKubeApiOptions = {}) {
|
||||
super({
|
||||
...opts,
|
||||
objectConstructor: Lease,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
export type KubeResource =
|
||||
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
||||
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" | "leases" |
|
||||
"secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" |
|
||||
"pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" |
|
||||
"endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets" |
|
||||
@ -35,6 +35,7 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
|
||||
"jobs": { kind: "Job", group: "batch" },
|
||||
"namespaces": { kind: "Namespace" },
|
||||
"limitranges": { kind: "LimitRange" },
|
||||
"leases": { kind: "Lease" },
|
||||
"networkpolicies": { kind: "NetworkPolicy", group: "networking.k8s.io" },
|
||||
"nodes": { kind: "Node" },
|
||||
"persistentvolumes": { kind: "PersistentVolume" },
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* 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 type { MessageChannel } from "../utils/channel/message-channel-injection-token";
|
||||
import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token";
|
||||
|
||||
export type RootFrameRenderedChannel = MessageChannel;
|
||||
|
||||
const rootFrameRenderedChannelInjectable = getInjectable({
|
||||
id: "root-frame-rendered-channel",
|
||||
|
||||
instantiate: (): RootFrameRenderedChannel => ({
|
||||
id: "root-frame-rendered",
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default rootFrameRenderedChannelInjectable;
|
||||
11
src/common/root-frame/root-frame-rendered-channel.ts
Normal file
11
src/common/root-frame/root-frame-rendered-channel.ts
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
export type RootFrameHasRenderedChannel = MessageChannel<void>;
|
||||
|
||||
export const rootFrameHasRenderedChannel: RootFrameHasRenderedChannel = {
|
||||
id: "root-frame-rendered",
|
||||
};
|
||||
13
src/common/user-store/resolved-shell.injectable.ts
Normal file
13
src/common/user-store/resolved-shell.injectable.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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 userStoreInjectable from "./user-store.injectable";
|
||||
|
||||
const resolvedShellInjectable = getInjectable({
|
||||
id: "resolved-shell",
|
||||
instantiate: (di) => di.inject(userStoreInjectable).resolvedShell,
|
||||
});
|
||||
|
||||
export default resolvedShellInjectable;
|
||||
@ -6,7 +6,8 @@
|
||||
// Convert object's keys to camelCase format
|
||||
import { camelCase } from "lodash";
|
||||
import type { SingleOrMany } from "./types";
|
||||
import { isObject } from "./type-narrowing";
|
||||
import { isObject, isString } from "./type-narrowing";
|
||||
import * as object from "./objects";
|
||||
|
||||
export function toCamelCase<T extends Record<string, unknown>[]>(obj: T): T;
|
||||
export function toCamelCase<T extends Record<string, unknown>>(obj: T): T;
|
||||
@ -17,11 +18,10 @@ export function toCamelCase(obj: SingleOrMany<Record<string, unknown> | unknown>
|
||||
}
|
||||
|
||||
if (isObject(obj)) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj)
|
||||
.map(([key, value]) => {
|
||||
return [camelCase(key), toCamelCase(value)];
|
||||
}),
|
||||
return object.fromEntries(
|
||||
object.entries(obj)
|
||||
.filter((pair): pair is [string, unknown] => isString(pair[0]))
|
||||
.map(([key, value]) => [camelCase(key), isObject(value) ? toCamelCase(value) : value]),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -4,31 +4,31 @@
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { MessageToChannel } from "./message-to-channel-injection-token";
|
||||
import { messageToChannelInjectionToken } from "./message-to-channel-injection-token";
|
||||
import type { SendMessageToChannel } from "./message-to-channel-injection-token";
|
||||
import { sendMessageToChannelInjectionToken } from "./message-to-channel-injection-token";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import type { MessageChannel } from "./message-channel-listener-injection-token";
|
||||
import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { RequestFromChannel } from "./request-from-channel-injection-token";
|
||||
import { requestFromChannelInjectionToken } from "./request-from-channel-injection-token";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
import { requestChannelListenerInjectionToken } from "./request-channel-listener-injection-token";
|
||||
import type { RequestChannel } from "./request-channel-listener-injection-token";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import { getPromiseStatus } from "../../test-utils/get-promise-status";
|
||||
import { runInAction } from "mobx";
|
||||
import type { RequestChannelHandler } from "../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
|
||||
type TestMessageChannel = MessageChannel<string>;
|
||||
type TestRequestChannel = RequestChannel<string, string>;
|
||||
|
||||
describe("channel", () => {
|
||||
describe("messaging from main to renderer, given listener for channel in a window and application has started", () => {
|
||||
let testMessageChannel: TestMessageChannel;
|
||||
let messageListenerInWindowMock: jest.Mock;
|
||||
let mainDi: DiContainer;
|
||||
let messageToChannel: MessageToChannel;
|
||||
let messageToChannel: SendMessageToChannel;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -39,24 +39,17 @@ describe("channel", () => {
|
||||
const testChannelListenerInTestWindowInjectable = getInjectable({
|
||||
id: "test-channel-listener-in-test-window",
|
||||
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(testMessageChannelInjectable),
|
||||
instantiate: () => ({
|
||||
channel: testMessageChannel,
|
||||
handler: messageListenerInWindowMock,
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
runInAction(() => {
|
||||
mainDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
runInAction(() => {
|
||||
windowDi.register(testChannelListenerInTestWindowInjectable);
|
||||
windowDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
@ -64,8 +57,7 @@ describe("channel", () => {
|
||||
|
||||
await builder.startHidden();
|
||||
|
||||
testMessageChannel = mainDi.inject(testMessageChannelInjectable);
|
||||
messageToChannel = mainDi.inject(messageToChannelInjectionToken);
|
||||
messageToChannel = mainDi.inject(sendMessageToChannelInjectionToken);
|
||||
});
|
||||
|
||||
describe("given window is started", () => {
|
||||
@ -109,9 +101,8 @@ describe("channel", () => {
|
||||
});
|
||||
|
||||
describe("messaging from renderer to main, given listener for channel in a main and application has started", () => {
|
||||
let testMessageChannel: TestMessageChannel;
|
||||
let messageListenerInMainMock: jest.Mock;
|
||||
let messageToChannel: MessageToChannel;
|
||||
let messageToChannel: SendMessageToChannel;
|
||||
|
||||
beforeEach(async () => {
|
||||
const applicationBuilder = getApplicationBuilder();
|
||||
@ -121,9 +112,8 @@ describe("channel", () => {
|
||||
const testChannelListenerInMainInjectable = getInjectable({
|
||||
id: "test-channel-listener-in-main",
|
||||
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(testMessageChannelInjectable),
|
||||
|
||||
instantiate: () => ({
|
||||
channel: testMessageChannel,
|
||||
handler: messageListenerInMainMock,
|
||||
}),
|
||||
|
||||
@ -133,13 +123,6 @@ describe("channel", () => {
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
runInAction(() => {
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
mainDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
runInAction(() => {
|
||||
windowDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
@ -147,8 +130,7 @@ describe("channel", () => {
|
||||
|
||||
const windowDi = applicationBuilder.applicationWindow.only.di;
|
||||
|
||||
testMessageChannel = windowDi.inject(testMessageChannelInjectable);
|
||||
messageToChannel = windowDi.inject(messageToChannelInjectionToken);
|
||||
messageToChannel = windowDi.inject(sendMessageToChannelInjectionToken);
|
||||
});
|
||||
|
||||
it("when sending message, triggers listener in main", () => {
|
||||
@ -159,8 +141,7 @@ describe("channel", () => {
|
||||
});
|
||||
|
||||
describe("requesting from main in renderer, given listener for channel in a main and application has started", () => {
|
||||
let testRequestChannel: TestRequestChannel;
|
||||
let requestListenerInMainMock: AsyncFnMock<(arg: string) => string>;
|
||||
let requestListenerInMainMock: AsyncFnMock<RequestChannelHandler<TestRequestChannel>>;
|
||||
let requestFromChannel: RequestFromChannel;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -168,28 +149,14 @@ describe("channel", () => {
|
||||
|
||||
requestListenerInMainMock = asyncFn();
|
||||
|
||||
const testChannelListenerInMainInjectable = getInjectable({
|
||||
id: "test-channel-listener-in-main",
|
||||
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(testRequestChannelInjectable),
|
||||
|
||||
handler: requestListenerInMainMock,
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({
|
||||
channel: testRequestChannel,
|
||||
handler: () => requestListenerInMainMock,
|
||||
});
|
||||
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
runInAction(() => {
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
mainDi.register(testRequestChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
runInAction(() => {
|
||||
windowDi.register(testRequestChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
@ -197,8 +164,6 @@ describe("channel", () => {
|
||||
|
||||
const windowDi = applicationBuilder.applicationWindow.only.di;
|
||||
|
||||
testRequestChannel = windowDi.inject(testRequestChannelInjectable);
|
||||
|
||||
requestFromChannel = windowDi.inject(
|
||||
requestFromChannelInjectionToken,
|
||||
);
|
||||
@ -230,21 +195,37 @@ describe("channel", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("when registering multiple handlers for the same channel, throws", async () => {
|
||||
const applicationBuilder = getApplicationBuilder();
|
||||
|
||||
const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({
|
||||
channel: testRequestChannel,
|
||||
handler: () => () => "some-value",
|
||||
});
|
||||
const testChannelListenerInMain2Injectable = getRequestChannelListenerInjectable({
|
||||
channel: testRequestChannel,
|
||||
handler: () => () => "some-other-value",
|
||||
});
|
||||
|
||||
testChannelListenerInMain2Injectable.id += "2";
|
||||
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
runInAction(() => {
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
mainDi.register(testChannelListenerInMain2Injectable);
|
||||
});
|
||||
});
|
||||
|
||||
await expect(applicationBuilder.render()).rejects.toThrow('Tried to register a multiple channel handlers for "some-request-channel-id", only one handler is supported for a request channel.');
|
||||
});
|
||||
});
|
||||
|
||||
const testMessageChannelInjectable = getInjectable({
|
||||
id: "some-message-test-channel",
|
||||
const testMessageChannel: TestMessageChannel = {
|
||||
id: "some-message-channel-id",
|
||||
};
|
||||
|
||||
instantiate: (): TestMessageChannel => ({
|
||||
id: "some-message-channel-id",
|
||||
}),
|
||||
});
|
||||
|
||||
const testRequestChannelInjectable = getInjectable({
|
||||
id: "some-request-test-channel",
|
||||
|
||||
instantiate: (): TestRequestChannel => ({
|
||||
id: "some-request-channel-id",
|
||||
}),
|
||||
});
|
||||
const testRequestChannel: TestRequestChannel = {
|
||||
id: "some-request-channel-id",
|
||||
};
|
||||
|
||||
|
||||
@ -3,14 +3,11 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { MessageChannelListener } from "./message-channel-listener-injection-token";
|
||||
import type { Disposer } from "../disposer";
|
||||
import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token";
|
||||
|
||||
export type EnlistMessageChannelListener = <
|
||||
TChannel extends MessageChannel<any>,
|
||||
>(listener: MessageChannelListener<TChannel>) => () => void;
|
||||
export type EnlistMessageChannelListener = (listener: MessageChannelListener<MessageChannel<unknown>>) => Disposer;
|
||||
|
||||
export const enlistMessageChannelListenerInjectionToken =
|
||||
getInjectionToken<EnlistMessageChannelListener>({
|
||||
id: "enlist-message-channel-listener",
|
||||
});
|
||||
export const enlistMessageChannelListenerInjectionToken = getInjectionToken<EnlistMessageChannelListener>({
|
||||
id: "enlist-message-channel-listener",
|
||||
});
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
import type { RequestChannelListener } from "./request-channel-listener-injection-token";
|
||||
|
||||
export type EnlistRequestChannelListener = <
|
||||
TChannel extends RequestChannel<any, any>,
|
||||
>(listener: RequestChannelListener<TChannel>) => () => void;
|
||||
|
||||
export const enlistRequestChannelListenerInjectionToken =
|
||||
getInjectionToken<EnlistRequestChannelListener>({
|
||||
id: "enlist-request-channel-listener",
|
||||
});
|
||||
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* 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 { getStartableStoppable } from "../get-startable-stoppable";
|
||||
import { disposer } from "../index";
|
||||
import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token";
|
||||
import { requestChannelListenerInjectionToken } from "./request-channel-listener-injection-token";
|
||||
import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token";
|
||||
import { enlistRequestChannelListenerInjectionToken } from "./enlist-request-channel-listener-injection-token";
|
||||
|
||||
const listeningOfChannelsInjectable = getInjectable({
|
||||
id: "listening-of-channels",
|
||||
|
||||
instantiate: (di) => {
|
||||
const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken);
|
||||
const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectionToken);
|
||||
const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken);
|
||||
const requestChannelListeners = di.injectMany(requestChannelListenerInjectionToken);
|
||||
|
||||
return getStartableStoppable("listening-of-channels", () => {
|
||||
const messageChannelDisposers = messageChannelListeners.map(enlistMessageChannelListener);
|
||||
const requestChannelDisposers = requestChannelListeners.map(enlistRequestChannelListener);
|
||||
|
||||
return disposer(...messageChannelDisposers, ...requestChannelDisposers);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
export default listeningOfChannelsInjectable;
|
||||
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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 { getStartableStoppable } from "../get-startable-stoppable";
|
||||
import { disposer } from "../index";
|
||||
import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token";
|
||||
import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token";
|
||||
|
||||
const listeningOnMessageChannelsInjectable = getInjectable({
|
||||
id: "listening-on-message-channels",
|
||||
|
||||
instantiate: (di) => {
|
||||
const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken);
|
||||
const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken);
|
||||
|
||||
return getStartableStoppable("listening-on-channels", () => (
|
||||
disposer(messageChannelListeners.map(enlistMessageChannelListener))
|
||||
));
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
export default listeningOnMessageChannelsInjectable;
|
||||
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { JsonValue } from "type-fest";
|
||||
|
||||
export interface MessageChannel<Message extends JsonValue | void = void> {
|
||||
id: string;
|
||||
_messageSignature?: Message;
|
||||
}
|
||||
|
||||
export const messageChannelInjectionToken = getInjectionToken<MessageChannel<any>>({
|
||||
id: "message-channel",
|
||||
});
|
||||
@ -2,17 +2,50 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { DiContainerForInjection } from "@ogre-tools/injectable";
|
||||
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||
|
||||
export interface MessageChannelListener<TChannel extends MessageChannel<any>> {
|
||||
channel: TChannel;
|
||||
handler: (value: SetRequired<TChannel, "_messageSignature">["_messageSignature"]) => void;
|
||||
export interface MessageChannel<Message> {
|
||||
id: string;
|
||||
_messageSignature?: Message; // only used to mark `Message` as used
|
||||
}
|
||||
|
||||
export const messageChannelListenerInjectionToken = getInjectionToken<MessageChannelListener<MessageChannel<any>>>(
|
||||
export type MessageChannelHandler<Channel> = Channel extends MessageChannel<infer Message>
|
||||
? (message: Message) => void
|
||||
: never;
|
||||
|
||||
export interface MessageChannelListener<Channel> {
|
||||
channel: Channel;
|
||||
handler: MessageChannelHandler<Channel>;
|
||||
}
|
||||
|
||||
export const messageChannelListenerInjectionToken = getInjectionToken<MessageChannelListener<MessageChannel<unknown>>>(
|
||||
{
|
||||
id: "message-channel-listener",
|
||||
},
|
||||
);
|
||||
|
||||
export interface GetMessageChannelListenerInfo<
|
||||
Channel extends MessageChannel<Message>,
|
||||
Message,
|
||||
> {
|
||||
id: string;
|
||||
channel: Channel;
|
||||
handler: (di: DiContainerForInjection) => MessageChannelHandler<Channel>;
|
||||
causesSideEffects?: boolean;
|
||||
}
|
||||
|
||||
export function getMessageChannelListenerInjectable<
|
||||
Channel extends MessageChannel<Message>,
|
||||
Message,
|
||||
>(info: GetMessageChannelListenerInfo<Channel, Message>) {
|
||||
return getInjectable({
|
||||
id: `${info.channel.id}-listener-${info.id}`,
|
||||
instantiate: (di) => ({
|
||||
channel: info.channel,
|
||||
handler: info.handler(di),
|
||||
}),
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
causesSideEffects: info.causesSideEffects,
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,21 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { MessageChannel } from "./message-channel-listener-injection-token";
|
||||
|
||||
export interface MessageToChannel {
|
||||
<TChannel extends MessageChannel<TMessage>, TMessage extends void>(
|
||||
channel: TChannel,
|
||||
): void;
|
||||
|
||||
<TChannel extends MessageChannel<any>>(
|
||||
channel: TChannel,
|
||||
message: SetRequired<TChannel, "_messageSignature">["_messageSignature"],
|
||||
): void;
|
||||
export interface SendMessageToChannel {
|
||||
(channel: MessageChannel<void>): void;
|
||||
<Message>(channel: MessageChannel<Message>, message: Message): void;
|
||||
}
|
||||
|
||||
export const messageToChannelInjectionToken =
|
||||
getInjectionToken<MessageToChannel>({
|
||||
id: "message-to-message-channel",
|
||||
});
|
||||
export const sendMessageToChannelInjectionToken = getInjectionToken<SendMessageToChannel>({
|
||||
id: "send-message-to-message-channel",
|
||||
});
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { JsonValue } from "type-fest";
|
||||
|
||||
export interface RequestChannel<
|
||||
Request extends JsonValue | void = void,
|
||||
Response extends JsonValue | void = void,
|
||||
> {
|
||||
id: string;
|
||||
_requestSignature?: Request;
|
||||
_responseSignature?: Response;
|
||||
}
|
||||
|
||||
export const requestChannelInjectionToken = getInjectionToken<RequestChannel<any, any>>({
|
||||
id: "request-channel",
|
||||
});
|
||||
@ -2,24 +2,9 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
|
||||
export interface RequestChannelListener<TChannel extends RequestChannel<any, any>> {
|
||||
channel: TChannel;
|
||||
|
||||
handler: (
|
||||
request: SetRequired<TChannel, "_requestSignature">["_requestSignature"]
|
||||
) =>
|
||||
| SetRequired<TChannel, "_responseSignature">["_responseSignature"]
|
||||
| Promise<
|
||||
SetRequired<TChannel, "_responseSignature">["_responseSignature"]
|
||||
>;
|
||||
export interface RequestChannel<Request, Response> {
|
||||
id: string;
|
||||
_requestSignature?: Request; // used only to mark `Request` as "used"
|
||||
_responseSignature?: Response; // used only to mark `Response` as "used"
|
||||
}
|
||||
|
||||
export const requestChannelListenerInjectionToken = getInjectionToken<RequestChannelListener<RequestChannel<any, any>>>(
|
||||
{
|
||||
id: "request-channel-listener",
|
||||
},
|
||||
);
|
||||
|
||||
@ -3,19 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
import type { RequestChannel } from "./request-channel-listener-injection-token";
|
||||
|
||||
export type RequestFromChannel = <
|
||||
TChannel extends RequestChannel<any, any>,
|
||||
>(
|
||||
channel: TChannel,
|
||||
...request: TChannel["_requestSignature"] extends void
|
||||
? []
|
||||
: [SetRequired<TChannel, "_requestSignature">["_requestSignature"]]
|
||||
) => Promise<SetRequired<TChannel, "_responseSignature">["_responseSignature"]>;
|
||||
export interface RequestFromChannel {
|
||||
<Request, Response>(channel: RequestChannel<Request, Response>, request: Request): Promise<Response>;
|
||||
<Response>(channel: RequestChannel<void, Response>): Promise<Response>;
|
||||
}
|
||||
|
||||
export const requestFromChannelInjectionToken =
|
||||
getInjectionToken<RequestFromChannel>({
|
||||
id: "request-from-request-channel",
|
||||
});
|
||||
export const requestFromChannelInjectionToken = getInjectionToken<RequestFromChannel>({
|
||||
id: "request-from-request-channel",
|
||||
});
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SingleOrMany } from "./types";
|
||||
|
||||
|
||||
|
||||
export interface Disposer {
|
||||
@ -17,9 +19,9 @@ export interface ExtendableDisposer extends Disposer {
|
||||
push(...vals: (Disposer | ExtendableDisposer | Disposable)[]): void;
|
||||
}
|
||||
|
||||
export function disposer(...items: (Disposer | Disposable | undefined | null)[]): ExtendableDisposer {
|
||||
export function disposer(...items: SingleOrMany<Disposer | Disposable | undefined | null>[]): ExtendableDisposer {
|
||||
return Object.assign(() => {
|
||||
for (const item of items) {
|
||||
for (const item of items.flat()) {
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import request from "request";
|
||||
import type { JsonValue } from "type-fest";
|
||||
import { parse } from "./json";
|
||||
|
||||
export interface DownloadFileOptions {
|
||||
url: string;
|
||||
gzip?: boolean;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export interface DownloadFileTicket<T> {
|
||||
url: string;
|
||||
promise: Promise<T>;
|
||||
cancel(): void;
|
||||
}
|
||||
|
||||
export function downloadFile({ url, timeout, gzip = true }: DownloadFileOptions): DownloadFileTicket<Buffer> {
|
||||
const fileChunks: Buffer[] = [];
|
||||
const req = request(url, { gzip, timeout });
|
||||
const promise: Promise<Buffer> = new Promise((resolve, reject) => {
|
||||
req.on("data", (chunk: Buffer) => {
|
||||
fileChunks.push(chunk);
|
||||
});
|
||||
req.once("error", err => {
|
||||
reject({ url, err });
|
||||
});
|
||||
req.once("complete", () => {
|
||||
resolve(Buffer.concat(fileChunks));
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
url,
|
||||
promise,
|
||||
cancel() {
|
||||
req.abort();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function downloadJson(args: DownloadFileOptions): DownloadFileTicket<JsonValue> {
|
||||
const { promise, ...rest } = downloadFile(args);
|
||||
|
||||
return {
|
||||
promise: promise.then(res => parse(res.toString())),
|
||||
...rest,
|
||||
};
|
||||
}
|
||||
@ -14,7 +14,6 @@ export * from "./convertMemory";
|
||||
export * from "./debouncePromise";
|
||||
export * from "./delay";
|
||||
export * from "./disposer";
|
||||
export * from "./downloadFile";
|
||||
export * from "./escapeRegExp";
|
||||
export * from "./formatDuration";
|
||||
export * from "./getRandId";
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* 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 type { RequestChannel } from "../channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../channel/request-channel-injection-token";
|
||||
|
||||
export type ResolveSystemProxyChannel = RequestChannel<string, string>;
|
||||
|
||||
const resolveSystemProxyChannelInjectable = getInjectable({
|
||||
id: "resolve-system-proxy-channel",
|
||||
|
||||
instantiate: (): ResolveSystemProxyChannel => ({
|
||||
id: "resolve-system-proxy-channel",
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default resolveSystemProxyChannelInjectable;
|
||||
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { RequestChannel } from "../channel/request-channel-listener-injection-token";
|
||||
|
||||
export type ResolveSystemProxyChannel = RequestChannel<string, string>;
|
||||
|
||||
export const resolveSystemProxyChannel: ResolveSystemProxyChannel = {
|
||||
id: "resolve-system-proxy-channel",
|
||||
};
|
||||
15
src/common/utils/sync-box/channel-listener.injectable.ts
Normal file
15
src/common/utils/sync-box/channel-listener.injectable.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { syncBoxChannel } from "./channels";
|
||||
import { getMessageChannelListenerInjectable } from "../channel/message-channel-listener-injection-token";
|
||||
import syncBoxStateInjectable from "./sync-box-state.injectable";
|
||||
|
||||
const syncBoxChannelListenerInjectable = getMessageChannelListenerInjectable({
|
||||
id: "init",
|
||||
channel: syncBoxChannel,
|
||||
handler: (di) => ({ id, value }) => di.inject(syncBoxStateInjectable, id).set(value),
|
||||
});
|
||||
|
||||
export default syncBoxChannelListenerInjectable;
|
||||
21
src/common/utils/sync-box/channels.ts
Normal file
21
src/common/utils/sync-box/channels.ts
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { MessageChannel } from "../channel/message-channel-listener-injection-token";
|
||||
import type { RequestChannel } from "../channel/request-channel-listener-injection-token";
|
||||
|
||||
export type SyncBoxChannel = MessageChannel<{ id: string; value: any }>;
|
||||
|
||||
export const syncBoxChannel: SyncBoxChannel = {
|
||||
id: "sync-box-channel",
|
||||
};
|
||||
|
||||
export type SyncBoxInitialValueChannel = RequestChannel<
|
||||
void,
|
||||
{ id: string; value: any }[]
|
||||
>;
|
||||
|
||||
export const syncBoxInitialValueChannel: SyncBoxInitialValueChannel = {
|
||||
id: "sync-box-initial-value-channel",
|
||||
};
|
||||
@ -5,17 +5,17 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { computed } from "mobx";
|
||||
import syncBoxChannelInjectable from "./sync-box-channel.injectable";
|
||||
import { messageToChannelInjectionToken } from "../channel/message-to-channel-injection-token";
|
||||
import { syncBoxChannel } from "./channels";
|
||||
import { sendMessageToChannelInjectionToken } from "../channel/message-to-channel-injection-token";
|
||||
import syncBoxStateInjectable from "./sync-box-state.injectable";
|
||||
import type { SyncBox } from "./sync-box-injection-token";
|
||||
import { toJS } from "../toJS";
|
||||
|
||||
const createSyncBoxInjectable = getInjectable({
|
||||
id: "create-sync-box",
|
||||
|
||||
instantiate: (di) => {
|
||||
const syncBoxChannel = di.inject(syncBoxChannelInjectable);
|
||||
const messageToChannel = di.inject(messageToChannelInjectionToken);
|
||||
const messageToChannel = di.inject(sendMessageToChannelInjectionToken);
|
||||
const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id);
|
||||
|
||||
return <Value>(id: string, initialValue: Value): SyncBox<Value> => {
|
||||
@ -26,7 +26,7 @@ const createSyncBoxInjectable = getInjectable({
|
||||
return {
|
||||
id,
|
||||
|
||||
value: computed(() => state.get()),
|
||||
value: computed(() => toJS(state.get())),
|
||||
|
||||
set: (value) => {
|
||||
state.set(value);
|
||||
|
||||
19
src/common/utils/sync-box/handler.injectable.ts
Normal file
19
src/common/utils/sync-box/handler.injectable.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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 type { MessageChannelHandler } from "../channel/message-channel-listener-injection-token";
|
||||
import type { SyncBoxChannel } from "./channels";
|
||||
import syncBoxStateInjectable from "./sync-box-state.injectable";
|
||||
|
||||
const syncBoxChannelHandlerInjectable = getInjectable({
|
||||
id: "sync-box-channel-handler",
|
||||
instantiate: (di): MessageChannelHandler<SyncBoxChannel> => {
|
||||
const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id);
|
||||
|
||||
return ({ id, value }) => getSyncBoxState(id)?.set(value);
|
||||
},
|
||||
});
|
||||
|
||||
export default syncBoxChannelHandlerInjectable;
|
||||
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* 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 type { SyncBoxChannel } from "./sync-box-channel.injectable";
|
||||
import syncBoxChannelInjectable from "./sync-box-channel.injectable";
|
||||
import syncBoxStateInjectable from "./sync-box-state.injectable";
|
||||
import type { MessageChannelListener } from "../channel/message-channel-listener-injection-token";
|
||||
import { messageChannelListenerInjectionToken } from "../channel/message-channel-listener-injection-token";
|
||||
|
||||
const syncBoxChannelListenerInjectable = getInjectable({
|
||||
id: "sync-box-channel-listener",
|
||||
|
||||
instantiate: (di): MessageChannelListener<SyncBoxChannel> => {
|
||||
const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id);
|
||||
const channel = di.inject(syncBoxChannelInjectable);
|
||||
|
||||
return {
|
||||
channel,
|
||||
|
||||
handler: ({ id, value }) => {
|
||||
const target = getSyncBoxState(id);
|
||||
|
||||
if (target) {
|
||||
target.set(value);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
export default syncBoxChannelListenerInjectable;
|
||||
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* 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 type { MessageChannel } from "../channel/message-channel-injection-token";
|
||||
import { messageChannelInjectionToken } from "../channel/message-channel-injection-token";
|
||||
|
||||
export type SyncBoxChannel = MessageChannel<{ id: string; value: any }>;
|
||||
|
||||
const syncBoxChannelInjectable = getInjectable({
|
||||
id: "sync-box-channel",
|
||||
|
||||
instantiate: (): SyncBoxChannel => ({
|
||||
id: "sync-box-channel",
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default syncBoxChannelInjectable;
|
||||
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* 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 type { RequestChannel } from "../channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../channel/request-channel-injection-token";
|
||||
|
||||
export type SyncBoxInitialValueChannel = RequestChannel<
|
||||
void,
|
||||
{ id: string; value: any }[]
|
||||
>;
|
||||
|
||||
const syncBoxInitialValueChannelInjectable = getInjectable({
|
||||
id: "sync-box-initial-value-channel",
|
||||
|
||||
instantiate: (): SyncBoxInitialValueChannel => ({
|
||||
id: "sync-box-initial-value-channel",
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default syncBoxInitialValueChannelInjectable;
|
||||
@ -5,7 +5,6 @@
|
||||
|
||||
// Helper for working with tarball files (.tar, .tgz)
|
||||
// Docs: https://github.com/npm/node-tar
|
||||
import type { FileStat } from "tar";
|
||||
import tar from "tar";
|
||||
import path from "path";
|
||||
import { parse } from "./json";
|
||||
@ -35,7 +34,7 @@ export function readFileFromTar<ParseJson extends boolean>({ tarPath, filePath,
|
||||
file: tarPath,
|
||||
filter: entryPath => path.normalize(entryPath) === filePath,
|
||||
sync: true,
|
||||
onentry(entry: FileStat) {
|
||||
onentry(entry) {
|
||||
entry.on("data", chunk => {
|
||||
fileChunks.push(chunk);
|
||||
});
|
||||
@ -63,7 +62,7 @@ export async function listTarEntries(filePath: string): Promise<string[]> {
|
||||
await tar.list({
|
||||
file: filePath,
|
||||
onentry: (entry) => {
|
||||
entries.push(path.normalize(entry.path as unknown as string));
|
||||
entries.push(path.normalize(entry.path));
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { defaultTo } from "lodash/fp";
|
||||
import { withErrorSuppression } from "./with-error-suppression/with-error-suppression";
|
||||
|
||||
export const tentativeParseJson = (toBeParsed: any) => pipeline(
|
||||
toBeParsed,
|
||||
withErrorSuppression(JSON.parse),
|
||||
defaultTo(toBeParsed),
|
||||
);
|
||||
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { defaultTo } from "lodash/fp";
|
||||
import { withErrorSuppression } from "./with-error-suppression/with-error-suppression";
|
||||
|
||||
export const tentativeStringifyJson = (toBeParsed: any) => pipeline(
|
||||
toBeParsed,
|
||||
withErrorSuppression(JSON.stringify),
|
||||
defaultTo(toBeParsed),
|
||||
);
|
||||
|
||||
|
||||
@ -103,7 +103,7 @@ export function isBoolean(val: unknown): val is boolean {
|
||||
* checks if val is of type object and isn't null
|
||||
* @param val the value to be checked
|
||||
*/
|
||||
export function isObject(val: unknown): val is object {
|
||||
export function isObject(val: unknown): val is Record<string | symbol | number, unknown> {
|
||||
return typeof val === "object" && val !== null;
|
||||
}
|
||||
|
||||
|
||||
@ -123,7 +123,7 @@ export const apiKubePrefix = "/api-kube"; // k8s cluster apis
|
||||
// Links
|
||||
export const issuesTrackerUrl = "https://github.com/lensapp/lens/issues" as string;
|
||||
export const slackUrl = "https://join.slack.com/t/k8slens/shared_invite/zt-wcl8jq3k-68R5Wcmk1o95MLBE5igUDQ" as string;
|
||||
export const supportUrl = "https://docs.k8slens.dev/latest/support/" as string;
|
||||
export const supportUrl = "https://docs.k8slens.dev/support/" as string;
|
||||
|
||||
export const lensWebsiteWeblinkId = "lens-website-link";
|
||||
export const lensDocumentationWeblinkId = "lens-documentation-link";
|
||||
@ -132,4 +132,4 @@ export const lensTwitterWeblinkId = "lens-twitter-link";
|
||||
export const lensBlogWeblinkId = "lens-blog-link";
|
||||
export const kubernetesDocumentationWeblinkId = "kubernetes-documentation-link";
|
||||
|
||||
export const docsUrl = "https://docs.k8slens.dev/main" as string;
|
||||
export const docsUrl = "https://docs.k8slens.dev" as string;
|
||||
|
||||
@ -7,6 +7,7 @@ import { getGlobalOverride } from "../test-utils/get-global-override";
|
||||
import applicationInformationInjectable from "./application-information.injectable";
|
||||
|
||||
export default getGlobalOverride(applicationInformationInjectable, () => ({
|
||||
name: "some-product-name",
|
||||
productName: "some-product-name",
|
||||
version: "6.0.0",
|
||||
build: {},
|
||||
|
||||
@ -5,16 +5,16 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import packageJson from "../../../package.json";
|
||||
|
||||
export type ApplicationInformation = Pick<typeof packageJson, "version" | "config" | "productName" | "copyright" | "description"> & {
|
||||
export type ApplicationInformation = Pick<typeof packageJson, "version" | "config" | "productName" | "copyright" | "description" | "name"> & {
|
||||
build: Partial<typeof packageJson["build"]> & { publish?: unknown[] };
|
||||
};
|
||||
|
||||
const applicationInformationInjectable = getInjectable({
|
||||
id: "application-information",
|
||||
instantiate: (): ApplicationInformation => {
|
||||
const { version, config, productName, build, copyright, description } = packageJson;
|
||||
const { version, config, productName, build, copyright, description, name } = packageJson;
|
||||
|
||||
return { version, config, productName, build, copyright, description };
|
||||
return { version, config, productName, build, copyright, description, name };
|
||||
},
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
@ -7,7 +7,7 @@ import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import { SemVer } from "semver";
|
||||
import type { InitializableState } from "../initializable-state/create";
|
||||
import { createInitializableState } from "../initializable-state/create";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-injection-token";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export const buildVersionInjectionToken = getInjectionToken<InitializableState<string>>({
|
||||
id: "build-version-token",
|
||||
|
||||
@ -182,6 +182,7 @@ exports[`extension special characters in page registrations renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -302,6 +303,7 @@ exports[`extension special characters in page registrations when navigating to r
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -182,6 +182,7 @@ exports[`navigate to extension page renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -302,6 +303,7 @@ exports[`navigate to extension page when extension navigates to child route rend
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -438,6 +440,7 @@ exports[`navigate to extension page when extension navigates to route with param
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -574,6 +577,7 @@ exports[`navigate to extension page when extension navigates to route without pa
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -710,6 +714,7 @@ exports[`navigate to extension page when extension navigates to route without pa
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -106,6 +106,7 @@ exports[`navigating between routes given route with optional path parameters whe
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -226,6 +227,7 @@ exports[`navigating between routes given route without path parameters when navi
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -182,6 +182,7 @@ exports[`add-cluster - navigation using application menu renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -278,7 +279,7 @@ exports[`add-cluster - navigation using application menu when navigating to add
|
||||
</code>
|
||||
file.
|
||||
<a
|
||||
href="https://docs.k8slens.dev/main/getting-started/add-cluster/"
|
||||
href="https://docs.k8slens.dev/getting-started/add-cluster/"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
@ -386,6 +387,7 @@ exports[`add-cluster - navigation using application menu when navigating to add
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -201,6 +201,7 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -420,6 +421,7 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -686,6 +688,7 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -201,6 +201,7 @@ exports[`encourage user to update when sufficient time passed since update was d
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -402,6 +403,7 @@ exports[`encourage user to update when sufficient time passed since update was d
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -183,6 +183,7 @@ exports[`installing update using tray when started renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -384,6 +385,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -585,6 +587,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -804,6 +807,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1023,6 +1027,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1224,6 +1229,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -183,6 +183,7 @@ exports[`installing update when started renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -384,6 +385,7 @@ exports[`installing update when started when user checks for updates renders 1`]
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -585,6 +587,7 @@ exports[`installing update when started when user checks for updates when new up
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -804,6 +807,7 @@ exports[`installing update when started when user checks for updates when new up
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1023,6 +1027,7 @@ exports[`installing update when started when user checks for updates when new up
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1224,6 +1229,7 @@ exports[`installing update when started when user checks for updates when no new
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -183,6 +183,7 @@ exports[`periodical checking of updates given updater is enabled and configurati
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -183,6 +183,7 @@ exports[`selection of update stability when started renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -222,7 +222,7 @@ describe("selection of update stability", () => {
|
||||
it('given user changes update channel to "alpha", when user would close the application, installs the update for being stable enough', () => {
|
||||
selectedUpdateChannel.setValue(updateChannels.alpha.id);
|
||||
|
||||
expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(false);
|
||||
expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -312,6 +312,7 @@ exports[`Deleting a cluster when an internal kubeconfig cluster is used when the
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -698,6 +699,7 @@ exports[`Deleting a cluster when the kubeconfig has multiple clusters when the d
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1117,6 +1119,7 @@ exports[`Deleting a cluster when the kubeconfig has multiple clusters when the d
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1615,6 +1618,7 @@ exports[`Deleting a cluster when the kubeconfig has multiple clusters when the d
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -2113,6 +2117,7 @@ exports[`Deleting a cluster when the kubeconfig has only one cluster when the di
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* 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 type { ClusterId } from "../../../../common/cluster-types";
|
||||
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token";
|
||||
|
||||
export type ClearClusterAsDeletingChannel = RequestChannel<ClusterId, void>;
|
||||
|
||||
const clearClusterAsDeletingChannelInjectable = getInjectable({
|
||||
id: "clear-cluster-as-deleting-channel",
|
||||
instantiate: (): ClearClusterAsDeletingChannel => ({
|
||||
id: "clear-cluster-as-deleting",
|
||||
}),
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default clearClusterAsDeletingChannelInjectable;
|
||||
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export type ClearClusterAsDeletingChannel = RequestChannel<ClusterId, void>;
|
||||
|
||||
export const clearClusterAsDeletingChannel: ClearClusterAsDeletingChannel = {
|
||||
id: "clear-cluster-as-deleting",
|
||||
};
|
||||
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* 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 type { ClusterId } from "../../../../common/cluster-types";
|
||||
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token";
|
||||
|
||||
export type DeleteClusterChannel = RequestChannel<ClusterId, void>;
|
||||
|
||||
const deleteClusterChannelInjectable = getInjectable({
|
||||
id: "delete-cluster-channel",
|
||||
instantiate: (): DeleteClusterChannel => ({
|
||||
id: "delete-cluster",
|
||||
}),
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default deleteClusterChannelInjectable;
|
||||
12
src/features/cluster/delete-dialog/common/delete-channel.ts
Normal file
12
src/features/cluster/delete-dialog/common/delete-channel.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export type DeleteClusterChannel = RequestChannel<ClusterId, void>;
|
||||
|
||||
export const deleteClusterChannel: DeleteClusterChannel = {
|
||||
id: "delete-cluster",
|
||||
};
|
||||
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* 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 type { ClusterId } from "../../../../common/cluster-types";
|
||||
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token";
|
||||
|
||||
export type SetClusterAsDeletingChannel = RequestChannel<ClusterId, void>;
|
||||
|
||||
const setClusterAsDeletingChannelInjectable = getInjectable({
|
||||
id: "set-cluster-as-deleting-channel",
|
||||
instantiate: (): SetClusterAsDeletingChannel => ({
|
||||
id: "set-cluster-as-deleting",
|
||||
}),
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default setClusterAsDeletingChannelInjectable;
|
||||
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export type SetClusterAsDeletingChannel = RequestChannel<ClusterId, void>;
|
||||
|
||||
export const setClusterAsDeletingChannel: SetClusterAsDeletingChannel = {
|
||||
id: "set-cluster-as-deleting",
|
||||
};
|
||||
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* 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 { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable";
|
||||
import clearClusterAsDeletingChannelInjectable from "../common/clear-as-deleting-channel.injectable";
|
||||
|
||||
const clearClusterAsDeletingChannelHandlerInjectable = getInjectable({
|
||||
id: "clear-cluster-as-deleting-channel-handler",
|
||||
instantiate: (di) => {
|
||||
const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable);
|
||||
|
||||
return {
|
||||
channel: di.inject(clearClusterAsDeletingChannelInjectable),
|
||||
handler: (clusterId) => clustersThatAreBeingDeleted.delete(clusterId),
|
||||
};
|
||||
},
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
export default clearClusterAsDeletingChannelHandlerInjectable;
|
||||
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable";
|
||||
import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel";
|
||||
|
||||
const clearClusterAsDeletingChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: clearClusterAsDeletingChannel,
|
||||
handler: (di) => {
|
||||
const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable);
|
||||
|
||||
return (clusterId) => {
|
||||
clustersThatAreBeingDeleted.delete(clusterId);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default clearClusterAsDeletingChannelListenerInjectable;
|
||||
@ -1,56 +0,0 @@
|
||||
/**
|
||||
* 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 appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable";
|
||||
import clusterFramesInjectable from "../../../../common/cluster-frames.injectable";
|
||||
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
|
||||
import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable";
|
||||
import deleteFileInjectable from "../../../../common/fs/delete-file.injectable";
|
||||
import joinPathsInjectable from "../../../../common/path/join-paths.injectable";
|
||||
import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import deleteClusterChannelInjectable from "../common/delete-channel.injectable";
|
||||
|
||||
const deleteClusterChannelHandlerInjectable = getInjectable({
|
||||
id: "delete-cluster-channel-handler",
|
||||
instantiate: (di) => {
|
||||
const appEventBus = di.inject(appEventBusInjectable);
|
||||
const clusterStore = di.inject(clusterStoreInjectable);
|
||||
const clusterFrames = di.inject(clusterFramesInjectable);
|
||||
const joinPaths = di.inject(joinPathsInjectable);
|
||||
const directoryForLensLocalStorage = di.inject(directoryForLensLocalStorageInjectable);
|
||||
const deleteFile = di.inject(deleteFileInjectable);
|
||||
|
||||
return {
|
||||
channel: di.inject(deleteClusterChannelInjectable),
|
||||
handler: async (clusterId) =>{
|
||||
appEventBus.emit({ name: "cluster", action: "remove" });
|
||||
|
||||
const cluster = clusterStore.getById(clusterId);
|
||||
|
||||
if (!cluster) {
|
||||
return;
|
||||
}
|
||||
|
||||
cluster.disconnect();
|
||||
clusterFrames.delete(cluster.id);
|
||||
|
||||
// Remove from the cluster store as well, this should clear any old settings
|
||||
clusterStore.clusters.delete(cluster.id);
|
||||
|
||||
try {
|
||||
// remove the local storage file
|
||||
const localStorageFilePath = joinPaths(directoryForLensLocalStorage, `${cluster.id}.json`);
|
||||
|
||||
await deleteFile(localStorageFilePath);
|
||||
} catch {
|
||||
// ignore error
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
export default deleteClusterChannelHandlerInjectable;
|
||||
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable";
|
||||
import clusterFramesInjectable from "../../../../common/cluster-frames.injectable";
|
||||
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
|
||||
import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable";
|
||||
import deleteFileInjectable from "../../../../common/fs/delete-file.injectable";
|
||||
import joinPathsInjectable from "../../../../common/path/join-paths.injectable";
|
||||
import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
import { deleteClusterChannel } from "../common/delete-channel";
|
||||
|
||||
const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: deleteClusterChannel,
|
||||
handler: (di) => {
|
||||
const appEventBus = di.inject(appEventBusInjectable);
|
||||
const clusterStore = di.inject(clusterStoreInjectable);
|
||||
const clusterFrames = di.inject(clusterFramesInjectable);
|
||||
const joinPaths = di.inject(joinPathsInjectable);
|
||||
const directoryForLensLocalStorage = di.inject(directoryForLensLocalStorageInjectable);
|
||||
const deleteFile = di.inject(deleteFileInjectable);
|
||||
|
||||
return async (clusterId) => {
|
||||
appEventBus.emit({ name: "cluster", action: "remove" });
|
||||
|
||||
const cluster = clusterStore.getById(clusterId);
|
||||
|
||||
if (!cluster) {
|
||||
return;
|
||||
}
|
||||
|
||||
cluster.disconnect();
|
||||
clusterFrames.delete(cluster.id);
|
||||
|
||||
// Remove from the cluster store as well, this should clear any old settings
|
||||
clusterStore.clusters.delete(cluster.id);
|
||||
|
||||
try {
|
||||
// remove the local storage file
|
||||
const localStorageFilePath = joinPaths(directoryForLensLocalStorage, `${cluster.id}.json`);
|
||||
|
||||
await deleteFile(localStorageFilePath);
|
||||
} catch {
|
||||
// ignore error
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default deleteClusterChannelListenerInjectable;
|
||||
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* 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 { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable";
|
||||
import setClusterAsDeletingChannelInjectable from "../common/set-as-deleting-channel.injectable";
|
||||
|
||||
const setClusterAsDeletingChannelHandlerInjectable = getInjectable({
|
||||
id: "set-cluster-as-deleting-channel-handler",
|
||||
instantiate: (di) => {
|
||||
const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable);
|
||||
|
||||
return {
|
||||
channel: di.inject(setClusterAsDeletingChannelInjectable),
|
||||
handler: (clusterId) => clustersThatAreBeingDeleted.add(clusterId),
|
||||
};
|
||||
},
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
export default setClusterAsDeletingChannelHandlerInjectable;
|
||||
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable";
|
||||
import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel";
|
||||
|
||||
const setClusterAsDeletingChannelHandlerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: setClusterAsDeletingChannel,
|
||||
handler: (di) => {
|
||||
const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable);
|
||||
|
||||
return (clusterId) => {
|
||||
clustersThatAreBeingDeleted.add(clusterId);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default setClusterAsDeletingChannelHandlerInjectable;
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
|
||||
import clearClusterAsDeletingChannelInjectable from "../common/clear-as-deleting-channel.injectable";
|
||||
import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel";
|
||||
|
||||
export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise<void>;
|
||||
|
||||
@ -13,7 +13,6 @@ const requestClearClusterAsDeletingInjectable = getInjectable({
|
||||
id: "request-clear-cluster-as-deleting",
|
||||
instantiate: (di): RequestClearClusterAsDeleting => {
|
||||
const requestChannel = di.inject(requestFromChannelInjectable);
|
||||
const clearClusterAsDeletingChannel = di.inject(clearClusterAsDeletingChannelInjectable);
|
||||
|
||||
return (clusterId) => requestChannel(clearClusterAsDeletingChannel, clusterId);
|
||||
},
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
|
||||
import deleteClusterChannelInjectable from "../common/delete-channel.injectable";
|
||||
import { deleteClusterChannel } from "../common/delete-channel";
|
||||
|
||||
export type RequestDeleteCluster = (clusterId: ClusterId) => Promise<void>;
|
||||
|
||||
@ -13,7 +13,6 @@ const requestDeleteClusterInjectable = getInjectable({
|
||||
id: "request-delete-cluster",
|
||||
instantiate: (di): RequestDeleteCluster => {
|
||||
const requestChannel = di.inject(requestFromChannelInjectable);
|
||||
const deleteClusterChannel = di.inject(deleteClusterChannelInjectable);
|
||||
|
||||
return (clusterId) => requestChannel(deleteClusterChannel, clusterId);
|
||||
},
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
|
||||
import setClusterAsDeletingChannelInjectable from "../common/set-as-deleting-channel.injectable";
|
||||
import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel";
|
||||
|
||||
export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise<void>;
|
||||
|
||||
@ -13,7 +13,6 @@ const requestSetClusterAsDeletingInjectable = getInjectable({
|
||||
id: "request-set-cluster-as-deleting",
|
||||
instantiate: (di): RequestSetClusterAsDeleting => {
|
||||
const requestChannel = di.inject(requestFromChannelInjectable);
|
||||
const setClusterAsDeletingChannel = di.inject(setClusterAsDeletingChannelInjectable);
|
||||
|
||||
return (clusterId) => requestChannel(setClusterAsDeletingChannel, clusterId);
|
||||
},
|
||||
|
||||
@ -264,6 +264,7 @@ exports[`Command Pallet: keyboard shortcut tests when on linux renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -546,6 +547,7 @@ exports[`Command Pallet: keyboard shortcut tests when on linux when pressing ESC
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -828,6 +830,7 @@ exports[`Command Pallet: keyboard shortcut tests when on linux when pressing SHI
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1122,6 +1125,7 @@ exports[`Command Pallet: keyboard shortcut tests when on linux when pressing SHI
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1323,6 +1327,7 @@ exports[`Command Pallet: keyboard shortcut tests when on macOS renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1524,6 +1529,7 @@ exports[`Command Pallet: keyboard shortcut tests when on macOS when pressing ESC
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1725,6 +1731,7 @@ exports[`Command Pallet: keyboard shortcut tests when on macOS when pressing SHI
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -1938,6 +1945,7 @@ exports[`Command Pallet: keyboard shortcut tests when on macOS when pressing SHI
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -182,6 +182,7 @@ exports[`extensions - navigation using application menu renders 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
@ -274,7 +275,7 @@ exports[`extensions - navigation using application menu when navigating to exten
|
||||
<p>
|
||||
Add new features via Lens Extensions. Check out the
|
||||
<a
|
||||
href="https://docs.k8slens.dev/main/extensions/"
|
||||
href="https://docs.k8slens.dev/extensions/"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
@ -408,6 +409,7 @@ exports[`extensions - navigation using application menu when navigating to exten
|
||||
</div>
|
||||
<div
|
||||
class="StatusBar"
|
||||
data-testid="status-bar"
|
||||
>
|
||||
<div
|
||||
class="leftSide"
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import downloadBinaryInjectable, { type DownloadBinary } from "../../common/fetch/download-binary.injectable";
|
||||
import downloadJsonInjectable, { type DownloadJson } from "../../common/fetch/download-json.injectable";
|
||||
import focusWindowInjectable from "../../renderer/navigation/focus-window.injectable";
|
||||
|
||||
// TODO: Make components free of side effects by making them deterministic
|
||||
@ -15,14 +17,20 @@ describe("extensions - navigation using application menu", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let focusWindowMock: jest.Mock;
|
||||
let downloadJson: jest.MockedFunction<DownloadJson>;
|
||||
let downloadBinary: jest.MockedFunction<DownloadBinary>;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
focusWindowMock = jest.fn();
|
||||
downloadJson = jest.fn().mockImplementation((url) => { throw new Error(`Unexpected call to downloadJson for url=${url}`); });
|
||||
downloadBinary = jest.fn().mockImplementation((url) => { throw new Error(`Unexpected call to downloadJson for url=${url}`); });
|
||||
|
||||
windowDi.override(focusWindowInjectable, () => focusWindowMock);
|
||||
windowDi.override(downloadJsonInjectable, () => downloadJson);
|
||||
windowDi.override(downloadBinaryInjectable, () => downloadBinary);
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user