diff --git a/docs/extensions/guides/renderer-extension.md b/docs/extensions/guides/renderer-extension.md index e9439fb0a9..5d41dff89d 100644 --- a/docs/extensions/guides/renderer-extension.md +++ b/docs/extensions/guides/renderer-extension.md @@ -6,29 +6,29 @@ The Renderer Extension API allows you to access, configure, and customize Lens d The custom Lens UI elements that you can add include: -* [Cluster pages](#clusterpages) -* [Cluster page menus](#clusterpagemenus) -* [Global pages](#globalpages) -* [Welcome menus](#welcomemenus) -* [App preferences](#apppreferences) -* [Top bar items](#topbaritems) -* [Status bar items](#statusbaritems) -* [KubeObject menu items](#kubeobjectmenuitems) -* [KubeObject detail items](#kubeobjectdetailitems) -* [KubeObject status texts](#kubeobjectstatustexts) -* [Kube workloads overview items](#kubeworkloadsoverviewitems) +- [Cluster pages](#clusterpages) +- [Cluster page menus](#clusterpagemenus) +- [Global pages](#globalpages) +- [Welcome menus](#welcomemenus) +- [App preferences](#apppreferences) +- [Top bar items](#topbaritems) +- [Status bar items](#statusbaritems) +- [KubeObject menu items](#kubeobjectmenuitems) +- [KubeObject detail items](#kubeobjectdetailitems) +- [KubeObject status texts](#kubeobjectstatustexts) +- [Kube workloads overview items](#kubeworkloadsoverviewitems) as well as catalog-related UI elements: -* [Entity settings](#entitysettings) -* [Catalog entity detail items](#catalogentitydetailitems) +- [Entity settings](#entitysettings) +- [Catalog entity detail items](#catalogentitydetailitems) All UI elements are based on React components. Finally, you can also add commands and protocol handlers: -* [Command palette commands](#commandpalettecommands) -* [protocol handlers](protocol-handlers.md) +- [Command palette commands](#commandpalettecommands) +- [protocol handlers](protocol-handlers.md) ## `Renderer.LensExtension` Class @@ -41,11 +41,11 @@ import { Renderer } from "@k8slens/extensions"; export default class ExampleExtensionMain extends Renderer.LensExtension { onActivate() { - console.log('custom renderer process extension code started'); + console.log("custom renderer process extension code started"); } onDeactivate() { - console.log('custom renderer process extension de-activated'); + console.log("custom renderer process extension de-activated"); } } ``` @@ -56,7 +56,7 @@ You can initiate custom code by implementing `onActivate()`. Implementing `onDeactivate()` gives you the opportunity to clean up after your extension. !!! info - Disable extensions from the Lens Extensions page: +Disable extensions from the Lens Extensions page: 1. Navigate to **File** > **Extensions** in the top menu bar. (On Mac, it is **Lens** > **Extensions**.) @@ -75,17 +75,17 @@ Add a cluster page definition to a `Renderer.LensExtension` subclass with the fo ```typescript import { Renderer } from "@k8slens/extensions"; -import { ExampleIcon, ExamplePage } from "./page" -import React from "react" +import { ExampleIcon, ExamplePage } from "./page"; +import React from "react"; export default class ExampleExtension extends Renderer.LensExtension { clusterPages = [ { id: "hello", components: { - Page: () => , - } - } + Page: () => , + }, + }, ]; } ``` @@ -93,24 +93,26 @@ export default class ExampleExtension extends Renderer.LensExtension { `clusterPages` is an array of objects that satisfy the `PageRegistration` interface. The properties of the `clusterPages` array objects are defined as follows: -* `id` is a string that identifies the page. -* `components` matches the `PageComponents` interface for which there is one field, `Page`. -* `Page` is of type ` React.ComponentType`. -It offers flexibility in defining the appearance and behavior of your page. +- `id` is a string that identifies the page. +- `components` matches the `PageComponents` interface for which there is one field, `Page`. +- `Page` is of type ` React.ComponentType`. + It offers flexibility in defining the appearance and behavior of your page. `ExamplePage` in the example above can be defined in `page.tsx`: ```typescript import { Renderer } from "@k8slens/extensions"; -import React from "react" +import React from "react"; -export class ExamplePage extends React.Component<{ extension: LensRendererExtension }> { +export class ExamplePage extends React.Component<{ + extension: LensRendererExtension; +}> { render() { return (

Hello world!

- ) + ); } } ``` @@ -130,17 +132,17 @@ By expanding on the above example, you can add a cluster page menu item to the ` ```typescript import { Renderer } from "@k8slens/extensions"; -import { ExampleIcon, ExamplePage } from "./page" -import React from "react" +import { ExampleIcon, ExamplePage } from "./page"; +import React from "react"; export default class ExampleExtension extends Renderer.LensExtension { clusterPages = [ { id: "hello", components: { - Page: () => , - } - } + Page: () => , + }, + }, ]; clusterPageMenus = [ @@ -149,7 +151,7 @@ export default class ExampleExtension extends Renderer.LensExtension { title: "Hello World", components: { Icon: ExampleIcon, - } + }, }, ]; } @@ -159,10 +161,10 @@ export default class ExampleExtension extends Renderer.LensExtension { This element defines how the cluster page menu item will appear and what it will do when you click it. The properties of the `clusterPageMenus` array objects are defined as follows: -* `target` links to the relevant cluster page using `pageId`. -* `pageId` takes the value of the relevant cluster page's `id` property. -* `title` sets the name of the cluster page menu item that will appear in the left side menu. -* `components` is used to set an icon that appears to the left of the `title` text in the left side menu. +- `target` links to the relevant cluster page using `pageId`. +- `pageId` takes the value of the relevant cluster page's `id` property. +- `title` sets the name of the cluster page menu item that will appear in the left side menu. +- `components` is used to set an icon that appears to the left of the `title` text in the left side menu. The above example creates a menu item that reads **Hello World**. When users click **Hello World**, the cluster dashboard will show the contents of `Example Page`. @@ -171,7 +173,7 @@ This example requires the definition of another React-based component, `ExampleI ```typescript import { Renderer } from "@k8slens/extensions"; -import React from "react" +import React from "react"; type IconProps = Renderer.Component.IconProps; @@ -180,16 +182,18 @@ const { } = Renderer; export function ExampleIcon(props: IconProps) { - return + return ; } -export class ExamplePage extends React.Component<{ extension: Renderer.LensExtension }> { +export class ExamplePage extends React.Component<{ + extension: Renderer.LensExtension; +}> { render() { return (

Hello world!

- ) + ); } } ``` @@ -198,32 +202,31 @@ Lens includes various built-in components available for extension developers to One of these is the `Renderer.Component.Icon`, introduced in `ExampleIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io). The properties that `Renderer.Component.Icon` uses are defined as follows: -* `material` takes the name of the icon you want to use. -* `tooltip` sets the text you want to appear when a user hovers over the icon. +- `material` takes the name of the icon you want to use. +- `tooltip` sets the text you want to appear when a user hovers over the icon. `clusterPageMenus` can also be used to define sub menu items, so that you can create groups of cluster pages. The following example groups two sub menu items under one parent menu item: - ```typescript import { Renderer } from "@k8slens/extensions"; -import { ExampleIcon, ExamplePage } from "./page" -import React from "react" +import { ExampleIcon, ExamplePage } from "./page"; +import React from "react"; export default class ExampleExtension extends Renderer.LensExtension { clusterPages = [ { id: "hello", components: { - Page: () => , - } + Page: () => , + }, }, { id: "bonjour", components: { - Page: () => , - } - } + Page: () => , + }, + }, ]; clusterPageMenus = [ @@ -232,7 +235,7 @@ export default class ExampleExtension extends Renderer.LensExtension { title: "Greetings", components: { Icon: ExampleIcon, - } + }, }, { parentId: "example", @@ -240,7 +243,7 @@ export default class ExampleExtension extends Renderer.LensExtension { title: "Hello World", components: { Icon: ExampleIcon, - } + }, }, { parentId: "example", @@ -248,8 +251,8 @@ export default class ExampleExtension extends Renderer.LensExtension { title: "Bonjour le monde", components: { Icon: ExempleIcon, - } - } + }, + }, ]; } ``` @@ -280,18 +283,18 @@ Unlike cluster pages, users can trigger global pages even when there is no activ The following example defines a `Renderer.LensExtension` subclass with a single global page definition: ```typescript -import { Renderer } from '@k8slens/extensions'; -import { HelpPage } from './page'; -import React from 'react'; +import { Renderer } from "@k8slens/extensions"; +import { HelpPage } from "./page"; +import React from "react"; export default class HelpExtension extends Renderer.LensExtension { globalPages = [ { id: "help", components: { - Page: () => , - } - } + Page: () => , + }, + }, ]; } ``` @@ -299,24 +302,26 @@ export default class HelpExtension extends Renderer.LensExtension { `globalPages` is an array of objects that satisfy the `PageRegistration` interface. The properties of the `globalPages` array objects are defined as follows: -* `id` is a string that identifies the page. -* `components` matches the `PageComponents` interface for which there is one field, `Page`. -* `Page` is of type `React.ComponentType`. -It offers flexibility in defining the appearance and behavior of your page. +- `id` is a string that identifies the page. +- `components` matches the `PageComponents` interface for which there is one field, `Page`. +- `Page` is of type `React.ComponentType`. + It offers flexibility in defining the appearance and behavior of your page. `HelpPage` in the example above can be defined in `page.tsx`: ```typescript import { Renderer } from "@k8slens/extensions"; -import React from "react" +import React from "react"; -export class HelpPage extends React.Component<{ extension: LensRendererExtension }> { +export class HelpPage extends React.Component<{ + extension: LensRendererExtension; +}> { render() { return (

Help yourself

- ) + ); } } ``` @@ -328,11 +333,12 @@ This way, `HelpPage` can access all `HelpExtension` subclass data. This example code shows how to create a global page, but not how to make that page available to the Lens user. Global pages are typically made available in the following ways: -* To add global pages to the top menu bar, see [`appMenus`](../main-extension#appmenus) in the Main Extension guide. -* To add global pages as an interactive element in the blue status bar along the bottom of the Lens UI, see [`statusBarItems`](#statusbaritems). -* To add global pages to the Welcome Page, see [`welcomeMenus`](#welcomemenus). +- To add global pages to the top menu bar, see [`appMenus`](../main-extension#appmenus) in the Main Extension guide. +- To add global pages as an interactive element in the blue status bar along the bottom of the Lens UI, see [`statusBarItems`](#statusbaritems). +- To add global pages to the Welcome Page, see [`welcomeMenus`](#welcomemenus). ### `welcomeMenus` + ### `appPreferences` The Lens **Preferences** page is a built-in global page. @@ -342,22 +348,24 @@ The following example demonstrates adding a custom preference: ```typescript import { Renderer } from "@k8slens/extensions"; -import { ExamplePreferenceHint, ExamplePreferenceInput } from "./src/example-preference"; +import { + ExamplePreferenceHint, + ExamplePreferenceInput, +} from "./src/example-preference"; import { observable } from "mobx"; import React from "react"; export default class ExampleRendererExtension extends Renderer.LensExtension { - @observable preference = { enabled: false }; appPreferences = [ { title: "Example Preferences", components: { - Input: () => , - Hint: () => - } - } + Input: () => , + Hint: () => , + }, + }, ]; } ``` @@ -365,13 +373,13 @@ export default class ExampleRendererExtension extends Renderer.LensExtension { `appPreferences` is an array of objects that satisfies the `AppPreferenceRegistration` interface. The properties of the `appPreferences` array objects are defined as follows: -* `title` sets the heading text displayed on the Preferences page. -* `components` specifies two `React.Component` objects that define the interface for the preference. - * `Input` specifies an interactive input element for the preference. - * `Hint` provides descriptive information for the preference, shown below the `Input` element. +- `title` sets the heading text displayed on the Preferences page. +- `components` specifies two `React.Component` objects that define the interface for the preference. + - `Input` specifies an interactive input element for the preference. + - `Hint` provides descriptive information for the preference, shown below the `Input` element. !!! note - Note that the input and the hint can be comprised of more sophisticated elements, according to the needs of the extension. +Note that the input and the hint can be comprised of more sophisticated elements, according to the needs of the extension. `ExamplePreferenceInput` expects its React props to be set to an `ExamplePreferenceProps` instance. This is how `ExampleRendererExtension` handles the state of the preference input. @@ -386,22 +394,19 @@ import { observer } from "mobx-react"; import React from "react"; const { - Component: { - Checkbox, - }, + Component: { Checkbox }, } = Renderer; export class ExamplePreferenceProps { preference: { enabled: boolean; - } + }; } @observer export class ExamplePreferenceInput extends React.Component { - public constructor() { - super({preference: { enabled: false}}); + super({ preference: { enabled: false } }); makeObservable(this); } @@ -411,7 +416,9 @@ export class ExamplePreferenceInput extends React.Component { preference.enabled = v; }} + onChange={(v) => { + preference.enabled = v; + }} /> ); } @@ -419,18 +426,16 @@ export class ExamplePreferenceInput extends React.ComponentThis is an example of an appPreference for extensions. - ); + return This is an example of an appPreference for extensions.; } } ``` `ExamplePreferenceInput` implements a simple checkbox using Lens's `Renderer.Component.Checkbox` using the following properties: -* `label` sets the text that displays next to the checkbox. -* `value` is initially set to `preference.enabled`. -* `onChange` is a function that responds when the state of the checkbox changes. +- `label` sets the text that displays next to the checkbox. +- `value` is initially set to `preference.enabled`. +- `onChange` is a function that responds when the state of the checkbox changes. `ExamplePreferenceInput` is defined with the `ExamplePreferenceProps` React props. This is an object with the single `enabled` property. @@ -461,18 +466,18 @@ The following example adds a `statusBarItems` definition and a `globalPages` def It configures the status bar item to navigate to the global page upon activation (normally a mouse click): ```typescript -import { Renderer } from '@k8slens/extensions'; -import { HelpIcon, HelpPage } from "./page" -import React from 'react'; +import { Renderer } from "@k8slens/extensions"; +import { HelpIcon, HelpPage } from "./page"; +import React from "react"; export default class HelpExtension extends Renderer.LensExtension { globalPages = [ { id: "help", components: { - Page: () => , - } - } + Page: () => , + }, + }, ]; statusBarItems = [ @@ -486,7 +491,7 @@ export default class HelpExtension extends Renderer.LensExtension { My Status Bar Item - ) + ), }, }, ]; @@ -495,14 +500,14 @@ export default class HelpExtension extends Renderer.LensExtension { The properties of the `statusBarItems` array objects are defined as follows: -* `Item` specifies the `React.Component` that will be shown on the status bar. -By default, items are added starting from the right side of the status bar. -Due to limited space in the status bar, `Item` will typically specify only an icon or a short string of text. -The example above reuses the `HelpIcon` from the [`globalPageMenus` guide](#globalpagemenus). -* `onClick` determines what the `statusBarItem` does when it is clicked. -In the example, `onClick` is set to a function that calls the `LensRendererExtension` `navigate()` method. -`navigate` takes the `id` of the associated global page as a parameter. -Thus, clicking the status bar item activates the associated global pages. +- `Item` specifies the `React.Component` that will be shown on the status bar. + By default, items are added starting from the right side of the status bar. + Due to limited space in the status bar, `Item` will typically specify only an icon or a short string of text. + The example above reuses the `HelpIcon` from the [`globalPageMenus` guide](#globalpagemenus). +- `onClick` determines what the `statusBarItem` does when it is clicked. + In the example, `onClick` is set to a function that calls the `LensRendererExtension` `navigate()` method. + `navigate` takes the `id` of the associated global page as a parameter. + Thus, clicking the status bar item activates the associated global pages. ### `kubeObjectMenuItems` @@ -518,9 +523,9 @@ They also appear on the title bar of the details page for specific resources: The following example shows how to add a `kubeObjectMenuItems` for namespace resources with an associated action: ```typescript -import React from "react" +import React from "react"; import { Renderer } from "@k8slens/extensions"; -import { NamespaceMenuItem } from "./src/namespace-menu-item" +import { NamespaceMenuItem } from "./src/namespace-menu-item"; type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps; type Namespace = Renderer.K8sApi.Namespace; @@ -531,23 +536,24 @@ export default class ExampleExtension extends Renderer.LensExtension { kind: "Namespace", apiVersions: ["v1"], components: { - MenuItem: (props: KubeObjectMenuProps) => - } - } + MenuItem: (props: KubeObjectMenuProps) => ( + + ), + }, + }, ]; } - ``` `kubeObjectMenuItems` is an array of objects matching the `KubeObjectMenuRegistration` interface. The example above adds a menu item for namespaces in the cluster dashboard. The properties of the `kubeObjectMenuItems` array objects are defined as follows: -* `kind` specifies the Kubernetes resource type the menu item will apply to. -* `apiVersion` specifies the Kubernetes API version number to use with the resource type. -* `components` defines the menu item's appearance and behavior. -* `MenuItem` provides a function that returns a `React.Component` given a set of menu item properties. -In this example a `NamespaceMenuItem` object is returned. +- `kind` specifies the Kubernetes resource type the menu item will apply to. +- `apiVersion` specifies the Kubernetes API version number to use with the resource type. +- `components` defines the menu item's appearance and behavior. +- `MenuItem` provides a function that returns a `React.Component` given a set of menu item properties. + In this example a `NamespaceMenuItem` object is returned. `NamespaceMenuItem` is defined in `./src/namespace-menu-item.tsx`: @@ -556,11 +562,7 @@ import React from "react"; import { Renderer } from "@k8slens/extensions"; const { - Component: { - terminalStore, - MenuItem, - Icon, - }, + Component: { terminalStore, MenuItem, Icon }, Navigation, } = Renderer; @@ -587,12 +589,15 @@ export function NamespaceMenuItem(props: KubeObjectMenuProps) { return ( - + Get Pods ); } - ``` `NamespaceMenuItem` returns a `Renderer.Component.MenuItem` which defines the menu item's appearance and its behavior when activated via the `onClick` property. @@ -629,9 +634,11 @@ export default class ExampleExtension extends Renderer.LensExtension { apiVersions: ["v1"], priority: 10, components: { - Details: (props: KubeObjectDetailsProps) => - } - } + Details: (props: KubeObjectDetailsProps) => ( + + ), + }, + }, ]; } ``` @@ -640,15 +647,15 @@ export default class ExampleExtension extends Renderer.LensExtension { This example above adds a detail item for namespaces in the cluster dashboard. The properties of the `kubeObjectDetailItems` array objects are defined as follows: -* `kind` specifies the Kubernetes resource type the detail item will apply to. -* `apiVersion` specifies the Kubernetes API version number to use with the resource type. -* `components` defines the detail item's appearance and behavior. -* `Details` provides a function that returns a `React.Component` given a set of detail item properties. -In this example a `NamespaceDetailsItem` object is returned. +- `kind` specifies the Kubernetes resource type the detail item will apply to. +- `apiVersion` specifies the Kubernetes API version number to use with the resource type. +- `components` defines the detail item's appearance and behavior. +- `Details` provides a function that returns a `React.Component` given a set of detail item properties. + In this example a `NamespaceDetailsItem` object is returned. `NamespaceDetailsItem` is defined in `./src/namespace-details-item.tsx`: -``` typescript +```typescript import { Renderer } from "@k8slens/extensions"; import { PodsDetailsList } from "./pods-details-list"; import React from "react"; @@ -656,12 +663,8 @@ import { observable } from "mobx"; import { observer } from "mobx-react"; const { - K8sApi: { - podsApi, - }, - Component: { - DrawerTitle, - }, + K8sApi: { podsApi }, + Component: { DrawerTitle }, } = Renderer; type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps; @@ -669,7 +672,9 @@ type Namespace = Renderer.K8sApi.Namespace; type Pod = Renderer.K8sApi.Pod; @observer -export class NamespaceDetailsItem extends React.Component> { +export class NamespaceDetailsItem extends React.Component< + KubeObjectDetailsProps +> { @observable private pods: Pod[]; async componentDidMount() { @@ -681,10 +686,10 @@ export class NamespaceDetailsItem extends React.Component - - + Pods + - ) + ); } } ``` @@ -709,17 +714,12 @@ Details are placed in drawers, and using `Renderer.Component.DrawerTitle` provid Multiple details in a drawer can be placed in `` elements for further separation, if desired. The rest of this example's details are defined in `PodsDetailsList`, found in `./pods-details-list.tsx`: -``` typescript +```typescript import React from "react"; import { Renderer } from "@k8slens/extensions"; const { - Component: { - TableHead, - TableRow, - TableCell, - Table, - }, + Component: { TableHead, TableRow, TableCell, Table }, } = Renderer; type Pod = Renderer.K8sApi.Pod; @@ -736,11 +736,11 @@ export class PodsDetailsList extends React.Component { {pods[index].getAge()} {pods[index].getStatus()} - ) + ); }; render() { - const { pods } = this.props + const { pods } = this.props; if (!pods?.length) { return null; @@ -754,7 +754,7 @@ export class PodsDetailsList extends React.Component { Age Status - { pods.map(this.getTableRow) } + {pods.map(this.getTableRow)} ); diff --git a/package.json b/package.json index a3136bca21..2b3fd43f4c 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "productName": "OpenLens", "description": "OpenLens - Open Source IDE for Kubernetes", "homepage": "https://github.com/lensapp/lens", - "version": "5.4.0", + "version": "5.5.0-alpha.0", "main": "static/build/main.js", "copyright": "© 2021 OpenLens Authors", "license": "MIT", @@ -28,6 +28,8 @@ "build:mac": "yarn run compile && electron-builder --mac --dir", "build:win": "yarn run compile && electron-builder --win --dir", "integration": "jest --runInBand --detectOpenHandles --forceExit integration", + "test:unit": "jest --watch --testPathIgnorePatterns integration", + "test:integration": "func() { jest ${1:-xyz} --watch --runInBand --detectOpenHandles --forceExit --modulePaths=[\"/integration/\"]; }; func", "dist": "yarn run compile && electron-builder --publish onTag", "dist:dir": "yarn run dist --dir -c.compression=store -c.mac.identity=null", "download:binaries": "yarn run ts-node build/download_binaries.ts", @@ -44,7 +46,7 @@ "postversion": "git push --set-upstream ${GIT_REMOTE:-origin} release/v$npm_package_version" }, "config": { - "k8sProxyVersion": "0.1.5", + "k8sProxyVersion": "0.2.1", "bundledKubectlVersion": "1.23.3", "bundledHelmVersion": "3.7.2", "sentryDsn": "" @@ -203,7 +205,7 @@ "@ogre-tools/injectable": "5.1.2", "@ogre-tools/injectable-react": "5.1.2", "@sentry/electron": "^2.5.4", - "@sentry/integrations": "^6.15.0", + "@sentry/integrations": "^6.19.2", "@types/circular-dependency-plugin": "5.0.5", "abort-controller": "^3.0.0", "auto-bind": "^4.0.0", @@ -214,7 +216,7 @@ "conf": "^7.1.2", "crypto-js": "^4.1.1", "electron-devtools-installer": "^3.2.0", - "electron-updater": "^4.6.1", + "electron-updater": "^4.6.5", "electron-window-state": "^5.0.3", "filehound": "^1.17.5", "fs-extra": "^9.0.1", @@ -223,7 +225,7 @@ "grapheme-splitter": "^1.0.4", "handlebars": "^4.7.7", "http-proxy": "^1.18.1", - "immer": "^9.0.6", + "immer": "^9.0.12", "joi": "^17.6.0", "js-yaml": "^4.1.0", "jsdom": "^16.7.0", @@ -243,7 +245,7 @@ "monaco-editor-webpack-plugin": "^5.0.0", "node-fetch": "lensapp/node-fetch#2.x", "node-pty": "^0.10.1", - "npm": "^6.14.15", + "npm": "^6.14.16", "p-limit": "^3.1.0", "path-to-regexp": "^6.2.0", "proper-lockfile": "^4.1.2", @@ -265,7 +267,7 @@ "tempy": "1.0.1", "url-parse": "^1.5.10", "uuid": "^8.3.2", - "win-ca": "^3.4.5", + "win-ca": "^3.5.0", "winston": "^3.6.0", "winston-console-format": "^1.0.8", "winston-transport-browserconsole": "^1.0.5", @@ -277,8 +279,8 @@ "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4", - "@sentry/types": "^6.18.2", - "@testing-library/jest-dom": "^5.16.2", + "@sentry/types": "^6.19.2", + "@testing-library/jest-dom": "^5.16.3", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^13.5.0", "@types/byline": "^4.2.33", @@ -293,18 +295,18 @@ "@types/gunzip-maybe": "^1.4.0", "@types/hoist-non-react-statics": "^3.3.1", "@types/html-webpack-plugin": "^3.2.6", - "@types/http-proxy": "^1.17.7", + "@types/http-proxy": "^1.17.8", "@types/jest": "^26.0.24", "@types/js-yaml": "^4.0.5", - "@types/jsdom": "^16.2.13", + "@types/jsdom": "^16.2.14", "@types/jsonpath": "^0.2.0", "@types/lodash": "^4.14.180", "@types/marked": "^4.0.3", "@types/md5-file": "^4.0.2", "@types/mini-css-extract-plugin": "^2.4.0", "@types/mock-fs": "^4.13.1", - "@types/node": "14.17.33", - "@types/node-fetch": "^2.5.12", + "@types/node": "14.18.12", + "@types/node-fetch": "^2.6.1", "@types/npm": "^2.0.32", "@types/proper-lockfile": "^4.1.2", "@types/randomcolor": "^0.5.6", @@ -320,7 +322,7 @@ "@types/request": "^2.48.7", "@types/request-promise-native": "^1.0.18", "@types/semver": "^7.3.9", - "@types/sharp": "^0.29.4", + "@types/sharp": "^0.30.0", "@types/spdy": "^3.4.5", "@types/tar": "^4.0.5", "@types/tar-stream": "^2.2.2", @@ -348,7 +350,7 @@ "electron": "^14.2.7", "electron-builder": "^22.14.13", "electron-notarize": "^0.3.0", - "esbuild": "^0.13.15", + "esbuild": "^0.14.27", "esbuild-loader": "^2.18.0", "eslint": "^8.11.0", "eslint-plugin-header": "^3.1.1", @@ -372,7 +374,7 @@ "node-gyp": "7.1.2", "node-loader": "^2.0.0", "nodemon": "^2.0.15", - "playwright": "^1.17.1", + "playwright": "^1.20.1", "postcss": "^8.4.12", "postcss-loader": "^6.2.1", "randomcolor": "^0.6.2", @@ -384,27 +386,27 @@ "react-select-event": "^5.3.0", "react-table": "^7.7.0", "react-window": "^1.8.6", - "sass": "^1.45.1", + "sass": "^1.49.9", "sass-loader": "^12.6.0", "sharp": "^0.29.3", "style-loader": "^3.3.1", - "tailwindcss": "^3.0.7", + "tailwindcss": "^3.0.23", "tar-stream": "^2.2.0", "ts-jest": "26.5.6", - "ts-loader": "^9.2.6", + "ts-loader": "^9.2.8", "ts-node": "^10.7.0", - "type-fest": "^1.4.0", + "type-fest": "^2.12.0", "typed-emitter": "^1.4.0", "typedoc": "0.22.10", "typedoc-plugin-markdown": "^3.11.12", "typeface-roboto": "^1.1.13", - "typescript": "^4.5.2", + "typescript": "^4.5.5", "typescript-plugin-css-modules": "^3.4.0", "webpack": "^5.69.0", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.7.4", "webpack-node-externals": "^3.0.0", - "xterm": "^4.15.0", + "xterm": "^4.18.0", "xterm-addon-fit": "^0.5.0" } } diff --git a/src/common/__tests__/catalog-entity.test.ts b/src/common/__tests__/catalog-entity.test.ts new file mode 100644 index 0000000000..3785ed1d49 --- /dev/null +++ b/src/common/__tests__/catalog-entity.test.ts @@ -0,0 +1,30 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { CatalogCategory, CatalogCategorySpec } from "../catalog"; + +class TestCatalogCategory extends CatalogCategory { + public readonly apiVersion = "catalog.k8slens.dev/v1alpha1"; + public readonly kind = "CatalogCategory"; + public metadata = { + name: "Test Category", + icon: "", + }; + public spec: CatalogCategorySpec = { + group: "entity.k8slens.dev", + versions: [], + names: { + kind: "Test", + }, + }; +} + +describe("CatalogCategory", () => { + it("returns name", () => { + const category = new TestCatalogCategory(); + + expect(category.getName()).toEqual("Test Category"); + }); +}); diff --git a/src/common/__tests__/cluster-store.test.ts b/src/common/__tests__/cluster-store.test.ts index bf074f7324..9bfc5346ed 100644 --- a/src/common/__tests__/cluster-store.test.ts +++ b/src/common/__tests__/cluster-store.test.ts @@ -24,8 +24,6 @@ import { createClusterInjectionToken } from "../cluster/create-cluster-injection import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; -import kubeAuthProxyCaInjectable from "../../main/kube-auth-proxy/kube-auth-proxy-ca.injectable"; -import createKubeAuthProxyCertFilesInjectable from "../../main/kube-auth-proxy/create-kube-auth-proxy-cert-files.injectable"; console = new Console(stdout, stderr); @@ -89,8 +87,6 @@ describe("cluster-store", () => { mainDi = dis.mainDi; mainDi.override(directoryForUserDataInjectable, () => "some-directory-for-user-data"); - mainDi.override(createKubeAuthProxyCertFilesInjectable, () => ({} as any)); - mainDi.override(kubeAuthProxyCaInjectable, () => ({} as any)); await dis.runSetups(); diff --git a/src/common/catalog/catalog-entity.ts b/src/common/catalog/catalog-entity.ts index daff2e6017..2704bed2e0 100644 --- a/src/common/catalog/catalog-entity.ts +++ b/src/common/catalog/catalog-entity.ts @@ -173,6 +173,13 @@ export abstract class CatalogCategory extends (EventEmitter as new () => TypedEm return `${this.spec.group}/${this.spec.names.kind}`; } + /** + * Get the name of this category + */ + public getName(): string { + return this.metadata.name; + } + /** * Add a filter for menu items of catalogAddMenu * @param fn The function that should return a truthy value if that menu item should be displayed diff --git a/src/common/k8s-api/api-base.ts b/src/common/k8s-api/api-base.ts new file mode 100644 index 0000000000..e511dd8454 --- /dev/null +++ b/src/common/k8s-api/api-base.ts @@ -0,0 +1,40 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { JsonApi } from "./json-api"; +import { apiPrefix, isDebugging, isDevelopment } from "../vars"; +import { appEventBus } from "../app-event-bus/event-bus"; + +export let apiBase: JsonApi; + +if (typeof window === "undefined") { + appEventBus.addListener((event) => { + if (event.name !== "lens-proxy" && event.action !== "listen") return; + + const params = event.params as { port?: number }; + + if (!params.port) return; + + apiBase = new JsonApi({ + serverAddress: `http://127.0.0.1:${params.port}`, + apiBase: apiPrefix, + debug: isDevelopment || isDebugging, + }, { + headers: { + "Host": `localhost:${params.port}`, + }, + }); + }); +} else { + apiBase = new JsonApi({ + serverAddress: `http://127.0.0.1:${window.location.port}`, + apiBase: apiPrefix, + debug: isDevelopment || isDebugging, + }, { + headers: { + "Host": window.location.host, + }, + }); +} diff --git a/src/common/k8s-api/api-kube.ts b/src/common/k8s-api/api-kube.ts new file mode 100644 index 0000000000..5ff8478694 --- /dev/null +++ b/src/common/k8s-api/api-kube.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { isClusterPageContext } from "../utils"; +import { KubeJsonApi } from "./kube-json-api"; +import { apiKubePrefix, isDevelopment } from "../vars"; + +export const apiKube = isClusterPageContext() + ? new KubeJsonApi({ + serverAddress: `http://127.0.0.1:${window.location.port}`, + apiBase: apiKubePrefix, + debug: isDevelopment, + }, { + headers: { + "Host": window.location.host, + }, + }) + : undefined; diff --git a/src/common/k8s-api/endpoints/metrics.api.ts b/src/common/k8s-api/endpoints/metrics.api.ts index 88efc166d1..ad4044c5d3 100644 --- a/src/common/k8s-api/endpoints/metrics.api.ts +++ b/src/common/k8s-api/endpoints/metrics.api.ts @@ -141,8 +141,11 @@ export function isMetricsEmpty(metrics: Record) { return Object.values(metrics).every(metric => !metric?.data?.result?.length); } -export function getItemMetrics(metrics: Record, itemName: string): Record | void { - if (!metrics) return; +export function getItemMetrics(metrics: Record, itemName: string): Record | undefined { + if (!metrics) { + return undefined; + } + const itemMetrics = { ...metrics }; for (const metric in metrics) { diff --git a/src/common/k8s-api/endpoints/persistent-volume-claims.api.ts b/src/common/k8s-api/endpoints/persistent-volume-claims.api.ts index a7815e774c..cbe920421d 100644 --- a/src/common/k8s-api/endpoints/persistent-volume-claims.api.ts +++ b/src/common/k8s-api/endpoints/persistent-volume-claims.api.ts @@ -31,17 +31,25 @@ export interface IPvcMetrics { diskCapacity: T; } -export interface PersistentVolumeClaim { - spec: { - accessModes: string[]; - storageClassName: string; - selector: LabelSelector; - resources: { - requests: { - storage: string; // 8Gi - }; - }; +export interface PersistentVolumeClaimSpec { + accessModes: string[]; + selector: LabelSelector; + resources: { + requests?: Record; + limits?: Record; }; + volumeName?: string; + storageClassName?: string; + volumeMode?: string; + dataSource?: { + apiGroup: string; + kind: string; + name: string; + }; +} + +export interface PersistentVolumeClaim { + spec: PersistentVolumeClaimSpec; status: { phase: string; // Pending }; diff --git a/src/common/k8s-api/endpoints/pods.api.ts b/src/common/k8s-api/endpoints/pods.api.ts index facc1fa3c3..83d2d2234e 100644 --- a/src/common/k8s-api/endpoints/pods.api.ts +++ b/src/common/k8s-api/endpoints/pods.api.ts @@ -9,6 +9,10 @@ import { IMetrics, metricsApi } from "./metrics.api"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; +import type { RequireExactlyOne } from "type-fest"; +import type { KubeObjectMetadata, LocalObjectReference } from "../kube-object"; +import type { SecretReference } from "./secret.api"; +import type { PersistentVolumeClaimSpec } from "./persistent-volume-claims.api"; export class PodsApi extends KubeApi { getLogs = async (params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise => { @@ -112,12 +116,8 @@ export interface IPodContainer extends Partial; + spec: PersistentVolumeClaimSpec; + }; +} + +export interface EmptyDirSource { + medium?: string; + sizeLimit?: string; +} + +export interface FiberChannelSource { + /** + * A list of World Wide Names + */ + targetWWNs: string[]; + /** + * Logical Unit number + */ + lun: number; + /** + * The type of filesystem + * @default "ext4" + */ + fsType?: string; + readOnly: boolean; +} + +export interface FlockerSource { + datasetName: string; +} + +export interface FlexVolumeSource { + driver: string; + fsType?: string; + secretRef?: LocalObjectReference; + /** + * @default false + */ + readOnly?: boolean; + options?: Record; +} + +export interface GcePersistentDiskSource { + pdName: string; + fsType: string; +} + +export interface GitRepoSource { + repository: string; + revision: string; +} + +export interface GlusterFsSource { + /** + * The name of the Endpoints object that represents a Gluster cluster configuration. + */ + endpoints: string; + /** + * The Glusterfs volume name. + */ + path: string; + /** + * The boolean that sets the mountpoint readOnly or readWrite. + */ + readOnly: boolean; +} + +export interface HostPathSource { + path: string; + /** + * Determines the sorts of checks that will be done + * @default "" + */ + type?: "" | "DirectoryOrCreate" | "Directory" | "FileOrCreate" | "File" | "Socket" | "CharDevice" | "BlockDevice"; +} + +export interface IScsiSource { + targetPortal: string; + iqn: string; + lun: number; + fsType: string; + readOnly: boolean; + chapAuthDiscovery?: boolean; + chapAuthSession?: boolean; + secretRef?: SecretReference; +} + +export interface LocalSource { + path: string; +} + +export interface NetworkFsSource { + server: string; + path: string; + readOnly?: boolean; +} + +export interface PersistentVolumeClaimSource { + claimName: string; +} + +export interface PhotonPersistentDiskSource { + pdID: string; + /** + * @default "ext4" + */ + fsType?: string; +} + +export interface PortworxVolumeSource { + volumeID: string; + fsType?: string; + readOnly?: boolean; +} + +export interface ProjectedSource { + sources: { + secret?: { + name: string; + items?: { + key: string; + path: string; + mode?: number; + }[]; + }; + downwardAPI?: { + items?: { + path: string; + fieldRef?: { + fieldPath: string; + apiVersion?: string; + }; + resourceFieldRef?: { + resource: string; + containerName?: string; + }; + mode?: number; + }[]; + }; + configMap?: { + name: string; + items?: { + key: string; + path: string; + mode?: number; + }[]; + optional?: boolean; + }; + serviceAccountToken?: { + audience?: string; + expirationSeconds?: number; + path: string; + }; + }[]; + defaultMode: number; +} + +export interface QuobyteSource { + registry: string; + volume: string; + /** + * @default false + */ + readOnly?: boolean; + /** + * @default "serivceaccount" + */ + user?: string; + group?: string; + tenant?: string; +} + +export interface RadosBlockDeviceSource { + monitors: string[]; + image: string; + /** + * @default "ext4" + */ + fsType?: string; + /** + * @default "rbd" + */ + pool?: string; + /** + * @default "admin" + */ + user?: string; + /** + * @default "/etc/ceph/keyring" + */ + keyring?: string; + secretRef?: SecretReference; + /** + * @default false + */ + readOnly?: boolean; +} + +export interface ScaleIoSource { + gateway: string; + system: string; + secretRef?: LocalObjectReference; + /** + * @default false + */ + sslEnabled?: boolean; + protectionDomain?: string; + storagePool?: string; + /** + * @default "ThinProvisioned" + */ + storageMode?: "ThickProvisioned" | "ThinProvisioned"; + volumeName: string; + /** + * @default "xfs" + */ + fsType?: string; + /** + * @default false + */ + readOnly?: boolean; +} + +export interface SecretSource { + secretName: string; + items?: { + key: string; + path: string; + mode?: number; + }[]; + defaultMode?: number; + optional?: boolean; +} + +export interface StorageOsSource { + volumeName: string; + /** + * @default Pod.metadata.namespace + */ + volumeNamespace?: string; + /** + * @default "ext4" + */ + fsType?: string; + /** + * @default false + */ + readOnly?: boolean; + secretRef?: LocalObjectReference; +} + +export interface VsphereVolumeSource { + volumePath: string; + /** + * @default "ext4" + */ + fsType?: string; + storagePolicyName?: string; + storagePolicyID?: string; +} + +export interface ContainerStorageInterfaceSource { + driver: string; + /** + * @default false + */ + readOnly?: boolean; + /** + * @default "ext4" + */ + fsType?: string; + volumeAttributes?: Record; + controllerPublishSecretRef?: SecretReference; + nodeStageSecretRef?: SecretReference; + nodePublishSecretRef?: SecretReference; + controllerExpandSecretRef?: SecretReference; +} + +export interface PodVolumeVariants { + awsElasticBlockStore: AwsElasticBlockStoreSource; + azureDisk: AzureDiskSource; + azureFile: AzureFileSource; + cephfs: CephfsSource; + cinder: CinderSource; + configMap: ConfigMapSource; + csi: ContainerStorageInterfaceSource; + downwardAPI: DownwardApiSource; + emptyDir: EmptyDirSource; + ephemeral: EphemeralSource; + fc: FiberChannelSource; + flexVolume: FlexVolumeSource; + flocker: FlockerSource; + gcePersistentDisk: GcePersistentDiskSource; + gitRepo: GitRepoSource; + glusterfs: GlusterFsSource; + hostPath: HostPathSource; + iscsi: IScsiSource; + local: LocalSource; + nfs: NetworkFsSource; + persistentVolumeClaim: PersistentVolumeClaimSource; + photonPersistentDisk: PhotonPersistentDiskSource; + portworxVolume: PortworxVolumeSource; + projected: ProjectedSource; + quobyte: QuobyteSource; + rbd: RadosBlockDeviceSource; + scaleIO: ScaleIoSource; + secret: SecretSource; + storageos: StorageOsSource; + vsphereVolume: VsphereVolumeSource; +} + +/** + * The valid kinds of volume + */ +export type PodVolumeKind = keyof PodVolumeVariants; + +export type PodVolume = RequireExactlyOne & { + name: string; +}; + export class Pod extends WorkloadKubeObject { static kind = "Pod"; static namespaced = true; @@ -206,23 +644,7 @@ export class Pod extends WorkloadKubeObject { } declare spec?: { - volumes?: { - name: string; - persistentVolumeClaim: { - claimName: string; - }; - emptyDir: { - medium?: string; - sizeLimit?: string; - }; - configMap: { - name: string; - }; - secret: { - secretName: string; - defaultMode: number; - }; - }[]; + volumes?: PodVolume[]; initContainers: IPodContainer[]; containers: IPodContainer[]; restartPolicy?: string; @@ -239,9 +661,7 @@ export class Pod extends WorkloadKubeObject { [selector: string]: string; }; securityContext?: {}; - imagePullSecrets?: { - name: string; - }[]; + imagePullSecrets?: LocalObjectReference[]; hostNetwork?: boolean; hostPID?: boolean; hostIPC?: boolean; diff --git a/src/common/k8s-api/endpoints/secret.api.ts b/src/common/k8s-api/endpoints/secret.api.ts index a3b821fcf8..93953ebf48 100644 --- a/src/common/k8s-api/endpoints/secret.api.ts +++ b/src/common/k8s-api/endpoints/secret.api.ts @@ -25,6 +25,11 @@ export interface ISecretRef { name: string; } +export interface SecretReference { + name: string; + namespace?: string; +} + export interface SecretData extends KubeJsonApiData { type: SecretType; data?: Record; diff --git a/src/common/k8s-api/index.ts b/src/common/k8s-api/index.ts index 441cb98687..0d47a643f3 100644 --- a/src/common/k8s-api/index.ts +++ b/src/common/k8s-api/index.ts @@ -3,58 +3,5 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { JsonApi } from "./json-api"; -import { KubeJsonApi } from "./kube-json-api"; -import { apiKubePrefix, apiPrefix, isDebugging, isDevelopment } from "../../common/vars"; -import { isClusterPageContext } from "../utils/cluster-id-url-parsing"; -import { appEventBus } from "../app-event-bus/event-bus"; - -let apiBase: JsonApi; -let apiKube: KubeJsonApi; - -if (typeof window === "undefined") { - appEventBus.addListener((event) => { - if (event.name !== "lens-proxy" && event.action !== "listen") return; - - const params = event.params as { port?: number }; - - if (!params.port) return; - - apiBase = new JsonApi({ - serverAddress: `http://127.0.0.1:${params.port}`, - apiBase: apiPrefix, - debug: isDevelopment || isDebugging, - }, { - headers: { - "Host": `localhost:${params.port}`, - }, - }); - }); -} else { - apiBase = new JsonApi({ - serverAddress: `http://127.0.0.1:${window.location.port}`, - apiBase: apiPrefix, - debug: isDevelopment || isDebugging, - }, { - headers: { - "Host": window.location.host, - }, - }); -} - -if (isClusterPageContext()) { - apiKube = new KubeJsonApi({ - serverAddress: `http://127.0.0.1:${window.location.port}`, - apiBase: apiKubePrefix, - debug: isDevelopment, - }, { - headers: { - "Host": window.location.host, - }, - }); -} - -export { - apiBase, - apiKube, -}; +export { apiBase } from "./api-base"; +export { apiKube } from "./api-kube"; diff --git a/src/common/k8s-api/kube-json-api.ts b/src/common/k8s-api/kube-json-api.ts index bc578641c3..30131545fe 100644 --- a/src/common/k8s-api/kube-json-api.ts +++ b/src/common/k8s-api/kube-json-api.ts @@ -5,8 +5,8 @@ import { JsonApi, JsonApiData, JsonApiError } from "./json-api"; import type { Response } from "node-fetch"; -import { LensProxy } from "../../main/lens-proxy"; import { apiKubePrefix, isDebugging } from "../vars"; +import { apiBase } from "./api-base"; export interface KubeJsonApiListMetadata { resourceVersion: string; @@ -57,15 +57,15 @@ export interface KubeJsonApiError extends JsonApiError { export class KubeJsonApi extends JsonApi { static forCluster(clusterId: string): KubeJsonApi { - const port = LensProxy.getInstance().port; + const url = new URL(apiBase.config.serverAddress); return new this({ - serverAddress: `http://127.0.0.1:${port}`, + serverAddress: apiBase.config.serverAddress, apiBase: apiKubePrefix, debug: isDebugging, }, { headers: { - "Host": `${clusterId}.localhost:${port}`, + "Host": `${clusterId}.localhost:${url.port}`, }, }); } diff --git a/src/common/k8s-api/kube-object.ts b/src/common/k8s-api/kube-object.ts index afabeaf638..8e1b6daee2 100644 --- a/src/common/k8s-api/kube-object.ts +++ b/src/common/k8s-api/kube-object.ts @@ -21,6 +21,13 @@ export type KubeObjectConstructor = (new (data: KubeJsonAp apiBase?: string; }; +/** + * A reference to an object in the same namespace + */ +export interface LocalObjectReference { + name: string; +} + export interface KubeObjectMetadata { uid: string; name: string; diff --git a/src/common/logger.ts b/src/common/logger.ts index 504b0e126d..f29008818b 100644 --- a/src/common/logger.ts +++ b/src/common/logger.ts @@ -65,6 +65,9 @@ if (ipcMain) { } export default winston.createLogger({ - format: format.simple(), + format: format.combine( + format.splat(), + format.simple(), + ), transports, }); diff --git a/src/common/vars.ts b/src/common/vars.ts index 1b9b9a92d1..63e441ed1a 100644 --- a/src/common/vars.ts +++ b/src/common/vars.ts @@ -72,11 +72,34 @@ const resourcesDir = lazyInitialized(() => ( : path.join(process.cwd(), "binaries", "client", normalizedPlatform) )); +/** + * @deprecated for being explicit side effect. + */ export const baseBinariesDir = lazyInitialized(() => path.join(resourcesDir.get(), normalizedArch)); + +/** + * @deprecated for being explicit side effect. + */ export const kubeAuthProxyBinaryName = getBinaryName("lens-k8s-proxy"); + +/** + * @deprecated for being explicit side effect. + */ export const helmBinaryName = getBinaryName("helm"); + +/** + * @deprecated for being explicit side effect. + */ export const helmBinaryPath = lazyInitialized(() => path.join(baseBinariesDir.get(), helmBinaryName)); + +/** + * @deprecated for being explicit side effect. + */ export const kubectlBinaryName = getBinaryName("kubectl"); + +/** + * @deprecated for being explicit side effect. + */ export const kubectlBinaryPath = lazyInitialized(() => path.join(baseBinariesDir.get(), kubectlBinaryName)); // Webpack build paths diff --git a/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts b/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts index cc9b5917d6..340a97c941 100644 --- a/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts +++ b/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts @@ -5,6 +5,9 @@ import { asLegacyGlobalForExtensionApi } from "./as-legacy-global-object-for-extension-api"; import type { Injectable } from "@ogre-tools/injectable"; +/** + * @deprecated use asLegacyGlobalForExtensionApi instead, and use proper implementations instead of "modifications". + */ export const asLegacyGlobalObjectForExtensionApiWithModifications = < InjectableInstance extends InjectionTokenInstance, InjectionTokenInstance, diff --git a/src/main/__test__/cluster.test.ts b/src/main/__test__/cluster.test.ts index 2b6ab2eb8b..d570919f3e 100644 --- a/src/main/__test__/cluster.test.ts +++ b/src/main/__test__/cluster.test.ts @@ -20,6 +20,7 @@ jest.mock("winston", () => ({ label: jest.fn(), timestamp: jest.fn(), printf: jest.fn(), + splat: jest.fn(), }, createLogger: jest.fn().mockReturnValue(logger), transports: { diff --git a/src/main/__test__/context-handler.test.ts b/src/main/__test__/context-handler.test.ts index 4563707d0c..9541889519 100644 --- a/src/main/__test__/context-handler.test.ts +++ b/src/main/__test__/context-handler.test.ts @@ -10,7 +10,6 @@ import mockFs from "mock-fs"; import { getDiForUnitTesting } from "../getDiForUnitTesting"; import createContextHandlerInjectable from "../context-handler/create-context-handler.injectable"; import type { Cluster } from "../../common/cluster/cluster"; -import kubeAuthProxyCaInjectable from "../kube-auth-proxy/kube-auth-proxy-ca.injectable"; import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable"; jest.mock("electron", () => ({ @@ -83,7 +82,6 @@ describe("ContextHandler", () => { }); di.override(createKubeAuthProxyInjectable, () => ({} as any)); - di.override(kubeAuthProxyCaInjectable, () => ({} as any)); await di.runSetups(); diff --git a/src/main/__test__/kube-auth-proxy.test.ts b/src/main/__test__/kube-auth-proxy.test.ts index 162cf823ee..348112e791 100644 --- a/src/main/__test__/kube-auth-proxy.test.ts +++ b/src/main/__test__/kube-auth-proxy.test.ts @@ -15,6 +15,7 @@ jest.mock("winston", () => ({ printf: jest.fn(), padLevels: jest.fn(), ms: jest.fn(), + splat: jest.fn(), }, createLogger: jest.fn().mockReturnValue({ silly: jest.fn(), @@ -51,8 +52,6 @@ import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-p import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; import path from "path"; import spawnInjectable from "../child-process/spawn.injectable"; -import kubeAuthProxyCaInjectable from "../kube-auth-proxy/kube-auth-proxy-ca.injectable"; -import createKubeAuthProxyCertFilesInjectable from "../kube-auth-proxy/create-kube-auth-proxy-cert-files.injectable"; console = new Console(stdout, stderr); @@ -96,8 +95,6 @@ describe("kube auth proxy tests", () => { const di = getDiForUnitTesting({ doGeneralOverrides: true }); di.override(spawnInjectable, () => mockSpawn); - di.override(createKubeAuthProxyCertFilesInjectable, () => ({} as any)); - di.override(kubeAuthProxyCaInjectable, () => ({} as any)); mockFs(mockMinikubeConfig); diff --git a/src/main/__test__/kubeconfig-manager.test.ts b/src/main/__test__/kubeconfig-manager.test.ts index 263d6be996..91792bfaf8 100644 --- a/src/main/__test__/kubeconfig-manager.test.ts +++ b/src/main/__test__/kubeconfig-manager.test.ts @@ -21,6 +21,7 @@ jest.mock("winston", () => ({ padLevels: jest.fn(), ms: jest.fn(), printf: jest.fn(), + splat: jest.fn(), }, createLogger: jest.fn().mockReturnValue(logger), transports: { diff --git a/src/main/app-updater.ts b/src/main/app-updater.ts index e63da9453e..4834a90234 100644 --- a/src/main/app-updater.ts +++ b/src/main/app-updater.ts @@ -5,11 +5,11 @@ import { autoUpdater, UpdateInfo } from "electron-updater"; import logger from "./logger"; -import { isLinux, isMac, isPublishConfigured, isTestEnv } from "../common/vars"; +import { isPublishConfigured, isTestEnv } from "../common/vars"; import { delay } from "../common/utils"; import { areArgsUpdateAvailableToBackchannel, AutoUpdateChecking, AutoUpdateLogPrefix, AutoUpdateNoUpdateAvailable, broadcastMessage, onceCorrect, UpdateAvailableChannel, UpdateAvailableToBackchannel } from "../common/ipc"; import { once } from "lodash"; -import { ipcMain, autoUpdater as electronAutoUpdater } from "electron"; +import { ipcMain } from "electron"; import { nextUpdateChannel } from "./utils/update-channel"; import { UserStore } from "../common/user-store"; @@ -23,25 +23,7 @@ function handleAutoUpdateBackChannel(event: Electron.IpcMainEvent, ...[arg]: Upd if (arg.doUpdate) { if (arg.now) { logger.info(`${AutoUpdateLogPrefix}: User chose to update now`); - setImmediate(() => { - if (isMac) { - /** - * This is a necessary workaround until electron-updater is fixed. - * The problem is that it downloads it but then never tries to - * download it from itself via electron. - */ - electronAutoUpdater.checkForUpdates(); - } else if (isLinux) { - /** - * This is a necessary workaround until electron-updater is fixed. - * The problem is that because linux updating is not implemented at - * all via electron. Electron's autoUpdater.quitAndInstall() is never - * called. - */ - electronAutoUpdater.emit("before-quit-for-update"); - } - autoUpdater.quitAndInstall(true, true); - }); + autoUpdater.quitAndInstall(true, true); } else { logger.info(`${AutoUpdateLogPrefix}: User chose to update on quit`); autoUpdater.autoInstallOnAppQuit = true; @@ -52,10 +34,10 @@ function handleAutoUpdateBackChannel(event: Electron.IpcMainEvent, ...[arg]: Upd } autoUpdater.logger = { - info: message => logger.info(`[AUTO-UPDATE]: electron-updater:`, message), - warn: message => logger.warn(`[AUTO-UPDATE]: electron-updater:`, message), - error: message => logger.error(`[AUTO-UPDATE]: electron-updater:`, message), - debug: message => logger.debug(`[AUTO-UPDATE]: electron-updater:`, message), + info: message => logger.info(`[AUTO-UPDATE]: electron-updater: %s`, message), + warn: message => logger.warn(`[AUTO-UPDATE]: electron-updater: %s`, message), + error: message => logger.error(`[AUTO-UPDATE]: electron-updater: %s`, message), + debug: message => logger.debug(`[AUTO-UPDATE]: electron-updater: %s`, message), }; /** diff --git a/src/main/catalog-sources/__test__/kubeconfig-sync.test.ts b/src/main/catalog-sources/__test__/kubeconfig-sync.test.ts index 75c58aa036..4d3820fd37 100644 --- a/src/main/catalog-sources/__test__/kubeconfig-sync.test.ts +++ b/src/main/catalog-sources/__test__/kubeconfig-sync.test.ts @@ -14,11 +14,8 @@ import { ClusterManager } from "../../cluster-manager"; import clusterStoreInjectable from "../../../common/cluster-store/cluster-store.injectable"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import { createClusterInjectionToken } from "../../../common/cluster/create-cluster-injection-token"; -import directoryForKubeConfigsInjectable - from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; -import kubeAuthProxyCaInjectable from "../../kube-auth-proxy/kube-auth-proxy-ca.injectable"; -import createKubeAuthProxyCertFilesInjectable from "../../kube-auth-proxy/create-kube-auth-proxy-cert-files.injectable"; - +import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; +import { ClusterStore } from "../../../common/cluster-store/cluster-store"; jest.mock("electron", () => ({ app: { @@ -42,9 +39,6 @@ describe("kubeconfig-sync.source tests", () => { beforeEach(async () => { const di = getDiForUnitTesting({ doGeneralOverrides: true }); - di.override(kubeAuthProxyCaInjectable, () => Promise.resolve(Buffer.from("ca"))); - di.override(createKubeAuthProxyCertFilesInjectable, () => ({} as any)); - mockFs(); await di.runSetups(); @@ -62,6 +56,7 @@ describe("kubeconfig-sync.source tests", () => { afterEach(() => { mockFs.restore(); ClusterManager.resetInstance(); + ClusterStore.resetInstance(); }); describe("configsToModels", () => { diff --git a/src/main/context-handler/context-handler.ts b/src/main/context-handler/context-handler.ts index d08d5ace1f..2eed4e1ad7 100644 --- a/src/main/context-handler/context-handler.ts +++ b/src/main/context-handler/context-handler.ts @@ -28,7 +28,7 @@ interface PrometheusServicePreferences { interface Dependencies { createKubeAuthProxy: CreateKubeAuthProxy; - authProxyCa: Promise; + authProxyCa: string; } export class ContextHandler { @@ -123,7 +123,7 @@ export class ContextHandler { return `https://127.0.0.1:${this.kubeAuthProxy.port}${this.kubeAuthProxy.apiPrefix}${path}`; } - async resolveAuthProxyCa() { + resolveAuthProxyCa() { return this.dependencies.authProxyCa; } @@ -140,7 +140,7 @@ export class ContextHandler { protected async newApiTarget(timeout: number): Promise { await this.ensureServer(); - const caFileContents = await this.resolveAuthProxyCa(); + const ca = this.dependencies.authProxyCa; const clusterPath = this.clusterUrl.path !== "/" ? this.clusterUrl.path : ""; const apiPrefix = `${this.kubeAuthProxy.apiPrefix}${clusterPath}`; @@ -150,7 +150,7 @@ export class ContextHandler { host: "127.0.0.1", port: this.kubeAuthProxy.port, path: apiPrefix, - ca: caFileContents.toString(), + ca, }, changeOrigin: true, timeout, diff --git a/src/main/context-handler/create-context-handler.injectable.ts b/src/main/context-handler/create-context-handler.injectable.ts index c08bd4276a..86867ccdfb 100644 --- a/src/main/context-handler/create-context-handler.injectable.ts +++ b/src/main/context-handler/create-context-handler.injectable.ts @@ -3,23 +3,27 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import selfsigned from "selfsigned"; import type { Cluster } from "../../common/cluster/cluster"; import { ContextHandler } from "./context-handler"; import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable"; -import kubeAuthProxyCaInjectable from "../kube-auth-proxy/kube-auth-proxy-ca.injectable"; +import { getKubeAuthProxyCertificate } from "../kube-auth-proxy/get-kube-auth-proxy-certificate"; +import URLParse from "url-parse"; const createContextHandlerInjectable = getInjectable({ id: "create-context-handler", instantiate: (di) => { - const authProxyCa = di.inject(kubeAuthProxyCaInjectable); + return (cluster: Cluster) => { + const clusterUrl = new URLParse(cluster.apiUrl); - const dependencies = { - createKubeAuthProxy: di.inject(createKubeAuthProxyInjectable), - authProxyCa, + const dependencies = { + createKubeAuthProxy: di.inject(createKubeAuthProxyInjectable), + authProxyCa: getKubeAuthProxyCertificate(clusterUrl.hostname, selfsigned.generate).cert, + }; + + return new ContextHandler(dependencies, cluster); }; - - return (cluster: Cluster) => new ContextHandler(dependencies, cluster); }, }); diff --git a/src/main/kube-auth-proxy/create-kube-auth-proxy-cert-files.injectable.ts b/src/main/kube-auth-proxy/create-kube-auth-proxy-cert-files.injectable.ts deleted file mode 100644 index 297a43daa4..0000000000 --- a/src/main/kube-auth-proxy/create-kube-auth-proxy-cert-files.injectable.ts +++ /dev/null @@ -1,26 +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 * as selfsigned from "selfsigned"; -import { createKubeAuthProxyCertFiles } from "./create-kube-auth-proxy-cert-files"; -import writeFileInjectable from "../../common/fs/write-file.injectable"; -import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; -import path from "path"; - -const createKubeAuthProxyCertFilesInjectable = getInjectable({ - id: "create-kube-auth-proxy-cert-files", - - instantiate: async (di) => { - const userData = di.inject(directoryForUserDataInjectable); - const certPath = path.join(userData, "kube-auth-proxy"); - - return createKubeAuthProxyCertFiles(certPath, { - generate: selfsigned.generate, - writeFile: di.inject(writeFileInjectable), - }); - }, -}); - -export default createKubeAuthProxyCertFilesInjectable; diff --git a/src/main/kube-auth-proxy/create-kube-auth-proxy-cert-files.ts b/src/main/kube-auth-proxy/create-kube-auth-proxy-cert-files.ts deleted file mode 100644 index 325495dc7a..0000000000 --- a/src/main/kube-auth-proxy/create-kube-auth-proxy-cert-files.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import path from "path"; -import type * as selfsigned from "selfsigned"; - -type SelfSignedGenerate = typeof selfsigned.generate; - -interface CreateKubeAuthProxyCertificateFilesDependencies { - generate: SelfSignedGenerate; - writeFile: (path: string, content: string | Buffer) => Promise; -} - -function getKubeAuthProxyCertificate(generate: SelfSignedGenerate): selfsigned.SelfSignedCert { - const opts = [ - { name: "commonName", value: "Lens Certificate Authority" }, - { name: "organizationName", value: "Lens" }, - ]; - - return generate(opts, { - keySize: 2048, - algorithm: "sha256", - days: 365, - extensions: [ - { name: "basicConstraints", cA: true }, - { name: "subjectAltName", altNames: [ - { type: 2, value: "localhost" }, - { type: 7, ip: "127.0.0.1" }, - ] }, - ], - }); -} - -export async function createKubeAuthProxyCertFiles(dir: string, dependencies: CreateKubeAuthProxyCertificateFilesDependencies): Promise { - const cert = getKubeAuthProxyCertificate(dependencies.generate); - - await dependencies.writeFile(path.join(dir, "proxy.key"), cert.private); - await dependencies.writeFile(path.join(dir, "proxy.crt"), cert.cert); - - return dir; -} diff --git a/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts b/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts index b566782197..9a8504c675 100644 --- a/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts +++ b/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts @@ -6,10 +6,11 @@ import { getInjectable } from "@ogre-tools/injectable"; import { KubeAuthProxy, KubeAuthProxyDependencies } from "./kube-auth-proxy"; import type { Cluster } from "../../common/cluster/cluster"; import path from "path"; +import selfsigned from "selfsigned"; import { getBinaryName } from "../../common/vars"; import directoryForBundledBinariesInjectable from "../../common/app-paths/directory-for-bundled-binaries/directory-for-bundled-binaries.injectable"; import spawnInjectable from "../child-process/spawn.injectable"; -import createKubeAuthProxyCertFilesInjectable from "./create-kube-auth-proxy-cert-files.injectable"; +import { getKubeAuthProxyCertificate } from "./get-kube-auth-proxy-certificate"; export type CreateKubeAuthProxy = (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy; @@ -18,15 +19,17 @@ const createKubeAuthProxyInjectable = getInjectable({ instantiate: (di): CreateKubeAuthProxy => { const binaryName = getBinaryName("lens-k8s-proxy"); - const dependencies: KubeAuthProxyDependencies = { - proxyBinPath: path.join(di.inject(directoryForBundledBinariesInjectable), binaryName), - proxyCertPath: di.inject(createKubeAuthProxyCertFilesInjectable), - spawn: di.inject(spawnInjectable), - }; - return (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => ( - new KubeAuthProxy(dependencies, cluster, environmentVariables) - ); + return (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => { + const clusterUrl = new URL(cluster.apiUrl); + const dependencies: KubeAuthProxyDependencies = { + proxyBinPath: path.join(di.inject(directoryForBundledBinariesInjectable), binaryName), + proxyCert: getKubeAuthProxyCertificate(clusterUrl.hostname, selfsigned.generate), + spawn: di.inject(spawnInjectable), + }; + + return new KubeAuthProxy(dependencies, cluster, environmentVariables); + }; }, }); diff --git a/src/main/kube-auth-proxy/get-kube-auth-proxy-certificate.ts b/src/main/kube-auth-proxy/get-kube-auth-proxy-certificate.ts new file mode 100644 index 0000000000..fb4c13da60 --- /dev/null +++ b/src/main/kube-auth-proxy/get-kube-auth-proxy-certificate.ts @@ -0,0 +1,39 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type * as selfsigned from "selfsigned"; + +type SelfSignedGenerate = typeof selfsigned.generate; + +const certCache: Map = new Map(); + +export function getKubeAuthProxyCertificate(hostname: string, generate: SelfSignedGenerate, useCache = true): selfsigned.SelfSignedCert { + if (useCache && certCache.has(hostname)) { + return certCache.get(hostname); + } + + const opts = [ + { name: "commonName", value: "Lens Certificate Authority" }, + { name: "organizationName", value: "Lens" }, + ]; + + const cert = generate(opts, { + keySize: 2048, + algorithm: "sha256", + days: 365, + extensions: [ + { name: "basicConstraints", cA: true }, + { name: "subjectAltName", altNames: [ + { type: 2, value: hostname }, + { type: 2, value: "localhost" }, + { type: 7, ip: "127.0.0.1" }, + ] }, + ], + }); + + certCache.set(hostname, cert); + + return cert; +} diff --git a/src/main/kube-auth-proxy/kube-auth-proxy-ca.injectable.ts b/src/main/kube-auth-proxy/kube-auth-proxy-ca.injectable.ts deleted file mode 100644 index 37aaafeeee..0000000000 --- a/src/main/kube-auth-proxy/kube-auth-proxy-ca.injectable.ts +++ /dev/null @@ -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 path from "path"; -import readFileInjectable from "../../common/fs/read-file.injectable"; -import createKubeAuthProxyCertFilesInjectable from "./create-kube-auth-proxy-cert-files.injectable"; - -const kubeAuthProxyCaInjectable = getInjectable({ - id: "kube-auth-proxy-ca", - - instantiate: async (di) => { - const certPath = await di.inject(createKubeAuthProxyCertFilesInjectable); - - const readFile = di.inject(readFileInjectable); - - return readFile(path.join(certPath, "proxy.crt")); - }, -}); - -export default kubeAuthProxyCaInjectable; diff --git a/src/main/kube-auth-proxy/kube-auth-proxy.ts b/src/main/kube-auth-proxy/kube-auth-proxy.ts index f25ea0f97b..dfeff29c98 100644 --- a/src/main/kube-auth-proxy/kube-auth-proxy.ts +++ b/src/main/kube-auth-proxy/kube-auth-proxy.ts @@ -10,12 +10,13 @@ import type { Cluster } from "../../common/cluster/cluster"; import logger from "../logger"; import { getPortFrom } from "../utils/get-port"; import { makeObservable, observable, when } from "mobx"; +import type { SelfSignedCert } from "selfsigned"; const startingServeRegex = /starting to serve on (?
.+)/i; export interface KubeAuthProxyDependencies { proxyBinPath: string; - proxyCertPath: Promise; + proxyCert: SelfSignedCert; spawn: typeof spawn; } @@ -44,7 +45,7 @@ export class KubeAuthProxy { } const proxyBin = this.dependencies.proxyBinPath; - const certPath = await this.dependencies.proxyCertPath; + const cert = this.dependencies.proxyCert; this.proxyProcess = this.dependencies.spawn(proxyBin, [], { env: { @@ -52,7 +53,8 @@ export class KubeAuthProxy { KUBECONFIG: this.cluster.kubeConfigPath, KUBECONFIG_CONTEXT: this.cluster.contextName, API_PREFIX: this.apiPrefix, - CERT_PATH: certPath, + PROXY_KEY: cert.private, + PROXY_CERT: cert.cert, }, }); this.proxyProcess.on("error", (error) => { diff --git a/src/main/lens-proxy.ts b/src/main/lens-proxy.ts index 7f2fbd7281..f37b7a087c 100644 --- a/src/main/lens-proxy.ts +++ b/src/main/lens-proxy.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type net from "net"; +import net from "net"; import type http from "http"; import spdy from "spdy"; import type httpProxy from "http-proxy"; @@ -79,19 +79,18 @@ export class LensProxy extends Singleton { this.proxyServer .on("upgrade", (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => { - const isInternal = req.url.startsWith(`${apiPrefix}?`); const cluster = getClusterForRequest(req); if (!cluster) { logger.error(`[LENS-PROXY]: Could not find cluster for upgrade request from url=${req.url}`); + socket.destroy(); + } else { + const isInternal = req.url.startsWith(`${apiPrefix}?`); + const reqHandler = isInternal ? shellApiRequest : kubeApiUpgradeRequest; - return socket.destroy(); + (async () => reqHandler({ req, socket, head, cluster }))() + .catch(error => logger.error("[LENS-PROXY]: failed to handle proxy upgrade", error)); } - - const reqHandler = isInternal ? shellApiRequest : kubeApiUpgradeRequest; - - (async () => reqHandler({ req, socket, head, cluster }))() - .catch(error => logger.error("[LENS-PROXY]: failed to handle proxy upgrade", error)); }); } @@ -189,7 +188,7 @@ export class LensProxy extends Singleton { }); proxy.on("error", (error, req, res, target) => { - if (this.closed) { + if (this.closed || res instanceof net.Socket) { return; } diff --git a/src/renderer/components/+catalog/catalog.test.tsx b/src/renderer/components/+catalog/catalog.test.tsx index 218bb60feb..5c221bb457 100644 --- a/src/renderer/components/+catalog/catalog.test.tsx +++ b/src/renderer/components/+catalog/catalog.test.tsx @@ -25,6 +25,8 @@ import { UserStore } from "../../../common/user-store"; import mockFs from "mock-fs"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import type { AppEvent } from "../../../common/app-event-bus/event-bus"; +import appEventBusInjectable from "../../../common/app-event-bus/app-event-bus.injectable"; mockWindow(); jest.mock("electron", () => ({ @@ -102,6 +104,7 @@ describe("", () => { let di: DiContainer; let catalogEntityStore: CatalogEntityStore; let catalogEntityRegistry: CatalogEntityRegistry; + let emitEvent: (event: AppEvent) => void; let render: DiRender; beforeEach(async () => { @@ -125,6 +128,12 @@ describe("", () => { di.override(catalogEntityRegistryInjectable, () => catalogEntityRegistry); + emitEvent = jest.fn(); + + di.override(appEventBusInjectable, () => ({ + emit: emitEvent, + })); + catalogEntityStore = di.inject(catalogEntityStoreInjectable); }); @@ -320,4 +329,39 @@ describe("", () => { userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon")); }); + + it("emits catalog open AppEvent", () => { + render( + , + ); + + expect(emitEvent).toHaveBeenCalledWith( { + action: "open", + name: "catalog", + }); + }); + + it("emits catalog change AppEvent when changing the category", () => { + render( + , + ); + + userEvent.click(screen.getByText("Web Links")); + + expect(emitEvent).toHaveBeenLastCalledWith({ + action: "change-category", + name: "catalog", + params: { + category: "Web Links", + }, + }); + }); }); diff --git a/src/renderer/components/+catalog/catalog.tsx b/src/renderer/components/+catalog/catalog.tsx index e536abf113..a371da0e18 100644 --- a/src/renderer/components/+catalog/catalog.tsx +++ b/src/renderer/components/+catalog/catalog.tsx @@ -33,6 +33,8 @@ import getCategoryColumnsInjectable from "./get-category-columns.injectable"; import type { RegisteredCustomCategoryViewDecl } from "./custom-views.injectable"; import customCategoryViewsInjectable from "./custom-views.injectable"; import type { CustomCategoryViewComponents } from "./custom-views"; +import type { AppEvent } from "../../../common/app-event-bus/event-bus"; +import appEventBusInjectable from "../../../common/app-event-bus/app-event-bus.injectable"; export interface CatalogProps extends RouteComponentProps {} @@ -41,6 +43,7 @@ interface Dependencies { catalogEntityStore: CatalogEntityStore; getCategoryColumns: (params: GetCategoryColumnsParams) => CategoryColumns; customCategoryViews: IComputedValue>>; + emitEvent: (event: AppEvent) => void; } @observer @@ -101,6 +104,11 @@ class NonInjectedCatalog extends React.Component { }); } })); + + this.props.emitEvent({ + name: "catalog", + action: "open", + }); } addToHotbar(entity: CatalogEntity): void { @@ -143,6 +151,14 @@ class NonInjectedCatalog extends React.Component { onTabChange = action((tabId: string | null) => { const activeCategory = this.categories.find(category => category.getId() === tabId); + this.props.emitEvent({ + name: "catalog", + action: "change-category", + params: { + category: activeCategory ? activeCategory.getName() : "Browse", + }, + }); + if (activeCategory) { navigate(catalogURL({ params: { group: activeCategory.spec.group, kind: activeCategory.spec.names.kind }})); } else { @@ -280,6 +296,7 @@ export const Catalog = withInjectables( NonInjectedC catalogPreviousActiveTabStorage: di.inject(catalogPreviousActiveTabStorageInjectable), getCategoryColumns: di.inject(getCategoryColumnsInjectable), customCategoryViews: di.inject(customCategoryViewsInjectable), + emitEvent: di.inject(appEventBusInjectable).emit, ...props, }), }); diff --git a/src/renderer/components/+config-autoscalers/hpa-details.tsx b/src/renderer/components/+config-autoscalers/hpa-details.tsx index 476ef07ade..45c35eacd3 100644 --- a/src/renderer/components/+config-autoscalers/hpa-details.tsx +++ b/src/renderer/components/+config-autoscalers/hpa-details.tsx @@ -134,7 +134,7 @@ export class HpaDetails extends React.Component { })} - + Metrics
{this.renderMetrics()}
diff --git a/src/renderer/components/+config-maps/config-map-details.tsx b/src/renderer/components/+config-maps/config-map-details.tsx index 074003a5bf..61d2ea4ae1 100644 --- a/src/renderer/components/+config-maps/config-map-details.tsx +++ b/src/renderer/components/+config-maps/config-map-details.tsx @@ -85,7 +85,7 @@ export class ConfigMapDetails extends React.Component { { data.length > 0 && ( <> - + Data { data.map(([name, value]) => (
diff --git a/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx b/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx index 363ba75662..3a1cff2080 100644 --- a/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx +++ b/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx @@ -82,7 +82,7 @@ export class ResourceQuotaDetails extends React.Component 0 && ( <> - + Scope Selector Operator diff --git a/src/renderer/components/+config-secrets/secret-details.tsx b/src/renderer/components/+config-secrets/secret-details.tsx index adb1877799..aecce6e1a0 100644 --- a/src/renderer/components/+config-secrets/secret-details.tsx +++ b/src/renderer/components/+config-secrets/secret-details.tsx @@ -116,7 +116,7 @@ export class SecretDetails extends React.Component { return ( <> - + Data {secrets.map(this.renderSecret)}
plural @@ -109,7 +109,7 @@ export class CRDDetails extends React.Component {
{printerColumns.length > 0 && <> - + Additional Printer Columns Name @@ -136,7 +136,7 @@ export class CRDDetails extends React.Component { } {validation && <> - + Validation { {type} - + Involved object
Name diff --git a/src/renderer/components/+helm-releases/release-details/release-details.tsx b/src/renderer/components/+helm-releases/release-details/release-details.tsx index 4346b11691..5f4168ed57 100644 --- a/src/renderer/components/+helm-releases/release-details/release-details.tsx +++ b/src/renderer/components/+helm-releases/release-details/release-details.tsx @@ -113,7 +113,7 @@ class NonInjectedReleaseDetails extends Component - + Values
{this.renderValues()} - + Notes {this.renderNotes()} - + Resources {resources && this.renderResources(resources)}
); diff --git a/src/renderer/components/+network-endpoints/endpoint-details.tsx b/src/renderer/components/+network-endpoints/endpoint-details.tsx index 5de9fdfe18..13a3a99ff0 100644 --- a/src/renderer/components/+network-endpoints/endpoint-details.tsx +++ b/src/renderer/components/+network-endpoints/endpoint-details.tsx @@ -35,7 +35,7 @@ export class EndpointDetails extends React.Component { return (
- + Subsets { endpoint.getEndpointSubsets().map((subset) => ( diff --git a/src/renderer/components/+network-ingresses/ingress-details.tsx b/src/renderer/components/+network-ingresses/ingress-details.tsx index 5254b2c663..9634e0149c 100644 --- a/src/renderer/components/+network-ingresses/ingress-details.tsx +++ b/src/renderer/components/+network-ingresses/ingress-details.tsx @@ -160,10 +160,10 @@ export class IngressDetails extends React.Component { {serviceName}:{servicePort} } - + Rules {this.renderPaths(ingress)} - + Load-Balancer Ingress Points {this.renderIngressPoints(ingressPoints)}
); diff --git a/src/renderer/components/+network-policies/network-policy-details.tsx b/src/renderer/components/+network-policies/network-policy-details.tsx index cc73a7ae1b..36e1e6da29 100644 --- a/src/renderer/components/+network-policies/network-policy-details.tsx +++ b/src/renderer/components/+network-policies/network-policy-details.tsx @@ -170,7 +170,7 @@ export class NetworkPolicyDetails extends React.Component - + Ingress {ingress.map((ingress, i) => (
{this.renderNetworkPolicyPorts(ingress.ports)} @@ -182,7 +182,7 @@ export class NetworkPolicyDetails extends React.Component - + Egress {egress.map((egress, i) => (
{this.renderNetworkPolicyPorts(egress.ports)} diff --git a/src/renderer/components/+network-services/service-details.tsx b/src/renderer/components/+network-services/service-details.tsx index 833fd7b59d..9bfa65bbbc 100644 --- a/src/renderer/components/+network-services/service-details.tsx +++ b/src/renderer/components/+network-services/service-details.tsx @@ -86,7 +86,7 @@ class NonInjectedServiceDetails extends React.Component - + Connection {spec.clusterIP} @@ -129,7 +129,7 @@ class NonInjectedServiceDetails extends React.Component )} - + Endpoint
diff --git a/src/renderer/components/+nodes/details.tsx b/src/renderer/components/+nodes/details.tsx index f9646478c1..feffd12d21 100644 --- a/src/renderer/components/+nodes/details.tsx +++ b/src/renderer/components/+nodes/details.tsx @@ -169,9 +169,9 @@ class NonInjectedNodeDetails extends React.Component } - + Capacity - + Allocatable { - renderRuleGroup( title: React.ReactNode, group: RuleGroup) { - if (!group) return null; - const { rule, ranges } = group; - - return ( - <> - - - {rule} + renderRuleGroup = (title: React.ReactNode, { rule, ranges }: RuleGroup) => ( + <> + {title} + + {rule} + + {ranges && ( + + {ranges.map(({ min, max }, index) => ( + + ))} - {ranges && ( - - {ranges.map(({ min, max }, index) => { - return ; - })} - - )} - - ); - } + )} + + ); render() { const { object: psp } = this.props; @@ -161,7 +158,7 @@ export class PodSecurityPolicyDetails extends React.Component - + Allowed Host Paths
Path Prefix @@ -179,14 +176,14 @@ export class PodSecurityPolicyDetails extends React.Component )} - {this.renderRuleGroup("Fs Group", fsGroup)} - {this.renderRuleGroup("Run As Group", runAsGroup)} - {this.renderRuleGroup("Run As User", runAsUser)} - {this.renderRuleGroup("Supplemental Groups", supplementalGroups)} + {fsGroup && this.renderRuleGroup("Fs Group", fsGroup)} + {runAsGroup && this.renderRuleGroup("Run As Group", runAsGroup)} + {runAsUser && this.renderRuleGroup("Run As User", runAsUser)} + {supplementalGroups && this.renderRuleGroup("Supplemental Groups", supplementalGroups)} {runtimeClass && ( <> - + Runtime Class {runtimeClass.allowedRuntimeClassNames?.join(", ") || "-"} @@ -198,7 +195,7 @@ export class PodSecurityPolicyDetails extends React.Component - + Se Linux {seLinux.rule} diff --git a/src/renderer/components/+storage-classes/storage-class-details.tsx b/src/renderer/components/+storage-classes/storage-class-details.tsx index dc8a118d6b..0a5f14161c 100644 --- a/src/renderer/components/+storage-classes/storage-class-details.tsx +++ b/src/renderer/components/+storage-classes/storage-class-details.tsx @@ -80,7 +80,7 @@ class NonInjectedStorageClassDetails extends React.Component - + Parameters { Object.entries(parameters).map(([name, value]) => ( diff --git a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx index a13d2175a5..bf2d824729 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx +++ b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx @@ -102,7 +102,7 @@ export class PersistentVolumeClaimDetails extends React.Component - + Selector {volumeClaim.getMatchLabels().map(label => )} diff --git a/src/renderer/components/+storage-volumes/volume-details-list.tsx b/src/renderer/components/+storage-volumes/volume-details-list.tsx index a58d41f6cf..1e9a8a93c4 100644 --- a/src/renderer/components/+storage-volumes/volume-details-list.tsx +++ b/src/renderer/components/+storage-volumes/volume-details-list.tsx @@ -67,7 +67,7 @@ export class VolumeDetailsList extends React.Component { return (
- + Persistent Volumes
- + Network File System { Object.entries(nfs).map(([name, value]) => ( @@ -78,7 +78,7 @@ export class PersistentVolumeDetails extends React.Component - + FlexVolume {flexVolume.driver} @@ -94,7 +94,7 @@ export class PersistentVolumeDetails extends React.Component - + Claim {claimRef.kind} diff --git a/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx b/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx index 6730227768..30704e5166 100644 --- a/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx +++ b/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx @@ -68,7 +68,7 @@ export class ClusterRoleBindingDetails extends React.Component - + Reference
Kind @@ -82,7 +82,7 @@ export class ClusterRoleBindingDetails extends React.Component
- + Bindings {subjects.length > 0 && ( diff --git a/src/renderer/components/+user-management/+cluster-roles/details.tsx b/src/renderer/components/+user-management/+cluster-roles/details.tsx index 96584e7f2c..f06e9785d1 100644 --- a/src/renderer/components/+user-management/+cluster-roles/details.tsx +++ b/src/renderer/components/+user-management/+cluster-roles/details.tsx @@ -28,7 +28,7 @@ export class ClusterRoleDetails extends React.Component
- + Rules {rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => { return (
diff --git a/src/renderer/components/+user-management/+role-bindings/details.tsx b/src/renderer/components/+user-management/+role-bindings/details.tsx index 2961a148cc..bbc3d56015 100644 --- a/src/renderer/components/+user-management/+role-bindings/details.tsx +++ b/src/renderer/components/+user-management/+role-bindings/details.tsx @@ -64,7 +64,7 @@ export class RoleBindingDetails extends React.Component
- + Reference
Kind @@ -78,7 +78,7 @@ export class RoleBindingDetails extends React.Component
- + Bindings {subjects.length > 0 && ( diff --git a/src/renderer/components/+user-management/+roles/details.tsx b/src/renderer/components/+user-management/+roles/details.tsx index 7342715fd1..0f24e9e711 100644 --- a/src/renderer/components/+user-management/+roles/details.tsx +++ b/src/renderer/components/+user-management/+roles/details.tsx @@ -27,7 +27,7 @@ export class RoleDetails extends React.Component { return (
- + Rules {rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => { return (
diff --git a/src/renderer/components/+user-management/+service-accounts/details.tsx b/src/renderer/components/+user-management/+service-accounts/details.tsx index f627b04b21..7d0beedfd8 100644 --- a/src/renderer/components/+user-management/+service-accounts/details.tsx +++ b/src/renderer/components/+user-management/+service-accounts/details.tsx @@ -143,7 +143,7 @@ export class ServiceAccountsDetails extends React.Component } - + Mountable secrets
{this.renderSecrets()}
diff --git a/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx b/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx index 19d49b2de8..4e73d11e6f 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx @@ -78,7 +78,7 @@ class NonInjectedCronJobDetails extends React.Component {childJobs.length > 0 && <> - + Jobs {childJobs.map((job: Job) => { const selectors = job.getSelectors(); const condition = job.getCondition(); diff --git a/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx b/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx index 110b1da86e..46795770f1 100644 --- a/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx @@ -53,7 +53,7 @@ export class DeploymentReplicaSets extends React.Component - + Deploy Revisions
{ + variant: PodVolumeVariants[Kind]; + pod: Pod; + volumeName: string; +} + +export type VolumeVariantComponent = React.FunctionComponent>; + +export interface LocalRefProps { + pod: Pod; + title: string; + kubeRef: LocalObjectReference | SecretReference | undefined; + api: KubeApi; +} + +export const LocalRef = ({ pod, title, kubeRef: ref, api }: LocalRefProps) => { + if (!ref) { + return null; + } + + return ( + + + {ref.name} + + + ); +}; diff --git a/src/renderer/components/+workloads-pods/details/volumes/variant.tsx b/src/renderer/components/+workloads-pods/details/volumes/variant.tsx new file mode 100644 index 0000000000..e08dc69527 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variant.tsx @@ -0,0 +1,291 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import type { Pod, PodVolume, PodVolumeKind } from "../../../../../common/k8s-api/endpoints"; +import { DrawerItem } from "../../../drawer"; +import { Icon } from "../../../icon"; +import { AwsElasticBlockStore } from "./variants/aws-elastic-block-store"; +import { AzureDisk } from "./variants/azure-disk"; +import { AzureFile } from "./variants/azure-file"; +import { CephFs } from "./variants/ceph-fs"; +import { Cinder } from "./variants/cinder"; +import { ConfigMap } from "./variants/config-map"; +import { ContainerStorageInterface } from "./variants/container-storage-interface"; +import { DownwardAPI } from "./variants/downward-api"; +import { EmptyDir } from "./variants/empty-dir"; +import { Ephemeral } from "./variants/ephemeral"; +import { FiberChannel } from "./variants/fiber-channel"; +import { FlexVolume } from "./variants/flex-volume"; +import { Flocker } from "./variants/flocker"; +import { GcePersistentDisk } from "./variants/gce-persistent-disk"; +import { GitRepo } from "./variants/git-repo"; +import { GlusterFs } from "./variants/gluster-fs"; +import { HostPath } from "./variants/host-path"; +import { IScsi } from "./variants/i-scsi"; +import { Local } from "./variants/local"; +import { NetworkFs } from "./variants/network-fs"; +import { PersistentVolumeClaim } from "./variants/persistent-volume-claim"; +import { PhotonPersistentDisk } from "./variants/photon-persistent-disk"; +import { PortworxVolume } from "./variants/portworx-volume"; +import { Projected } from "./variants/projected"; +import { Quobyte } from "./variants/quobyte"; +import { RadosBlockDevice } from "./variants/rados-block-device"; +import { ScaleIo } from "./variants/scale-io"; +import { Secret } from "./variants/secret"; +import { StorageOs } from "./variants/storage-os"; +import { VsphereVolume } from "./variants/vsphere-volume"; + +const deprecatedVolumeTypes = new Set([ + "flocker", + "gitRepo", + "quobyte", + "storageos", +]); + +interface VolumeVariantProps { + pod: Pod; + volume: PodVolume; +} + +interface VolumeVariantRender { + kind: PodVolumeKind; + element: JSX.Element; +} + +function renderVolumeVariant({ pod, volume }: VolumeVariantProps): VolumeVariantRender | null { + if (volume.awsElasticBlockStore) { + return { + kind: "awsElasticBlockStore", + element: , + }; + } + + if (volume.azureDisk) { + return { + kind: "azureDisk", + element: , + }; + } + + if (volume.azureFile) { + return { + kind: "azureFile", + element: , + }; + } + + if (volume.cephfs) { + return { + kind: "cephfs", + element: , + }; + } + + if (volume.cinder) { + return { + kind: "cinder", + element: , + }; + } + + if (volume.configMap) { + return { + kind: "configMap", + element: , + }; + } + + if (volume.csi) { + return { + kind: "csi", + element: , + }; + } + + if (volume.downwardAPI) { + return { + kind: "downwardAPI", + element: , + }; + } + + if (volume.emptyDir) { + return { + kind: "emptyDir", + element: , + }; + } + + if (volume.ephemeral) { + return { + kind: "ephemeral", + element: , + }; + } + + if (volume.fc) { + return { + kind: "fc", + element: , + }; + } + + if (volume.flexVolume) { + return { + kind: "flexVolume", + element: , + }; + } + + if (volume.flocker) { + return { + kind: "flocker", + element: , + }; + } + + if (volume.gcePersistentDisk) { + return { + kind: "gcePersistentDisk", + element: , + }; + } + + if (volume.gitRepo) { + return { + kind: "gitRepo", + element: , + }; + } + + if (volume.glusterfs) { + return { + kind: "glusterfs", + element: , + }; + } + + if (volume.hostPath) { + return { + kind: "hostPath", + element: , + }; + } + + if (volume.iscsi) { + return { + kind: "iscsi", + element: , + }; + } + + if (volume.local) { + return { + kind: "local", + element: , + }; + } + + if (volume.nfs) { + return { + kind: "nfs", + element: , + }; + } + + if (volume.persistentVolumeClaim) { + return { + kind: "persistentVolumeClaim", + element: , + }; + } + + if (volume.photonPersistentDisk) { + return { + kind: "photonPersistentDisk", + element: , + }; + } + + if (volume.portworxVolume) { + return { + kind: "portworxVolume", + element: , + }; + } + + if (volume.projected) { + return { + kind: "projected", + element: , + }; + } + + if (volume.quobyte) { + return { + kind: "quobyte", + element: , + }; + } + + if (volume.rbd) { + return { + kind: "rbd", + element: , + }; + } + + if (volume.scaleIO) { + return { + kind: "scaleIO", + element: , + }; + } + + if (volume.secret) { + return { + kind: "secret", + element: , + }; + } + + if (volume.storageos) { + return { + kind: "storageos", + element: , + }; + } + + if (volume.vsphereVolume) { + return { + kind: "vsphereVolume", + element: , + }; + } + + return null; +} + +export function VolumeVariant(props: VolumeVariantProps) { + const result = renderVolumeVariant(props); + + if (!result) { + return

Error! Unknown pod volume kind

; + } + + const { kind, element } = result; + const isDeprecated = deprecatedVolumeTypes.has(kind); + + return ( + <> + + {kind} + {isDeprecated && } + + {element} + + ); +} diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/aws-elastic-block-store.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/aws-elastic-block-store.tsx new file mode 100644 index 0000000000..285a0fa12e --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/aws-elastic-block-store.tsx @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const AwsElasticBlockStore: VolumeVariantComponent<"awsElasticBlockStore"> = ( + ({ variant: { volumeID, fsType = "ext4" }}) => ( + <> + + {volumeID} + + + {fsType} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/azure-disk.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/azure-disk.tsx new file mode 100644 index 0000000000..0e19b41843 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/azure-disk.tsx @@ -0,0 +1,32 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const AzureDisk: VolumeVariantComponent<"azureDisk"> = ( + ({ variant: { diskName, diskURI, kind = "Shared", cachingMode = "None", fsType = "ext4", readonly = false }}) => ( + <> + + {diskName} + + + {diskURI} + + + {kind} + + + {cachingMode} + + + {fsType} + + + {readonly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/azure-file.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/azure-file.tsx new file mode 100644 index 0000000000..c73fd42c02 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/azure-file.tsx @@ -0,0 +1,26 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const AzureFile: VolumeVariantComponent<"azureFile"> = ( + ({ variant: { readOnly = false, secretName, shareName, secretNamespace = "default" }}) => ( + <> + + {secretName} + + + {shareName} + + + {secretNamespace} + + + {readOnly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/ceph-fs.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/ceph-fs.tsx new file mode 100644 index 0000000000..2f9260a58c --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/ceph-fs.tsx @@ -0,0 +1,46 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { secretsApi } from "../../../../../../common/k8s-api/endpoints"; +import { DrawerItem } from "../../../../drawer"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const CephFs: VolumeVariantComponent<"cephfs"> = ( + ({ pod, variant: { monitors, path = "/", user = "admin", secretFile = "/etc/ceph/user.secret", secretRef, readOnly }}) => ( + <> + +
    + {monitors.map(monitor =>
  • {monitor}
  • )} +
+
+ + {path} + + + {user} + + { + secretRef + ? ( + + ) + : ( + + {secretFile} + + ) + } + + {readOnly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/cinder.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/cinder.tsx new file mode 100644 index 0000000000..366438e0d8 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/cinder.tsx @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const Cinder: VolumeVariantComponent<"cinder"> = ( + ({ variant: { volumeID, fsType = "ext4" }}) => ( + <> + + {volumeID} + + + {fsType} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/config-map.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/config-map.tsx new file mode 100644 index 0000000000..35cace6617 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/config-map.tsx @@ -0,0 +1,19 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { configMapApi } from "../../../../../../common/k8s-api/endpoints"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const ConfigMap: VolumeVariantComponent<"configMap"> = ( + ({ pod, variant: { name }}) => ( + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/container-storage-interface.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/container-storage-interface.tsx new file mode 100644 index 0000000000..57dff33196 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/container-storage-interface.tsx @@ -0,0 +1,67 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { secretsApi } from "../../../../../../common/k8s-api/endpoints"; +import { DrawerItem } from "../../../../drawer"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const ContainerStorageInterface: VolumeVariantComponent<"csi"> = ({ + pod, + variant: { + driver, + readOnly = false, + fsType = "ext4", + volumeAttributes = {}, + nodePublishSecretRef, + controllerPublishSecretRef, + nodeStageSecretRef, + controllerExpandSecretRef, + }, +}) => ( + <> + + {driver} + + + {readOnly.toString()} + + + {fsType} + + + + + + { + Object.entries(volumeAttributes) + .map(([key, value]) => ( + + {value} + + )) + } + +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/downward-api.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/downward-api.tsx new file mode 100644 index 0000000000..c6c14bda2e --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/downward-api.tsx @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const DownwardAPI: VolumeVariantComponent<"downwardAPI"> = ( + ({ variant: { items }}) => ( + <> + +
    + {items.map(item =>
  • {item.path}
  • )} +
+
+ + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/empty-dir.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/empty-dir.tsx new file mode 100644 index 0000000000..c648d42354 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/empty-dir.tsx @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const EmptyDir: VolumeVariantComponent<"emptyDir"> = ( + ({ variant: { medium, sizeLimit }}) => ( + <> + + {medium || ""} + + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/ephemeral.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/ephemeral.tsx new file mode 100644 index 0000000000..0ec5878c4f --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/ephemeral.tsx @@ -0,0 +1,29 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { dump } from "js-yaml"; +import React from "react"; +import { DrawerItem, DrawerItemLabels } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const Ephemeral: VolumeVariantComponent<"ephemeral"> = ( + ({ pod, volumeName, variant: { volumeClaimTemplate: { metadata, spec }}}) => ( + <> + + {pod.getName()}-{volumeName} + + + + + {dump(spec)} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/fiber-channel.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/fiber-channel.tsx new file mode 100644 index 0000000000..684c4f1f32 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/fiber-channel.tsx @@ -0,0 +1,29 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const FiberChannel: VolumeVariantComponent<"fc"> = ( + ({ variant: { targetWWNs, lun, fsType = "ext4", readOnly = false }}) => ( + <> + +
    + {targetWWNs.map(targetWWN =>
  • {targetWWN}
  • )} +
+
+ + {lun.toString()} + + + {fsType} + + + {readOnly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/flex-volume.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/flex-volume.tsx new file mode 100644 index 0000000000..f7cc60de35 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/flex-volume.tsx @@ -0,0 +1,39 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { secretsApi } from "../../../../../../common/k8s-api/endpoints"; +import { DrawerItem } from "../../../../drawer"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const FlexVolume: VolumeVariantComponent<"flexVolume"> = ( + ({ pod, variant: { driver, fsType, secretRef, readOnly = false, options }}) => ( + <> + + {driver} + + + {fsType || "-- system default --"} + + + + {readOnly.toString()} + + { + ...Object.entries(options) + .map(([key, value]) => ( + + {value} + + )) + } + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/flocker.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/flocker.tsx new file mode 100644 index 0000000000..d4edefcba2 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/flocker.tsx @@ -0,0 +1,18 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const Flocker: VolumeVariantComponent<"flocker"> = ( + ({ variant: { datasetName }}) => ( + <> + + {datasetName} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/gce-persistent-disk.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/gce-persistent-disk.tsx new file mode 100644 index 0000000000..7c15b53109 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/gce-persistent-disk.tsx @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const GcePersistentDisk: VolumeVariantComponent<"gcePersistentDisk"> = ( + ({ variant: { pdName, fsType = "ext4" }}) => ( + <> + + {pdName} + + + {fsType} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/git-repo.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/git-repo.tsx new file mode 100644 index 0000000000..23e6421210 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/git-repo.tsx @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const GitRepo: VolumeVariantComponent<"gitRepo"> = ( + ({ variant: { repository, revision }}) => ( + <> + + {repository} + + + {revision} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/gluster-fs.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/gluster-fs.tsx new file mode 100644 index 0000000000..b3937b7610 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/gluster-fs.tsx @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const GlusterFs: VolumeVariantComponent<"glusterfs"> = ( + ({ variant: { endpoints, path, readOnly = false }}) => ( + <> + + {endpoints} + + + {path} + + + {readOnly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/host-path.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/host-path.tsx new file mode 100644 index 0000000000..5b80431733 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/host-path.tsx @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const HostPath: VolumeVariantComponent<"hostPath"> = ( + ({ variant: { path, type }}) => ( + <> + + {path} + + + {type || "-- none --"} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/i-scsi.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/i-scsi.tsx new file mode 100644 index 0000000000..1146752061 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/i-scsi.tsx @@ -0,0 +1,45 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const IScsi: VolumeVariantComponent<"iscsi"> = ( + ({ variant: { targetPortal, iqn, lun, fsType = "ext4", readOnly = false, chapAuthDiscovery, chapAuthSession, secretRef }}) => ( + <> + + {targetPortal} + + + {iqn} + + + {lun.toString()} + + + {fsType} + + + {readOnly.toString()} + + {chapAuthDiscovery && ( + + {chapAuthDiscovery.toString()} + + )} + {chapAuthSession && ( + + {chapAuthSession.toString()} + + )} + { secretRef && ( + + {secretRef.name} + + )} + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/local.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/local.tsx new file mode 100644 index 0000000000..a4e087ae2c --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/local.tsx @@ -0,0 +1,18 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const Local: VolumeVariantComponent<"local"> = ( + ({ variant: { path }}) => ( + <> + + {path} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/network-fs.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/network-fs.tsx new file mode 100644 index 0000000000..d40f2eaa08 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/network-fs.tsx @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const NetworkFs: VolumeVariantComponent<"nfs"> = ( + ({ variant: { server, path, readOnly = false }}) => ( + <> + + {server} + + + {path} + + + {readOnly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/persistent-volume-claim.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/persistent-volume-claim.tsx new file mode 100644 index 0000000000..f7d89907a9 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/persistent-volume-claim.tsx @@ -0,0 +1,19 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { pvcApi } from "../../../../../../common/k8s-api/endpoints"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const PersistentVolumeClaim: VolumeVariantComponent<"persistentVolumeClaim"> = ( + ({ pod, variant: { claimName }}) => ( + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/photon-persistent-disk.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/photon-persistent-disk.tsx new file mode 100644 index 0000000000..457da2f62b --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/photon-persistent-disk.tsx @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const PhotonPersistentDisk: VolumeVariantComponent<"photonPersistentDisk"> = ( + ({ variant: { pdID, fsType = "ext4" }}) => ( + <> + + {pdID} + + + {fsType} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/portworx-volume.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/portworx-volume.tsx new file mode 100644 index 0000000000..103be78acf --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/portworx-volume.tsx @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const PortworxVolume: VolumeVariantComponent<"portworxVolume"> = ( + ({ variant: { volumeID, fsType = "ext4", readOnly = false }}) => ( + <> + + {volumeID} + + + {fsType} + + + {readOnly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/projected.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/projected.tsx new file mode 100644 index 0000000000..8b04d61755 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/projected.tsx @@ -0,0 +1,88 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem, DrawerTitle } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const Projected: VolumeVariantComponent<"projected"> = ( + ({ variant: { sources, defaultMode }}) => ( + <> + + 0o{defaultMode.toString(8)} + + + { + sources.map(({ secret, downwardAPI, configMap, serviceAccountToken }, index) => ( + + {secret && ( + <> + Secret + + {secret.name} + + +
    + {secret.items?.map(({ key, path }) => ( +
  • + {key} ⇢ {path} +
  • + ))} +
+
+ + )} + {downwardAPI && ( + <> + Downward API + +
    + {downwardAPI.items?.map(({ path }) => ( +
  • + {path} +
  • + ))} +
+
+ + )} + {configMap && ( + <> + Config Map + + {configMap.name} + + +
    + {configMap.items?.map(({ key, path }) => ( +
  • + {key} ⇢ {path} +
  • + ))} +
+
+ + )} + {serviceAccountToken && ( + <> + Service Account Token + + + {String(serviceAccountToken.expirationSeconds || (60*60 /* an hour */))}s + + + {serviceAccountToken.path} + + + )} +
+ )) + } +
+ + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/quobyte.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/quobyte.tsx new file mode 100644 index 0000000000..a315f254e8 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/quobyte.tsx @@ -0,0 +1,33 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const Quobyte: VolumeVariantComponent<"quobyte"> = ( + ({ variant: { registry, volume, readOnly = false, user = "serviceaccount", group, tenant }}) => ( + <> + + {registry} + + + {volume} + + + {readOnly.toString()} + + + {user} + + + {group ?? "-- no group --"} + + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/rados-block-device.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/rados-block-device.tsx new file mode 100644 index 0000000000..060aa14554 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/rados-block-device.tsx @@ -0,0 +1,52 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { secretsApi } from "../../../../../../common/k8s-api/endpoints"; +import { DrawerItem } from "../../../../drawer"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const RadosBlockDevice: VolumeVariantComponent<"rbd"> = ( + ({ pod, variant: { monitors, image, fsType = "ext4", pool = "rbd", user = "admin", keyring = "/etc/ceph/keyright", secretRef, readOnly = false }}) => ( + <> + +
    + {monitors.map(monitor =>
  • {monitor}
  • )} +
+
+ + {image} + + + {fsType} + + + {pool} + + + {user} + + { + secretRef + ? ( + + ) + : ( + + {keyring} + + ) + } + + {readOnly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/scale-io.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/scale-io.tsx new file mode 100644 index 0000000000..be9ae981e8 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/scale-io.tsx @@ -0,0 +1,49 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { secretsApi } from "../../../../../../common/k8s-api/endpoints"; +import { DrawerItem } from "../../../../drawer"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const ScaleIo: VolumeVariantComponent<"scaleIO"> = ( + ({ pod, variant: { gateway, system, secretRef, sslEnabled = false, protectionDomain, storagePool, storageMode = "ThinProvisioned", volumeName, fsType = "xfs", readOnly = false }}) => ( + <> + + {gateway} + + + {system} + + + + {sslEnabled.toString()} + + + + + + {volumeName} + + + {fsType} + + + {readOnly.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/secret.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/secret.tsx new file mode 100644 index 0000000000..ae67a8ce83 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/secret.tsx @@ -0,0 +1,33 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { secretsApi } from "../../../../../../common/k8s-api/endpoints"; +import { DrawerItem } from "../../../../drawer"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const Secret: VolumeVariantComponent<"secret"> = ( + ({ pod, variant: { secretName, items = [], defaultMode = 0o644, optional = false }}) => ( + <> + + + + 0o{defaultMode.toString(8)} + + + {optional.toString()} + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/storage-os.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/storage-os.tsx new file mode 100644 index 0000000000..0954b9288f --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/storage-os.tsx @@ -0,0 +1,38 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { secretsApi } from "../../../../../../common/k8s-api/endpoints"; +import { DrawerItem } from "../../../../drawer"; +import { LocalRef, VolumeVariantComponent } from "../variant-helpers"; + +export const StorageOs: VolumeVariantComponent<"storageos"> = ( + ({ pod, variant: { volumeName, volumeNamespace, fsType = "ext4", readOnly = false, secretRef }}) => ( + <> + + {volumeName} + + + + {fsType} + + + {readOnly.toString()} + + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/variants/vsphere-volume.tsx b/src/renderer/components/+workloads-pods/details/volumes/variants/vsphere-volume.tsx new file mode 100644 index 0000000000..eb97917e91 --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/variants/vsphere-volume.tsx @@ -0,0 +1,27 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import React from "react"; +import { DrawerItem } from "../../../../drawer"; +import type { VolumeVariantComponent } from "../variant-helpers"; + +export const VsphereVolume: VolumeVariantComponent<"vsphereVolume"> = ( + ({ variant: { volumePath, fsType = "ext4", storagePolicyName, storagePolicyID }}) => ( + <> + + {volumePath} + + + {fsType} + + + + + ) +); diff --git a/src/renderer/components/+workloads-pods/details/volumes/view.tsx b/src/renderer/components/+workloads-pods/details/volumes/view.tsx new file mode 100644 index 0000000000..f90ca6a31e --- /dev/null +++ b/src/renderer/components/+workloads-pods/details/volumes/view.tsx @@ -0,0 +1,38 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { observer } from "mobx-react"; +import React from "react"; +import type { Pod } from "../../../../../common/k8s-api/endpoints"; +import { DrawerTitle } from "../../../drawer"; +import { Icon } from "../../../icon"; +import { VolumeVariant } from "./variant"; + +export interface PodVolumesProps { + pod: Pod; +} + +export const PodVolumes = observer(({ pod }: PodVolumesProps) => { + const volumes = pod.getVolumes() ?? []; + + if (volumes.length === 0) { + return null; + } + + return ( + <> + Volumes + {volumes.map(volume => ( +
+
+ + {volume.name} +
+ +
+ ))} + + ); +}); diff --git a/src/renderer/components/+workloads-pods/pod-details-list.tsx b/src/renderer/components/+workloads-pods/pod-details-list.tsx index c7679706fd..12939a4a1f 100644 --- a/src/renderer/components/+workloads-pods/pod-details-list.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-list.tsx @@ -131,7 +131,7 @@ export class PodDetailsList extends React.Component { return (
- + Pods
{ - @observable secrets: Map = observable.map(); +export const PodDetailsSecrets = observer(({ pod }: PodDetailsSecretsProps) => { + const [secrets, setSecrets] = useState(new Map()); - componentDidMount(): void { - disposeOnUnmount(this, [ - autorun(async () => { - const { pod } = this.props; - - const secrets = await Promise.all( - pod.getSecrets().map(secretName => secretsApi.get({ + useEffect(() => ( + reaction( + () => pod.getSecrets(), + async (secretNames) => { + const results = await Promise.allSettled( + secretNames.map(secretName => secretsApi.get({ name: secretName, namespace: pod.getNs(), })), ); - secrets.forEach(secret => secret && this.secrets.set(secret.getName(), secret)); - }), - ]); - } + setSecrets(new Map( + results + .filter(result => result.status === "fulfilled" && result.value) + .map(result => (result as PromiseFulfilledResult).value) + .map(secret => [secret.getName(), secret]), + )); + }, + { + fireImmediately: true, + }) + ), []); - constructor(props: PodDetailsSecretsProps) { - super(props); - makeObservable(this); - } + const renderSecret = (name: string) => { + const secret = secrets.get(name); - render() { - const { pod } = this.props; + if (!secret) { + return {name}; + } - return ( -
- { - pod.getSecrets().map(secretName => { - const secret = this.secrets.get(secretName); - - if (secret) { - return this.renderSecretLink(secret); - } else { - return ( - {secretName} - ); - } - }) - } -
- ); - } - - protected renderSecretLink(secret: Secret) { return ( {secret.getName()} ); - } -} + }; + + return ( +
+ {pod.getSecrets().map(renderSecret)} +
+ ); +}); + diff --git a/src/renderer/components/+workloads-pods/pod-details.tsx b/src/renderer/components/+workloads-pods/pod-details.tsx index 2b592ebe04..857faeefab 100644 --- a/src/renderer/components/+workloads-pods/pod-details.tsx +++ b/src/renderer/components/+workloads-pods/pod-details.tsx @@ -10,14 +10,13 @@ import kebabCase from "lodash/kebabCase"; import { disposeOnUnmount, observer } from "mobx-react"; import { Link } from "react-router-dom"; import { observable, reaction, makeObservable } from "mobx"; -import { type IPodMetrics, nodesApi, Pod, pvcApi, configMapApi, getMetricsForPods } from "../../../common/k8s-api/endpoints"; +import { type IPodMetrics, nodesApi, Pod, getMetricsForPods } from "../../../common/k8s-api/endpoints"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; import { boundMethod, cssNames, toJS } from "../../utils"; import { PodDetailsContainer } from "./pod-details-container"; import { PodDetailsAffinities } from "./pod-details-affinities"; import { PodDetailsTolerations } from "./pod-details-tolerations"; -import { Icon } from "../icon"; import { PodDetailsSecrets } from "./pod-details-secrets"; import { ResourceMetrics } from "../resource-metrics"; import type { KubeObjectDetailsProps } from "../kube-object-details"; @@ -28,6 +27,7 @@ import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { getDetailsUrl } from "../kube-detail-params"; import logger from "../../../common/logger"; +import { PodVolumes } from "./details/volumes/view"; export interface PodDetailsProps extends KubeObjectDetailsProps { } @@ -73,12 +73,13 @@ export class PodDetails extends React.Component { } const { status, spec } = pod; - const { conditions, podIP } = status; + const { conditions = [], podIP } = status ?? {}; const podIPs = pod.getIPs(); - const { nodeName } = spec; + const { nodeName } = spec ?? {}; const nodeSelector = pod.getNodeSelectors(); - const volumes = pod.getVolumes(); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod); + const initContainers = pod.getInitContainers(); + const containers = pod.getContainers(); return (
@@ -90,26 +91,22 @@ export class PodDetails extends React.Component { )} + + {pod.getStatusMessage()} - - {nodeName && ( - - {nodeName} - - )} + {podIP} -
); } diff --git a/src/renderer/components/app.scss b/src/renderer/components/app.scss index bedc1d1f59..97a2057ed2 100755 --- a/src/renderer/components/app.scss +++ b/src/renderer/components/app.scss @@ -7,9 +7,9 @@ @tailwind components; @tailwind utilities; -@import "~flex.box"; // todo: replace with tailwind's flexbox classes -@import "./fonts"; +@import "~flex.box"; @import "../themes/theme-vars"; +@import "./fonts"; :root { --unit: 8px; diff --git a/src/renderer/components/avatar/avatar.tsx b/src/renderer/components/avatar/avatar.tsx index c504d773f1..c63df5054e 100644 --- a/src/renderer/components/avatar/avatar.tsx +++ b/src/renderer/components/avatar/avatar.tsx @@ -59,6 +59,10 @@ export function Avatar(props: AvatarProps) { const { title, variant = "rounded", size = 32, colorHash, children, background, imgProps, src, className, disabled, ...rest } = props; const getBackgroundColor = () => { + if (src) { + return "transparent"; + } + return background || randomColor({ seed: colorHash, luminosity: "dark" }); }; diff --git a/src/renderer/components/dock/dock-tab.module.scss b/src/renderer/components/dock/dock-tab.module.scss index 3093260ae0..3b803f32c7 100644 --- a/src/renderer/components/dock/dock-tab.module.scss +++ b/src/renderer/components/dock/dock-tab.module.scss @@ -81,7 +81,7 @@ .close { position: absolute; right: 0px; - width: 5ch; + width: 4ch; opacity: 0; text-align: center; background: linear-gradient(90deg, transparent 0%, var(--color-active) 25%); diff --git a/src/renderer/components/dock/edit-resource/view.tsx b/src/renderer/components/dock/edit-resource/view.tsx index 61d2ffa2ef..9d92848f49 100644 --- a/src/renderer/components/dock/edit-resource/view.tsx +++ b/src/renderer/components/dock/edit-resource/view.tsx @@ -46,7 +46,7 @@ class NonInjectedEditResource extends React.Component { const overlay = document.querySelector(".PodLogs .list span.active"); - if (!overlay) return; - overlay.scrollIntoViewIfNeeded(); + if (typeof overlay?.scrollIntoViewIfNeeded === "function") { + overlay.scrollIntoViewIfNeeded(); + } }, 100); }; diff --git a/src/renderer/components/dock/terminal/terminal-dock-tab.scss b/src/renderer/components/dock/terminal/terminal-dock-tab.scss index 34a49e1330..c65e0bfb7d 100644 --- a/src/renderer/components/dock/terminal/terminal-dock-tab.scss +++ b/src/renderer/components/dock/terminal/terminal-dock-tab.scss @@ -4,7 +4,4 @@ */ .TerminalTab { - @include font-preload { - font-family: "RobotoMono", monospace; - } } diff --git a/src/renderer/components/drawer/drawer-item-labels.tsx b/src/renderer/components/drawer/drawer-item-labels.tsx index c3dfb41bfc..e25e615910 100644 --- a/src/renderer/components/drawer/drawer-item-labels.tsx +++ b/src/renderer/components/drawer/drawer-item-labels.tsx @@ -6,21 +6,30 @@ import React from "react"; import { DrawerItem, DrawerItemProps } from "./drawer-item"; import { Badge } from "../badge"; +import { KubeObject } from "../../../common/k8s-api/kube-object"; export interface DrawerItemLabelsProps extends DrawerItemProps { - labels: string[]; + labels: string[] | Record; } export function DrawerItemLabels(props: DrawerItemLabelsProps) { const { labels, ...itemProps } = props; - if (!labels || !labels.length) { + if (!labels || typeof labels !== "object") { + return null; + } + + const labelStrings = Array.isArray(labels) + ? labels + : KubeObject.stringifyLabels(labels); + + if (labelStrings.length === 0) { return null; } return ( - {labels.map(label => )} + {labelStrings.map(label => )} ); } diff --git a/src/renderer/components/drawer/drawer-item.tsx b/src/renderer/components/drawer/drawer-item.tsx index 2656a635e2..1f49ca92e7 100644 --- a/src/renderer/components/drawer/drawer-item.tsx +++ b/src/renderer/components/drawer/drawer-item.tsx @@ -7,29 +7,32 @@ import "./drawer-item.scss"; import React from "react"; import { cssNames, displayBooleans } from "../../utils"; -export interface DrawerItemProps extends React.HTMLAttributes { +export interface DrawerItemProps extends React.HTMLAttributes { name: React.ReactNode; - className?: string; title?: string; labelsOnly?: boolean; hidden?: boolean; renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean" } -export class DrawerItem extends React.Component { - render() { - const { name, title, labelsOnly, children, hidden, className, renderBoolean, ...elemProps } = this.props; - - if (hidden) return null; - - const classNames = cssNames("DrawerItem", className, { labelsOnly }); - const content = displayBooleans(renderBoolean, children); - - return ( -
- {name} - {content} -
- ); +export function DrawerItem({ + name, + title, + labelsOnly, + children, + hidden = false, + className, + renderBoolean, + ...elemProps +}: DrawerItemProps) { + if (hidden) { + return null; } + + return ( +
+ {name} + {displayBooleans(renderBoolean, children)} +
+ ); } diff --git a/src/renderer/components/drawer/drawer-title.scss b/src/renderer/components/drawer/drawer-title.module.css similarity index 77% rename from src/renderer/components/drawer/drawer-title.scss rename to src/renderer/components/drawer/drawer-title.module.css index 74e525f1d2..7a4be3ee34 100644 --- a/src/renderer/components/drawer/drawer-title.scss +++ b/src/renderer/components/drawer/drawer-title.module.css @@ -4,7 +4,14 @@ */ .DrawerTitle { - padding: $padding * 1.5 $padding * 3; margin: $margin * 3 (-$margin * 3); background: var(--drawerSubtitleBackground); } + +.DrawerTitle.title { + padding: $padding * 1.5 $padding * 3; +} + +.DrawerTitle.sub-title { + padding: $padding $padding * 2; +} diff --git a/src/renderer/components/drawer/drawer-title.tsx b/src/renderer/components/drawer/drawer-title.tsx index 3ef2858c9b..81be36f5ac 100644 --- a/src/renderer/components/drawer/drawer-title.tsx +++ b/src/renderer/components/drawer/drawer-title.tsx @@ -3,23 +3,29 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import "./drawer-title.scss"; +import styles from "./drawer-title.module.css"; import React from "react"; import { cssNames } from "../../utils"; export interface DrawerTitleProps { className?: string; - title?: React.ReactNode; + children: React.ReactNode; + + /** + * Specifies how large this title is + * + * @default "title" + */ + size?: "sub-title" | "title"; } -export class DrawerTitle extends React.Component { - render() { - const { title, children, className } = this.props; - - return ( -
- {title || children} -
- ); - } +export function DrawerTitle({ className, children, size = "title" }: DrawerTitleProps) { + return ( +
+ {children} +
+ ); } diff --git a/src/renderer/components/fonts.scss b/src/renderer/components/fonts.scss index 239f6dce45..fc594561d8 100644 --- a/src/renderer/components/fonts.scss +++ b/src/renderer/components/fonts.scss @@ -24,3 +24,13 @@ font-display: block; src: local('RobotoMono'), url('./fonts/roboto-mono-nerd.ttf') format('truetype'); } + +#fonts-preloading { + > .icons { + @include font-preload("Material Icons"); + } + + > .terminal { + @include font-preload("RobotoMono"); + } +} diff --git a/src/renderer/components/layout/sidebar-cluster.tsx b/src/renderer/components/layout/sidebar-cluster.tsx index 58cae55c99..34d9b733fc 100644 --- a/src/renderer/components/layout/sidebar-cluster.tsx +++ b/src/renderer/components/layout/sidebar-cluster.tsx @@ -16,6 +16,7 @@ import { navigate } from "../../navigation"; import { Menu, MenuItem } from "../menu"; import { ConfirmDialog } from "../confirm-dialog"; import { Tooltip } from "../tooltip"; +import { observer } from "mobx-react"; const contextMenu: CatalogEntityContextMenuContext = observable({ menuItems: [], @@ -59,7 +60,7 @@ function renderLoadingSidebarCluster() { ); } -export function SidebarCluster({ clusterEntity }: { clusterEntity: CatalogEntity }) { +export const SidebarCluster = observer(({ clusterEntity }: { clusterEntity: CatalogEntity }) => { const [opened, setOpened] = useState(false); if (!clusterEntity) { @@ -138,4 +139,4 @@ export function SidebarCluster({ clusterEntity }: { clusterEntity: CatalogEntity ); -} +}); diff --git a/src/renderer/components/mixins.scss b/src/renderer/components/mixins.scss index c9bfd4a835..dd62568219 100755 --- a/src/renderer/components/mixins.scss +++ b/src/renderer/components/mixins.scss @@ -60,14 +60,19 @@ } } -// Makes custom font available at earlier stages (start preloading) -// Element must be in DOM and contain some text of loading font. -@mixin font-preload() { +// Makes custom @font-family available at earlier stages. +// Element must exist in DOM as soon as possible to initiate preloading. +@mixin font-preload($fontFamily) { + position: absolute; + visibility: hidden; + height: 0; + &:before { width: 0; display: block; overflow: hidden; - content: "x"; // required - @content; // must contain `font-family` + content: "x"; // some text required to start applying font in document + font-family: $fontFamily; // imported name in @font-face declaration + @content; } } diff --git a/src/renderer/components/tabs/tabs.tsx b/src/renderer/components/tabs/tabs.tsx index 3913886365..be70447f5a 100644 --- a/src/renderer/components/tabs/tabs.tsx +++ b/src/renderer/components/tabs/tabs.tsx @@ -17,8 +17,6 @@ interface TabsContextValue { onChange?(value: D): void; } -type Omit = Pick>; - export interface TabsProps extends TabsContextValue, Omit, "onChange"> { className?: string; center?: boolean; @@ -81,7 +79,9 @@ export class Tab extends React.PureComponent { } scrollIntoView() { - this.ref.current?.scrollIntoViewIfNeeded(); + if (typeof this.ref.current?.scrollIntoViewIfNeeded === "function") { + this.ref.current.scrollIntoViewIfNeeded(); + } } @boundMethod diff --git a/src/renderer/initializers/catalog-entity-detail-registry.tsx b/src/renderer/initializers/catalog-entity-detail-registry.tsx index f04f4e7aa9..0ffccd8063 100644 --- a/src/renderer/initializers/catalog-entity-detail-registry.tsx +++ b/src/renderer/initializers/catalog-entity-detail-registry.tsx @@ -17,7 +17,7 @@ export function initCatalogEntityDetailRegistry() { components: { Details: ({ entity }: CatalogEntityDetailsProps) => ( <> - + Kubernetes Information
{entity.metadata.distro || "unknown"} @@ -36,7 +36,7 @@ export function initCatalogEntityDetailRegistry() { components: { Details: ({ entity }: CatalogEntityDetailsProps) => ( <> - + More Information {entity.spec.url} diff --git a/src/renderer/template.html b/src/renderer/template.html index ba4dbb153d..79014c6009 100755 --- a/src/renderer/template.html +++ b/src/renderer/template.html @@ -2,13 +2,16 @@ - -
+
+ + +
+ diff --git a/types/dom.d.ts b/types/dom.d.ts index eb6bc83dbe..0e3e1bcb43 100644 --- a/types/dom.d.ts +++ b/types/dom.d.ts @@ -6,7 +6,7 @@ export {}; declare global { interface Element { - scrollIntoViewIfNeeded(opt_center?: boolean): void; + scrollIntoViewIfNeeded?(opt_center?: boolean): void; } interface Window { diff --git a/yarn.lock b/yarn.lock index ea54ce216c..655e196ef7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1043,13 +1043,13 @@ "@sentry/utils" "6.7.1" tslib "^1.9.3" -"@sentry/integrations@^6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-6.15.0.tgz#3c83617c301b5f77a57514ad7812aedc03613a31" - integrity sha512-fSBAipas6zwyYo4U91pyQOnaTcRCfwvH6ZFwu0Fqmkm64nU9rYpbTNiKkwOWbbiXXT6+LEF6RzBpsyhm4QvgmQ== +"@sentry/integrations@^6.19.2": + version "6.19.2" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-6.19.2.tgz#d5abcab94ae23ada097eb454c269e9ab573e14bb" + integrity sha512-RjkZXPrtrM+lJVEa4OpZ9CYjJdkpPoWslEQzLMvbaRpURpHFqmABGtXRAnJRYKmy6h7/9q9sABcDgCD4OZw11g== dependencies: - "@sentry/types" "6.15.0" - "@sentry/utils" "6.15.0" + "@sentry/types" "6.19.2" + "@sentry/utils" "6.19.2" localforage "^1.8.1" tslib "^1.9.3" @@ -1088,27 +1088,22 @@ "@sentry/utils" "6.7.1" tslib "^1.9.3" -"@sentry/types@6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.15.0.tgz#a2917f8aed91471bdfd6651384ffcd47b95c43ad" - integrity sha512-zBw5gPUsofXUSpS3ZAXqRNedLRBvirl3sqkj2Lez7X2EkKRgn5D8m9fQIrig/X3TsKcXUpijDW5Buk5zeCVzJA== +"@sentry/types@6.19.2", "@sentry/types@^6.19.2": + version "6.19.2" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.19.2.tgz#0219c9da21ed975951108b8541913b1966464435" + integrity sha512-XO5qmVBdTs+7PdCz7fAwn1afWxSnRE2KLBFg5/vOdKosPSSHsSHUURSkxiEZc2QsR+JpRB4AeQ26AkIRX38qTg== "@sentry/types@6.7.1": version "6.7.1" resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.7.1.tgz#c8263e1886df5e815570c4668eb40a1cfaa1c88b" integrity sha512-9AO7HKoip2MBMNQJEd6+AKtjj2+q9Ze4ooWUdEvdOVSt5drg7BGpK221/p9JEOyJAZwEPEXdcMd3VAIMiOb4MA== -"@sentry/types@^6.18.2": - version "6.18.2" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.18.2.tgz#f528fec8b75c19d5a6976004e71703184c6cf7be" - integrity sha512-WzpJf/Q5aORTzrSwer/As1NlO90dBAQpaHV2ikDDKqOyMWEgjKb5/4gh59p9gH8JMMnLetP1AvQel0fOj5UnUw== - -"@sentry/utils@6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.15.0.tgz#0c247cb092b1796d39c3d16d8e6977b9cdab9ca2" - integrity sha512-gnhKKyFtnNmKWjDizo7VKD0/Vx8cgW1lCusM6WI7jy2jlO3bQA0+Dzgmr4mIReZ74mq4VpOd2Vfrx7ZldW1DMw== +"@sentry/utils@6.19.2": + version "6.19.2" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.19.2.tgz#995efb896c5159369509f4896c27a2d2ea9191f2" + integrity sha512-2DQQ2OJaxjtyxGq5FmMlqb6hptsqMs2xoBiVRMkTS/rvyTrk1oQdKZ8ePwjtgX3nJ728ni3IXIyXV+vfGp4EBw== dependencies: - "@sentry/types" "6.15.0" + "@sentry/types" "6.19.2" tslib "^1.9.3" "@sentry/utils@6.7.1": @@ -1202,10 +1197,10 @@ lz-string "^1.4.4" pretty-format "^26.6.2" -"@testing-library/jest-dom@^5.16.2": - version "5.16.2" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" - integrity sha512-6ewxs1MXWwsBFZXIk4nKKskWANelkdUehchEOokHsN8X7c2eKXGw+77aRV63UU8f/DTSVUPLaGxdrj4lN7D/ug== +"@testing-library/jest-dom@^5.16.3": + version "5.16.3" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.3.tgz#b76851a909586113c20486f1679ffb4d8ec27bfa" + integrity sha512-u5DfKj4wfSt6akfndfu1eG06jsdyA/IUrlX2n3pyq5UXgXMhXY+NJb8eNK/7pqPWAhCKsCGWDdDO0zKMKAYkEA== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.9.1" @@ -1562,13 +1557,6 @@ resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== -"@types/http-proxy@^1.17.7": - version "1.17.7" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.7.tgz#30ea85cc2c868368352a37f0d0d3581e24834c6f" - integrity sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w== - dependencies: - "@types/node" "*" - "@types/http-proxy@^1.17.8": version "1.17.8" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" @@ -1608,10 +1596,10 @@ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== -"@types/jsdom@^16.2.13": - version "16.2.13" - resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.13.tgz#126c8b7441b159d6234610a48de77b6066f1823f" - integrity sha512-8JQCjdeAidptSsOcRWk2iTm9wCcwn9l+kRG6k5bzUacrnm1ezV4forq0kWjUih/tumAeoG+OspOvQEbbRucBTw== +"@types/jsdom@^16.2.14": + version "16.2.14" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.14.tgz#26fe9da6a8870715b154bb84cd3b2e53433d8720" + integrity sha512-6BAy1xXEmMuHeAJ4Fv4yXKwBDTGTOseExKE3OaHiNycdHdZw59KfYzrt0DkDluvwmik1HRt6QS7bImxUmpSy+w== dependencies: "@types/node" "*" "@types/parse5" "*" @@ -1695,18 +1683,18 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== -"@types/node-fetch@^2.5.12": - version "2.5.12" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" - integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== +"@types/node-fetch@^2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" + integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== dependencies: "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@14.17.33", "@types/node@^14.6.2": - version "14.17.33" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.33.tgz#011ee28e38dc7aee1be032ceadf6332a0ab15b12" - integrity sha512-noEeJ06zbn3lOh4gqe2v7NMGS33jrulfNqYFDjjEbhpDEHR5VTxgYNQSBqBlJIsBJW3uEYDgD6kvMnrrhGzq8g== +"@types/node@*", "@types/node@14.18.12", "@types/node@^14.6.2": + version "14.18.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" + integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== "@types/node@^10.12.0": version "10.17.24" @@ -1943,10 +1931,10 @@ "@types/mime" "^1" "@types/node" "*" -"@types/sharp@^0.29.4": - version "0.29.4" - resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.29.4.tgz#e47d8677befc9944d4b9d76ed837452814166de0" - integrity sha512-asrPef2LYenr76zBzyy+Fw40yGzq/q/CY77mUP5n43DnuWjQoOB+8vxnzFcqccz+LF+A7mbnknGCfpVWSG82Bw== +"@types/sharp@^0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.30.0.tgz#58cb016c8fdc558b4c5771ad1f3668336685c843" + integrity sha512-bZ0Y/JVlrOyqwlBMJ2taEgnwFavjLnyZmLOLecmOesuG5kR2Lx9b2fM4osgfVjLJi8UlE+t3R1JzRVMxF6MbfA== dependencies: "@types/node" "*" @@ -3302,14 +3290,6 @@ buffer@^5.1.0, buffer@^5.5.0: base64-js "^1.0.2" ieee754 "^1.1.4" -builder-util-runtime@8.9.1: - version "8.9.1" - resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.1.tgz#25f066b3fbc20b3e6236a9b956b1ebb0e33ff66a" - integrity sha512-c8a8J3wK6BIVLW7ls+7TRK9igspTbzWmUqxFbgK0m40Ggm6efUbxtWVCGIjc+dtchyr5qAMAUL6iEGRdS/6vwg== - dependencies: - debug "^4.3.2" - sax "^1.2.4" - builder-util-runtime@8.9.2: version "8.9.2" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz#a9669ae5b5dcabfe411ded26678e7ae997246c28" @@ -3860,7 +3840,7 @@ colors@1.0.3: resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= -colors@^1.1.2, colors@^1.4.0: +colors@1.4.0, colors@^1.1.2, colors@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -3895,6 +3875,11 @@ commander@2.9.0: dependencies: graceful-readlink ">= 1.0.0" +commander@8.3.0, commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + commander@^2.20.0, commander@~2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -3910,11 +3895,6 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^8.2.0, commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -4389,6 +4369,13 @@ debug@4.3.1: dependencies: ms "2.1.2" +debug@4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -4396,7 +4383,7 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" -debuglog@^1.0.1: +debuglog@*, debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= @@ -4924,13 +4911,13 @@ electron-to-chromium@^1.4.17: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.57.tgz#2b2766df76ac8dbc0a1d41249bc5684a31849892" integrity sha512-FNC+P5K1n6pF+M0zIK+gFCoXcJhhzDViL3DRIGy2Fv5PohuSES1JHR7T+GlwxSxlzx4yYbsuzCZvHxcBSRCIOw== -electron-updater@^4.6.1: - version "4.6.1" - resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.1.tgz#80ca805c4f51b2e682aac29d18fed75d6a533d32" - integrity sha512-YsU1mHqXLrXXmBMsxhxy24PrbaB8rnpZDPmFa2gOkTYk/Ch13+R0fjsRSpPYvqtskVVY0ux8fu+HnUkVkqc7og== +electron-updater@^4.6.5: + version "4.6.5" + resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.5.tgz#e9a75458bbfd6bb41a58a829839e150ad2eb2d3d" + integrity sha512-kdTly8O9mSZfm9fslc1mnCY+mYOeaYRy7ERa2Fed240u01BKll3aiupzkd07qKw69KvhBSzuHroIW3mF0D8DWA== dependencies: "@types/semver" "^7.3.6" - builder-util-runtime "8.9.1" + builder-util-runtime "8.9.2" fs-extra "^10.0.0" js-yaml "^4.1.0" lazy-val "^1.0.5" @@ -5004,15 +4991,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.0.0: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -enhanced-resolve@^5.9.2: +enhanced-resolve@^5.0.0, enhanced-resolve@^5.9.2: version "5.9.2" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9" integrity sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA== @@ -5142,120 +5121,75 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -esbuild-android-arm64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz#3fc3ff0bab76fe35dd237476b5d2b32bb20a3d44" - integrity sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg== +esbuild-android-64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.27.tgz#b868bbd9955a92309c69df628d8dd1945478b45c" + integrity sha512-LuEd4uPuj/16Y8j6kqy3Z2E9vNY9logfq8Tq+oTE2PZVuNs3M1kj5Qd4O95ee66yDGb3isaOCV7sOLDwtMfGaQ== -esbuild-android-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.14.tgz#3705f32f209deeb11c275af47c298c8783dd5f0c" - integrity sha512-be/Uw6DdpQiPfula1J4bdmA+wtZ6T3BRCZsDMFB5X+k0Gp8TIh9UvmAcqvKNnbRAafSaXG3jPCeXxDKqnc8hFQ== +esbuild-android-arm64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.27.tgz#e7d6430555e8e9c505fd87266bbc709f25f1825c" + integrity sha512-E8Ktwwa6vX8q7QeJmg8yepBYXaee50OdQS3BFtEHKrzbV45H4foMOeEE7uqdjGQZFBap5VAqo7pvjlyA92wznQ== -esbuild-darwin-64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz#8e9169c16baf444eacec60d09b24d11b255a8e72" - integrity sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ== +esbuild-darwin-64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.27.tgz#4dc7484127564e89b4445c0a560a3cb50b3d68e1" + integrity sha512-czw/kXl/1ZdenPWfw9jDc5iuIYxqUxgQ/Q+hRd4/3udyGGVI31r29LCViN2bAJgGvQkqyLGVcG03PJPEXQ5i2g== -esbuild-darwin-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.14.tgz#c07e4eae6d938300a2d330ea82494c55bcea84e5" - integrity sha512-BEexYmjWafcISK8cT6O98E3TfcLuZL8DKuubry6G54n2+bD4GkoRD6HYUOnCkfl2p7jodA+s4369IjSFSWjtHg== +esbuild-darwin-arm64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.27.tgz#469e59c665f84a8ed323166624c5e7b9b2d22ac1" + integrity sha512-BEsv2U2U4o672oV8+xpXNxN9bgqRCtddQC6WBh4YhXKDcSZcdNh7+6nS+DM2vu7qWIWNA4JbRG24LUUYXysimQ== -esbuild-darwin-arm64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz#1b07f893b632114f805e188ddfca41b2b778229a" - integrity sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ== +esbuild-freebsd-64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.27.tgz#895df03bf5f87094a56c9a5815bf92e591903d70" + integrity sha512-7FeiFPGBo+ga+kOkDxtPmdPZdayrSzsV9pmfHxcyLKxu+3oTcajeZlOO1y9HW+t5aFZPiv7czOHM4KNd0tNwCA== -esbuild-darwin-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.14.tgz#a8631e13a51a6f784fb0906e2a64c6ab53988755" - integrity sha512-tnBKm41pDOB1GtZ8q/w26gZlLLRzVmP8fdsduYjvM+yFD7E2DLG4KbPAqFMWm4Md9B+DitBglP57FY7AznxbTg== +esbuild-freebsd-arm64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.27.tgz#0b72a41a6b8655e9a8c5608f2ec1afdcf6958441" + integrity sha512-8CK3++foRZJluOWXpllG5zwAVlxtv36NpHfsbWS7TYlD8S+QruXltKlXToc/5ZNzBK++l6rvRKELu/puCLc7jA== -esbuild-freebsd-64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz#0b8b7eca1690c8ec94c75680c38c07269c1f4a85" - integrity sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA== +esbuild-linux-32@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.27.tgz#43b8ba3803b0bbe7f051869c6a8bf6de1e95de28" + integrity sha512-qhNYIcT+EsYSBClZ5QhLzFzV5iVsP1YsITqblSaztr3+ZJUI+GoK8aXHyzKd7/CKKuK93cxEMJPpfi1dfsOfdw== -esbuild-freebsd-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.14.tgz#c280c2b944746b27ee6c6487c2691865c90bed2e" - integrity sha512-Q9Rx6sgArOHalQtNwAaIzJ6dnQ8A+I7f/RsQsdkS3JrdzmnlFo8JEVofTmwVQLoIop7OKUqIVOGP4PoQcwfVMA== +esbuild-linux-64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.27.tgz#dc8072097327ecfadba1735562824ce8c05dd0bd" + integrity sha512-ESjck9+EsHoTaKWlFKJpPZRN26uiav5gkI16RuI8WBxUdLrrAlYuYSndxxKgEn1csd968BX/8yQZATYf/9+/qg== -esbuild-freebsd-arm64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz#2e1a6c696bfdcd20a99578b76350b41db1934e52" - integrity sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ== +esbuild-linux-arm64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.27.tgz#c52b58cbe948426b1559910f521b0a3f396f10b8" + integrity sha512-no6Mi17eV2tHlJnqBHRLekpZ2/VYx+NfGxKcBE/2xOMYwctsanCaXxw4zapvNrGE9X38vefVXLz6YCF8b1EHiQ== -esbuild-freebsd-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.14.tgz#aa4e21276efcf20e5ab2487e91ca1d789573189b" - integrity sha512-TJvq0OpLM7BkTczlyPIphcvnwrQwQDG1HqxzoYePWn26SMUAlt6wrLnEvxdbXAvNvDLVzG83kA+JimjK7aRNBA== +esbuild-linux-arm@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.27.tgz#df869dbd67d4ee3a04b3c7273b6bd2b233e78a18" + integrity sha512-JnnmgUBdqLQO9hoNZQqNHFWlNpSX82vzB3rYuCJMhtkuaWQEmQz6Lec1UIxJdC38ifEghNTBsF9bbe8dFilnCw== -esbuild-linux-32@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz#6fd39f36fc66dd45b6b5f515728c7bbebc342a69" - integrity sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g== +esbuild-linux-mips64le@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.27.tgz#a2b646d9df368b01aa970a7b8968be6dd6b01d19" + integrity sha512-NolWP2uOvIJpbwpsDbwfeExZOY1bZNlWE/kVfkzLMsSgqeVcl5YMen/cedRe9mKnpfLli+i0uSp7N+fkKNU27A== -esbuild-linux-32@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.14.tgz#3db4d929239203ce38a9060d5419ac6a6d28846c" - integrity sha512-h/CrK9Baimt5VRbu8gqibWV7e1P9l+mkanQgyOgv0Ng3jHT1NVFC9e6rb1zbDdaJVmuhWX5xVliUA5bDDCcJeg== +esbuild-linux-ppc64le@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.27.tgz#9a21af766a0292578a3009c7408b8509cac7cefd" + integrity sha512-/7dTjDvXMdRKmsSxKXeWyonuGgblnYDn0MI1xDC7J1VQXny8k1qgNp6VmrlsawwnsymSUUiThhkJsI+rx0taNA== -esbuild-linux-64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz#9cb8e4bcd7574e67946e4ee5f1f1e12386bb6dd3" - integrity sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA== +esbuild-linux-riscv64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.27.tgz#344a27f91568056a5903ad5841b447e00e78d740" + integrity sha512-D+aFiUzOJG13RhrSmZgrcFaF4UUHpqj7XSKrIiCXIj1dkIkFqdrmqMSOtSs78dOtObWiOrFCDDzB24UyeEiNGg== -esbuild-linux-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.14.tgz#f880026254c1f565a7a10fdebb7cff9b083a127d" - integrity sha512-IC+wAiIg/egp5OhQp4W44D9PcBOH1b621iRn1OXmlLzij9a/6BGr9NMIL4CRwz4j2kp3WNZu5sT473tYdynOuQ== - -esbuild-linux-arm64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz#3891aa3704ec579a1b92d2a586122e5b6a2bfba1" - integrity sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA== - -esbuild-linux-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.14.tgz#a34bc3076e50b109c3b8c8bad9c146e35942322b" - integrity sha512-6QVul3RI4M5/VxVIRF/I5F+7BaxzR3DfNGoqEVSCZqUbgzHExPn+LXr5ly1C7af2Kw4AHpo+wDqx8A4ziP9avw== - -esbuild-linux-arm@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz#8a00e99e6a0c6c9a6b7f334841364d8a2b4aecfe" - integrity sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA== - -esbuild-linux-arm@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.14.tgz#231ffd12fef69ee06365d4c94b69850e4830e927" - integrity sha512-gxpOaHOPwp7zSmcKYsHrtxabScMqaTzfSQioAMUaB047YiMuDBzqVcKBG8OuESrYkGrL9DDljXr/mQNg7pbdaQ== - -esbuild-linux-mips64le@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz#36b07cc47c3d21e48db3bb1f4d9ef8f46aead4f7" - integrity sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg== - -esbuild-linux-mips64le@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.14.tgz#bd00570e3a30422224b732c7a5f262146c357403" - integrity sha512-4Jl5/+xoINKbA4cesH3f4R+q0vltAztZ6Jm8YycS8lNhN1pgZJBDxWfI6HUMIAdkKlIpR1PIkA9aXQgZ8sxFAg== - -esbuild-linux-ppc64le@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz#f7e6bba40b9a11eb9dcae5b01550ea04670edad2" - integrity sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ== - -esbuild-linux-ppc64le@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.14.tgz#430609413fd9e04d9def4e3f06726b031b23d825" - integrity sha512-BitW37GxeebKxqYNl4SVuSdnIJAzH830Lr6Mkq3pBHXtzQay0vK+IeOR/Ele1GtNVJ+/f8wYM53tcThkv5SC5w== - -esbuild-linux-s390x@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.14.tgz#2f0d8cbfe53cf3cb97f6372549a41a8051dbd689" - integrity sha512-vLj6p76HOZG3wfuTr5MyO3qW5iu8YdhUNxuY+tx846rPo7GcKtYSPMusQjeVEfZlJpSYoR+yrNBBxq+qVF9zrw== +esbuild-linux-s390x@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.27.tgz#73a7309bd648a07ef58f069658f989a5096130db" + integrity sha512-CD/D4tj0U4UQjELkdNlZhQ8nDHU5rBn6NGp47Hiz0Y7/akAY5i0oGadhEIg0WCY/HYVXFb3CsSPPwaKcTOW3bg== esbuild-loader@^2.18.0: version "2.18.0" @@ -5269,112 +5203,61 @@ esbuild-loader@^2.18.0: tapable "^2.2.0" webpack-sources "^2.2.0" -esbuild-netbsd-64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz#a2fedc549c2b629d580a732d840712b08d440038" - integrity sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w== +esbuild-netbsd-64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.27.tgz#482a587cdbd18a6c264a05136596927deb46c30a" + integrity sha512-h3mAld69SrO1VoaMpYl3a5FNdGRE/Nqc+E8VtHOag4tyBwhCQXxtvDDOAKOUQexBGca0IuR6UayQ4ntSX5ij1Q== -esbuild-netbsd-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.14.tgz#3e44de35e1add7e9582f3c0d2558d86aafbc813b" - integrity sha512-fn8looXPQhpVqUyCBWUuPjesH+yGIyfbIQrLKG05rr1Kgm3rZD/gaYrd3Wpmf5syVZx70pKZPvdHp8OTA+y7cQ== +esbuild-openbsd-64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.27.tgz#e99f8cdc63f1628747b63edd124d53cf7796468d" + integrity sha512-xwSje6qIZaDHXWoPpIgvL+7fC6WeubHHv18tusLYMwL+Z6bEa4Pbfs5IWDtQdHkArtfxEkIZz77944z8MgDxGw== -esbuild-openbsd-64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz#b22c0e5806d3a1fbf0325872037f885306b05cd7" - integrity sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g== +esbuild-sunos-64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.27.tgz#8611d825bcb8239c78d57452e83253a71942f45c" + integrity sha512-/nBVpWIDjYiyMhuqIqbXXsxBc58cBVH9uztAOIfWShStxq9BNBik92oPQPJ57nzWXRNKQUEFWr4Q98utDWz7jg== -esbuild-openbsd-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.14.tgz#04710ef1d01cd9f15d54f50d20b5a3778f8306a2" - integrity sha512-HdAnJ399pPff3SKbd8g+P4o5znseni5u5n5rJ6Z7ouqOdgbOwHe2ofZbMow17WMdNtz1IyOZk2Wo9Ve6/lZ4Rg== +esbuild-windows-32@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.27.tgz#c06374206d4d92dd31d4fda299b09f51a35e82f6" + integrity sha512-Q9/zEjhZJ4trtWhFWIZvS/7RUzzi8rvkoaS9oiizkHTTKd8UxFwn/Mm2OywsAfYymgUYm8+y2b+BKTNEFxUekw== -esbuild-sunos-64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz#d0b6454a88375ee8d3964daeff55c85c91c7cef4" - integrity sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw== +esbuild-windows-64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.27.tgz#756631c1d301dfc0d1a887deed2459ce4079582f" + integrity sha512-b3y3vTSl5aEhWHK66ngtiS/c6byLf6y/ZBvODH1YkBM+MGtVL6jN38FdHUsZasCz9gFwYs/lJMVY9u7GL6wfYg== -esbuild-sunos-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.14.tgz#8e583dd92c5c7ac4303ddc37f588e44211e04e19" - integrity sha512-bmDHa99ulsGnYlh/xjBEfxoGuC8CEG5OWvlgD+pF7bKKiVTbtxqVCvOGEZeoDXB+ja6AvHIbPxrEE32J+m5nqQ== +esbuild-windows-arm64@0.14.27: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.27.tgz#ad7e187193dcd18768b16065a950f4441d7173f4" + integrity sha512-I/reTxr6TFMcR5qbIkwRGvldMIaiBu2+MP0LlD7sOlNXrfqIl9uNjsuxFPGEG4IRomjfQ5q8WT+xlF/ySVkqKg== -esbuild-windows-32@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz#c96d0b9bbb52f3303322582ef8e4847c5ad375a7" - integrity sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw== - -esbuild-windows-32@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.14.tgz#6d293ddfb71229f21cc13d85d5d2f43e8131693b" - integrity sha512-6tVooQcxJCNenPp5GHZBs/RLu31q4B+BuF4MEoRxswT+Eq2JGF0ZWDRQwNKB8QVIo3t6Svc5wNGez+CwKNQjBg== - -esbuild-windows-64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz#1f79cb9b1e1bb02fb25cd414cb90d4ea2892c294" - integrity sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ== - -esbuild-windows-64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.14.tgz#08a36844b69542f8ec1cb33a5ddcea02b9d0b2e8" - integrity sha512-kl3BdPXh0/RD/dad41dtzj2itMUR4C6nQbXQCyYHHo4zoUoeIXhpCrSl7BAW1nv5EFL8stT1V+TQVXGZca5A2A== - -esbuild-windows-arm64@0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz#482173070810df22a752c686509c370c3be3b3c3" - integrity sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA== - -esbuild-windows-arm64@0.14.14: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.14.tgz#ca747ce4066d5b8a79dbe48fe6ecd92d202e5366" - integrity sha512-dCm1wTOm6HIisLanmybvRKvaXZZo4yEVrHh1dY0v582GThXJOzuXGja1HIQgV09RpSHYRL3m4KoUBL00l6SWEg== - -esbuild@^0.13.15: - version "0.13.15" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.15.tgz#db56a88166ee373f87dbb2d8798ff449e0450cdf" - integrity sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw== +esbuild@^0.14.27, esbuild@^0.14.6: + version "0.14.27" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.27.tgz#41fe0f1b6b68b9f77cac025009bc54bb96e616f1" + integrity sha512-MZQt5SywZS3hA9fXnMhR22dv0oPGh6QtjJRIYbgL1AeqAoQZE+Qn5ppGYQAoHv/vq827flj4tIJ79Mrdiwk46Q== optionalDependencies: - esbuild-android-arm64 "0.13.15" - esbuild-darwin-64 "0.13.15" - esbuild-darwin-arm64 "0.13.15" - esbuild-freebsd-64 "0.13.15" - esbuild-freebsd-arm64 "0.13.15" - esbuild-linux-32 "0.13.15" - esbuild-linux-64 "0.13.15" - esbuild-linux-arm "0.13.15" - esbuild-linux-arm64 "0.13.15" - esbuild-linux-mips64le "0.13.15" - esbuild-linux-ppc64le "0.13.15" - esbuild-netbsd-64 "0.13.15" - esbuild-openbsd-64 "0.13.15" - esbuild-sunos-64 "0.13.15" - esbuild-windows-32 "0.13.15" - esbuild-windows-64 "0.13.15" - esbuild-windows-arm64 "0.13.15" - -esbuild@^0.14.6: - version "0.14.14" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.14.tgz#3b99f20d628013c3e2ae90e67687e03f1d6eb071" - integrity sha512-aiK4ddv+uui0k52OqSHu4xxu+SzOim7Rlz4i25pMEiC8rlnGU0HJ9r+ZMfdWL5bzifg+nhnn7x4NSWTeehYblg== - optionalDependencies: - esbuild-android-arm64 "0.14.14" - esbuild-darwin-64 "0.14.14" - esbuild-darwin-arm64 "0.14.14" - esbuild-freebsd-64 "0.14.14" - esbuild-freebsd-arm64 "0.14.14" - esbuild-linux-32 "0.14.14" - esbuild-linux-64 "0.14.14" - esbuild-linux-arm "0.14.14" - esbuild-linux-arm64 "0.14.14" - esbuild-linux-mips64le "0.14.14" - esbuild-linux-ppc64le "0.14.14" - esbuild-linux-s390x "0.14.14" - esbuild-netbsd-64 "0.14.14" - esbuild-openbsd-64 "0.14.14" - esbuild-sunos-64 "0.14.14" - esbuild-windows-32 "0.14.14" - esbuild-windows-64 "0.14.14" - esbuild-windows-arm64 "0.14.14" + esbuild-android-64 "0.14.27" + esbuild-android-arm64 "0.14.27" + esbuild-darwin-64 "0.14.27" + esbuild-darwin-arm64 "0.14.27" + esbuild-freebsd-64 "0.14.27" + esbuild-freebsd-arm64 "0.14.27" + esbuild-linux-32 "0.14.27" + esbuild-linux-64 "0.14.27" + esbuild-linux-arm "0.14.27" + esbuild-linux-arm64 "0.14.27" + esbuild-linux-mips64le "0.14.27" + esbuild-linux-ppc64le "0.14.27" + esbuild-linux-riscv64 "0.14.27" + esbuild-linux-s390x "0.14.27" + esbuild-netbsd-64 "0.14.27" + esbuild-openbsd-64 "0.14.27" + esbuild-sunos-64 "0.14.27" + esbuild-windows-32 "0.14.27" + esbuild-windows-64 "0.14.27" + esbuild-windows-arm64 "0.14.27" escalade@^3.1.1: version "3.1.1" @@ -5830,17 +5713,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@^1.0.3: - version "1.7.0" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" - integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== - dependencies: - concat-stream "^1.6.2" - debug "^2.6.9" - mkdirp "^0.5.4" - yauzl "^2.10.0" - -extract-zip@^2.0.1: +extract-zip@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== @@ -5851,6 +5724,16 @@ extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +extract-zip@^1.0.3: + version "1.7.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" + integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + dependencies: + concat-stream "^1.6.2" + debug "^2.6.9" + mkdirp "^0.5.4" + yauzl "^2.10.0" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -5866,10 +5749,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.1.1, fast-glob@^3.2.11: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -6555,12 +6438,7 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== - -graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== @@ -6903,6 +6781,14 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + https-proxy-agent@^2.2.3: version "2.2.4" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" @@ -6911,14 +6797,6 @@ https-proxy-agent@^2.2.3: agent-base "^4.3.0" debug "^3.1.0" -https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -7022,10 +6900,10 @@ immediate@~3.0.5: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= -immer@^9.0.6: - version "9.0.6" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73" - integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ== +immer@^9.0.12: + version "9.0.12" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" + integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== immutable@^4.0.0: version "4.0.0" @@ -7067,7 +6945,7 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" -imurmurhash@^0.1.4: +imurmurhash@*, imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= @@ -8140,7 +8018,7 @@ joycon@^3.0.1: resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.0.1.tgz#9074c9b08ccf37a6726ff74a18485f85efcaddaf" integrity sha512-SJcJNBg32dGgxhPtM0wQqxqV0ax9k/9TaUskGDSJkSFSQOEWWvQ3zzWdGQRIUry2j1zA5+ReH13t0Mf3StuVZA== -jpeg-js@^0.4.2: +jpeg-js@0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b" integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q== @@ -8788,6 +8666,11 @@ lodash-es@^4.17.21: resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== +lodash._baseindexof@*: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" + integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw= + lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -8796,11 +8679,33 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" +lodash._bindcallback@*: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" + integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4= + +lodash._cacheindexof@*: + version "3.0.2" + resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" + integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI= + +lodash._createcache@*: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" + integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM= + dependencies: + lodash._getnative "^3.0.0" + lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= +lodash._getnative@*, lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= + lodash._root@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" @@ -8831,6 +8736,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.restparam@*: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= + lodash.union@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" @@ -9100,15 +9010,7 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.0, micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -micromatch@^4.0.4: +micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== @@ -9145,7 +9047,12 @@ mime@1.6.0, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.6, mime@^2.5.2: +mime@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + +mime@^2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== @@ -9208,9 +9115,9 @@ minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: brace-expansion "^1.1.7" minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" @@ -9513,10 +9420,10 @@ node-forge@^0.10.0: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== -node-forge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" - integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== +node-forge@^1.2.0, node-forge@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2" + integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA== node-gyp@7.1.2: version "7.1.2" @@ -9790,10 +9697,10 @@ npm-user-validate@^1.0.1: resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.1.tgz#31428fc5475fe8416023f178c0ab47935ad8c561" integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw== -npm@^6.14.15: - version "6.14.15" - resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.15.tgz#97dd51af5b5d6225b611b40c5cb4d31da1d467fe" - integrity sha512-dkcQc4n+DiJAMYG2haNAMyJbmuvevjXz+WC9dCUzodw8EovwTIc6CATSsTEplCY6c0jG4OshxFGFJsrnKJguWA== +npm@^6.14.16: + version "6.14.16" + resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.16.tgz#a882d6b0b32d5212461f0c58719152add1a7b99a" + integrity sha512-LMiLGYsVNJfVPlQg7v2NYjG7iRIapcLv+oMunlq7fkXVx0BATCjRu7XyWl0G+iuZzHy4CjtM32QB8ox8juTgaw== dependencies: JSONStream "^1.3.5" abbrev "~1.1.1" @@ -9813,6 +9720,7 @@ npm@^6.14.15: cmd-shim "^3.0.3" columnify "~1.5.4" config-chain "^1.1.12" + debuglog "*" detect-indent "~5.0.0" detect-newline "^2.1.0" dezalgo "~1.0.3" @@ -9827,6 +9735,7 @@ npm@^6.14.15: has-unicode "~2.0.1" hosted-git-info "^2.8.9" iferr "^1.0.2" + imurmurhash "*" infer-owner "^1.0.4" inflight "~1.0.6" inherits "^2.0.4" @@ -9845,8 +9754,14 @@ npm@^6.14.15: libnpx "^10.2.4" lock-verify "^2.1.0" lockfile "^1.0.4" + lodash._baseindexof "*" lodash._baseuniq "~4.6.0" + lodash._bindcallback "*" + lodash._cacheindexof "*" + lodash._createcache "*" + lodash._getnative "*" lodash.clonedeep "~4.5.0" + lodash.restparam "*" lodash.union "~4.6.0" lodash.uniq "~4.5.0" lodash.without "~4.4.0" @@ -10512,7 +10427,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: +picomatch@^2.0.4, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -10544,6 +10459,13 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" +pixelmatch@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-5.2.1.tgz#9e4e4f4aa59648208a31310306a5bed5522b0d65" + integrity sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ== + dependencies: + pngjs "^4.0.1" + pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -10558,47 +10480,54 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -playwright-core@=1.17.1: - version "1.17.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.17.1.tgz#a16e0f89284a0ed8ae6d77e1c905c84b8a2ba022" - integrity sha512-C3c8RpPiC3qr15fRDN6dx6WnUkPLFmST37gms2aoHPDRvp7EaGDPMMZPpqIm/QWB5J40xDrQCD4YYHz2nBTojQ== +playwright-core@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.20.1.tgz#2d892964dd3ddc93f6e185be4b59621f3a339d4c" + integrity sha512-A8ZsZ09gaSbxP0UijoLyzp3LJc0kWMxDooLPi+mm4/5iYnTbd6PF5nKjoFw1a7KwjZIEgdhJduah4BcUIh+IPA== dependencies: - commander "^8.2.0" - debug "^4.1.1" - extract-zip "^2.0.1" - https-proxy-agent "^5.0.0" - jpeg-js "^0.4.2" - mime "^2.4.6" - pngjs "^5.0.0" - progress "^2.0.3" - proper-lockfile "^4.1.1" - proxy-from-env "^1.1.0" - rimraf "^3.0.2" - socks-proxy-agent "^6.1.0" - stack-utils "^2.0.3" - ws "^7.4.6" - yauzl "^2.10.0" - yazl "^2.5.1" + colors "1.4.0" + commander "8.3.0" + debug "4.3.3" + extract-zip "2.0.1" + https-proxy-agent "5.0.0" + jpeg-js "0.4.3" + mime "3.0.0" + pixelmatch "5.2.1" + pngjs "6.0.0" + progress "2.0.3" + proper-lockfile "4.1.2" + proxy-from-env "1.1.0" + rimraf "3.0.2" + socks-proxy-agent "6.1.1" + stack-utils "2.0.5" + ws "8.4.2" + yauzl "2.10.0" + yazl "2.5.1" -playwright@^1.17.1: - version "1.17.1" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.17.1.tgz#a6d63302ee40f41283c4bf869de261c4743a787c" - integrity sha512-DisCkW9MblDJNS3rG61p8LiLA2WA7IY/4A4W7DX4BphWe/HuWjKmGQptuk4NVIh5UuSwXpW/jaH2+ZgjHs3GMA== +playwright@^1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.20.1.tgz#2796c7d4de10afd39d2ca741a754565291803d4d" + integrity sha512-d/25SFUk6Rkt3h+RU13T7h6o0UTCLKXKYJILWVlC+NmrE7Tvn3LlXxoREfFXVNFikRZWTV60WBCZKgNbj7RfrA== dependencies: - playwright-core "=1.17.1" + playwright-core "1.20.1" plist@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.4.tgz#a62df837e3aed2bb3b735899d510c4f186019cbe" - integrity sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg== + version "3.0.5" + resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.5.tgz#2cbeb52d10e3cdccccf0c11a63a85d830970a987" + integrity sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA== dependencies: base64-js "^1.5.1" xmlbuilder "^9.0.7" -pngjs@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" - integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== +pngjs@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821" + integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg== + +pngjs@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-4.0.1.tgz#f803869bb2fc1bfe1bf99aa4ec21c108117cfdbe" + integrity sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg== popper.js@1.16.1-lts: version "1.16.1-lts" @@ -10646,13 +10575,12 @@ postcss-icss-selectors@^2.0.3: lodash "^4.17.4" postcss "^6.0.2" -postcss-js@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-3.0.3.tgz#2f0bd370a2e8599d45439f6970403b5873abda33" - integrity sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw== +postcss-js@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00" + integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ== dependencies: camelcase-css "^2.0.1" - postcss "^8.1.6" postcss-load-config@^3.0.1, postcss-load-config@^3.1.0: version "3.1.0" @@ -10707,18 +10635,10 @@ postcss-nested@5.0.6: dependencies: postcss-selector-parser "^6.0.6" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" - integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-selector-parser@^6.0.7: - version "6.0.7" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.7.tgz#48404830a635113a71fd79397de8209ed05a66fc" - integrity sha512-U+b/Deoi4I/UmE6KOVPpnhS7I7AYdKbhGcat+qTQ27gycvaACvNEw11ba6RrkwVmDVRW7sigWgLj4/KbbJjeDA== +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9: + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -10742,7 +10662,7 @@ postcss@^6.0.14, postcss@^6.0.2: source-map "^0.6.1" supports-color "^5.4.0" -postcss@^8.1.6, postcss@^8.3.0, postcss@^8.4.12, postcss@^8.4.7: +postcss@^8.3.0, postcss@^8.4.12, postcss@^8.4.6, postcss@^8.4.7: version "8.4.12" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905" integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg== @@ -10823,7 +10743,7 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@^2.0.3: +progress@2.0.3, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -10870,6 +10790,15 @@ prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +proper-lockfile@4.1.2, proper-lockfile@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + proper-lockfile@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-1.2.0.tgz#ceff5dd89d3e5f10fb75e1e8e76bc75801a59c34" @@ -10880,15 +10809,6 @@ proper-lockfile@^1.2.0: graceful-fs "^4.1.2" retry "^0.10.0" -proper-lockfile@^4.1.1, proper-lockfile@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" - integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== - dependencies: - graceful-fs "^4.2.4" - retry "^0.12.0" - signal-exit "^3.0.2" - proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" @@ -10909,7 +10829,7 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-from-env@^1.1.0: +proxy-from-env@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== @@ -11584,24 +11504,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6: - version "1.21.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f" - integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA== - dependencies: - is-core-module "^2.8.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.18.1, resolve@^1.20.0, resolve@^1.3.2: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -resolve@^1.9.0: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.18.1, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.3.2, resolve@^1.9.0: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== @@ -11667,6 +11570,13 @@ rfc6902@^4.0.2: resolved "https://registry.yarnpkg.com/rfc6902/-/rfc6902-4.0.2.tgz#ce99d3562b9e3287d403462e6bcc81eead8fcea0" integrity sha512-MJOC4iDSv3Qn5/QvhPbrNoRongti6moXSShcRmtbNqOk0WPxlviEdMV4bb9PaULhSxLUXzWd4AjAMKQ3j3y54w== +rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -11674,13 +11584,6 @@ rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: dependencies: glob "^7.1.3" -rimraf@^3.0.0, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - roarr@^2.15.3: version "2.15.3" resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.3.tgz#65248a291a15af3ebfd767cbf7e44cb402d1d836" @@ -11774,18 +11677,10 @@ sass-loader@^12.6.0: klona "^2.0.4" neo-async "^2.6.2" -sass@^1.32.13: - version "1.44.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.44.0.tgz#619aa0a2275c097f9af5e6b8fe8a95e3056430fb" - integrity sha512-0hLREbHFXGQqls/K8X+koeP+ogFRPF4ZqetVB19b7Cst9Er8cOR0rc6RU7MaI4W1JmUShd1BPgPoeqmmgMMYFw== - dependencies: - chokidar ">=3.0.0 <4.0.0" - immutable "^4.0.0" - -sass@^1.45.1: - version "1.45.1" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.45.1.tgz#fa03951f924d1ba5762949567eaf660e608a1ab0" - integrity sha512-pwPRiq29UR0o4X3fiQyCtrESldXvUQAAE0QmcJTpsI4kuHHcLzZ54M1oNBVIXybQv8QF2zfkpFcTxp8ta97dUA== +sass@^1.32.13, sass@^1.49.9: + version "1.49.9" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.49.9.tgz#b15a189ecb0ca9e24634bae5d1ebc191809712f9" + integrity sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A== dependencies: chokidar ">=3.0.0 <4.0.0" immutable "^4.0.0" @@ -12158,15 +12053,7 @@ sockjs@^0.3.21: uuid "^8.3.2" websocket-driver "^0.7.4" -socks-proxy-agent@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386" - integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg== - dependencies: - agent-base "~4.2.1" - socks "~2.3.2" - -socks-proxy-agent@^6.1.0: +socks-proxy-agent@6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== @@ -12175,6 +12062,14 @@ socks-proxy-agent@^6.1.0: debug "^4.3.1" socks "^2.6.1" +socks-proxy-agent@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386" + integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg== + dependencies: + agent-base "~4.2.1" + socks "~2.3.2" + socks@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" @@ -12379,7 +12274,14 @@ stack-trace@0.0.x: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= -stack-utils@^2.0.2, stack-utils@^2.0.3: +stack-utils@2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + dependencies: + escape-string-regexp "^2.0.0" + +stack-utils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== @@ -12725,32 +12627,32 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -tailwindcss@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.7.tgz#15936881f042a7eb8d6f2b6a454bac9f51181bbd" - integrity sha512-rZdKNHtC64jcQncLoWOuCzj4lQDTAgLtgK3WmQS88tTdpHh9OwLqULTQxI3tw9AMJsqSpCKlmcjW/8CSnni6zQ== +tailwindcss@^3.0.23: + version "3.0.23" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10" + integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA== dependencies: arg "^5.0.1" chalk "^4.1.2" - chokidar "^3.5.2" + chokidar "^3.5.3" color-name "^1.1.4" cosmiconfig "^7.0.1" detective "^5.2.0" didyoumean "^1.2.2" dlv "^1.1.3" - fast-glob "^3.2.7" + fast-glob "^3.2.11" glob-parent "^6.0.2" is-glob "^4.0.3" normalize-path "^3.0.0" object-hash "^2.2.0" - postcss-js "^3.0.3" + postcss "^8.4.6" + postcss-js "^4.0.0" postcss-load-config "^3.1.0" postcss-nested "5.0.6" - postcss-selector-parser "^6.0.7" + postcss-selector-parser "^6.0.9" postcss-value-parser "^4.2.0" quick-lru "^5.1.1" - resolve "^1.20.0" - tmp "^0.2.1" + resolve "^1.22.0" tapable@^1.0.0: version "1.1.3" @@ -12960,7 +12862,7 @@ tmp-promise@^3.0.2: dependencies: tmp "^0.2.0" -tmp@^0.2.0, tmp@^0.2.1: +tmp@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== @@ -13093,10 +12995,10 @@ ts-jest@26.5.6: semver "7.x" yargs-parser "20.x" -ts-loader@^9.2.6: - version "9.2.6" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" - integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw== +ts-loader@^9.2.8: + version "9.2.8" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.8.tgz#e89aa32fa829c5cad0a1d023d6b3adecd51d5a48" + integrity sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw== dependencies: chalk "^4.1.0" enhanced-resolve "^5.0.0" @@ -13147,16 +13049,11 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3: +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== -tslib@^2.1.0, tslib@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" - integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -13230,10 +13127,10 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-fest@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" - integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== +type-fest@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.0.tgz#ce342f58cab9114912f54b493d60ab39c3fc82b6" + integrity sha512-Qe5GRT+n/4GoqCNGGVp5Snapg1Omq3V7irBJB3EaKsp7HWDo5Gv2d/67gfNyV+d5EXD+x/RF5l1h4yJ7qNkcGA== type-is@~1.6.18: version "1.6.18" @@ -13302,10 +13199,10 @@ typescript-plugin-css-modules@^3.4.0: stylus "^0.54.8" tsconfig-paths "^3.9.0" -typescript@^4.5.2: - version "4.5.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.2.tgz#8ac1fba9f52256fdb06fb89e4122fa6a346c2998" - integrity sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw== +typescript@^4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== uglify-js@^3.1.4: version "3.9.4" @@ -13884,14 +13781,14 @@ wildcard@^2.0.0: resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== -win-ca@^3.4.5: - version "3.4.5" - resolved "https://registry.yarnpkg.com/win-ca/-/win-ca-3.4.5.tgz#634f5603e3b1c57e273da2334cf849f6c53a61d1" - integrity sha512-2xTLq3jah7Sg8Pt8me2rbTnDMxulrX6gSfU9lscyqjyE4gj34sd9w6LK0v8aNHzow+s0WEX1vve58EixZbXiLg== +win-ca@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/win-ca/-/win-ca-3.5.0.tgz#87fa778d629077651d323169aadf122ff16954e7" + integrity sha512-0TgO/+2iz2pS3OxBy2ikovPHOYyZRdLRxRTT9ze7DpZwEpaahLFOBuac93GM3lYEVzDyf8fXskJjIX/EILvkhQ== dependencies: is-electron "^2.2.0" make-dir "^1.3.0" - node-forge "^0.10.0" + node-forge "^1.2.1" split "^1.0.1" winston-console-format@^1.0.8: @@ -14012,16 +13909,16 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@8.4.2, ws@^8.4.2: + version "8.4.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b" + integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA== + ws@^7.3.1, ws@^7.4.6, ws@^7.5.5: version "7.5.5" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== -ws@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b" - integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA== - xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" @@ -14062,10 +13959,10 @@ xterm-addon-fit@^0.5.0: resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596" integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ== -xterm@^4.15.0: - version "4.15.0" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.15.0.tgz#e52038507eba7e0d36d47f81e29fe548c82b9561" - integrity sha512-Ik1GoSq1yqKZQ2LF37RPS01kX9t4TP8gpamUYblD09yvWX5mEYuMK4CcqH6+plgiNEZduhTz/UrcaWs97gOlOw== +xterm@^4.18.0: + version "4.18.0" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.18.0.tgz#a1f6ab2c330c3918fb094ae5f4c2562987398ea1" + integrity sha512-JQoc1S0dti6SQfI0bK1AZvGnAxH4MVw45ZPFSO6FHTInAiau3Ix77fSxNx3mX4eh9OL4AYa8+4C8f5UvnSfppQ== y18n@^3.2.1: version "3.2.2" @@ -14214,7 +14111,7 @@ yargs@^8.0.2: y18n "^3.2.1" yargs-parser "^7.0.0" -yauzl@^2.10.0: +yauzl@2.10.0, yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= @@ -14222,7 +14119,7 @@ yauzl@^2.10.0: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" -yazl@^2.5.1: +yazl@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==