1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Merge branch 'master' into fix/close-proxy-server-on-app-quit

This commit is contained in:
Lauri Nevala 2020-06-09 18:03:28 +03:00
commit e5b7eb8e95
36 changed files with 782 additions and 214 deletions

View File

@ -44,7 +44,6 @@ jobs:
WIN_CSC_KEY_PASSWORD: $(WIN_CSC_KEY_PASSWORD) WIN_CSC_KEY_PASSWORD: $(WIN_CSC_KEY_PASSWORD)
GH_TOKEN: $(GH_TOKEN) GH_TOKEN: $(GH_TOKEN)
- job: macOS - job: macOS
condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))"
pool: pool:
vmImage: macOS-10.14 vmImage: macOS-10.14
strategy: strategy:
@ -75,7 +74,10 @@ jobs:
displayName: Lint displayName: Lint
- script: make test - script: make test
displayName: Run tests displayName: Run tests
- script: make integration-mac
displayName: Run integration tests
- script: make build - script: make build
condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))"
displayName: Build displayName: Build
env: env:
APPLEID: $(APPLEID) APPLEID: $(APPLEID)
@ -119,6 +121,15 @@ jobs:
displayName: Lint displayName: Lint
- script: make test - script: make test
displayName: Run tests displayName: Run tests
- bash: |
sudo apt-get update
sudo apt-get install libgconf-2-4 conntrack -y
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
sudo minikube start --driver=none
displayName: Install integration test dependencies
- script: xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' make integration-linux
displayName: Run integration tests
- bash: | - bash: |
sudo chown root:root / sudo chown root:root /
sudo apt-get update && sudo apt-get install -y snapd sudo apt-get update && sudo apt-get install -y snapd

View File

@ -6,11 +6,26 @@ endif
.PHONY: dev build test clean .PHONY: dev build test clean
download-bins:
yarn download:bins
dev: app-deps dashboard-deps dev: app-deps dashboard-deps
yarn dev yarn dev
test: test-app test-dashboard test: test-app test-dashboard
integration-linux:
yarn build:linux
yarn integration
integration-mac:
yarn build:mac
yarn integration
integration-win:
yarn build:win
yarn integration
lint: lint:
yarn lint yarn lint

View File

@ -25,6 +25,7 @@ Download a pre-built package from the [releases](https://github.com/lensapp/lens
> Prerequisities: Nodejs v12, make, yarn > Prerequisities: Nodejs v12, make, yarn
* `make download-bins` - downloads bundled binaries to dev environment
* `make dev` - builds and starts the app * `make dev` - builds and starts the app
* `make test` - run tests * `make test` - run tests

View File

@ -198,21 +198,4 @@ export class HelmRelease implements ItemObject {
const chartVersion = versions.find(chartVersion => chartVersion.version === version); const chartVersion = versions.find(chartVersion => chartVersion.version === version);
return chartVersion ? chartVersion.repo : ""; return chartVersion ? chartVersion.repo : "";
} }
getLastVersion(): string | null {
const chartName = this.getChart();
const versions = helmChartStore.versions.get(chartName);
if (!versions) {
return null; // checking new version state
}
if (versions.length) {
return versions[0].version; // versions already sorted when loaded, the first is latest
}
return this.getVersion();
}
hasNewVersion() {
const lastVersion = this.getLastVersion();
return lastVersion && lastVersion !== this.getVersion();
}
} }

View File

@ -105,8 +105,9 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
this.onData.emit(data, res); this.onData.emit(data, res);
this.writeLog({ ...log, data }); this.writeLog({ ...log, data });
return data; return data;
} } else if (log.method === "GET" && res.status === 403) {
else { this.writeLog({ ...log, data });
} else {
const error = new JsonApiErrorParsed(data, this.parseError(data, res)); const error = new JsonApiErrorParsed(data, this.parseError(data, res));
this.onError.emit(error, res); this.onError.emit(error, res);
this.writeLog({ ...log, error }) this.writeLog({ ...log, error })

View File

@ -107,8 +107,12 @@ export class KubeWatchApi {
const { apiBase, namespace } = KubeApi.parseApi(url); const { apiBase, namespace } = KubeApi.parseApi(url);
const api = apiManager.getApi(apiBase); const api = apiManager.getApi(apiBase);
if (api) { if (api) {
await api.refreshResourceVersion({ namespace }); try {
this.reconnect(); await api.refreshResourceVersion({ namespace });
this.reconnect();
} catch(error) {
console.debug("failed to refresh resource version", error)
}
} }
} }
} }

View File

@ -0,0 +1,15 @@
import { configStore } from "../config.store";
import { isArray } from "util";
export function isAllowedResource(resources: string|string[]) {
if (!isArray(resources)) {
resources = [resources];
}
const { allowedResources } = configStore;
for (const resource of resources) {
if (!allowedResources.includes(resource)) {
return false;
}
}
return true;
}

View File

@ -19,7 +19,6 @@ import { AceEditor } from "../ace-editor";
import { Button } from "../button"; import { Button } from "../button";
import { releaseStore } from "./release.store"; import { releaseStore } from "./release.store";
import { Notifications } from "../notifications"; import { Notifications } from "../notifications";
import { Icon } from "../icon";
import { createUpgradeChartTab } from "../dock/upgrade-chart.store"; import { createUpgradeChartTab } from "../dock/upgrade-chart.store";
import { getDetailsUrl } from "../../navigation"; import { getDetailsUrl } from "../../navigation";
import { _i18n } from "../../i18n"; import { _i18n } from "../../i18n";
@ -190,14 +189,12 @@ export class ReleaseDetails extends Component<Props> {
<DrawerItem name={<Trans>Chart</Trans>} className="chart"> <DrawerItem name={<Trans>Chart</Trans>} className="chart">
<div className="flex gaps align-center"> <div className="flex gaps align-center">
<span>{release.getChart()}</span> <span>{release.getChart()}</span>
{release.hasNewVersion() && ( <Button
<Button primary
primary label={_i18n._(t`Upgrade`)}
label={_i18n._(t`Upgrade`)} className="box right upgrade"
className="box right upgrade" onClick={this.upgradeVersion}
onClick={this.upgradeVersion} />
/>
)}
</div> </div>
</DrawerItem> </DrawerItem>
<DrawerItem name={<Trans>Updated</Trans>}> <DrawerItem name={<Trans>Updated</Trans>}>
@ -211,12 +208,6 @@ export class ReleaseDetails extends Component<Props> {
<span> <span>
{release.getVersion()} {release.getVersion()}
</span> </span>
{!release.getLastVersion() && (
<Icon svg="spinner" small/>
)}
{release.hasNewVersion() && (
<span><Trans>New version available:</Trans> <b>{release.getLastVersion()}</b></span>
)}
</div> </div>
</DrawerItem> </DrawerItem>
<DrawerItem name={<Trans>Status</Trans>} className="status" labelsOnly> <DrawerItem name={<Trans>Status</Trans>} className="status" labelsOnly>

View File

@ -37,7 +37,6 @@ export class HelmReleaseMenu extends React.Component<Props> {
const { release, toolbar } = this.props; const { release, toolbar } = this.props;
if (!release) return; if (!release) return;
const hasRollback = release && release.getRevision() > 1; const hasRollback = release && release.getRevision() > 1;
const hasNewVersion = release.hasNewVersion();
return ( return (
<> <>
{hasRollback && ( {hasRollback && (
@ -46,12 +45,6 @@ export class HelmReleaseMenu extends React.Component<Props> {
<span className="title"><Trans>Rollback</Trans></span> <span className="title"><Trans>Rollback</Trans></span>
</MenuItem> </MenuItem>
)} )}
{hasNewVersion && (
<MenuItem onClick={this.upgrade}>
<Icon material="build" interactive={toolbar} title={_i18n._(t`Upgrade`)}/>
<span className="title"><Trans>Upgrade</Trans></span>
</MenuItem>
)}
</> </>
) )
} }

View File

@ -5,9 +5,7 @@ import kebabCase from "lodash/kebabCase";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Trans } from "@lingui/macro"; import { Trans } from "@lingui/macro";
import { RouteComponentProps } from "react-router"; import { RouteComponentProps } from "react-router";
import { autobind, interval } from "../../utils";
import { releaseStore } from "./release.store"; import { releaseStore } from "./release.store";
import { helmChartStore } from "../+apps-helm-charts/helm-chart.store";
import { IReleaseRouteParams, releaseURL } from "./release.route"; import { IReleaseRouteParams, releaseURL } from "./release.route";
import { HelmRelease } from "../../api/endpoints/helm-releases.api"; import { HelmRelease } from "../../api/endpoints/helm-releases.api";
import { ReleaseDetails } from "./release-details"; import { ReleaseDetails } from "./release-details";
@ -15,9 +13,7 @@ import { ReleaseRollbackDialog } from "./release-rollback-dialog";
import { navigation } from "../../navigation"; import { navigation } from "../../navigation";
import { ItemListLayout } from "../item-object-list/item-list-layout"; import { ItemListLayout } from "../item-object-list/item-list-layout";
import { HelmReleaseMenu } from "./release-menu"; import { HelmReleaseMenu } from "./release-menu";
import { Icon } from "../icon";
import { secretsStore } from "../+config-secrets/secrets.store"; import { secretsStore } from "../+config-secrets/secrets.store";
import { when } from "mobx";
enum sortBy { enum sortBy {
name = "name", name = "name",
@ -33,31 +29,16 @@ interface Props extends RouteComponentProps<IReleaseRouteParams> {
@observer @observer
export class HelmReleases extends Component<Props> { export class HelmReleases extends Component<Props> {
private versionsWatcher = interval(3600, this.checkVersions);
componentDidMount() { componentDidMount() {
// Watch for secrets associated with releases and react to their changes // Watch for secrets associated with releases and react to their changes
releaseStore.watch(); releaseStore.watch();
this.versionsWatcher.start();
when(() => releaseStore.isLoaded, this.checkVersions);
} }
componentWillUnmount() { componentWillUnmount() {
releaseStore.unwatch(); releaseStore.unwatch();
this.versionsWatcher.stop();
} }
// Check all available versions every 1 hour for installed releases.
// This required to show "upgrade" icon in the list and upgrade button in the details view.
@autobind()
checkVersions() {
const charts = releaseStore.items.map(release => release.getChart());
return charts.reduce((promise, chartName) => {
const loadVersions = () => helmChartStore.getVersions(chartName, true);
return promise.then(loadVersions, loadVersions);
}, Promise.resolve({}))
};
get selectedRelease() { get selectedRelease() {
const { match: { params: { name, namespace } } } = this.props; const { match: { params: { name, namespace } } } = this.props;
return releaseStore.items.find(release => { return releaseStore.items.find(release => {
@ -130,7 +111,6 @@ export class HelmReleases extends Component<Props> {
]} ]}
renderTableContents={(release: HelmRelease) => { renderTableContents={(release: HelmRelease) => {
const version = release.getVersion(); const version = release.getVersion();
const lastVersion = release.getLastVersion();
return [ return [
release.getName(), release.getName(),
release.getNs(), release.getNs(),
@ -138,20 +118,6 @@ export class HelmReleases extends Component<Props> {
release.getRevision(), release.getRevision(),
<> <>
{version} {version}
{!lastVersion && (
<Icon
small svg="spinner"
className="checking-update"
tooltip={<Trans>Checking update</Trans>}
/>
)}
{release.hasNewVersion() && (
<Icon
material="new_releases"
className="new-version"
tooltip={<Trans>New version: {lastVersion}</Trans>}
/>
)}
</>, </>,
release.appVersion, release.appVersion,
{ title: release.getStatus(), className: kebabCase(release.getStatus()) }, { title: release.getStatus(), className: kebabCase(release.getStatus()) },

View File

@ -13,6 +13,7 @@ import { nodesStore } from "../+nodes/nodes.store";
import { podsStore } from "../+workloads-pods/pods.store"; import { podsStore } from "../+workloads-pods/pods.store";
import { clusterStore } from "./cluster.store"; import { clusterStore } from "./cluster.store";
import { eventStore } from "../+events/event.store"; import { eventStore } from "../+events/event.store";
import { isAllowedResource } from "../../api/rbac";
@observer @observer
export class Cluster extends React.Component { export class Cluster extends React.Component {
@ -25,6 +26,9 @@ export class Cluster extends React.Component {
async componentDidMount() { async componentDidMount() {
const { dependentStores } = this; const { dependentStores } = this;
if (!isAllowedResource("nodes")) {
dependentStores.splice(dependentStores.indexOf(nodesStore), 1)
}
this.watchers.forEach(watcher => watcher.start(true)); this.watchers.forEach(watcher => watcher.start(true));
await Promise.all([ await Promise.all([

View File

@ -9,8 +9,8 @@ import { namespaceStore } from "../+namespaces/namespace.store";
import { resourceQuotaRoute, ResourceQuotas, resourceQuotaURL } from "../+config-resource-quotas"; import { resourceQuotaRoute, ResourceQuotas, resourceQuotaURL } from "../+config-resource-quotas";
import { configURL } from "./config.route"; import { configURL } from "./config.route";
import { HorizontalPodAutoscalers, hpaRoute, hpaURL } from "../+config-autoscalers"; import { HorizontalPodAutoscalers, hpaRoute, hpaURL } from "../+config-autoscalers";
import { Certificates, ClusterIssuers, Issuers } from "../+custom-resources/certmanager.k8s.io";
import { buildURL } from "../../navigation"; import { buildURL } from "../../navigation";
import { isAllowedResource } from "../../api/rbac"
export const certificatesURL = buildURL("/certificates"); export const certificatesURL = buildURL("/certificates");
export const issuersURL = buildURL("/issuers"); export const issuersURL = buildURL("/issuers");
@ -20,32 +20,40 @@ export const clusterIssuersURL = buildURL("/clusterissuers");
export class Config extends React.Component { export class Config extends React.Component {
static get tabRoutes(): TabRoute[] { static get tabRoutes(): TabRoute[] {
const query = namespaceStore.getContextParams() const query = namespaceStore.getContextParams()
return [ const routes: TabRoute[] = []
{ if (isAllowedResource("configmaps")) {
routes.push({
title: <Trans>ConfigMaps</Trans>, title: <Trans>ConfigMaps</Trans>,
component: ConfigMaps, component: ConfigMaps,
url: configMapsURL({ query }), url: configMapsURL({ query }),
path: configMapsRoute.path, path: configMapsRoute.path,
}, })
{ }
if (isAllowedResource("secrets")) {
routes.push({
title: <Trans>Secrets</Trans>, title: <Trans>Secrets</Trans>,
component: Secrets, component: Secrets,
url: secretsURL({ query }), url: secretsURL({ query }),
path: secretsRoute.path, path: secretsRoute.path,
}, })
{ }
if (isAllowedResource("resourcequotas")) {
routes.push({
title: <Trans>Resource Quotas</Trans>, title: <Trans>Resource Quotas</Trans>,
component: ResourceQuotas, component: ResourceQuotas,
url: resourceQuotaURL({ query }), url: resourceQuotaURL({ query }),
path: resourceQuotaRoute.path, path: resourceQuotaRoute.path,
}, })
{ }
if (isAllowedResource("horizontalpodautoscalers")) {
routes.push({
title: <Trans>HPA</Trans>, title: <Trans>HPA</Trans>,
component: HorizontalPodAutoscalers, component: HorizontalPodAutoscalers,
url: hpaURL({ query }), url: hpaURL({ query }),
path: hpaRoute.path, path: hpaRoute.path,
}, })
] }
return routes;
} }
render() { render() {

View File

@ -11,6 +11,7 @@ import { namespaceStore } from "./namespace.store";
import { _i18n } from "../../i18n"; import { _i18n } from "../../i18n";
import { FilterIcon } from "../item-object-list/filter-icon"; import { FilterIcon } from "../item-object-list/filter-icon";
import { FilterType } from "../item-object-list/page-filters.store"; import { FilterType } from "../item-object-list/page-filters.store";
import { isAllowedResource } from "../../api/rbac"
interface Props extends SelectProps { interface Props extends SelectProps {
showIcons?: boolean; showIcons?: boolean;
@ -33,7 +34,9 @@ export class NamespaceSelect extends React.Component<Props> {
private unsubscribe = noop; private unsubscribe = noop;
async componentDidMount() { async componentDidMount() {
if (!namespaceStore.isLoaded) await namespaceStore.loadAll(); if (isAllowedResource("namespaces") && !namespaceStore.isLoaded) {
await namespaceStore.loadAll();
}
this.unsubscribe = namespaceStore.subscribe(); this.unsubscribe = namespaceStore.subscribe();
} }

View File

@ -12,6 +12,7 @@ import { Ingresses, ingressRoute, ingressURL } from "../+network-ingresses";
import { NetworkPolicies, networkPoliciesRoute, networkPoliciesURL } from "../+network-policies"; import { NetworkPolicies, networkPoliciesRoute, networkPoliciesURL } from "../+network-policies";
import { namespaceStore } from "../+namespaces/namespace.store"; import { namespaceStore } from "../+namespaces/namespace.store";
import { networkURL } from "./network.route"; import { networkURL } from "./network.route";
import { isAllowedResource } from "../../api/rbac";
interface Props extends RouteComponentProps<{}> { interface Props extends RouteComponentProps<{}> {
} }
@ -20,32 +21,40 @@ interface Props extends RouteComponentProps<{}> {
export class Network extends React.Component<Props> { export class Network extends React.Component<Props> {
static get tabRoutes(): TabRoute[] { static get tabRoutes(): TabRoute[] {
const query = namespaceStore.getContextParams() const query = namespaceStore.getContextParams()
return [ const routes: TabRoute[] = [];
{ if (isAllowedResource("services")) {
routes.push({
title: <Trans>Services</Trans>, title: <Trans>Services</Trans>,
component: Services, component: Services,
url: servicesURL({ query }), url: servicesURL({ query }),
path: servicesRoute.path, path: servicesRoute.path,
}, })
{ }
if (isAllowedResource("endpoints")) {
routes.push({
title: <Trans>Endpoints</Trans>, title: <Trans>Endpoints</Trans>,
component: Endpoints, component: Endpoints,
url: endpointURL({ query }), url: endpointURL({ query }),
path: endpointRoute.path, path: endpointRoute.path,
}, })
{ }
if (isAllowedResource("ingresses")) {
routes.push({
title: <Trans>Ingresses</Trans>, title: <Trans>Ingresses</Trans>,
component: Ingresses, component: Ingresses,
url: ingressURL({ query }), url: ingressURL({ query }),
path: ingressRoute.path, path: ingressRoute.path,
}, })
{ }
if (isAllowedResource("networkpolicies")) {
routes.push({
title: <Trans>Network Policies</Trans>, title: <Trans>Network Policies</Trans>,
component: NetworkPolicies, component: NetworkPolicies,
url: networkPoliciesURL({ query }), url: networkPoliciesURL({ query }),
path: networkPoliciesRoute.path, path: networkPoliciesRoute.path,
}, })
] }
return routes
} }
render() { render() {
@ -59,4 +68,4 @@ export class Network extends React.Component<Props> {
</MainLayout> </MainLayout>
) )
} }
} }

View File

@ -16,10 +16,11 @@
.workloads { .workloads {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, 155px); grid-template-columns: repeat(auto-fit, 155px);
justify-content: space-between; justify-content: space-evenly;
grid-gap: $margin; grid-gap: $margin;
padding: $padding * 2; padding: $padding * 2;
.workload { .workload {
margin-bottom: $margin * 2; margin-bottom: $margin * 2;
@ -32,4 +33,4 @@
} }
} }
} }
} }

View File

@ -15,17 +15,20 @@ import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
import { namespaceStore } from "../+namespaces/namespace.store"; import { namespaceStore } from "../+namespaces/namespace.store";
import { PageFiltersList } from "../item-object-list/page-filters-list"; import { PageFiltersList } from "../item-object-list/page-filters-list";
import { NamespaceSelectFilter } from "../+namespaces/namespace-select"; import { NamespaceSelectFilter } from "../+namespaces/namespace-select";
import { configStore } from "../../config.store";
import { isAllowedResource } from "../../api/rbac";
@observer @observer
export class OverviewStatuses extends React.Component { export class OverviewStatuses extends React.Component {
render() { render() {
const { allowedResources } = configStore;
const { contextNs } = namespaceStore; const { contextNs } = namespaceStore;
const pods = podsStore.getAllByNs(contextNs); const pods = isAllowedResource("pods") ? podsStore.getAllByNs(contextNs) : [];
const deployments = deploymentStore.getAllByNs(contextNs); const deployments = isAllowedResource("deployments") ? deploymentStore.getAllByNs(contextNs) : [];
const statefulSets = statefulSetStore.getAllByNs(contextNs); const statefulSets = isAllowedResource("statefulsets") ? statefulSetStore.getAllByNs(contextNs) : [];
const daemonSets = daemonSetStore.getAllByNs(contextNs); const daemonSets = isAllowedResource("daemonsets") ? daemonSetStore.getAllByNs(contextNs) : [];
const jobs = jobStore.getAllByNs(contextNs); const jobs = isAllowedResource("jobs") ? jobStore.getAllByNs(contextNs) : [];
const cronJobs = cronJobStore.getAllByNs(contextNs); const cronJobs = isAllowedResource("cronjobs") ? cronJobStore.getAllByNs(contextNs) : [];
return ( return (
<div className="OverviewStatuses"> <div className="OverviewStatuses">
<div className="header flex gaps align-center"> <div className="header flex gaps align-center">
@ -34,30 +37,42 @@ export class OverviewStatuses extends React.Component {
</div> </div>
<PageFiltersList/> <PageFiltersList/>
<div className="workloads"> <div className="workloads">
{ isAllowedResource("pods") &&
<div className="workload"> <div className="workload">
<div className="title"><Link to={podsURL()}><Trans>Pods</Trans> ({pods.length})</Link></div> <div className="title"><Link to={podsURL()}><Trans>Pods</Trans> ({pods.length})</Link></div>
<OverviewWorkloadStatus status={podsStore.getStatuses(pods)}/> <OverviewWorkloadStatus status={podsStore.getStatuses(pods)}/>
</div> </div>
}
{ isAllowedResource("deployments") &&
<div className="workload"> <div className="workload">
<div className="title"><Link to={deploymentsURL()}><Trans>Deployments</Trans> ({deployments.length})</Link></div> <div className="title"><Link to={deploymentsURL()}><Trans>Deployments</Trans> ({deployments.length})</Link></div>
<OverviewWorkloadStatus status={deploymentStore.getStatuses(deployments)}/> <OverviewWorkloadStatus status={deploymentStore.getStatuses(deployments)}/>
</div> </div>
}
{ isAllowedResource("statefulsets") &&
<div className="workload"> <div className="workload">
<div className="title"><Link to={statefulSetsURL()}><Trans>StatefulSets</Trans> ({statefulSets.length})</Link></div> <div className="title"><Link to={statefulSetsURL()}><Trans>StatefulSets</Trans> ({statefulSets.length})</Link></div>
<OverviewWorkloadStatus status={statefulSetStore.getStatuses(statefulSets)}/> <OverviewWorkloadStatus status={statefulSetStore.getStatuses(statefulSets)}/>
</div> </div>
}
{ isAllowedResource("daemonsets") &&
<div className="workload"> <div className="workload">
<div className="title"><Link to={daemonSetsURL()}><Trans>DaemonSets</Trans> ({daemonSets.length})</Link></div> <div className="title"><Link to={daemonSetsURL()}><Trans>DaemonSets</Trans> ({daemonSets.length})</Link></div>
<OverviewWorkloadStatus status={daemonSetStore.getStatuses(daemonSets)}/> <OverviewWorkloadStatus status={daemonSetStore.getStatuses(daemonSets)}/>
</div> </div>
}
{ isAllowedResource("jobs") &&
<div className="workload"> <div className="workload">
<div className="title"><Link to={jobsURL()}><Trans>Jobs</Trans> ({jobs.length})</Link></div> <div className="title"><Link to={jobsURL()}><Trans>Jobs</Trans> ({jobs.length})</Link></div>
<OverviewWorkloadStatus status={jobStore.getStatuses(jobs)}/> <OverviewWorkloadStatus status={jobStore.getStatuses(jobs)}/>
</div> </div>
}
{ isAllowedResource("cronjobs") &&
<div className="workload"> <div className="workload">
<div className="title"><Link to={cronJobsURL()}><Trans>CronJobs</Trans> ({cronJobs.length})</Link></div> <div className="title"><Link to={cronJobsURL()}><Trans>CronJobs</Trans> ({cronJobs.length})</Link></div>
<OverviewWorkloadStatus status={cronJobStore.getStatuses(cronJobs)}/> <OverviewWorkloadStatus status={cronJobStore.getStatuses(cronJobs)}/>
</div> </div>
}
</div> </div>
</div> </div>
) )

View File

@ -16,6 +16,8 @@ import { jobStore } from "../+workloads-jobs/job.store";
import { cronJobStore } from "../+workloads-cronjobs/cronjob.store"; import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
import { Spinner } from "../spinner"; import { Spinner } from "../spinner";
import { Events } from "../+events"; import { Events } from "../+events";
import { KubeObjectStore } from "../../kube-object.store";
import { isAllowedResource } from "../../api/rbac"
interface Props extends RouteComponentProps<IWorkloadsOverviewRouteParams> { interface Props extends RouteComponentProps<IWorkloadsOverviewRouteParams> {
} }
@ -26,16 +28,31 @@ export class WorkloadsOverview extends React.Component<Props> {
@observable isUnmounting = false; @observable isUnmounting = false;
async componentDidMount() { async componentDidMount() {
const stores = [ const stores: KubeObjectStore[] = [];
podsStore, if (isAllowedResource("pods")) {
deploymentStore, stores.push(podsStore);
daemonSetStore, }
statefulSetStore, if (isAllowedResource("deployments")) {
replicaSetStore, stores.push(deploymentStore);
jobStore, }
cronJobStore, if (isAllowedResource("daemonsets")) {
eventStore, stores.push(daemonSetStore);
]; }
if (isAllowedResource("statefulsets")) {
stores.push(statefulSetStore);
}
if (isAllowedResource("replicasets")) {
stores.push(replicaSetStore);
}
if (isAllowedResource("jobs")) {
stores.push(jobStore);
}
if (isAllowedResource("cronjobs")) {
stores.push(cronJobStore);
}
if (isAllowedResource("events")) {
stores.push(eventStore);
}
this.isReady = stores.every(store => store.isLoaded); this.isReady = stores.every(store => store.isLoaded);
await Promise.all(stores.map(store => store.loadAll())); await Promise.all(stores.map(store => store.loadAll()));
this.isReady = true; this.isReady = true;
@ -55,11 +72,11 @@ export class WorkloadsOverview extends React.Component<Props> {
return ( return (
<> <>
<OverviewStatuses/> <OverviewStatuses/>
<Events { isAllowedResource("events") && <Events
compact compact
hideFilters hideFilters
className="box grow" className="box grow"
/> /> }
</> </>
) )
} }
@ -71,4 +88,4 @@ export class WorkloadsOverview extends React.Component<Props> {
</div> </div>
) )
} }
} }

View File

@ -15,6 +15,7 @@ import { DaemonSets } from "../+workloads-daemonsets";
import { StatefulSets } from "../+workloads-statefulsets"; import { StatefulSets } from "../+workloads-statefulsets";
import { Jobs } from "../+workloads-jobs"; import { Jobs } from "../+workloads-jobs";
import { CronJobs } from "../+workloads-cronjobs"; import { CronJobs } from "../+workloads-cronjobs";
import { isAllowedResource } from "../../api/rbac"
interface Props extends RouteComponentProps { interface Props extends RouteComponentProps {
} }
@ -23,50 +24,63 @@ interface Props extends RouteComponentProps {
export class Workloads extends React.Component<Props> { export class Workloads extends React.Component<Props> {
static get tabRoutes(): TabRoute[] { static get tabRoutes(): TabRoute[] {
const query = namespaceStore.getContextParams(); const query = namespaceStore.getContextParams();
return [ const routes: TabRoute[] = [
{ {
title: <Trans>Overview</Trans>, title: <Trans>Overview</Trans>,
component: WorkloadsOverview, component: WorkloadsOverview,
url: overviewURL({ query }), url: overviewURL({ query }),
path: overviewRoute.path path: overviewRoute.path
}, }
{ ]
if (isAllowedResource("pods")) {
routes.push({
title: <Trans>Pods</Trans>, title: <Trans>Pods</Trans>,
component: Pods, component: Pods,
url: podsURL({ query }), url: podsURL({ query }),
path: podsRoute.path path: podsRoute.path
}, })
{ }
if (isAllowedResource("deployments")) {
routes.push({
title: <Trans>Deployments</Trans>, title: <Trans>Deployments</Trans>,
component: Deployments, component: Deployments,
url: deploymentsURL({ query }), url: deploymentsURL({ query }),
path: deploymentsRoute.path, path: deploymentsRoute.path,
}, })
{ }
if (isAllowedResource("daemonsets")) {
routes.push({
title: <Trans>DaemonSets</Trans>, title: <Trans>DaemonSets</Trans>,
component: DaemonSets, component: DaemonSets,
url: daemonSetsURL({ query }), url: daemonSetsURL({ query }),
path: daemonSetsRoute.path, path: daemonSetsRoute.path,
}, })
{ }
if (isAllowedResource("statefulsets")) {
routes.push({
title: <Trans>StatefulSets</Trans>, title: <Trans>StatefulSets</Trans>,
component: StatefulSets, component: StatefulSets,
url: statefulSetsURL({ query }), url: statefulSetsURL({ query }),
path: statefulSetsRoute.path, path: statefulSetsRoute.path,
}, })
{ }
if (isAllowedResource("jobs")) {
routes.push({
title: <Trans>Jobs</Trans>, title: <Trans>Jobs</Trans>,
component: Jobs, component: Jobs,
url: jobsURL({ query }), url: jobsURL({ query }),
path: jobsRoute.path, path: jobsRoute.path,
}, })
{ }
if (isAllowedResource("cronjobs")) {
routes.push({
title: <Trans>CronJobs</Trans>, title: <Trans>CronJobs</Trans>,
component: CronJobs, component: CronJobs,
url: cronJobsURL({ query }), url: cronJobsURL({ query }),
path: cronJobsRoute.path, path: cronJobsRoute.path,
}, })
] }
return routes;
}; };
render() { render() {
@ -80,4 +94,4 @@ export class Workloads extends React.Component<Props> {
</MainLayout> </MainLayout>
) )
} }
} }

View File

@ -32,6 +32,7 @@ import { PodLogsDialog } from "./+workloads-pods/pod-logs-dialog";
import { DeploymentScaleDialog } from "./+workloads-deployments/deployment-scale-dialog"; import { DeploymentScaleDialog } from "./+workloads-deployments/deployment-scale-dialog";
import { CustomResources } from "./+custom-resources/custom-resources"; import { CustomResources } from "./+custom-resources/custom-resources";
import { crdRoute } from "./+custom-resources"; import { crdRoute } from "./+custom-resources";
import { isAllowedResource } from "../api/rbac";
@observer @observer
class App extends React.Component { class App extends React.Component {
@ -46,7 +47,7 @@ class App extends React.Component {
}; };
render() { render() {
const homeUrl = clusterURL(); const homeUrl = (isAllowedResource(["events", "nodes", "pods"])) ? clusterURL() : workloadsURL();
return ( return (
<I18nProvider i18n={_i18n}> <I18nProvider i18n={_i18n}>
<Router history={browserHistory}> <Router history={browserHistory}>

View File

@ -38,7 +38,7 @@ export class ErrorBoundary extends React.Component<Props, State> {
render() { render() {
const { error, errorInfo } = this.state; const { error, errorInfo } = this.state;
if (error) { if (error) {
const slackLink = <a href="https://join.slack.com/t/kontenacommunity/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI" target="_blank">Slack</a> const slackLink = <a href="https://join.slack.com/t/k8slens/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI" target="_blank">Slack</a>
const githubLink = <a href="https://github.com/lensapp/lens/issues" target="_blank">Github</a> const githubLink = <a href="https://github.com/lensapp/lens/issues" target="_blank">Github</a>
const pageUrl = location.href; const pageUrl = location.href;
return ( return (
@ -72,4 +72,4 @@ export class ErrorBoundary extends React.Component<Props, State> {
} }
return this.props.children; return this.props.children;
} }
} }

View File

@ -114,10 +114,15 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
const { store, dependentStores, isClusterScoped } = this.props; const { store, dependentStores, isClusterScoped } = this.props;
const stores = [store, ...dependentStores]; const stores = [store, ...dependentStores];
if (!isClusterScoped) stores.push(namespaceStore); if (!isClusterScoped) stores.push(namespaceStore);
await Promise.all(stores.map(store => store.loadAll())); try {
const subscriptions = stores.map(store => store.subscribe()); await Promise.all(stores.map(store => store.loadAll()));
const subscriptions = stores.map(store => store.subscribe());
subscriptions.forEach(dispose => dispose()); // unsubscribe all
} catch(error) {
console.log("catched", error)
}
await when(() => this.isUnmounting); await when(() => this.isUnmounting);
subscriptions.forEach(dispose => dispose()); // unsubscribe all
} }
componentWillUnmount() { componentWillUnmount() {

View File

@ -28,6 +28,7 @@ import { crdStore } from "../+custom-resources/crd.store";
import { CrdList, crdResourcesRoute, crdRoute, crdURL } from "../+custom-resources"; import { CrdList, crdResourcesRoute, crdRoute, crdURL } from "../+custom-resources";
import { CustomResources } from "../+custom-resources/custom-resources"; import { CustomResources } from "../+custom-resources/custom-resources";
import { navigation } from "../../navigation"; import { navigation } from "../../navigation";
import { isAllowedResource } from "../../api/rbac"
const SidebarContext = React.createContext<SidebarContextValue>({ pinned: false }); const SidebarContext = React.createContext<SidebarContextValue>({ pinned: false });
type SidebarContextValue = { type SidebarContextValue = {
@ -43,7 +44,7 @@ interface Props {
@observer @observer
export class Sidebar extends React.Component<Props> { export class Sidebar extends React.Component<Props> {
async componentDidMount() { async componentDidMount() {
if (!crdStore.isLoaded) crdStore.loadAll() if (!crdStore.isLoaded && isAllowedResource('customresourcedefinitions')) crdStore.loadAll()
} }
renderCustomResources() { renderCustomResources() {
@ -71,7 +72,7 @@ export class Sidebar extends React.Component<Props> {
render() { render() {
const { toggle, isPinned, className } = this.props; const { toggle, isPinned, className } = this.props;
const { isClusterAdmin, allowedResources } = configStore; const { allowedResources } = configStore;
const query = namespaceStore.getContextParams(); const query = namespaceStore.getContextParams();
return ( return (
<SidebarContext.Provider value={{ pinned: isPinned }}> <SidebarContext.Provider value={{ pinned: isPinned }}>
@ -91,19 +92,21 @@ export class Sidebar extends React.Component<Props> {
<div className="sidebar-nav flex column box grow-fixed"> <div className="sidebar-nav flex column box grow-fixed">
<SidebarNavItem <SidebarNavItem
id="cluster" id="cluster"
isHidden={!isAllowedResource('nodes')}
url={clusterURL()} url={clusterURL()}
text={<Trans>Cluster</Trans>} text={<Trans>Cluster</Trans>}
icon={<Icon svg="kube"/>} icon={<Icon svg="kube"/>}
/> />
<SidebarNavItem <SidebarNavItem
id="nodes" id="nodes"
isHidden={!allowedResources.includes('nodes')} isHidden={!isAllowedResource('nodes')}
url={nodesURL()} url={nodesURL()}
text={<Trans>Nodes</Trans>} text={<Trans>Nodes</Trans>}
icon={<Icon svg="nodes"/>} icon={<Icon svg="nodes"/>}
/> />
<SidebarNavItem <SidebarNavItem
id="workloads" id="workloads"
isHidden={Workloads.tabRoutes.length == 0}
url={workloadsURL({ query })} url={workloadsURL({ query })}
routePath={workloadsRoute.path} routePath={workloadsRoute.path}
subMenus={Workloads.tabRoutes} subMenus={Workloads.tabRoutes}
@ -112,6 +115,7 @@ export class Sidebar extends React.Component<Props> {
/> />
<SidebarNavItem <SidebarNavItem
id="config" id="config"
isHidden={Config.tabRoutes.length == 0}
url={configURL({ query })} url={configURL({ query })}
routePath={configRoute.path} routePath={configRoute.path}
subMenus={Config.tabRoutes} subMenus={Config.tabRoutes}
@ -120,6 +124,7 @@ export class Sidebar extends React.Component<Props> {
/> />
<SidebarNavItem <SidebarNavItem
id="networks" id="networks"
isHidden={Network.tabRoutes.length == 0}
url={networkURL({ query })} url={networkURL({ query })}
routePath={networkRoute.path} routePath={networkRoute.path}
subMenus={Network.tabRoutes} subMenus={Network.tabRoutes}
@ -128,6 +133,7 @@ export class Sidebar extends React.Component<Props> {
/> />
<SidebarNavItem <SidebarNavItem
id="storage" id="storage"
isHidden={Storage.tabRoutes.length == 0}
url={storageURL({ query })} url={storageURL({ query })}
routePath={storageRoute.path} routePath={storageRoute.path}
subMenus={Storage.tabRoutes} subMenus={Storage.tabRoutes}
@ -136,12 +142,14 @@ export class Sidebar extends React.Component<Props> {
/> />
<SidebarNavItem <SidebarNavItem
id="namespaces" id="namespaces"
isHidden={!isAllowedResource('namespaces')}
url={namespacesURL()} url={namespacesURL()}
icon={<Icon material="layers"/>} icon={<Icon material="layers"/>}
text={<Trans>Namespaces</Trans>} text={<Trans>Namespaces</Trans>}
/> />
<SidebarNavItem <SidebarNavItem
id="events" id="events"
isHidden={!isAllowedResource('events')}
url={eventsURL({ query })} url={eventsURL({ query })}
routePath={eventRoute.path} routePath={eventRoute.path}
icon={<Icon material="access_time"/>} icon={<Icon material="access_time"/>}
@ -165,7 +173,7 @@ export class Sidebar extends React.Component<Props> {
/> />
<SidebarNavItem <SidebarNavItem
id="custom-resources" id="custom-resources"
isHidden={!allowedResources.includes('customresourcedefinitions')} isHidden={!isAllowedResource('customresourcedefinitions')}
url={crdURL()} url={crdURL()}
subMenus={CustomResources.tabRoutes} subMenus={CustomResources.tabRoutes}
routePath={crdRoute.path} routePath={crdRoute.path}

View File

@ -1,12 +0,0 @@
export interface ILicense {
name?: string;
maxNodes?: number;
owner?: {
company?: string;
firstName?: string;
lastName?: string;
username?: string;
};
validUntil?: string;
recurring?: boolean;
}

View File

@ -10669,9 +10669,9 @@ websocket-driver@>=0.5.1:
websocket-extensions ">=0.1.1" websocket-extensions ">=0.1.1"
websocket-extensions@>=0.1.1: websocket-extensions@>=0.1.1:
version "0.1.3" version "0.1.4"
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
version "1.0.5" version "1.0.5"

View File

@ -8,7 +8,7 @@
"copyright": "© 2020, Lakend Labs, Inc.", "copyright": "© 2020, Lakend Labs, Inc.",
"license": "MIT", "license": "MIT",
"description": "Lens - The Kubernetes IDE", "description": "Lens - The Kubernetes IDE",
"version": "3.4.0", "version": "3.5.0-beta.1",
"main": "main.ts", "main": "main.ts",
"config": { "config": {
"bundledKubectlVersion": "1.17.4", "bundledKubectlVersion": "1.17.4",
@ -109,16 +109,17 @@
"dev-dashboard": "cd dashboard && yarn dev", "dev-dashboard": "cd dashboard && yarn dev",
"dev-electron": "electron-webpack dev", "dev-electron": "electron-webpack dev",
"compile": "yarn download:bins && electron-webpack", "compile": "yarn download:bins && electron-webpack",
"build:linux": "yarn compile && electron-builder --linux --dir", "build:linux": "yarn compile && electron-builder --linux --dir -c.productName=LensDev",
"build:mac": "yarn compile && electron-builder --mac --dir", "build:mac": "yarn compile && electron-builder --mac --dir -c.productName=LensDev",
"build:win": "yarn compile && electron-builder --win --dir", "build:win": "yarn compile && electron-builder --win --dir -c.productName=LensDev",
"dist": "yarn compile && electron-builder -p onTag", "dist": "yarn compile && electron-builder -p onTag",
"dist:win": "yarn compile && electron-builder -p onTag --x64 --ia32", "dist:win": "yarn compile && electron-builder -p onTag --x64 --ia32",
"dist:dir": "yarn dist --dir -c.compression=store -c.mac.identity=null", "dist:dir": "yarn dist --dir -c.compression=store -c.mac.identity=null",
"lint": "eslint $@ --ext js,ts,vue --max-warnings=0 src/", "lint": "eslint $@ --ext js,ts,vue --max-warnings=0 src/",
"lint-dashboard": "eslint $@ --ext js,ts,tsx --max-warnings=0 dashboard/client dashboard/server", "lint-dashboard": "eslint $@ --ext js,ts,tsx --max-warnings=0 dashboard/client dashboard/server",
"postinstall": "patch-package", "postinstall": "patch-package",
"test": "node_modules/.bin/jest", "test": "node_modules/.bin/jest spec/src/",
"integration": "node_modules/.bin/jest spec/integration/",
"download:bins": "concurrently \"yarn download:kubectl\" \"yarn download:helm\"", "download:bins": "concurrently \"yarn download:kubectl\" \"yarn download:helm\"",
"download:kubectl": "yarn run ts-node build/download_kubectl.ts", "download:kubectl": "yarn run ts-node build/download_kubectl.ts",
"download:helm": "yarn run ts-node build/download_helm.ts" "download:helm": "yarn run ts-node build/download_helm.ts"
@ -185,6 +186,7 @@
"@types/tempy": "0.1.0", "@types/tempy": "0.1.0",
"@types/universal-analytics": "^0.4.3", "@types/universal-analytics": "^0.4.3",
"@types/uuid": "^3.4.5", "@types/uuid": "^3.4.5",
"@types/webdriverio": "^4.13.0",
"@typescript-eslint/eslint-plugin": "^2.7.0", "@typescript-eslint/eslint-plugin": "^2.7.0",
"@typescript-eslint/parser": "^2.7.0", "@typescript-eslint/parser": "^2.7.0",
"bootstrap": "^4.3.1", "bootstrap": "^4.3.1",
@ -212,6 +214,7 @@
"postinstall-postinstall": "^2.0.0", "postinstall-postinstall": "^2.0.0",
"prismjs": "^1.17.1", "prismjs": "^1.17.1",
"sass-loader": "^8.0.0", "sass-loader": "^8.0.0",
"spectron": "^8.0.0",
"ts-jest": "^24.1.0", "ts-jest": "^24.1.0",
"ts-loader": "^6.0.4", "ts-loader": "^6.0.4",
"ts-node": "^8.4.1", "ts-node": "^8.4.1",

View File

@ -0,0 +1,34 @@
import { Application } from "spectron";
let appPath = ""
switch(process.platform) {
case "win32":
appPath = "./dist/win-unpacked/Lens.exe"
break
case "linux":
appPath = "./dist/linux-unpacked/kontena-lens"
break
case "darwin":
appPath = "./dist/mac/LensDev.app/Contents/MacOS/LensDev"
break
}
export function setup() {
return new Application({
// path to electron app
args: [],
path: appPath,
startTimeout: 30000,
waitTimeout: 30000,
})
}
export async function tearDown(app: Application) {
const pid = app.mainProcess.pid
await app.stop()
try {
process.kill(pid, 0);
} catch(e) {
return
}
}

View File

@ -0,0 +1,56 @@
import { Application } from "spectron"
import * as util from "../helpers/utils"
import { spawnSync } from "child_process"
import { stat } from "fs"
jest.setTimeout(20000)
describe("app start", () => {
let app: Application
const clickWhatsNew = async (app: Application) => {
await app.client.waitUntilTextExists("h1", "What's new")
await app.client.click("button.btn-primary")
await app.client.waitUntilTextExists("h1", "Welcome")
}
beforeEach(async () => {
app = util.setup()
await app.start()
const windowCount = await app.client.getWindowCount()
await app.client.windowByIndex(windowCount - 1)
await app.client.waitUntilWindowLoaded()
}, 20000)
it('shows "whats new"', async () => {
await clickWhatsNew(app)
})
it('allows to add a cluster', async () => {
const status = spawnSync("minikube status", {shell: true})
if (status.status !== 0) {
console.warn("minikube not running, skipping test")
return
}
await clickWhatsNew(app)
await app.client.click("a#add-cluster")
await app.client.waitUntilTextExists("legend", "Choose config:")
await app.client.selectByVisibleText("select#kubecontext-select", "minikube (new)")
await app.client.click("button.btn-primary")
await app.client.waitUntilTextExists("pre.auth-output", "Authentication proxy started")
let windowCount = await app.client.getWindowCount()
// wait for webview to appear on window count
while (windowCount == 1) {
windowCount = await app.client.getWindowCount()
}
await app.client.windowByIndex(windowCount - 1)
await app.client.waitUntilTextExists("span.link-text", "Cluster")
await app.client.click('a[href="/nodes"]')
await app.client.waitUntilTextExists("div.TableCell", "minikube")
})
afterEach(async () => {
if (app && app.isRunning()) {
return util.tearDown(app)
}
})
})

View File

@ -23,11 +23,19 @@ spec:
operator: In operator: In
values: values:
- linux - linux
- key: kubernetes.io/arch
operator: In
values:
- amd64
- matchExpressions: - matchExpressions:
- key: beta.kubernetes.io/os - key: beta.kubernetes.io/os
operator: In operator: In
values: values:
- linux - linux
- key: beta.kubernetes.io/arch
operator: In
values:
- amd64
serviceAccountName: kube-state-metrics serviceAccountName: kube-state-metrics
containers: containers:
- name: kube-state-metrics - name: kube-state-metrics

View File

@ -183,7 +183,7 @@ export default function initMenu(opts: MenuOptions, promiseIpc: any) {
{ {
label: 'Community Slack', label: 'Community Slack',
click: async () => { click: async () => {
shell.openExternal('https://join.slack.com/t/kontenacommunity/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI'); shell.openExternal('https://join.slack.com/t/k8slens/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI');
}, },
}, },
{ {

View File

@ -5,6 +5,31 @@ import { getAppVersion } from "../../common/app-utils"
import { CoreV1Api, AuthorizationV1Api } from "@kubernetes/client-node" import { CoreV1Api, AuthorizationV1Api } from "@kubernetes/client-node"
import { Cluster } from "../cluster" import { Cluster } from "../cluster"
// TODO: auto-populate all resources dynamically
const apiResources = [
{ resource: "configmaps" },
{ resource: "cronjobs", group: "batch" },
{ resource: "customresourcedefinitions", group: "apiextensions.k8s.io" },
{ resource: "daemonsets", group: "apps" },
{ resource: "deployments", group: "apps" },
{ resource: "endpoints" },
{ resource: "events" },
{ resource: "horizontalpodautoscalers" },
{ resource: "ingresses", group: "networking.k8s.io" },
{ resource: "jobs", group: "batch" },
{ resource: "namespaces" },
{ resource: "networkpolicies", group: "networking.k8s.io" },
{ resource: "nodes" },
{ resource: "persistentvolumes" },
{ resource: "pods" },
{ resource: "podsecuritypolicies" },
{ resource: "resourcequotas" },
{ resource: "secrets" },
{ resource: "services" },
{ resource: "statefulsets", group: "apps" },
{ resource: "storageclasses", group: "storage.k8s.io" },
]
async function getAllowedNamespaces(cluster: Cluster) { async function getAllowedNamespaces(cluster: Cluster) {
const api = cluster.contextHandler.kc.makeApiClient(CoreV1Api) const api = cluster.contextHandler.kc.makeApiClient(CoreV1Api)
try { try {
@ -30,21 +55,18 @@ async function getAllowedNamespaces(cluster: Cluster) {
} }
} }
async function getAllowedResources(cluster: Cluster) { async function getAllowedResources(cluster: Cluster, namespaces: string[]) {
// TODO: auto-populate all resources dynamically
const resources = [
"nodes", "persistentvolumes", "storageclasses", "customresourcedefinitions",
"podsecuritypolicies"
]
try { try {
const resourceAccessStatuses = await Promise.all( const resourceAccessStatuses = await Promise.all(
resources.map(resource => cluster.canI({ apiResources.map(apiResource => cluster.canI({
resource: resource, resource: apiResource.resource,
verb: "list" group: apiResource.group,
verb: "list",
namespace: namespaces[0]
})) }))
) )
return resources return apiResources
.filter((resource, i) => resourceAccessStatuses[i]) .filter((resource, i) => resourceAccessStatuses[i]).map(apiResource => apiResource.resource)
} catch(error) { } catch(error) {
return [] return []
} }
@ -55,6 +77,7 @@ class ConfigRoute extends LensApi {
public async routeConfig(request: LensApiRequest) { public async routeConfig(request: LensApiRequest) {
const { params, response, cluster} = request const { params, response, cluster} = request
const namespaces = await getAllowedNamespaces(cluster)
const data = { const data = {
clusterName: cluster.contextName, clusterName: cluster.contextName,
lensVersion: getAppVersion(), lensVersion: getAppVersion(),
@ -62,8 +85,8 @@ class ConfigRoute extends LensApi {
kubeVersion: cluster.version, kubeVersion: cluster.version,
chartsEnabled: true, chartsEnabled: true,
isClusterAdmin: cluster.isAdmin, isClusterAdmin: cluster.isAdmin,
allowedResources: await getAllowedResources(cluster), allowedResources: await getAllowedResources(cluster, namespaces),
allowedNamespaces: await getAllowedNamespaces(cluster) allowedNamespaces: namespaces
}; };
this.respondJson(response, data) this.respondJson(response, data)

View File

@ -159,7 +159,7 @@ export class ShellSession extends EventEmitter {
} }
protected exit(code = 1000) { protected exit(code = 1000) {
this.websocket.close(code) if (this.websocket.readyState == this.websocket.OPEN) this.websocket.close(code)
this.emit('exit') this.emit('exit')
} }
@ -179,12 +179,25 @@ export class ShellSession extends EventEmitter {
protected exitProcessOnWebsocketClose() { protected exitProcessOnWebsocketClose() {
this.websocket.on("close", () => { this.websocket.on("close", () => {
if (this.shellProcess) { this.killShellProcess()
this.shellProcess.kill();
}
}) })
} }
protected killShellProcess(){
if(this.running) {
// On Windows we need to kill the shell process by pid, since Lens won't respond after a while if using `this.shellProcess.kill()`
if (process.platform == "win32") {
try {
process.kill(this.shellProcess.pid)
} catch(e) {
return
}
} else {
this.shellProcess.kill()
}
}
}
protected sendResponse(msg: string) { protected sendResponse(msg: string) {
this.websocket.send("1" + Buffer.from(msg).toString("base64")) this.websocket.send("1" + Buffer.from(msg).toString("base64"))
} }

View File

@ -27,7 +27,10 @@ export class WindowManager {
center: true, center: true,
frame: false, frame: false,
resizable: false, resizable: false,
show: false show: false,
webPreferences: {
nodeIntegration: true
}
}) })
if (showSplash) { if (showSplash) {
this.splashWindow.loadFile(path.join(__static, "/splash.html")) this.splashWindow.loadFile(path.join(__static, "/splash.html"))

View File

@ -11,6 +11,7 @@
label="Choose config:" label="Choose config:"
> >
<b-form-select <b-form-select
id="kubecontext-select"
v-model="kubecontext" v-model="kubecontext"
:options="contextNames" :options="contextNames"
@change="onSelect($event)" @change="onSelect($event)"

View File

@ -8,8 +8,8 @@
<div> <div>
<b-row align-h="center" class="banner"> <b-row align-h="center" class="banner">
<b-col sm="8"> <b-col sm="8">
<h1 v-if="user && clusters.length === 0" class="display-4 text-center"> <h1 v-if="clusters.length === 0" class="display-4 text-center">
Welcome, {{ greetingName }}! Welcome!
</h1> </h1>
<p v-if="clusters.length === 0" class="text-center"> <p v-if="clusters.length === 0" class="text-center">
Get started by associating one or more clusters to Lens. Get started by associating one or more clusters to Lens.
@ -35,12 +35,6 @@ export default {
}, },
clusters: function() { clusters: function() {
return this.$store.getters.clusters; return this.$store.getters.clusters;
},
user: function() {
return this.$store.getters.user;
},
greetingName: function() {
return (this.user['first-name'] && this.user['first-name'] !== "") ? this.user['first-name'] : this.user.username
} }
} }
} }

View File

@ -2,7 +2,17 @@
Here you can find description of changes we've built into each release. While we try our best to make each upgrade automatic and as smooth as possible, there may be some cases where your might need to do something to ensure the application works smoothly. So please read through the release highlights! Here you can find description of changes we've built into each release. While we try our best to make each upgrade automatic and as smooth as possible, there may be some cases where your might need to do something to ensure the application works smoothly. So please read through the release highlights!
## 3.4.0 (current version) ## 3.5.0-beta.1 (current version)
- Dynamic dashboard UI based on RBAC rules
- Show object reference for all objects
- Unify scrollbars/paddings
- Fix: add arch node selector for hybrid clusters
- Fix pod shell command on Windows
- Translation correction: transit to transmit
- Remove Kontena reference from Lens logo
## 3.4.0
- Auto-detect Prometheus installation - Auto-detect Prometheus installation
- Allow to select Prometheus query style - Allow to select Prometheus query style

406
yarn.lock
View File

@ -1444,6 +1444,13 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/webdriverio@^4.13.0":
version "4.13.3"
resolved "https://registry.yarnpkg.com/@types/webdriverio/-/webdriverio-4.13.3.tgz#c1571c4e62724135c0b11e7d7e36b07af5168856"
integrity sha512-AfSQM1xTO9Ax+u9uSQPDuw69DQ0qA2RMoKHn86jCgWNcwKVUjGMSP4sfSl3JOfcZN8X/gWvn7znVPp2/g9zcJA==
dependencies:
"@types/node" "*"
"@types/webpack-env@^1.13.9": "@types/webpack-env@^1.13.9":
version "1.14.0" version "1.14.0"
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.14.0.tgz#8edfc5f8e6eae20eeed3ca0d02974ed4ee5e4efc" resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.14.0.tgz#8edfc5f8e6eae20eeed3ca0d02974ed4ee5e4efc"
@ -1914,6 +1921,32 @@ aproba@^1.0.3, aproba@^1.1.1:
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
archiver-utils@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174"
integrity sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=
dependencies:
glob "^7.0.0"
graceful-fs "^4.1.0"
lazystream "^1.0.0"
lodash "^4.8.0"
normalize-path "^2.0.0"
readable-stream "^2.0.0"
archiver@~2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.1.1.tgz#ff662b4a78201494a3ee544d3a33fe7496509ebc"
integrity sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=
dependencies:
archiver-utils "^1.3.0"
async "^2.0.0"
buffer-crc32 "^0.2.1"
glob "^7.0.0"
lodash "^4.8.0"
readable-stream "^2.0.0"
tar-stream "^1.5.0"
zip-stream "^1.2.0"
are-we-there-yet@~1.1.2: are-we-there-yet@~1.1.2:
version "1.1.5" version "1.1.5"
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
@ -2055,7 +2088,7 @@ async@^1.5.2:
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
async@^2.6.1: async@^2.0.0, async@^2.6.1:
version "2.6.3" version "2.6.3"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
@ -2067,7 +2100,7 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
atob@^2.1.1: atob@^2.1.1, atob@^2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
@ -2165,6 +2198,14 @@ babel-preset-jest@^24.9.0:
"@babel/plugin-syntax-object-rest-spread" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
babel-plugin-jest-hoist "^24.9.0" babel-plugin-jest-hoist "^24.9.0"
babel-runtime@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
balanced-match@^0.4.2: balanced-match@^0.4.2:
version "0.4.2" version "0.4.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
@ -2225,6 +2266,14 @@ binary-extensions@^1.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
bl@^1.0.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==
dependencies:
readable-stream "^2.3.5"
safe-buffer "^5.1.1"
block-stream@*: block-stream@*:
version "0.0.9" version "0.0.9"
resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
@ -2468,11 +2517,34 @@ bser@^2.0.0:
dependencies: dependencies:
node-int64 "^0.4.0" node-int64 "^0.4.0"
buffer-alloc-unsafe@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
buffer-alloc@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
dependencies:
buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0"
buffer-crc32@^0.2.1, buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
buffer-equal-constant-time@1.0.1: buffer-equal-constant-time@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
buffer-fill@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
buffer-from@1.x, buffer-from@^1.0.0: buffer-from@1.x, buffer-from@^1.0.0:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
@ -2497,6 +2569,14 @@ buffer@^4.3.0:
ieee754 "^1.1.4" ieee754 "^1.1.4"
isarray "^1.0.0" isarray "^1.0.0"
buffer@^5.1.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786"
integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
builder-util-runtime@8.3.0: builder-util-runtime@8.3.0:
version "8.3.0" version "8.3.0"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz#f5fac9139af6facf42a21fbe4d3aebed88fda33e" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz#f5fac9139af6facf42a21fbe4d3aebed88fda33e"
@ -2730,6 +2810,11 @@ chalk@^3.0.0:
ansi-styles "^4.1.0" ansi-styles "^4.1.0"
supports-color "^7.1.0" supports-color "^7.1.0"
chardet@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=
chardet@^0.7.0: chardet@^0.7.0:
version "0.7.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
@ -3080,6 +3165,16 @@ component-xor@0.0.4:
resolved "https://registry.yarnpkg.com/component-xor/-/component-xor-0.0.4.tgz#c55d83ccc1b94cd5089a4e93fa7891c7263e59aa" resolved "https://registry.yarnpkg.com/component-xor/-/component-xor-0.0.4.tgz#c55d83ccc1b94cd5089a4e93fa7891c7263e59aa"
integrity sha1-xV2DzMG5TNUImk6T+niRxyY+Wao= integrity sha1-xV2DzMG5TNUImk6T+niRxyY+Wao=
compress-commons@^1.2.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.2.tgz#524a9f10903f3a813389b0225d27c48bb751890f"
integrity sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=
dependencies:
buffer-crc32 "^0.2.1"
crc32-stream "^2.0.0"
normalize-path "^2.0.0"
readable-stream "^2.0.0"
compressible@~2.0.16: compressible@~2.0.16:
version "2.0.17" version "2.0.17"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1"
@ -3105,7 +3200,7 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
concat-stream@1.6.2, concat-stream@^1.5.0: concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.2:
version "1.6.2" version "1.6.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
@ -3257,11 +3352,31 @@ core-js-compat@^3.1.1:
browserslist "^4.6.6" browserslist "^4.6.6"
semver "^6.3.0" semver "^6.3.0"
core-js@^2.4.0:
version "2.6.11"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
core-util-is@1.0.2, core-util-is@~1.0.0: core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
crc32-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4"
integrity sha1-483TtN8xaN10494/u8t7KX/pCPQ=
dependencies:
crc "^3.4.4"
readable-stream "^2.0.0"
crc@^3.4.4:
version "3.8.0"
resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==
dependencies:
buffer "^5.1.0"
create-ecdh@^4.0.0: create-ecdh@^4.0.0:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff"
@ -3399,6 +3514,13 @@ css-loader@^3.0.0, css-loader@^3.2.0:
postcss-value-parser "^4.0.0" postcss-value-parser "^4.0.0"
schema-utils "^2.0.0" schema-utils "^2.0.0"
css-parse@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4"
integrity sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=
dependencies:
css "^2.0.0"
css-select-base-adapter@^0.1.1: css-select-base-adapter@^0.1.1:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7"
@ -3440,11 +3562,26 @@ css-tree@1.0.0-alpha.33:
mdn-data "2.0.4" mdn-data "2.0.4"
source-map "^0.5.3" source-map "^0.5.3"
css-value@~0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/css-value/-/css-value-0.0.1.tgz#5efd6c2eea5ea1fd6b6ac57ec0427b18452424ea"
integrity sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=
css-what@2.1, css-what@^2.1.2: css-what@2.1, css-what@^2.1.2:
version "2.1.3" version "2.1.3"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
css@^2.0.0:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
dependencies:
inherits "^2.0.3"
source-map "^0.6.1"
source-map-resolve "^0.5.2"
urix "^0.1.0"
cssesc@^2.0.0: cssesc@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703"
@ -3571,7 +3708,7 @@ de-indent@^1.0.2:
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3: debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
version "2.6.9" version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@ -3631,6 +3768,11 @@ deep-is@^0.1.3, deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
deepmerge@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.0.1.tgz#25c1c24f110fb914f80001b925264dd77f3f4312"
integrity sha512-VIPwiMJqJ13ZQfaCsIFnp5Me9tnjURiaIFxfz7EH0Ci0dTSQpZtSLrqOicXqEd/z2r+z+Klk9GzmnRsgpgbOsQ==
default-gateway@^4.2.0: default-gateway@^4.2.0:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
@ -3749,6 +3891,11 @@ detect-node@^2.0.4:
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
dev-null@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dev-null/-/dev-null-0.1.1.tgz#5a205ce3c2b2ef77b6238d6ba179eb74c6a0e818"
integrity sha1-WiBc48Ky73e2I41roXnrdMag6Bg=
diagnostics@^1.1.1: diagnostics@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a" resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a"
@ -3956,6 +4103,11 @@ ejs@^3.0.1:
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.0.1.tgz#30c8f6ee9948502cc32e85c37a3f8b39b5a614a5" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.0.1.tgz#30c8f6ee9948502cc32e85c37a3f8b39b5a614a5"
integrity sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw== integrity sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==
ejs@~2.5.6:
version "2.5.9"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.9.tgz#7ba254582a560d267437109a68354112475b0ce5"
integrity sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==
electron-builder@^22.4.0: electron-builder@^22.4.0:
version "22.4.1" version "22.4.1"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.4.1.tgz#7a7a2cbd9955c90cecc36de32ecba7f565265bab" resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.4.1.tgz#7a7a2cbd9955c90cecc36de32ecba7f565265bab"
@ -3976,6 +4128,14 @@ electron-builder@^22.4.0:
update-notifier "^4.1.0" update-notifier "^4.1.0"
yargs "^15.1.0" yargs "^15.1.0"
electron-chromedriver@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/electron-chromedriver/-/electron-chromedriver-6.0.0.tgz#a91b940c83f1c42ced52c9ef0605d8721613a8a2"
integrity sha512-UIhRl0sN5flfUjqActXsFrZQU1NmBObvlxzPnyeud8vhR67TllXCoqfvhQJmIrJAJJK+5M1DFhJ5iTGT++dvkg==
dependencies:
electron-download "^4.1.1"
extract-zip "^1.6.7"
electron-devtools-installer@^2.2.4: electron-devtools-installer@^2.2.4:
version "2.2.4" version "2.2.4"
resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-2.2.4.tgz#261a50337e37121d338b966f07922eb4939a8763" resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-2.2.4.tgz#261a50337e37121d338b966f07922eb4939a8763"
@ -3986,7 +4146,7 @@ electron-devtools-installer@^2.2.4:
rimraf "^2.5.2" rimraf "^2.5.2"
semver "^5.3.0" semver "^5.3.0"
electron-download@^4.1.0: electron-download@^4.1.0, electron-download@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8" resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8"
integrity sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg== integrity sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==
@ -4649,6 +4809,15 @@ extend@~3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
external-editor@^2.0.4:
version "2.2.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5"
integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==
dependencies:
chardet "^0.4.0"
iconv-lite "^0.4.17"
tmp "^0.0.33"
external-editor@^3.0.3: external-editor@^3.0.3:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
@ -4682,6 +4851,16 @@ extract-zip@^1.0.3:
mkdirp "0.5.1" mkdirp "0.5.1"
yauzl "2.4.1" yauzl "2.4.1"
extract-zip@^1.6.7:
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: extsprintf@1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@ -4750,6 +4929,13 @@ fd-slicer@~1.0.1:
dependencies: dependencies:
pend "~1.2.0" pend "~1.2.0"
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
dependencies:
pend "~1.2.0"
fecha@^2.3.3: fecha@^2.3.3:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd" resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd"
@ -4986,6 +5172,11 @@ from2@^2.1.0, from2@^2.1.1:
inherits "^2.0.1" inherits "^2.0.1"
readable-stream "^2.0.0" readable-stream "^2.0.0"
fs-constants@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs-extra@^4.0.1, fs-extra@^4.0.3: fs-extra@^4.0.1, fs-extra@^4.0.3:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
@ -5084,7 +5275,7 @@ gauge@~2.7.3:
strip-ansi "^3.0.1" strip-ansi "^3.0.1"
wide-align "^1.1.0" wide-align "^1.1.0"
gaze@^1.0.0: gaze@^1.0.0, gaze@~1.1.2:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a"
integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==
@ -5303,6 +5494,11 @@ got@^9.6.0:
to-readable-stream "^1.0.0" to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0" url-parse-lax "^3.0.0"
graceful-fs@^4.1.0:
version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
@ -5313,6 +5509,11 @@ graceful-fs@^4.1.15:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02"
integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==
grapheme-splitter@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
growly@^1.3.0: growly@^1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@ -5370,6 +5571,11 @@ has-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
has-flag@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=
has-flag@^3.0.0: has-flag@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@ -5687,7 +5893,7 @@ https-proxy-agent@^3.0.1:
agent-base "^4.3.0" agent-base "^4.3.0"
debug "^3.1.0" debug "^3.1.0"
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24" version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@ -5835,6 +6041,26 @@ inquirer@^6.4.1:
strip-ansi "^5.1.0" strip-ansi "^5.1.0"
through "^2.3.6" through "^2.3.6"
inquirer@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.0"
cli-cursor "^2.1.0"
cli-width "^2.0.0"
external-editor "^2.0.4"
figures "^2.0.0"
lodash "^4.3.0"
mute-stream "0.0.7"
run-async "^2.2.0"
rx-lite "^4.0.8"
rx-lite-aggregates "^4.0.8"
string-width "^2.1.0"
strip-ansi "^4.0.0"
through "^2.3.6"
internal-ip@^4.3.0: internal-ip@^4.3.0:
version "4.3.0" version "4.3.0"
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"
@ -6971,6 +7197,13 @@ lazy-val@^1.0.4:
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65" resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65"
integrity sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q== integrity sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==
lazystream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=
dependencies:
readable-stream "^2.0.5"
lcid@^1.0.0: lcid@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
@ -7148,7 +7381,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.5, lodash@^4.2.0, lodash@~4.17.10: lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.8.0, lodash@~4.17.10:
version "4.17.15" version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@ -7519,7 +7752,7 @@ minimist@0.0.8:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5" version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
@ -7595,6 +7828,13 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@
dependencies: dependencies:
minimist "0.0.8" minimist "0.0.8"
mkdirp@^0.5.4:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
dependencies:
minimist "^1.2.5"
mock-fs@^4.10.3: mock-fs@^4.10.3:
version "4.10.3" version "4.10.3"
resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.10.3.tgz#d0550663dd2b5d33a7c1b8713c6925aab07a04ae" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.10.3.tgz#d0550663dd2b5d33a7c1b8713c6925aab07a04ae"
@ -7896,7 +8136,7 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-
semver "2 || 3 || 4 || 5" semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1" validate-npm-package-license "^3.0.1"
normalize-path@^2.1.1: normalize-path@^2.0.0, normalize-path@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
@ -7942,6 +8182,11 @@ npm-bundled@^1.0.1:
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd"
integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==
npm-install-package@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/npm-install-package/-/npm-install-package-2.1.0.tgz#d7efe3cfcd7ab00614b896ea53119dc9ab259125"
integrity sha1-1+/jz816sAYUuJbqUxGdyaslkSU=
npm-packlist@^1.1.6: npm-packlist@^1.1.6:
version "1.4.4" version "1.4.4"
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44"
@ -8152,7 +8397,7 @@ opn@^5.5.0:
dependencies: dependencies:
is-wsl "^1.1.0" is-wsl "^1.1.0"
optimist@^0.6.1: optimist@^0.6.1, optimist@~0.6.1:
version "0.6.1" version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY=
@ -9126,7 +9371,7 @@ pupa@^2.0.1:
dependencies: dependencies:
escape-goat "^2.0.0" escape-goat "^2.0.0"
q@^1.1.2: q@^1.1.2, q@~1.5.0:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
@ -9305,7 +9550,7 @@ read-pkg@^4.0.1:
string_decoder "~1.1.1" string_decoder "~1.1.1"
util-deprecate "~1.0.1" util-deprecate "~1.0.1"
readable-stream@^2.2.2: readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5:
version "2.3.7" version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@ -9396,6 +9641,11 @@ regenerate@^1.4.0:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
regenerator-runtime@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
regenerator-transform@^0.14.0: regenerator-transform@^0.14.0:
version "0.14.1" version "0.14.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
@ -9679,6 +9929,11 @@ rfc4648@^1.3.0:
resolved "https://registry.yarnpkg.com/rfc4648/-/rfc4648-1.3.0.tgz#2a69c76f05bc0e388feab933672de9b492af95f1" resolved "https://registry.yarnpkg.com/rfc4648/-/rfc4648-1.3.0.tgz#2a69c76f05bc0e388feab933672de9b492af95f1"
integrity sha512-x36K12jOflpm1V8QjPq3I+pt7Z1xzeZIjiC8J2Oxd7bE1efTrOG241DTYVJByP/SxR9jl1t7iZqYxDX864jgBQ== integrity sha512-x36K12jOflpm1V8QjPq3I+pt7Z1xzeZIjiC8J2Oxd7bE1efTrOG241DTYVJByP/SxR9jl1t7iZqYxDX864jgBQ==
rgb2hex@^0.1.9:
version "0.1.10"
resolved "https://registry.yarnpkg.com/rgb2hex/-/rgb2hex-0.1.10.tgz#4fdd432665273e2d5900434940ceba0a04c8a8a8"
integrity sha512-vKz+kzolWbL3rke/xeTE2+6vHmZnNxGyDnaVW4OckntAIcc7DcZzWkQSfxMDwqHS8vhgySnIFyBUH7lIk6PxvQ==
rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
version "2.7.1" version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
@ -9720,6 +9975,18 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies: dependencies:
aproba "^1.1.1" aproba "^1.1.1"
rx-lite-aggregates@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=
dependencies:
rx-lite "*"
rx-lite@*, rx-lite@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=
rxjs@^6.4.0: rxjs@^6.4.0:
version "6.5.3" version "6.5.3"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"
@ -10143,6 +10410,17 @@ source-map-resolve@^0.5.0:
source-map-url "^0.4.0" source-map-url "^0.4.0"
urix "^0.1.0" urix "^0.1.0"
source-map-resolve@^0.5.2:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
dependencies:
atob "^2.1.2"
decode-uri-component "^0.2.0"
resolve-url "^0.2.1"
source-map-url "^0.4.0"
urix "^0.1.0"
source-map-support@^0.5.12, source-map-support@^0.5.13, source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12: source-map-support@^0.5.12, source-map-support@^0.5.13, source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12:
version "0.5.13" version "0.5.13"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
@ -10235,6 +10513,17 @@ spdy@^4.0.1:
select-hose "^2.0.0" select-hose "^2.0.0"
spdy-transport "^3.0.0" spdy-transport "^3.0.0"
spectron@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/spectron/-/spectron-8.0.0.tgz#86e83c5dccb174850c052e2e718d5b1158764a52"
integrity sha512-MI9+lAamDnw7S0vKaxXjU3g5qaW5KANaFLc+Hgq+QmMCkQbZLt6ukFFGfalmwIuYrmq+yWQPCD4CXgt3VSHrLA==
dependencies:
dev-null "^0.1.1"
electron-chromedriver "^6.0.0"
request "^2.87.0"
split "^1.0.0"
webdriverio "^4.13.0"
speedometer@~0.1.2: speedometer@~0.1.2:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d"
@ -10247,7 +10536,7 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies: dependencies:
extend-shallow "^3.0.0" extend-shallow "^3.0.0"
split@^1.0.1: split@^1.0.0, split@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
@ -10549,6 +10838,13 @@ supports-color@^7.1.0:
dependencies: dependencies:
has-flag "^4.0.0" has-flag "^4.0.0"
supports-color@~5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.0.1.tgz#1c5331f22250c84202805b2f17adf16699f3a39a"
integrity sha512-7FQGOlSQ+AQxBNXJpVDj8efTA/FtyB5wcNE1omXXJ0cq6jm1jjDwuROlYDbnzHqdNPqliWFhcioCWSyav+xBnA==
dependencies:
has-flag "^2.0.0"
svgo@^0.7.0: svgo@^0.7.0:
version "0.7.2" version "0.7.2"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"
@ -10601,6 +10897,19 @@ tapable@^1.0.0, tapable@^1.1.0:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar-stream@^1.5.0:
version "1.6.2"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
dependencies:
bl "^1.0.0"
buffer-alloc "^1.2.0"
end-of-stream "^1.0.0"
fs-constants "^1.0.0"
readable-stream "^2.3.0"
to-buffer "^1.1.1"
xtend "^4.0.0"
tar@^2.0.0: tar@^2.0.0:
version "2.2.2" version "2.2.2"
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
@ -10800,6 +11109,11 @@ to-arraybuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
to-buffer@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
to-fast-properties@^2.0.0: to-fast-properties@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@ -11280,7 +11594,7 @@ url-to-options@^1.0.1:
resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"
integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=
url@^0.11.0: url@^0.11.0, url@~0.11.0:
version "0.11.0" version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
@ -11512,6 +11826,39 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies: dependencies:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
wdio-dot-reporter@~0.0.8:
version "0.0.10"
resolved "https://registry.yarnpkg.com/wdio-dot-reporter/-/wdio-dot-reporter-0.0.10.tgz#facfb7c9c5984149951f59cbc3cd0752101cf0e0"
integrity sha512-A0TCk2JdZEn3M1DSG9YYbNRcGdx/YRw19lTiRpgwzH4qqWkO/oRDZRmi3Snn4L2j54KKTfPalBhlOtc8fojVgg==
webdriverio@^4.13.0:
version "4.14.4"
resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-4.14.4.tgz#f7a94e9a6530819796088f42b009833d83de0386"
integrity sha512-Knp2vzuzP5c5ybgLu+zTwy/l1Gh0bRP4zAr8NWcrStbuomm9Krn9oRF0rZucT6AyORpXinETzmeowFwIoo7mNA==
dependencies:
archiver "~2.1.0"
babel-runtime "^6.26.0"
css-parse "^2.0.0"
css-value "~0.0.1"
deepmerge "~2.0.1"
ejs "~2.5.6"
gaze "~1.1.2"
glob "~7.1.1"
grapheme-splitter "^1.0.2"
inquirer "~3.3.0"
json-stringify-safe "~5.0.1"
mkdirp "~0.5.1"
npm-install-package "~2.1.0"
optimist "~0.6.1"
q "~1.5.0"
request "^2.83.0"
rgb2hex "^0.1.9"
safe-buffer "~5.1.1"
supports-color "~5.0.0"
url "~0.11.0"
wdio-dot-reporter "~0.0.8"
wgxpath "~1.0.0"
webidl-conversions@^4.0.2: webidl-conversions@^4.0.2:
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@ -11645,9 +11992,14 @@ websocket-driver@>=0.5.1:
websocket-extensions ">=0.1.1" websocket-extensions ">=0.1.1"
websocket-extensions@>=0.1.1: websocket-extensions@>=0.1.1:
version "0.1.3" version "0.1.4"
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
wgxpath@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wgxpath/-/wgxpath-1.0.0.tgz#eef8a4b9d558cc495ad3a9a2b751597ecd9af690"
integrity sha1-7vikudVYzEla06mit1FZfs2a9pA=
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
version "1.0.5" version "1.0.5"
@ -12084,7 +12436,25 @@ yauzl@2.4.1:
dependencies: dependencies:
fd-slicer "~1.0.1" fd-slicer "~1.0.1"
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=
dependencies:
buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0"
yn@^3.0.0: yn@^3.0.0:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
zip-stream@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04"
integrity sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=
dependencies:
archiver-utils "^1.3.0"
compress-commons "^1.2.0"
lodash "^4.8.0"
readable-stream "^2.0.0"