Merge branch 'master' into eide/shortcut-plugin
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-explore': patch
|
||||
---
|
||||
|
||||
Add "Organization" tab with a diagram
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
'@backstage/create-app': patch
|
||||
'@backstage/plugin-catalog-graphql': patch
|
||||
---
|
||||
|
||||
chore: bump `ts-node` versions to 9.1.1
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/catalog-model': patch
|
||||
---
|
||||
|
||||
Renamed parameters to input in template schema
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Show error on task page if task does not exist.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
update plugins created to use react-use 17.2.4
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/core': patch
|
||||
'@backstage/plugin-api-docs': patch
|
||||
---
|
||||
|
||||
Fix state persisted in the URL make search input in the table toolbar lose their
|
||||
focus.
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
'@backstage/core': patch
|
||||
'@backstage/core-api': patch
|
||||
'@backstage/integration-react': patch
|
||||
'@backstage/plugin-api-docs': patch
|
||||
'@backstage/plugin-badges': patch
|
||||
'@backstage/plugin-bitrise': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-circleci': patch
|
||||
'@backstage/plugin-cloudbuild': patch
|
||||
'@backstage/plugin-code-coverage': patch
|
||||
'@backstage/plugin-config-schema': patch
|
||||
'@backstage/plugin-cost-insights': patch
|
||||
'@backstage/plugin-explore': patch
|
||||
'@backstage/plugin-fossa': patch
|
||||
'@backstage/plugin-gcp-projects': patch
|
||||
'@backstage/plugin-github-actions': patch
|
||||
'@backstage/plugin-github-deployments': patch
|
||||
'@backstage/plugin-gitops-profiles': patch
|
||||
'@backstage/plugin-graphiql': patch
|
||||
'@backstage/plugin-jenkins': patch
|
||||
'@backstage/plugin-kafka': patch
|
||||
'@backstage/plugin-kubernetes': patch
|
||||
'@backstage/plugin-lighthouse': patch
|
||||
'@backstage/plugin-newrelic': patch
|
||||
'@backstage/plugin-org': patch
|
||||
'@backstage/plugin-pagerduty': patch
|
||||
'@backstage/plugin-register-component': patch
|
||||
'@backstage/plugin-rollbar': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
'@backstage/plugin-search': patch
|
||||
'@backstage/plugin-sentry': patch
|
||||
'@backstage/plugin-sonarqube': patch
|
||||
'@backstage/plugin-splunk-on-call': patch
|
||||
'@backstage/plugin-tech-radar': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
'@backstage/plugin-todo': patch
|
||||
'@backstage/plugin-user-settings': patch
|
||||
'@backstage/plugin-welcome': patch
|
||||
---
|
||||
|
||||
chore: bump `react-use` dependency in all packages
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-backend': patch
|
||||
---
|
||||
|
||||
Add possibility to configure TLS verification for `gke` type clusters
|
||||
@@ -33,6 +33,7 @@ kubernetes:
|
||||
- type: 'gke'
|
||||
projectId: 'gke-clusters'
|
||||
region: 'europe-west1'
|
||||
skipTLSVerify: true
|
||||
```
|
||||
|
||||
### `serviceLocatorMethod`
|
||||
@@ -129,6 +130,11 @@ The Google Cloud project to look for Kubernetes clusters in.
|
||||
The Google Cloud region to look for Kubernetes clusters in. Defaults to all
|
||||
regions.
|
||||
|
||||
##### `skipTLSVerify`
|
||||
|
||||
This determines whether or not the Kubernetes client verifies the TLS
|
||||
certificate presented by the API server. Defaults to `false`.
|
||||
|
||||
### `customResources` (optional)
|
||||
|
||||
Configures which [custom resources][3] to look for when returning an entity's
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
"react-hot-loader": "^4.12.21",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -514,7 +514,7 @@ export interface TemplateEntityV1beta2 extends Entity {
|
||||
id?: string;
|
||||
name?: string;
|
||||
action: string;
|
||||
parameters?: JsonObject;
|
||||
input?: JsonObject;
|
||||
}>;
|
||||
output?: {
|
||||
[name: string]: string;
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('templateEntityV1beta2Validator', () => {
|
||||
id: 'fetch',
|
||||
name: 'Fetch',
|
||||
action: 'fetch:plan',
|
||||
parameters: {
|
||||
input: {
|
||||
url: './template',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -38,7 +38,7 @@ export interface TemplateEntityV1beta2 extends Entity {
|
||||
id?: string;
|
||||
name?: string;
|
||||
action: string;
|
||||
parameters?: JsonObject;
|
||||
input?: JsonObject;
|
||||
}>;
|
||||
output?: { [name: string]: string };
|
||||
};
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
"type": "string",
|
||||
"description": "The name of the action to execute."
|
||||
},
|
||||
"parameters": {
|
||||
"input": {
|
||||
"type": "object",
|
||||
"description": "A templated object describing the inputs to the action."
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"del": "^5.1.0",
|
||||
"mock-fs": "^4.13.0",
|
||||
"nodemon": "^2.0.2",
|
||||
"ts-node": "^8.6.2"
|
||||
"ts-node": "^9.1.1"
|
||||
},
|
||||
"files": [
|
||||
"asset-types",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^{{version '@backstage/cli'}}",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.12.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"react-sparklines": "^1.7.0",
|
||||
"react-syntax-highlighter": "^15.4.3",
|
||||
"react-text-truncate": "^0.16.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"remark-gfm": "^1.0.0",
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
makeStyles,
|
||||
Typography,
|
||||
useTheme,
|
||||
withStyles,
|
||||
} from '@material-ui/core';
|
||||
// Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51
|
||||
import AddBox from '@material-ui/icons/AddBox';
|
||||
@@ -49,6 +50,7 @@ import MTable, {
|
||||
} from 'material-table';
|
||||
import React, {
|
||||
forwardRef,
|
||||
MutableRefObject,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
@@ -100,19 +102,20 @@ function extractValueByField(data: any, field: string): any | undefined {
|
||||
return value;
|
||||
}
|
||||
|
||||
const useHeaderStyles = makeStyles<BackstageTheme>(theme => ({
|
||||
const StyledMTableHeader = withStyles(theme => ({
|
||||
header: {
|
||||
padding: theme.spacing(1, 2, 1, 2.5),
|
||||
borderTop: `1px solid ${theme.palette.grey.A100}`,
|
||||
borderBottom: `1px solid ${theme.palette.grey.A100}`,
|
||||
color: theme.palette.textSubtle,
|
||||
// withStyles hasn't a generic overload for theme
|
||||
color: (theme as BackstageTheme).palette.textSubtle,
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
position: 'static',
|
||||
wordBreak: 'normal',
|
||||
},
|
||||
}));
|
||||
}))(MTableHeader);
|
||||
|
||||
const useToolbarStyles = makeStyles<BackstageTheme>(theme => ({
|
||||
const StyledMTableToolbar = withStyles(theme => ({
|
||||
root: {
|
||||
padding: theme.spacing(3, 0, 2.5, 2.5),
|
||||
},
|
||||
@@ -124,7 +127,7 @@ const useToolbarStyles = makeStyles<BackstageTheme>(theme => ({
|
||||
searchField: {
|
||||
paddingRight: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
}))(MTableToolbar);
|
||||
|
||||
const useFilterStyles = makeStyles<BackstageTheme>(() => ({
|
||||
root: {
|
||||
@@ -208,6 +211,59 @@ export interface TableProps<T extends object = {}>
|
||||
onStateChange?: (state: TableState) => any;
|
||||
}
|
||||
|
||||
export function TableToolbar(toolbarProps: {
|
||||
toolbarRef: MutableRefObject<any>;
|
||||
setSearch: (value: string) => void;
|
||||
onSearchChanged: (value: string) => void;
|
||||
toggleFilters: () => void;
|
||||
hasFilters: boolean;
|
||||
selectedFiltersLength: number;
|
||||
}) {
|
||||
const {
|
||||
toolbarRef,
|
||||
setSearch,
|
||||
hasFilters,
|
||||
selectedFiltersLength,
|
||||
toggleFilters,
|
||||
} = toolbarProps;
|
||||
const filtersClasses = useFilterStyles();
|
||||
const onSearchChanged = useCallback(
|
||||
(searchText: string) => {
|
||||
toolbarProps.onSearchChanged(searchText);
|
||||
setSearch(searchText);
|
||||
},
|
||||
[toolbarProps, setSearch],
|
||||
);
|
||||
|
||||
if (hasFilters) {
|
||||
return (
|
||||
<div className={filtersClasses.root}>
|
||||
<div className={filtersClasses.root}>
|
||||
<IconButton onClick={toggleFilters} aria-label="filter list">
|
||||
<FilterList />
|
||||
</IconButton>
|
||||
<Typography className={filtersClasses.title}>
|
||||
Filters ({selectedFiltersLength})
|
||||
</Typography>
|
||||
</div>
|
||||
<StyledMTableToolbar
|
||||
{...toolbarProps}
|
||||
ref={toolbarRef}
|
||||
onSearchChanged={onSearchChanged}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledMTableToolbar
|
||||
{...toolbarProps}
|
||||
ref={toolbarRef}
|
||||
onSearchChanged={onSearchChanged}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function Table<T extends object = {}>({
|
||||
columns,
|
||||
options,
|
||||
@@ -219,10 +275,7 @@ export function Table<T extends object = {}>({
|
||||
onStateChange,
|
||||
...props
|
||||
}: TableProps<T>) {
|
||||
const headerClasses = useHeaderStyles();
|
||||
const toolbarClasses = useToolbarStyles();
|
||||
const tableClasses = useTableStyles();
|
||||
const filtersClasses = useFilterStyles();
|
||||
|
||||
const { data, ...propsWithoutData } = props;
|
||||
|
||||
@@ -230,9 +283,12 @@ export function Table<T extends object = {}>({
|
||||
|
||||
const calculatedInitialState = { ...defaultInitialState, ...initialState };
|
||||
|
||||
const [filtersOpen, toggleFilters] = useState(
|
||||
const [filtersOpen, setFiltersOpen] = useState(
|
||||
calculatedInitialState.filtersOpen,
|
||||
);
|
||||
const toggleFilters = useCallback(() => setFiltersOpen(v => !v), [
|
||||
setFiltersOpen,
|
||||
]);
|
||||
const [selectedFiltersLength, setSelectedFiltersLength] = useState(0);
|
||||
const [tableData, setTableData] = useState(data as any[]);
|
||||
const [selectedFilters, setSelectedFilters] = useState(
|
||||
@@ -379,64 +435,32 @@ export function Table<T extends object = {}>({
|
||||
}));
|
||||
};
|
||||
|
||||
const hasFilters = !!filters?.length;
|
||||
const Toolbar = useCallback(
|
||||
toolbarProps => {
|
||||
const onSearchChanged = (searchText: string) => {
|
||||
toolbarProps.onSearchChanged(searchText);
|
||||
setSearch(searchText);
|
||||
};
|
||||
|
||||
if (filters?.length) {
|
||||
return (
|
||||
<div className={filtersClasses.root}>
|
||||
<div className={filtersClasses.root}>
|
||||
<IconButton
|
||||
onClick={() => toggleFilters(el => !el)}
|
||||
aria-label="filter list"
|
||||
>
|
||||
<FilterList />
|
||||
</IconButton>
|
||||
<Typography className={filtersClasses.title}>
|
||||
Filters ({selectedFiltersLength})
|
||||
</Typography>
|
||||
</div>
|
||||
<MTableToolbar
|
||||
classes={toolbarClasses}
|
||||
{...toolbarProps}
|
||||
ref={toolbarRef}
|
||||
onSearchChanged={onSearchChanged}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<MTableToolbar
|
||||
classes={toolbarClasses}
|
||||
<TableToolbar
|
||||
toolbarRef={toolbarRef}
|
||||
setSearch={setSearch}
|
||||
hasFilters={hasFilters}
|
||||
selectedFiltersLength={selectedFiltersLength}
|
||||
toggleFilters={toggleFilters}
|
||||
{...toolbarProps}
|
||||
ref={toolbarRef}
|
||||
onSearchChanged={onSearchChanged}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[
|
||||
filters?.length,
|
||||
selectedFiltersLength,
|
||||
toggleFilters,
|
||||
toolbarClasses,
|
||||
filtersClasses,
|
||||
setSearch,
|
||||
toolbarRef,
|
||||
],
|
||||
[toggleFilters, hasFilters, selectedFiltersLength, setSearch, toolbarRef],
|
||||
);
|
||||
|
||||
const hasNoRows = typeof data !== 'function' && data.length === 0;
|
||||
const columnCount = columns.length;
|
||||
const Body = useCallback(
|
||||
bodyProps => {
|
||||
if (emptyContent && typeof data !== 'function' && data.length === 0) {
|
||||
if (emptyContent && hasNoRows) {
|
||||
return (
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colSpan={columns.length}>{emptyContent}</td>
|
||||
<td colSpan={columnCount}>{emptyContent}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
);
|
||||
@@ -444,7 +468,7 @@ export function Table<T extends object = {}>({
|
||||
|
||||
return <MTableBody {...bodyProps} />;
|
||||
},
|
||||
[data, emptyContent, columns],
|
||||
[hasNoRows, emptyContent, columnCount],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -458,9 +482,7 @@ export function Table<T extends object = {}>({
|
||||
)}
|
||||
<MTable<T>
|
||||
components={{
|
||||
Header: headerProps => (
|
||||
<MTableHeader classes={headerClasses} {...headerProps} />
|
||||
),
|
||||
Header: StyledMTableHeader,
|
||||
Toolbar,
|
||||
Body,
|
||||
}}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { isEqual } from 'lodash';
|
||||
import qs from 'qs';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useDebounce } from 'react-use';
|
||||
|
||||
function stringify(queryParams: any): string {
|
||||
@@ -58,36 +58,37 @@ type SetQueryParams<T> = (params: T) => void;
|
||||
|
||||
export function useQueryParamState<T>(
|
||||
stateName: string,
|
||||
debounceTime: number = 100,
|
||||
/** @deprecated Don't configure a custom debouceTime */
|
||||
debounceTime: number = 250,
|
||||
): [T | undefined, SetQueryParams<T>] {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const searchParamsString = searchParams.toString();
|
||||
const [queryParamState, setQueryParamState] = useState<T>(
|
||||
extractState(location.search, stateName),
|
||||
extractState(searchParamsString, stateName),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const newState = extractState(location.search, stateName);
|
||||
const newState = extractState(searchParamsString, stateName);
|
||||
|
||||
setQueryParamState(oldState =>
|
||||
isEqual(newState, oldState) ? oldState : newState,
|
||||
);
|
||||
}, [location, stateName]);
|
||||
}, [searchParamsString, setQueryParamState, stateName]);
|
||||
|
||||
useDebounce(
|
||||
() => {
|
||||
const queryString = joinQueryString(
|
||||
location.search,
|
||||
searchParamsString,
|
||||
stateName,
|
||||
queryParamState,
|
||||
);
|
||||
|
||||
if (location.search !== queryString) {
|
||||
navigate({ ...location, search: `?${queryString}` }, { replace: true });
|
||||
if (searchParamsString !== queryString) {
|
||||
setSearchParams(queryString, { replace: true });
|
||||
}
|
||||
},
|
||||
debounceTime,
|
||||
[queryParamState],
|
||||
[setSearchParams, queryParamState, searchParamsString, stateName],
|
||||
);
|
||||
|
||||
return [queryParamState, setQueryParamState];
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"@types/inquirer": "^7.3.1",
|
||||
"@types/react-dev-utils": "^9.0.4",
|
||||
"@types/recursive-readdir": "^2.2.0",
|
||||
"ts-node": "^8.6.2"
|
||||
"ts-node": "^9.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@backstage/backend-common": "*",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"commander": "^6.1.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"github-slugger": "^1.3.0",
|
||||
"ts-node": "^8.6.2",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"handlebars": "^4.7.3",
|
||||
"pgtools": "^0.3.0",
|
||||
"tree-kill": "^1.2.2",
|
||||
"ts-node": "^8.6.2",
|
||||
"ts-node": "^9.1.1",
|
||||
"zombie": "^6.1.4"
|
||||
},
|
||||
"nodemonConfig": {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.3",
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"swagger-ui-react": "^3.37.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -156,7 +156,6 @@ export const ApiExplorerTable = ({
|
||||
}: ExplorerTableProps) => {
|
||||
const [queryParamState, setQueryParamState] = useQueryParamState<TableState>(
|
||||
'apiTable',
|
||||
500,
|
||||
);
|
||||
|
||||
if (error) {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"qs": "^6.9.6",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"recharts": "^1.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -185,7 +185,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase {
|
||||
),
|
||||
-- All the nodes that can be reached upwards from the descendants
|
||||
ancestors(root_id, via_entity_ref, to_entity_ref) AS (
|
||||
SELECT NULL, entity_ref, entity_ref
|
||||
SELECT CAST(NULL as INT), entity_ref, entity_ref
|
||||
FROM descendants
|
||||
UNION
|
||||
SELECT
|
||||
@@ -235,7 +235,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase {
|
||||
.withRecursive('ancestors', function ancestors(outer) {
|
||||
return outer
|
||||
.select({
|
||||
root_id: tx.raw('NULL', []),
|
||||
root_id: tx.raw('CAST(NULL as INT)', []),
|
||||
via_entity_ref: 'entity_ref',
|
||||
to_entity_ref: 'entity_ref',
|
||||
})
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
"eslint-plugin-graphql": "^4.0.0",
|
||||
"msw": "^0.21.2",
|
||||
"supertest": "^6.1.3",
|
||||
"ts-node": "^8.10.2"
|
||||
"ts-node": "^9.1.1"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"react-hook-form": "^6.15.4",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"yaml": "^1.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"react-helmet": "6.1.0",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"react-lazylog": "^4.5.2",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"react-lazylog": "^4.5.3",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"recharts": "^1.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"zen-observable": "^0.8.15",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"recharts": "^1.8.5",
|
||||
"regression": "^2.0.1",
|
||||
"yup": "^0.29.3"
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import { TabbedLayout } from '@backstage/core';
|
||||
import React from 'react';
|
||||
import { DomainExplorerContent } from '../DomainExplorerContent';
|
||||
import { GroupsExplorerContent } from '../GroupsExplorerContent';
|
||||
import { ToolExplorerContent } from '../ToolExplorerContent';
|
||||
|
||||
export const ExploreTabs = () => (
|
||||
@@ -23,6 +24,9 @@ export const ExploreTabs = () => (
|
||||
<TabbedLayout.Route path="domains" title="Domains">
|
||||
<DomainExplorerContent />
|
||||
</TabbedLayout.Route>
|
||||
<TabbedLayout.Route path="groups" title="Groups">
|
||||
<GroupsExplorerContent />
|
||||
</TabbedLayout.Route>
|
||||
<TabbedLayout.Route path="tools" title="Tools">
|
||||
<ToolExplorerContent />
|
||||
</TabbedLayout.Route>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import {
|
||||
catalogApiRef,
|
||||
CatalogApi,
|
||||
entityRouteRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import React from 'react';
|
||||
import { GroupsDiagram } from './GroupsDiagram';
|
||||
|
||||
describe('<GroupsDiagram />', () => {
|
||||
beforeAll(() => {
|
||||
Object.defineProperty(window.SVGElement.prototype, 'getBBox', {
|
||||
value: () => ({ width: 100, height: 100 }),
|
||||
configurable: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('shows groups', async () => {
|
||||
const catalogApi: Partial<CatalogApi> = {
|
||||
getEntities: () =>
|
||||
Promise.resolve({
|
||||
items: [
|
||||
{
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Group',
|
||||
metadata: {
|
||||
name: 'group-a',
|
||||
namespace: 'my-namespace',
|
||||
},
|
||||
spec: {
|
||||
type: 'organization',
|
||||
},
|
||||
},
|
||||
] as Entity[],
|
||||
}),
|
||||
};
|
||||
|
||||
const { getByText } = await renderInTestApp(
|
||||
<ApiProvider apis={ApiRegistry.from([[catalogApiRef, catalogApi]])}>
|
||||
<GroupsDiagram />
|
||||
</ApiProvider>,
|
||||
{
|
||||
mountedRoutes: {
|
||||
'/catalog/:namespace/:kind/:name': entityRouteRef,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(getByText('my-namespace/group-a')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
RELATION_CHILD_OF,
|
||||
stringifyEntityRef,
|
||||
parseEntityRef,
|
||||
} from '@backstage/catalog-model';
|
||||
import {
|
||||
catalogApiRef,
|
||||
entityRouteRef,
|
||||
getEntityRelations,
|
||||
formatEntityRefTitle,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
DependencyGraph,
|
||||
DependencyGraphTypes,
|
||||
Progress,
|
||||
useApi,
|
||||
ResponseErrorPanel,
|
||||
Link,
|
||||
useRouteRef,
|
||||
configApiRef,
|
||||
} from '@backstage/core';
|
||||
import { makeStyles, Typography } from '@material-ui/core';
|
||||
import ZoomOutMap from '@material-ui/icons/ZoomOutMap';
|
||||
import React from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import { BackstageTheme } from '@backstage/theme';
|
||||
|
||||
const useStyles = makeStyles((theme: BackstageTheme) => ({
|
||||
organizationNode: {
|
||||
fill: 'coral',
|
||||
stroke: theme.palette.border,
|
||||
},
|
||||
groupNode: {
|
||||
fill: 'yellowgreen',
|
||||
stroke: theme.palette.border,
|
||||
},
|
||||
}));
|
||||
|
||||
function RenderNode(props: DependencyGraphTypes.RenderNodeProps<any>) {
|
||||
const classes = useStyles();
|
||||
const catalogEntityRoute = useRouteRef(entityRouteRef);
|
||||
|
||||
if (props.node.id === 'root') {
|
||||
return (
|
||||
<g>
|
||||
<rect
|
||||
width={180}
|
||||
height={80}
|
||||
rx={20}
|
||||
className={classes.organizationNode}
|
||||
/>
|
||||
<text
|
||||
x={90}
|
||||
y={45}
|
||||
textAnchor="middle"
|
||||
alignmentBaseline="baseline"
|
||||
style={{ fontWeight: 'bold' }}
|
||||
>
|
||||
{props.node.name}
|
||||
</text>
|
||||
</g>
|
||||
);
|
||||
}
|
||||
|
||||
const ref = parseEntityRef(props.node.id);
|
||||
|
||||
return (
|
||||
<g>
|
||||
<rect width={180} height={80} rx={20} className={classes.groupNode} />
|
||||
<Link
|
||||
to={catalogEntityRoute({
|
||||
kind: ref.kind,
|
||||
namespace: ref.namespace,
|
||||
name: ref.name,
|
||||
})}
|
||||
>
|
||||
<text
|
||||
x={90}
|
||||
y={45}
|
||||
textAnchor="middle"
|
||||
alignmentBaseline="baseline"
|
||||
style={{ fontWeight: 'bold' }}
|
||||
>
|
||||
{props.node.name}
|
||||
</text>
|
||||
</Link>
|
||||
</g>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically generates a diagram of groups registered in the catalog.
|
||||
*/
|
||||
export function GroupsDiagram() {
|
||||
const nodes = new Array<{ id: string; kind: string; name: string }>();
|
||||
const edges = new Array<{ from: string; to: string; label: string }>();
|
||||
|
||||
const configApi = useApi(configApiRef);
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const organizationName =
|
||||
configApi.getOptionalString('organization.name') ?? 'Backstage';
|
||||
const { loading, error, value: catalogResponse } = useAsync(() => {
|
||||
return catalogApi.getEntities({
|
||||
filter: {
|
||||
kind: ['Group'],
|
||||
},
|
||||
});
|
||||
}, [catalogApi]);
|
||||
|
||||
if (loading) {
|
||||
return <Progress />;
|
||||
} else if (error) {
|
||||
return <ResponseErrorPanel error={error} />;
|
||||
}
|
||||
|
||||
// the root of this diagram is the organization
|
||||
nodes.push({
|
||||
id: 'root',
|
||||
kind: 'Organization',
|
||||
name: organizationName,
|
||||
});
|
||||
|
||||
for (const catalogItem of catalogResponse?.items || []) {
|
||||
const currentItemId = stringifyEntityRef(catalogItem);
|
||||
|
||||
nodes.push({
|
||||
id: stringifyEntityRef(catalogItem),
|
||||
kind: catalogItem.kind,
|
||||
name: formatEntityRefTitle(catalogItem, { defaultKind: 'Group' }),
|
||||
});
|
||||
|
||||
// Edge to parent
|
||||
const catalogItemRelations_childOf = getEntityRelations(
|
||||
catalogItem,
|
||||
RELATION_CHILD_OF,
|
||||
);
|
||||
|
||||
// if no parent is found, link the node to the root
|
||||
if (catalogItemRelations_childOf.length === 0) {
|
||||
edges.push({
|
||||
from: currentItemId,
|
||||
to: 'root',
|
||||
label: '',
|
||||
});
|
||||
}
|
||||
|
||||
catalogItemRelations_childOf.forEach(relation => {
|
||||
edges.push({
|
||||
from: currentItemId,
|
||||
to: stringifyEntityRef(relation),
|
||||
label: '',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<DependencyGraph
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
nodeMargin={10}
|
||||
direction={DependencyGraphTypes.Direction.RIGHT_LEFT}
|
||||
renderNode={RenderNode}
|
||||
/>
|
||||
<Typography
|
||||
variant="caption"
|
||||
style={{ display: 'block', textAlign: 'right' }}
|
||||
>
|
||||
<ZoomOutMap style={{ verticalAlign: 'bottom' }} /> Use pinch & zoom
|
||||
to move around the diagram.
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { GroupsExplorerContent } from '../GroupsExplorerContent';
|
||||
|
||||
describe('<GroupsExplorerContent />', () => {
|
||||
const catalogApi: jest.Mocked<typeof catalogApiRef.T> = {
|
||||
addLocation: jest.fn(_a => new Promise(() => {})),
|
||||
getEntities: jest.fn(),
|
||||
getOriginLocationByEntity: jest.fn(),
|
||||
getLocationByEntity: jest.fn(),
|
||||
getLocationById: jest.fn(),
|
||||
removeLocationById: jest.fn(),
|
||||
removeEntityByUid: jest.fn(),
|
||||
getEntityByName: jest.fn(),
|
||||
};
|
||||
|
||||
const Wrapper = ({ children }: { children?: React.ReactNode }) => (
|
||||
<ApiProvider apis={ApiRegistry.with(catalogApiRef, catalogApi)}>
|
||||
{children}
|
||||
</ApiProvider>
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
||||
Object.defineProperty(window.SVGElement.prototype, 'getBBox', {
|
||||
value: () => ({ width: 100, height: 100 }),
|
||||
configurable: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a groups diagram', async () => {
|
||||
const entities: Entity[] = [
|
||||
{
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Group',
|
||||
metadata: {
|
||||
name: 'group-a',
|
||||
namespace: 'my-namespace',
|
||||
},
|
||||
spec: {
|
||||
type: 'organization',
|
||||
},
|
||||
},
|
||||
];
|
||||
catalogApi.getEntities.mockResolvedValue({ items: entities });
|
||||
|
||||
const { getByText } = await renderInTestApp(
|
||||
<Wrapper>
|
||||
<GroupsExplorerContent />
|
||||
</Wrapper>,
|
||||
{
|
||||
mountedRoutes: {
|
||||
'/catalog/:namespace/:kind/:name': entityRouteRef,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getByText('my-namespace/group-a')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a friendly error if it cannot collect domains', async () => {
|
||||
const catalogError = new Error('Network timeout');
|
||||
catalogApi.getEntities.mockRejectedValueOnce(catalogError);
|
||||
|
||||
const { getByText } = await renderInTestApp(
|
||||
<Wrapper>
|
||||
<GroupsExplorerContent />
|
||||
</Wrapper>,
|
||||
{
|
||||
mountedRoutes: {
|
||||
'/catalog/:namespace/:kind/:name': entityRouteRef,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(getByText(/Warning: Network timeout/)).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Content, ContentHeader, SupportButton } from '@backstage/core';
|
||||
import React from 'react';
|
||||
import { GroupsDiagram } from './GroupsDiagram';
|
||||
|
||||
export const GroupsExplorerContent = () => {
|
||||
return (
|
||||
<Content noPadding>
|
||||
<ContentHeader title="Groups">
|
||||
<SupportButton>Explore your groups.</SupportButton>
|
||||
</ContentHeader>
|
||||
|
||||
<GroupsDiagram />
|
||||
</Content>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { GroupsExplorerContent } from './GroupsExplorerContent';
|
||||
@@ -44,7 +44,7 @@
|
||||
"p-limit": "^3.0.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "^6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"react-lazylog": "^4.5.3",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"luxon": "^1.26.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"graphql": "15.5.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
+33
-4
@@ -14,14 +14,43 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ClusterLocatorMethod, CustomResource } from './src/types';
|
||||
|
||||
export interface Config {
|
||||
kubernetes?: {
|
||||
serviceLocatorMethod: {
|
||||
type: 'multiTenant';
|
||||
};
|
||||
clusterLocatorMethods: ClusterLocatorMethod[];
|
||||
customResources?: CustomResource[];
|
||||
clusterLocatorMethods: Array<
|
||||
| {
|
||||
/** @visibility frontend */
|
||||
type: 'gke';
|
||||
/** @visibility frontend */
|
||||
projectId: string;
|
||||
/** @visibility frontend */
|
||||
region?: string;
|
||||
/** @visibility frontend */
|
||||
skipTLSVerify?: boolean;
|
||||
}
|
||||
| {
|
||||
/** @visibility frontend */
|
||||
type: 'config';
|
||||
clusters: Array<{
|
||||
/** @visibility frontend */
|
||||
url: string;
|
||||
/** @visibility frontend */
|
||||
name: string;
|
||||
/** @visibility secret */
|
||||
serviceAccountToken?: string;
|
||||
/** @visibility frontend */
|
||||
authProvider: 'aws' | 'google' | 'serviceAccount';
|
||||
/** @visibility frontend */
|
||||
skipTLSVerify?: boolean;
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
customResources?: Array<{
|
||||
group: string;
|
||||
apiVersion: string;
|
||||
plural: string;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ describe('GkeClusterLocator', () => {
|
||||
authProvider: 'google',
|
||||
name: 'some-cluster',
|
||||
url: 'https://1.2.3.4',
|
||||
skipTLSVerify: false,
|
||||
},
|
||||
]);
|
||||
expect(mockedListClusters).toBeCalledTimes(1);
|
||||
@@ -141,6 +142,7 @@ describe('GkeClusterLocator', () => {
|
||||
authProvider: 'google',
|
||||
name: 'some-cluster',
|
||||
url: 'https://1.2.3.4',
|
||||
skipTLSVerify: false,
|
||||
},
|
||||
]);
|
||||
expect(mockedListClusters).toBeCalledTimes(1);
|
||||
@@ -181,11 +183,13 @@ describe('GkeClusterLocator', () => {
|
||||
authProvider: 'google',
|
||||
name: 'some-cluster',
|
||||
url: 'https://1.2.3.4',
|
||||
skipTLSVerify: false,
|
||||
},
|
||||
{
|
||||
authProvider: 'google',
|
||||
name: 'some-other-cluster',
|
||||
url: 'https://6.7.8.9',
|
||||
skipTLSVerify: false,
|
||||
},
|
||||
]);
|
||||
expect(mockedListClusters).toBeCalledTimes(1);
|
||||
|
||||
@@ -18,28 +18,28 @@ import { Config } from '@backstage/config';
|
||||
import * as container from '@google-cloud/container';
|
||||
import { ClusterDetails, KubernetesClustersSupplier } from '../types/types';
|
||||
|
||||
export class GkeClusterLocator implements KubernetesClustersSupplier {
|
||||
private readonly projectId: string;
|
||||
private readonly region: string | undefined;
|
||||
private readonly client: container.v1.ClusterManagerClient;
|
||||
type GkeClusterLocatorOptions = {
|
||||
projectId: string;
|
||||
region?: string;
|
||||
skipTLSVerify?: boolean;
|
||||
};
|
||||
|
||||
export class GkeClusterLocator implements KubernetesClustersSupplier {
|
||||
constructor(
|
||||
projectId: string,
|
||||
client: container.v1.ClusterManagerClient,
|
||||
region?: string,
|
||||
) {
|
||||
this.projectId = projectId;
|
||||
this.region = region;
|
||||
this.client = client;
|
||||
}
|
||||
private readonly options: GkeClusterLocatorOptions,
|
||||
private readonly client: container.v1.ClusterManagerClient,
|
||||
) {}
|
||||
|
||||
static fromConfigWithClient(
|
||||
config: Config,
|
||||
client: container.v1.ClusterManagerClient,
|
||||
): GkeClusterLocator {
|
||||
const projectId = config.getString('projectId');
|
||||
const region = config.getOptionalString('region');
|
||||
return new GkeClusterLocator(projectId, client, region);
|
||||
const options = {
|
||||
projectId: config.getString('projectId'),
|
||||
region: config.getOptionalString('region') ?? '-',
|
||||
skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,
|
||||
};
|
||||
return new GkeClusterLocator(options, client);
|
||||
}
|
||||
|
||||
static fromConfig(config: Config): GkeClusterLocator {
|
||||
@@ -50,9 +50,9 @@ export class GkeClusterLocator implements KubernetesClustersSupplier {
|
||||
}
|
||||
|
||||
async getClusters(): Promise<ClusterDetails[]> {
|
||||
const region = this.region ?? '-';
|
||||
const { projectId, region, skipTLSVerify } = this.options;
|
||||
const request = {
|
||||
parent: `projects/${this.projectId}/locations/${region}`,
|
||||
parent: `projects/${projectId}/locations/${region}`,
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -62,10 +62,11 @@ export class GkeClusterLocator implements KubernetesClustersSupplier {
|
||||
name: r.name ?? 'unknown',
|
||||
url: `https://${r.endpoint ?? ''}`,
|
||||
authProvider: 'google',
|
||||
skipTLSVerify,
|
||||
}));
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`There was an error retrieving clusters from GKE for projectId=${this.projectId} region=${region} : [${e.message}]`,
|
||||
`There was an error retrieving clusters from GKE for projectId=${projectId} region=${region} : [${e.message}]`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,50 +19,6 @@ import type {
|
||||
KubernetesFetchError,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
|
||||
export type ClusterLocatorMethod =
|
||||
| ConfigClusterLocatorMethod
|
||||
| GKEClusterLocatorMethod;
|
||||
|
||||
export interface ConfigClusterLocatorMethod {
|
||||
/**
|
||||
* @visibility frontend
|
||||
*/
|
||||
type: 'config';
|
||||
clusters: {
|
||||
/**
|
||||
* @visibility frontend
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* @visibility frontend
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* @visibility secret
|
||||
*/
|
||||
serviceAccountToken: string | undefined;
|
||||
/**
|
||||
* @visibility frontend
|
||||
*/
|
||||
authProvider: 'aws' | 'google' | 'serviceAccount';
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface GKEClusterLocatorMethod {
|
||||
/**
|
||||
* @visibility frontend
|
||||
*/
|
||||
type: 'gke';
|
||||
/**
|
||||
* @visibility frontend
|
||||
*/
|
||||
projectId: string;
|
||||
/**
|
||||
* @visibility frontend
|
||||
*/
|
||||
region?: string;
|
||||
}
|
||||
|
||||
export interface CustomResource {
|
||||
group: string;
|
||||
apiVersion: string;
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"react-hook-form": "^6.15.4",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-sparklines": "^1.7.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"@backstage/catalog-client": "^0.3.11",
|
||||
"@backstage/catalog-model": "^0.7.8",
|
||||
"@backstage/config": "^0.1.5",
|
||||
"@backstage/errors": "^0.1.1",
|
||||
"@backstage/core": "^0.7.8",
|
||||
"@backstage/integration": "^0.5.2",
|
||||
"@backstage/integration-react": "^0.1.1",
|
||||
@@ -54,7 +55,7 @@
|
||||
"react-lazylog": "^4.5.2",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"use-immer": "^0.5.1",
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
IdentityApi,
|
||||
Observable,
|
||||
} from '@backstage/core';
|
||||
import { ResponseError } from '@backstage/errors';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
import { ListActionsResponse, ScaffolderTask, Status } from './types';
|
||||
@@ -128,9 +129,7 @@ export class ScaffolderClient implements ScaffolderApi {
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch template parameter schema, ${await response.text()}`,
|
||||
);
|
||||
throw ResponseError.fromResponse(response);
|
||||
}
|
||||
|
||||
const schema: TemplateParameterSchema = await response.json();
|
||||
@@ -173,9 +172,15 @@ export class ScaffolderClient implements ScaffolderApi {
|
||||
const token = await this.identityApi.getIdToken();
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
|
||||
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}`;
|
||||
return fetch(url, {
|
||||
const response = await fetch(url, {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
}).then(x => x.json());
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw ResponseError.fromResponse(response);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
streamLogs({
|
||||
@@ -234,6 +239,11 @@ export class ScaffolderClient implements ScaffolderApi {
|
||||
async listActions(): Promise<ListActionsResponse> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
|
||||
const response = await fetch(`${baseUrl}/v2/actions`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw ResponseError.fromResponse(response);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-sparklines": "^1.7.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"timeago.js": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"rc-progress": "^3.0.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3",
|
||||
"react-use": "^17.2.4",
|
||||
"sanitize-html": "^2.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^15.3.3"
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.10",
|
||||
|
||||
@@ -2351,18 +2351,18 @@
|
||||
tslib "~2.2.0"
|
||||
|
||||
"@graphql-codegen/typescript-resolvers@^1.17.7":
|
||||
version "1.18.2"
|
||||
resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-1.18.2.tgz#7513b92df7c5a0d3c27342c591ada7340696cf8f"
|
||||
integrity sha512-aWfRR5y1gXCPUNK7zaUiSbmceqidvZ38mNHIBvXmZArRigyz1QZgN26kKpXjJjtFbPvROPnlGsYcZBReybvZXA==
|
||||
version "1.19.1"
|
||||
resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-1.19.1.tgz#56677ec56c1ca7174d22a2f236e3fb7f6503e708"
|
||||
integrity sha512-KdCVfg2u2RMbHu7eV9SOh5rmfnEQaMsQ0k8741bMbBmCESLnrWltujF2RT1OPN7WCn7xJejBtrFg/3UgT0fNug==
|
||||
dependencies:
|
||||
"@graphql-codegen/plugin-helpers" "^1.18.2"
|
||||
"@graphql-codegen/typescript" "^1.21.0"
|
||||
"@graphql-codegen/visitor-plugin-common" "^1.18.3"
|
||||
"@graphql-codegen/plugin-helpers" "^1.18.5"
|
||||
"@graphql-codegen/typescript" "^1.22.0"
|
||||
"@graphql-codegen/visitor-plugin-common" "^1.20.0"
|
||||
"@graphql-tools/utils" "^7.0.0"
|
||||
auto-bind "~4.0.0"
|
||||
tslib "~2.1.0"
|
||||
tslib "~2.2.0"
|
||||
|
||||
"@graphql-codegen/typescript@^1.17.7", "@graphql-codegen/typescript@^1.21.0":
|
||||
"@graphql-codegen/typescript@^1.17.7", "@graphql-codegen/typescript@^1.22.0":
|
||||
version "1.22.0"
|
||||
resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-1.22.0.tgz#d05be3a971e5d75a076a43e123b6330f4366a6ab"
|
||||
integrity sha512-YzN/3MBYHrP110m8JgUWQIHt7Ivi3JXiq0RT5XNx/F9mVOSbZz6Ezbaji8YJA3y04Gl2f6ZgtdGazWANUvcOcg==
|
||||
@@ -2372,7 +2372,7 @@
|
||||
auto-bind "~4.0.0"
|
||||
tslib "~2.2.0"
|
||||
|
||||
"@graphql-codegen/visitor-plugin-common@^1.18.3", "@graphql-codegen/visitor-plugin-common@^1.20.0":
|
||||
"@graphql-codegen/visitor-plugin-common@^1.20.0":
|
||||
version "1.20.0"
|
||||
resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.20.0.tgz#38d829eab7370c79aa5229190788f94adcae8f76"
|
||||
integrity sha512-AYrpy8NA3DpvhDLqYGerQRv44S+YAMPKtwT8x9GNVjzP0gVfmqi3gG1bDWbP5sm6kOZKvDC0kTxGePuBSZerxw==
|
||||
@@ -2664,16 +2664,7 @@
|
||||
camel-case "4.1.1"
|
||||
tslib "~2.0.1"
|
||||
|
||||
"@graphql-tools/utils@^7.0.0", "@graphql-tools/utils@^7.1.0":
|
||||
version "7.2.6"
|
||||
resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.2.6.tgz#5d974cbdec5ddf4d7fdc593816335512ee5fe4de"
|
||||
integrity sha512-/kY7Nb+cCHi/MvU3tjz3KrXzuJNWMlnn7EoWazLmpDvl6b2Qt69hlVoPd5zQtKlGib35zZw9NZ5zs5qTAw8Y9g==
|
||||
dependencies:
|
||||
"@ardatan/aggregate-error" "0.0.6"
|
||||
camel-case "4.1.2"
|
||||
tslib "~2.1.0"
|
||||
|
||||
"@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.7.0":
|
||||
"@graphql-tools/utils@^7.0.0", "@graphql-tools/utils@^7.1.0", "@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.7.0":
|
||||
version "7.7.1"
|
||||
resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.7.1.tgz#81f32cb4819b34b3a378d51ab2cd60935977f0b4"
|
||||
integrity sha512-SFT4/dTfrwWer1wSOLU+jqgv3oa/xTR8q+MiNbE9nCH2FXyMsqIOaXKm9wHfKIWFWHozqBdcnwFkQZrdD7H2TQ==
|
||||
@@ -8883,11 +8874,6 @@ boolbase@^1.0.0, boolbase@~1.0.0:
|
||||
resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
|
||||
|
||||
bowser@^1.7.3:
|
||||
version "1.9.4"
|
||||
resolved "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a"
|
||||
integrity sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==
|
||||
|
||||
boxen@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
|
||||
@@ -10820,14 +10806,6 @@ css-tree@1.0.0-alpha.37:
|
||||
mdn-data "2.0.4"
|
||||
source-map "^0.6.1"
|
||||
|
||||
css-tree@^1.0.0-alpha.28:
|
||||
version "1.0.0-alpha.39"
|
||||
resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb"
|
||||
integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==
|
||||
dependencies:
|
||||
mdn-data "2.0.6"
|
||||
source-map "^0.6.1"
|
||||
|
||||
css-tree@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.2.tgz#9ae393b5dafd7dae8a622475caec78d3d8fbd7b5"
|
||||
@@ -10982,7 +10960,7 @@ cssstyle@^2.2.0:
|
||||
dependencies:
|
||||
cssom "~0.3.6"
|
||||
|
||||
csstype@^2.2.0, csstype@^2.5.2, csstype@^2.5.5, csstype@^2.5.7, csstype@^2.6.7:
|
||||
csstype@^2.2.0, csstype@^2.5.2, csstype@^2.5.7, csstype@^2.6.7:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098"
|
||||
integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==
|
||||
@@ -13204,11 +13182,6 @@ fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3:
|
||||
resolved "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53"
|
||||
integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==
|
||||
|
||||
fastest-stable-stringify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028"
|
||||
integrity sha1-kSLUBtTJ2YvqZEpraFPVh0uHsCg=
|
||||
|
||||
fastest-stable-stringify@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz#3757a6774f6ec8de40c4e86ec28ea02417214c76"
|
||||
@@ -15436,14 +15409,6 @@ init-package-json@^2.0.2:
|
||||
validate-npm-package-license "^3.0.4"
|
||||
validate-npm-package-name "^3.0.0"
|
||||
|
||||
inline-style-prefixer@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-4.0.2.tgz#d390957d26f281255fe101da863158ac6eb60911"
|
||||
integrity sha512-N8nVhwfYga9MiV9jWlwfdj1UDIaZlBFu4cJSJkIr7tZX7sHpHhGR5su1qdpW+7KPL8ISTvCIkcaFi/JdBknvPg==
|
||||
dependencies:
|
||||
bowser "^1.7.3"
|
||||
css-in-js-utils "^2.0.0"
|
||||
|
||||
inline-style-prefixer@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.0.tgz#f73d5dbf2855733d6b153a4d24b7b47a73e9770b"
|
||||
@@ -18361,11 +18326,6 @@ mdn-data@2.0.4:
|
||||
resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
|
||||
integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
|
||||
|
||||
mdn-data@2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978"
|
||||
integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==
|
||||
|
||||
mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
@@ -19074,21 +19034,7 @@ nan@2.14.1, nan@^2.12.1, nan@^2.14.0:
|
||||
resolved "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
|
||||
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
|
||||
|
||||
nano-css@^5.1.0, nano-css@^5.2.1:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmjs.org/nano-css/-/nano-css-5.3.0.tgz#9d3cd29788d48b6a07f52aa4aec7cf4da427b6b5"
|
||||
integrity sha512-uM/9NGK9/E9/sTpbIZ/bQ9xOLOIHZwrrb/CRlbDHBU/GFS7Gshl24v/WJhwsVViWkpOXUmiZ66XO7fSB4Wd92Q==
|
||||
dependencies:
|
||||
css-tree "^1.0.0-alpha.28"
|
||||
csstype "^2.5.5"
|
||||
fastest-stable-stringify "^1.0.1"
|
||||
inline-style-prefixer "^4.0.0"
|
||||
rtl-css-js "^1.9.0"
|
||||
sourcemap-codec "^1.4.1"
|
||||
stacktrace-js "^2.0.0"
|
||||
stylis "3.5.0"
|
||||
|
||||
nano-css@^5.3.1:
|
||||
nano-css@^5.1.0, nano-css@^5.2.1, nano-css@^5.3.1:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.npmjs.org/nano-css/-/nano-css-5.3.1.tgz#b709383e07ad3be61f64edffacb9d98250b87a1f"
|
||||
integrity sha512-ENPIyNzANQRyYVvb62ajDd7PAyIgS2LIUnT9ewih4yrXSZX4hKoUwssy8WjUH++kEOA5wUTMgNnV7ko5n34kUA==
|
||||
@@ -21586,9 +21532,9 @@ prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0,
|
||||
react-is "^16.8.1"
|
||||
|
||||
property-expr@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/property-expr/-/property-expr-2.0.2.tgz#fff2a43919135553a3bc2fdd94bdb841965b2330"
|
||||
integrity sha512-bc/5ggaYZxNkFKj374aLbEDqVADdYaLcFo8XBkishUWbaAdjlphaBFns9TvRA2pUseVL/wMFmui9X3IdNDU37g==
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910"
|
||||
integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==
|
||||
|
||||
property-information@^5.0.0:
|
||||
version "5.4.0"
|
||||
@@ -22441,10 +22387,10 @@ react-use@^15.3.3, react-use@^15.3.6:
|
||||
ts-easing "^0.2.0"
|
||||
tslib "^2.0.0"
|
||||
|
||||
react-use@^17.2.1:
|
||||
version "17.2.1"
|
||||
resolved "https://registry.npmjs.org/react-use/-/react-use-17.2.1.tgz#c81e12544115ed049c7deba1e3bb3d977dfee9b8"
|
||||
integrity sha512-9r51/at7/Nr/nEP4CsHz+pl800EAqhIY9R6O68m68kaWc8slDAfx1UrIedQqpsb4ImddFYb+6hF1i5Vj4u4Cnw==
|
||||
react-use@^17.2.1, react-use@^17.2.4:
|
||||
version "17.2.4"
|
||||
resolved "https://registry.npmjs.org/react-use/-/react-use-17.2.4.tgz#1f89be3db0a8237c79253db0a15e12bbe3cfeff1"
|
||||
integrity sha512-vQGpsAM0F5UIlshw5UI8ULGPS4yn5rm7/qvn3T1Gnkrz7YRMEEMh+ynKcmRloOyiIeLvKWiQjMiwRGtdbgs5qQ==
|
||||
dependencies:
|
||||
"@types/js-cookie" "^2.2.6"
|
||||
"@xobotyi/scrollbar-width" "^1.9.5"
|
||||
@@ -23352,7 +23298,7 @@ rsvp@^4.8.4:
|
||||
resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
|
||||
integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
|
||||
|
||||
rtl-css-js@^1.14.0, rtl-css-js@^1.9.0:
|
||||
rtl-css-js@^1.14.0:
|
||||
version "1.14.0"
|
||||
resolved "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.14.0.tgz#daa4f192a92509e292a0519f4b255e6e3c076b7d"
|
||||
integrity sha512-Dl5xDTeN3e7scU1cWX8c9b6/Nqz3u/HgR4gePc1kWXYiQWVQbKCEyK6+Hxve9LbcJ5EieHy1J9nJCN3grTtGwg==
|
||||
@@ -23509,12 +23455,7 @@ schema-utils@^3.0.0:
|
||||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
screenfull@^5.0.0:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.npmjs.org/screenfull/-/screenfull-5.0.2.tgz#b9acdcf1ec676a948674df5cd0ff66b902b0bed7"
|
||||
integrity sha512-cCF2b+L/mnEiORLN5xSAz6H3t18i2oHh9BA8+CQlAh5DRw2+NFAGQJOSYbcGw8B2k04g/lVvFcfZ83b3ysH5UQ==
|
||||
|
||||
screenfull@^5.1.0:
|
||||
screenfull@^5.0.0, screenfull@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.npmjs.org/screenfull/-/screenfull-5.1.0.tgz#85c13c70f4ead4c1b8a935c70010dfdcd2c0e5c8"
|
||||
integrity sha512-dYaNuOdzr+kc6J6CFcBrzkLCfyGcMg+gWkJ8us93IQ7y1cevhQAugFsaCdMHb6lw8KV3xPzSxzH7zM1dQap9mA==
|
||||
@@ -24084,7 +24025,7 @@ source-map@^0.7.3:
|
||||
resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
||||
sourcemap-codec@^1.4.1, sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8:
|
||||
sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8:
|
||||
version "1.4.8"
|
||||
resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
|
||||
@@ -24317,7 +24258,7 @@ stacktrace-gps@^3.0.4:
|
||||
source-map "0.5.6"
|
||||
stackframe "^1.1.1"
|
||||
|
||||
stacktrace-js@^2.0.0, stacktrace-js@^2.0.2:
|
||||
stacktrace-js@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b"
|
||||
integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==
|
||||
@@ -24737,11 +24678,6 @@ stylehacks@^4.0.0:
|
||||
postcss "^7.0.0"
|
||||
postcss-selector-parser "^3.0.0"
|
||||
|
||||
stylis@3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.npmjs.org/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1"
|
||||
integrity sha512-pP7yXN6dwMzAR29Q0mBrabPCe0/mNO1MSr93bhay+hcZondvMMTpeGyd8nbhYJdyperNT2DRxONQuUGcJr5iPw==
|
||||
|
||||
stylis@^4.0.6:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.npmjs.org/stylis/-/stylis-4.0.7.tgz#412a90c28079417f3d27c028035095e4232d2904"
|
||||
@@ -25588,17 +25524,6 @@ ts-log@^2.2.3:
|
||||
resolved "https://registry.npmjs.org/ts-log/-/ts-log-2.2.3.tgz#4da5640fe25a9fb52642cd32391c886721318efb"
|
||||
integrity sha512-XvB+OdKSJ708Dmf9ore4Uf/q62AYDTzFcAdxc8KNML1mmAWywRFVt/dn1KYJH8Agt5UJNujfM3znU5PxgAzA2w==
|
||||
|
||||
ts-node@^8.10.2, ts-node@^8.6.2:
|
||||
version "8.10.2"
|
||||
resolved "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d"
|
||||
integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==
|
||||
dependencies:
|
||||
arg "^4.1.0"
|
||||
diff "^4.0.1"
|
||||
make-error "^1.1.1"
|
||||
source-map-support "^0.5.17"
|
||||
yn "3.1.1"
|
||||
|
||||
ts-node@^9, ts-node@^9.1.1:
|
||||
version "9.1.1"
|
||||
resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
|
||||
|
||||
Reference in New Issue
Block a user