From ac3b033665e1d5b9833e40faf269cc28db66433a Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Wed, 21 Oct 2020 10:01:10 +0200 Subject: [PATCH 01/32] Add catalog import plugin to router --- packages/app/package.json | 1 + packages/app/src/App.tsx | 2 ++ packages/app/src/plugins.ts | 1 + 3 files changed, 4 insertions(+) diff --git a/packages/app/package.json b/packages/app/package.json index dc452e0803..254bae9c46 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -37,6 +37,7 @@ "@roadiehq/backstage-plugin-github-insights": "^0.2.7", "@roadiehq/backstage-plugin-github-pull-requests": "^0.5.2", "@roadiehq/backstage-plugin-travis-ci": "^0.2.3", + "@roadiehq/backstage-plugin-catalog-import": "^0.1.0", "dayjs": "^1.9.1", "history": "^5.0.0", "prop-types": "^15.7.2", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 81d08f58a9..883fe1e1ca 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -27,6 +27,7 @@ import * as plugins from './plugins'; import { apis } from './apis'; import { hot } from 'react-hot-loader/root'; import { providers } from './identityProviders'; +import { Router as CatalogImportRouter } from '@roadiehq/backstage-plugin-catalog-import'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql'; @@ -83,6 +84,7 @@ const AppRoutes = () => ( element={} /> } /> + } /> {...deprecatedAppRoutes} ); diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts index bdc3851318..64c49eceba 100644 --- a/packages/app/src/plugins.ts +++ b/packages/app/src/plugins.ts @@ -37,4 +37,5 @@ export { plugin as Kubernetes } from '@backstage/plugin-kubernetes'; export { plugin as Cloudbuild } from '@backstage/plugin-cloudbuild'; export { plugin as CostInsights } from '@backstage/plugin-cost-insights'; export { plugin as GitHubInsights } from '@roadiehq/backstage-plugin-github-insights'; +export { plugin as CatalogImport } from '@roadiehq/backstage-plugin-catalog-import'; export { plugin as UserSettings } from '@backstage/plugin-user-settings'; From 0ef0518262668d4754d2fa6e18c5a5099edf77d4 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Wed, 21 Oct 2020 10:01:10 +0200 Subject: [PATCH 02/32] Add catalog import plugin to router --- packages/app/package.json | 1 + packages/app/src/App.tsx | 2 ++ packages/app/src/plugins.ts | 1 + 3 files changed, 4 insertions(+) diff --git a/packages/app/package.json b/packages/app/package.json index dc452e0803..254bae9c46 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -37,6 +37,7 @@ "@roadiehq/backstage-plugin-github-insights": "^0.2.7", "@roadiehq/backstage-plugin-github-pull-requests": "^0.5.2", "@roadiehq/backstage-plugin-travis-ci": "^0.2.3", + "@roadiehq/backstage-plugin-catalog-import": "^0.1.0", "dayjs": "^1.9.1", "history": "^5.0.0", "prop-types": "^15.7.2", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 81d08f58a9..883fe1e1ca 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -27,6 +27,7 @@ import * as plugins from './plugins'; import { apis } from './apis'; import { hot } from 'react-hot-loader/root'; import { providers } from './identityProviders'; +import { Router as CatalogImportRouter } from '@roadiehq/backstage-plugin-catalog-import'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql'; @@ -83,6 +84,7 @@ const AppRoutes = () => ( element={} /> } /> + } /> {...deprecatedAppRoutes} ); diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts index bdc3851318..64c49eceba 100644 --- a/packages/app/src/plugins.ts +++ b/packages/app/src/plugins.ts @@ -37,4 +37,5 @@ export { plugin as Kubernetes } from '@backstage/plugin-kubernetes'; export { plugin as Cloudbuild } from '@backstage/plugin-cloudbuild'; export { plugin as CostInsights } from '@backstage/plugin-cost-insights'; export { plugin as GitHubInsights } from '@roadiehq/backstage-plugin-github-insights'; +export { plugin as CatalogImport } from '@roadiehq/backstage-plugin-catalog-import'; export { plugin as UserSettings } from '@backstage/plugin-user-settings'; From 3a438e1833ba3a23e24ce1f06e735721f08537d9 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Sun, 25 Oct 2020 23:38:29 +0100 Subject: [PATCH 03/32] Add config-backend endpoint to generate config --- packages/app/src/App.tsx | 2 +- packages/app/src/apis.ts | 14 - packages/backend/src/plugins/catalog.ts | 2 + packages/catalog-model/src/location/index.ts | 6 +- .../catalog-model/src/location/validation.ts | 7 + .../src/ingestion/ConfigGenerator.ts | 57 +++ .../catalog-backend/src/ingestion/types.ts | 8 + .../src/service/CatalogBuilder.ts | 5 + plugins/catalog-backend/src/service/router.ts | 20 +- yarn.lock | 471 +++++++++++++++--- 10 files changed, 516 insertions(+), 76 deletions(-) create mode 100644 plugins/catalog-backend/src/ingestion/ConfigGenerator.ts diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 883fe1e1ca..8b10366c6e 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -84,7 +84,7 @@ const AppRoutes = () => ( element={} /> } /> - } /> + } /> {...deprecatedAppRoutes} ); diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index c129bebfa2..567ac13c78 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -25,16 +25,6 @@ import { GraphQLEndpoints, } from '@backstage/plugin-graphiql'; -import { - TravisCIApi, - travisCIApiRef, -} from '@roadiehq/backstage-plugin-travis-ci'; - -import { - GithubPullRequestsClient, - githubPullRequestsApiRef, -} from '@roadiehq/backstage-plugin-github-pull-requests'; - import { costInsightsApiRef } from '@backstage/plugin-cost-insights'; import { ExampleCostInsightsClient } from './plugins/cost-insights'; @@ -59,8 +49,4 @@ export const apis = [ }), createApiFactory(costInsightsApiRef, new ExampleCostInsightsClient()), - - // TODO: move to plugins - createApiFactory(travisCIApiRef, new TravisCIApi()), - createApiFactory(githubPullRequestsApiRef, new GithubPullRequestsClient()), ]; diff --git a/packages/backend/src/plugins/catalog.ts b/packages/backend/src/plugins/catalog.ts index 3c205a3800..8d6c823dce 100644 --- a/packages/backend/src/plugins/catalog.ts +++ b/packages/backend/src/plugins/catalog.ts @@ -28,6 +28,7 @@ export default async function createPlugin(env: PluginEnvironment) { entitiesCatalog, locationsCatalog, higherOrderOperation, + configGenerator, } = await builder.build(); useHotCleanup( @@ -39,6 +40,7 @@ export default async function createPlugin(env: PluginEnvironment) { entitiesCatalog, locationsCatalog, higherOrderOperation, + configGenerator, logger: env.logger, }); } diff --git a/packages/catalog-model/src/location/index.ts b/packages/catalog-model/src/location/index.ts index ff696524ab..1b7587c1f0 100644 --- a/packages/catalog-model/src/location/index.ts +++ b/packages/catalog-model/src/location/index.ts @@ -15,5 +15,9 @@ */ export type { Location, LocationSpec } from './types'; -export { locationSchema, locationSpecSchema } from './validation'; +export { + locationSchema, + locationSpecSchema, + repoPathSchema, +} from './validation'; export { LOCATION_ANNOTATION } from './annotation'; diff --git a/packages/catalog-model/src/location/validation.ts b/packages/catalog-model/src/location/validation.ts index 27d74b9a82..28662119b0 100644 --- a/packages/catalog-model/src/location/validation.ts +++ b/packages/catalog-model/src/location/validation.ts @@ -34,3 +34,10 @@ export const locationSchema = yup }) .noUnknown() .required(); + +export const repoPathSchema = yup + .object<{ repoPath: string }>({ + repoPath: yup.string().required(), + }) + .noUnknown() + .required(); diff --git a/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts b/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts new file mode 100644 index 0000000000..6879cd8291 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts @@ -0,0 +1,57 @@ +/* + * 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 { InputError } from '@backstage/backend-common'; +import { Entity, Location, LocationSpec } from '@backstage/catalog-model'; +import { v4 as uuidv4 } from 'uuid'; +import { Logger } from 'winston'; +import { EntitiesCatalog, LocationsCatalog } from '../catalog'; +import { EntityUpsertResponse } from '../catalog/types'; +import { durationText } from '../util/timing'; +import { AddLocationResult, ConfigGenerator, LocationReader } from './types'; + +/** + * Placeholder for operations that span several catalogs and/or stretches out + * in time. + * + * TODO(freben): Find a better home for these, possibly refactoring to use the + * database more directly. + */ +export class ConfigGeneratorClient implements ConfigGenerator { + logger: Logger; + + constructor(logger: Logger) { + this.logger = logger; + } + async generateConfig(repoPath: string): Promise { + const [ownerName, repoName] = [ + repoPath.split('/')[0], + repoPath.split('/')[1], + ]; + const config = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: repoName, + description: '', + annotations: { 'github.com/project-slug': repoPath }, + }, + spec: { type: 'service', owner: ownerName, lifecycle: 'experimental' }, + }; + + return [config]; + } +} diff --git a/plugins/catalog-backend/src/ingestion/types.ts b/plugins/catalog-backend/src/ingestion/types.ts index c586e2d438..2d7165c140 100644 --- a/plugins/catalog-backend/src/ingestion/types.ts +++ b/plugins/catalog-backend/src/ingestion/types.ts @@ -65,3 +65,11 @@ export type ReadLocationError = { location: LocationSpec; error: Error; }; + +// +// ConfigGenerator +// + +export type ConfigGenerator = { + generateConfig(repoPath: string): Promise; +}; diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 4ec2a0834d..c232887b04 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -64,12 +64,14 @@ import { YamlProcessor, } from '../ingestion'; import { CatalogRulesEnforcer } from '../ingestion/CatalogRules'; +import { ConfigGeneratorClient } from '../ingestion/ConfigGenerator'; import { LdapOrgReaderProcessor } from '../ingestion/processors/LdapOrgReaderProcessor'; import { jsonPlaceholderResolver, textPlaceholderResolver, yamlPlaceholderResolver, } from '../ingestion/processors/PlaceholderProcessor'; +import { ConfigGenerator } from '../ingestion/types'; export type CatalogEnvironment = { logger: Logger; @@ -249,6 +251,7 @@ export class CatalogBuilder { entitiesCatalog: EntitiesCatalog; locationsCatalog: LocationsCatalog; higherOrderOperation: HigherOrderOperation; + configGenerator: ConfigGenerator; }> { const { config, database, logger } = this.env; @@ -276,11 +279,13 @@ export class CatalogBuilder { locationReader, logger, ); + const configGenerator = new ConfigGeneratorClient(logger); return { entitiesCatalog, locationsCatalog, higherOrderOperation, + configGenerator, }; } diff --git a/plugins/catalog-backend/src/service/router.ts b/plugins/catalog-backend/src/service/router.ts index c7d05afb2d..aefcca28e2 100644 --- a/plugins/catalog-backend/src/service/router.ts +++ b/plugins/catalog-backend/src/service/router.ts @@ -15,27 +15,33 @@ */ import { errorHandler, InputError } from '@backstage/backend-common'; -import { locationSpecSchema } from '@backstage/catalog-model'; +import { locationSpecSchema, repoPathSchema } from '@backstage/catalog-model'; import type { Entity } from '@backstage/catalog-model'; import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; import { EntitiesCatalog, LocationsCatalog } from '../catalog'; import { EntityFilters } from '../database'; -import { HigherOrderOperation } from '../ingestion/types'; +import { ConfigGenerator, HigherOrderOperation } from '../ingestion/types'; import { requireRequestBody, validateRequestBody } from './util'; export interface RouterOptions { entitiesCatalog?: EntitiesCatalog; locationsCatalog?: LocationsCatalog; higherOrderOperation?: HigherOrderOperation; + configGenerator?: ConfigGenerator; logger: Logger; } export async function createRouter( options: RouterOptions, ): Promise { - const { entitiesCatalog, locationsCatalog, higherOrderOperation } = options; + const { + entitiesCatalog, + locationsCatalog, + higherOrderOperation, + configGenerator, + } = options; const router = Router(); router.use(express.json()); @@ -121,6 +127,14 @@ export async function createRouter( }); } + if (configGenerator) { + router.post('/generate-config', async (req, res) => { + const input = await validateRequestBody(req, repoPathSchema); + const output = await configGenerator.generateConfig(input.repoPath); + res.status(201).send(output); + }); + } + router.use(errorHandler()); return router; } diff --git a/yarn.lock b/yarn.lock index 82dc99d277..84334952e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1673,6 +1673,22 @@ resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@eslint/eslintrc@^0.2.0": + version "0.2.0" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.0.tgz#bc7e3c4304d4c8720968ccaee793087dfb5fe6b4" + integrity sha512-+cIGPCBdLCzqxdtwppswP+zTsH9BOIGzAeKfBIbtb4gW/giMlfMwP0HUSFfhzh20f9u8uZ8hOp62+4GPquTbwQ== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@evocateur/libnpmaccess@^3.1.2": version "3.1.2" resolved "https://registry.npmjs.org/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845" @@ -3218,7 +3234,7 @@ resolved "https://registry.npmjs.org/@material-icons/font/-/font-1.0.3.tgz#f722e5a69a03f20ef47d015cb69420bebeeaabe5" integrity sha512-aIRd0Z9b/HJ/O24KOaP7dNsXypMnXhpWrpLVYvQB/JesVqXYSbioYND200sR+C14a0LSCp+qWnWCnSXmN1hWGw== -"@material-ui/core@^4.11.0", "@material-ui/core@^4.9.1": +"@material-ui/core@^4.11.0", "@material-ui/core@^4.9.1", "@material-ui/core@^4.9.10": version "4.11.0" resolved "https://registry.npmjs.org/@material-ui/core/-/core-4.11.0.tgz#b69b26e4553c9e53f2bfaf1053e216a0af9be15a" integrity sha512-bYo9uIub8wGhZySHqLQ833zi4ZML+XCBE1XwJ8EuUVSpTWWG57Pm+YugQToJNFsEyiKFhPh8DPD0bgupz8n01g== @@ -3254,7 +3270,7 @@ prop-types "^15.7.2" react-is "^16.8.0" -"@material-ui/lab@^4.0.0-alpha.56": +"@material-ui/lab@^4.0.0-alpha.49", "@material-ui/lab@^4.0.0-alpha.56": version "4.0.0-alpha.56" resolved "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.56.tgz#ff63080949b55b40625e056bbda05e130d216d34" integrity sha512-xPlkK+z/6y/24ka4gVJgwPfoCF4RCh8dXb1BNE7MtF9bXEBLN/lBxNTK8VAa0qm3V2oinA6xtUIdcRh0aeRtVw== @@ -3547,7 +3563,7 @@ dependencies: "@types/node" ">= 8" -"@open-draft/until@^1.0.3": +"@open-draft/until@^1.0.0", "@open-draft/until@^1.0.3": version "1.0.3" resolved "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca" integrity sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q== @@ -3628,6 +3644,11 @@ prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" +"@rehooks/local-storage@^2.4.0": + version "2.4.0" + resolved "https://registry.npmjs.org/@rehooks/local-storage/-/local-storage-2.4.0.tgz#fb884b2b657cad5f77aa6ab60bb3532f0e0725d2" + integrity sha512-LoXDbEHsuIckVgBsFAv8SuU/M7memjyfWut9Zf36TQXqqCHBRFv8bweg9PymQCa1aWIMjNrZQflFdo55FDlXYg== + "@rjsf/core@^2.4.0": version "2.4.0" resolved "https://registry.npmjs.org/@rjsf/core/-/core-2.4.0.tgz#c50bcff0d8178948ce08123177399d8816d51929" @@ -3670,51 +3691,6 @@ react-router "^6.0.0-beta.0" react-use "^15.3.3" -"@roadiehq/backstage-plugin-github-pull-requests@^0.5.2": - version "0.5.2" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-0.5.2.tgz#455355fe5cdcc43c22b80a8ef3697378084680a1" - integrity sha512-GM+nWQZ+aehMclN70Pp35UQe3I46SQCjWiGZ6/0TfDzrueHln39L2UspUj1L/713xDDtDK8ZnTJdFn/qKx7j4A== - dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.25" - "@backstage/core" "^0.1.1-alpha.25" - "@backstage/plugin-catalog" "^0.1.1-alpha.25" - "@backstage/theme" "^0.1.1-alpha.25" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "^4.0.0-alpha.56" - "@octokit/rest" "^18.0.0" - "@octokit/types" "^5.0.1" - "@types/react-dom" "^16.9.8" - history "^5.0.0" - moment "^2.27.0" - react "^16.13.1" - react-dom "^16.13.1" - react-router "6.0.0-beta.0" - react-use "^15.3.3" - -"@roadiehq/backstage-plugin-travis-ci@^0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.2.3.tgz#2d1c5a7ed3eab4fdcf95243b73dee44c0cff5a57" - integrity sha512-Xi8vZFbcm+D4ykyU3I9hImAd22F1v6M1F/H9CJanRHqj5esJxnuCS2+Kf+w09bwb9DuM8/c68PuMlf3PMIsOwg== - dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.22" - "@backstage/core" "^0.1.1-alpha.22" - "@backstage/core-api" "^0.1.1-alpha.22" - "@backstage/plugin-catalog" "^0.1.1-alpha.22" - "@backstage/theme" "^0.1.1-alpha.22" - "@material-ui/core" "^4.9.1" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - date-fns "^2.15.0" - history "^5.0.0" - moment "^2.27.0" - react "^16.13.1" - react-dom "^16.13.1" - 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" - "@rollup/plugin-commonjs@^13.0.0": version "13.0.0" resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-13.0.0.tgz#8a1d684ba6848afe8b9e3d85649d4b2f6f7217ec" @@ -3728,6 +3704,19 @@ magic-string "^0.25.2" resolve "^1.11.0" +"@rollup/plugin-commonjs@^14.0.0": + version "14.0.0" + resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz#4285f9ec2db686a31129e5a2b415c94aa1f836f0" + integrity sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw== + dependencies: + "@rollup/pluginutils" "^3.0.8" + commondir "^1.0.1" + estree-walker "^1.0.1" + glob "^7.1.2" + is-reference "^1.1.2" + magic-string "^0.25.2" + resolve "^1.11.0" + "@rollup/plugin-json@^4.0.2": version "4.1.0" resolved "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3" @@ -3735,6 +3724,19 @@ dependencies: "@rollup/pluginutils" "^3.0.8" +"@rollup/plugin-node-resolve@^8.4.0": + version "8.4.0" + resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz#261d79a680e9dc3d86761c14462f24126ba83575" + integrity sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + builtin-modules "^3.1.0" + deep-freeze "^0.0.1" + deepmerge "^4.2.2" + is-module "^1.0.0" + resolve "^1.17.0" + "@rollup/plugin-node-resolve@^9.0.0": version "9.0.0" resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-9.0.0.tgz#39bd0034ce9126b39c1699695f440b4b7d2b62e6" @@ -3765,6 +3767,15 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.0.0.tgz#e18e9f5a3925779fc15209dd316c1bd260d195ef" + integrity sha512-b5QiJRye4JlSg29bKNEECoKbLuPXZkPEHSgEjjP1CJV1CPdDBybfYHfm6kyq8yK51h/Zsyl8OvWUrp0FUBukEQ== + dependencies: + "@types/estree" "0.0.45" + estree-walker "^2.0.1" + picomatch "^2.2.2" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -4696,7 +4707,7 @@ "@babel/runtime" "^7.5.4" "@types/testing-library__react-hooks" "^3.3.0" -"@testing-library/react-hooks@^3.4.2": +"@testing-library/react-hooks@^3.4.1", "@testing-library/react-hooks@^3.4.2": version "3.4.2" resolved "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-3.4.2.tgz#8deb94f7684e0d896edd84a4c90e5b79a0810bc2" integrity sha512-RfPG0ckOzUIVeIqlOc1YztKgFW+ON8Y5xaSPbiBkfj9nMkkiLhLeBXT5icfPX65oJV/zCZu4z8EVnUc6GY9C5A== @@ -4936,6 +4947,11 @@ dependencies: "@types/express" "*" +"@types/cookie@^0.3.3": + version "0.3.3" + resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" + integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== + "@types/cookie@^0.4.0": version "0.4.0" resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108" @@ -5027,6 +5043,11 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/estree@0.0.45": + version "0.0.45" + resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" + integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== + "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.5": version "4.17.9" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz#2d7b34dcfd25ec663c25c85d76608f8b249667f1" @@ -5117,6 +5138,11 @@ resolved "https://registry.npmjs.org/@types/history/-/history-4.7.5.tgz#527d20ef68571a4af02ed74350164e7a67544860" integrity sha512-wLD/Aq2VggCJXSjxEwrMafIP51Z+13H78nXIX0ABEuIGhmB5sNGbR113MOKo+yfw+RDo1ZU3DM6yfnnRF/+ouw== +"@types/history@^4.7.7": + version "4.7.8" + resolved "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + "@types/html-minifier-terser@^5.0.0": version "5.1.0" resolved "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880" @@ -5226,6 +5252,14 @@ jest-diff "^25.2.1" pretty-format "^25.2.1" +"@types/jest@^25.2.2": + version "25.2.3" + resolved "https://registry.npmjs.org/@types/jest/-/jest-25.2.3.tgz#33d27e4c4716caae4eced355097a47ad363fdcaf" + integrity sha512-JXc1nK/tXHiDhV55dvfzqtmP4S3sy3T3ouV2tkViZgxY/zeUkcpQcQPGRlgF4KmWzWW5oiWYSZwtCB+2RsE4Fw== + dependencies: + jest-diff "^25.2.1" + pretty-format "^25.2.1" + "@types/jquery@^3.3.34": version "3.5.1" resolved "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.1.tgz#cebb057acf5071c40e439f30e840c57a30d406c3" @@ -5970,7 +6004,7 @@ resolved "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== -"@typescript-eslint/eslint-plugin@^v3.10.1": +"@typescript-eslint/eslint-plugin@^3.8.0", "@typescript-eslint/eslint-plugin@^v3.10.1": version "3.10.1" resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== @@ -6005,7 +6039,7 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^v3.10.1": +"@typescript-eslint/parser@^3.8.0", "@typescript-eslint/parser@^v3.10.1": version "3.10.1" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== @@ -6342,6 +6376,11 @@ acorn@^7.1.1, acorn@^7.2.0: resolved "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + address@1.1.2, address@^1.0.1: version "1.1.2" resolved "https://registry.npmjs.org/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" @@ -9231,7 +9270,7 @@ cross-env@^7.0.0: dependencies: cross-spawn "^7.0.1" -cross-fetch@3.0.6, cross-fetch@^3.0.5, cross-fetch@^3.0.6: +cross-fetch@3.0.6, cross-fetch@^3.0.4, cross-fetch@^3.0.5, cross-fetch@^3.0.6: version "3.0.6" resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c" integrity sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ== @@ -9597,7 +9636,7 @@ cyclist@^1.0.1: resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= -cypress@*, cypress@^4.2.0: +cypress@*, cypress@^4.11.0, cypress@^4.2.0: version "4.12.1" resolved "https://registry.npmjs.org/cypress/-/cypress-4.12.1.tgz#0ead1b9f4c0917d69d8b57f996b6e01fe693b6ec" integrity sha512-9SGIPEmqU8vuRA6xst2CMTYd9sCFCxKSzrHt0wr+w2iAQMCIIsXsQ5Gplns1sT6LDbZcmLv6uehabAOl3fhc9Q== @@ -9930,6 +9969,11 @@ deep-extend@0.6.0, deep-extend@^0.6.0, deep-extend@~0.6.0: resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +deep-freeze@^0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84" + integrity sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ= + deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -10683,6 +10727,41 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es- string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" +es-abstract@^1.17.5: + version "1.17.7" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + es-array-method-boxes-properly@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" @@ -10773,6 +10852,11 @@ es6-weak-map@^2.0.2: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +esbuild@^0.6.18: + version "0.6.34" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.6.34.tgz#76565a60e006f45d5f273b6e59e61ed0816551f5" + integrity sha512-InRdL/Q96pUucPqovJzvuLhquZr6jOn81FDVwFjCKz1rYKIm9OdOC+7Fs4vr6x48vKBl5LzKgtjU39BUpO636A== + esbuild@^0.7.7: version "0.7.7" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.7.7.tgz#fd86332d1c0a047231bd6da930666028c40c14bf" @@ -10861,6 +10945,13 @@ eslint-plugin-cypress@^2.10.3: dependencies: globals "^11.12.0" +eslint-plugin-cypress@^2.11.1: + version "2.11.2" + resolved "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.2.tgz#a8f3fe7ec840f55e4cea37671f93293e6c3e76a0" + integrity sha512-1SergF1sGbVhsf7MYfOLiBhdOg6wqyeV9pXUAIDIffYTGMN3dTBQS9nFAzhLsHhO+Bn0GaVM1Ecm71XUidQ7VA== + dependencies: + globals "^11.12.0" + eslint-plugin-graphql@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/eslint-plugin-graphql/-/eslint-plugin-graphql-4.0.0.tgz#d238ff2baee4d632cfcbe787a7a70a1f50428358" @@ -10957,6 +11048,23 @@ eslint-plugin-react@^7.12.4: string.prototype.matchall "^4.0.2" xregexp "^4.3.0" +eslint-plugin-react@^7.20.5: + version "7.21.5" + resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz#50b21a412b9574bfe05b21db176e8b7b3b15bff3" + integrity sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g== + dependencies: + array-includes "^3.1.1" + array.prototype.flatmap "^1.2.3" + doctrine "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.4.1 || ^3.0.0" + object.entries "^1.1.2" + object.fromentries "^2.0.2" + object.values "^1.1.1" + prop-types "^15.7.2" + resolve "^1.18.1" + string.prototype.matchall "^4.0.2" + eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -10973,6 +11081,14 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + eslint-utils@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" @@ -10980,11 +11096,23 @@ eslint-utils@^2.0.0: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== +eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + eslint-visitor-keys@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" @@ -11032,6 +11160,49 @@ eslint@^7.1.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" +eslint@^7.6.0: + version "7.12.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-7.12.0.tgz#7b6a85f87a9adc239e979bb721cde5ce0dc27da6" + integrity sha512-n5pEU27DRxCSlOhJ2rO57GDLcNsxO0LPpAbpFdh7xmcDmjmlGUfoyrsB3I7yYdQXO5N3gkSTiDrPSPNFiiirXA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.2.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.0" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.19" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + esm@^3.2.25: version "3.2.25" resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" @@ -11046,6 +11217,15 @@ espree@^7.1.0: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.2.0" +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.3.0" + esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -11065,6 +11245,13 @@ esrecurse@^4.1.0: dependencies: estraverse "^4.1.0" +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" @@ -11075,6 +11262,11 @@ estraverse@^5.1.0: resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== +estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + estree-walker@^0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" @@ -11085,6 +11277,11 @@ estree-walker@^1.0.1: resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== +estree-walker@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.1.tgz#f8e030fb21cefa183b44b7ad516b747434e7a3e0" + integrity sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -12705,7 +12902,7 @@ graphql-upload@^8.0.2: http-errors "^1.7.3" object-path "^0.11.4" -graphql@15.3.0, graphql@^15.3.0: +graphql@15.3.0, graphql@^15.0.0, graphql@^15.3.0: version "15.3.0" resolved "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278" integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w== @@ -12881,7 +13078,7 @@ he@^1.1.0, he@^1.2.0: resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -headers-utils@^1.2.0: +headers-utils@^1.1.9, headers-utils@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/headers-utils/-/headers-utils-1.2.0.tgz#5e10d1bc9d2bccf789547afca5b991a3167241e8" integrity sha512-4/BMXcWrJErw7JpM87gF8MNEXcIMLzepYZjNRv/P9ctgupl2Ywa3u1PgHtNhSRq84bHH9Ndlkdy7bSi+bZ9I9A== @@ -13684,6 +13881,11 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -13703,6 +13905,13 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" +is-core-module@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz#58531b70aed1db7c0e8d4eb1a0a2d1ddd64bd12d" + integrity sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -13871,6 +14080,11 @@ is-module@^1.0.0: resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + is-npm@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" @@ -14389,6 +14603,14 @@ jest-esm-transformer@^1.0.0: "@babel/core" "^7.4.4" "@babel/plugin-transform-modules-commonjs" "^7.4.4" +jest-fetch-mock@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz#31749c456ae27b8919d69824f1c2bd85fe0a1f3b" + integrity sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw== + dependencies: + cross-fetch "^3.0.4" + promise-polyfill "^8.1.3" + jest-get-type@^25.2.6: version "25.2.6" resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" @@ -14683,6 +14905,11 @@ jose@^2.0.2: dependencies: "@panva/asn1.js" "^1.0.0" +joycon@^2.2.5: + version "2.2.5" + resolved "https://registry.npmjs.org/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615" + integrity sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ== + js-cookie@^2.2.1: version "2.2.1" resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" @@ -15088,6 +15315,14 @@ jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3: array-includes "^3.0.3" object.assign "^4.1.0" +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.1.0" + resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz#642f1d7b88aa6d7eb9d8f2210e166478444fa891" + integrity sha512-d4/UOjg+mxAWxCiF0c5UTSwyqbchkbqCvK87aBovhnh8GtysTjWmgC63tY0cJx/HzGgm9qnA147jVBdpOiQ2RA== + dependencies: + array-includes "^3.1.1" + object.assign "^4.1.1" + jwa@^1.4.1: version "1.4.1" resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" @@ -16516,6 +16751,22 @@ ms@2.1.2, ms@^2.0.0, ms@^2.1.1: resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +msw@^0.19.5: + version "0.19.5" + resolved "https://registry.npmjs.org/msw/-/msw-0.19.5.tgz#7d2a1a852ccf1644d3db6735d69fff6777aac33f" + integrity sha512-J5eQ++gDVZoHPC8gVXtWcakLjgmPipvFj/sEnlRV/WViXuiq2CamSqO3Wbh6H8bAmj+k2vUWCfcVT1HjMdKB2Q== + dependencies: + "@open-draft/until" "^1.0.0" + "@types/cookie" "^0.3.3" + chalk "^4.0.0" + cookie "^0.4.1" + graphql "^15.0.0" + headers-utils "^1.1.9" + node-match-path "^0.4.2" + node-request-interceptor "^0.2.5" + statuses "^2.0.0" + yargs "^15.3.1" + msw@^0.20.5: version "0.20.5" resolved "https://registry.npmjs.org/msw/-/msw-0.20.5.tgz#b6141080c0d8b17c451d9ca36c28cc47b4ac487a" @@ -16829,7 +17080,7 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-match-path@^0.4.4: +node-match-path@^0.4.2, node-match-path@^0.4.4: version "0.4.4" resolved "https://registry.npmjs.org/node-match-path/-/node-match-path-0.4.4.tgz#516a10926093c0cc6f237d020685b593b19baebb" integrity sha512-pBq9gp7TG0r0VXuy/oeZmQsjBSnYQo7G886Ly/B3azRwZuEtHCY155dzmfoKWcDPGgyfIGD8WKVC7h3+6y7yTg== @@ -16888,6 +17139,14 @@ node-releases@^1.1.52, node-releases@^1.1.58: resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== +node-request-interceptor@^0.2.5: + version "0.2.6" + resolved "https://registry.npmjs.org/node-request-interceptor/-/node-request-interceptor-0.2.6.tgz#541278d7033bb6a8befb5dd793f83428cf6446a2" + integrity sha512-aJW1tPSM7nzuZFRe+C/KSz22GJO3CVFMxHHmMGX8Z+tjP7TCIVbzeckLFVfJG68BdVgrdOOP7Ejc57ag820eyA== + dependencies: + debug "^4.1.1" + headers-utils "^1.2.0" + node-request-interceptor@^0.3.5: version "0.3.5" resolved "https://registry.npmjs.org/node-request-interceptor/-/node-request-interceptor-0.3.5.tgz#4b26159617829c9a70643012c0fdc3ae4c78ae43" @@ -17150,6 +17409,11 @@ object-inspect@^1.7.0: resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== +object-inspect@^1.8.0: + version "1.8.0" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== + object-is@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" @@ -17182,6 +17446,16 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" + integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.0" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.defaults@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" @@ -17202,6 +17476,15 @@ object.entries@^1.1.0, object.entries@^1.1.1: function-bind "^1.1.1" has "^1.0.3" +object.entries@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" + integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + has "^1.0.3" + "object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" @@ -18862,6 +19145,11 @@ promise-inflight@^1.0.1: resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +promise-polyfill@^8.1.3: + version "8.2.0" + resolved "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.0.tgz#367394726da7561457aba2133c9ceefbd6267da0" + integrity sha512-k/TC0mIcPVF6yHhUvwAp7cvL6I2fFV7TzF1DuGPI8mBh4QQazf36xCKEHKTZKRysEoTQoQdKyP25J8MPJp7j5g== + promise-retry@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" @@ -20449,6 +20737,14 @@ resolve@1.17.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.0 dependencies: path-parse "^1.0.6" +resolve@^1.18.1: + version "1.18.1" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" + integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== + dependencies: + is-core-module "^2.0.0" + path-parse "^1.0.6" + responselike@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -20563,13 +20859,20 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rollup-plugin-dts@1.4.13: +rollup-plugin-dts@1.4.13, rollup-plugin-dts@^1.4.10: version "1.4.13" resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-1.4.13.tgz#4f086e84f4fdcc1f49160799ebc66f6b09db292b" integrity sha512-7mxoQ6PcmCkBE5ZhrjGDL4k42XLy8BkSqpiRi1MipwiGs+7lwi4mQkp2afX+OzzLjJp/TGM8llfe8uayIUhPEw== optionalDependencies: "@babel/code-frame" "^7.10.4" +rollup-plugin-dts@1.4.8: + version "1.4.8" + resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-1.4.8.tgz#3b0eadc285aede11c3f5ced72b56b5f7735df95c" + integrity sha512-2qHB4B3oaTyi1mDmqDzsRGKlev32v3EhMUAmc45Cn9eB22R7FsYDiigvT9XdM/oQzfd0qv5MkeZju8DP0nauiA== + optionalDependencies: + "@babel/code-frame" "^7.10.4" + rollup-plugin-esbuild@^2.0.0: version "2.3.0" resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-2.3.0.tgz#7c107d4508af80d30966a148b306cb7d5b36b258" @@ -20577,11 +20880,25 @@ rollup-plugin-esbuild@^2.0.0: dependencies: "@rollup/pluginutils" "^3.1.0" +rollup-plugin-esbuild@^2.4.2: + version "2.5.2" + resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-2.5.2.tgz#fd7d4a88518898012a9d07e4c3ef8b4009c244d3" + integrity sha512-E4q3ac1AlMd0m0ZRYffdiorOt2eZcxfbdPaqBLs7JLnPE8krgIAihOD6cTUc54UJjoOMA9WcY63TR+JKWLzYNw== + dependencies: + "@rollup/pluginutils" "^4.0.0" + joycon "^2.2.5" + strip-json-comments "^3.1.1" + rollup-plugin-peer-deps-external@^2.2.2: version "2.2.3" resolved "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.3.tgz#059a8aec1eefb48a475e9fcedc3b9e3deb521213" integrity sha512-W6IePXTExGXVDAlfZbNUUrx3GxUOZP248u5n4a4ID1XZMrbQ+uGeNiEfapvdzwx0qZi5DNH/hDLiPUP+pzFIxg== +rollup-plugin-peer-deps-external@^2.2.3: + version "2.2.4" + resolved "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz#8a420bbfd6dccc30aeb68c9bf57011f2f109570d" + integrity sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g== + rollup-plugin-postcss@^3.1.1: version "3.1.8" resolved "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-3.1.8.tgz#d1bcaf8eb0fcb0936e3684c22dd8628d13a82fd1" @@ -20620,6 +20937,13 @@ rollup-pluginutils@^2.8.2: dependencies: estree-walker "^0.6.1" +rollup@2.23.1: + version "2.23.1" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.23.1.tgz#d458d28386dc7660c2e8a4978bea6f9494046c20" + integrity sha512-Heyl885+lyN/giQwxA8AYT2GY3U+gOlTqVLrMQYno8Z1X9lAOpfXPiKiZCyPc25e9BLJM3Zlh957dpTlO4pa8A== + optionalDependencies: + fsevents "~2.1.2" + rollup@2.23.x: version "2.23.0" resolved "https://registry.npmjs.org/rollup/-/rollup-2.23.0.tgz#b7ab1fee0c0e60132fd0553c4df1e9cdacfada9d" @@ -20635,6 +20959,13 @@ rollup@^0.63.4: "@types/estree" "0.0.39" "@types/node" "*" +rollup@^2.23.1: + version "2.32.1" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz#625a92c54f5b4d28ada12d618641491d4dbb548c" + integrity sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw== + optionalDependencies: + fsevents "~2.1.2" + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -21756,6 +22087,14 @@ string.prototype.padstart@^3.0.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" +string.prototype.trimend@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" + integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + string.prototype.trimleft@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" @@ -21772,6 +22111,14 @@ string.prototype.trimright@^2.1.1: define-properties "^1.1.3" function-bind "^1.1.1" +string.prototype.trimstart@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" + integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -21874,6 +22221,11 @@ strip-json-comments@^3.1.0: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -24194,6 +24546,11 @@ yaml@*, yaml@^1.10.0, yaml@^1.7.2, yaml@^1.9.2: resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== +yaml@^2.0.0-1: + version "2.0.0-1" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz#8c3029b3ee2028306d5bcf396980623115ff8d18" + integrity sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ== + yargs-parser@18.x, yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" From 2ceddba979ea487052826e71147ca78a2c306907 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Tue, 27 Oct 2020 08:31:53 +0100 Subject: [PATCH 04/32] Cleanup --- .../src/ingestion/ConfigGenerator.ts | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts b/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts index 6879cd8291..d4d586b4de 100644 --- a/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts +++ b/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts @@ -14,22 +14,10 @@ * limitations under the License. */ -import { InputError } from '@backstage/backend-common'; -import { Entity, Location, LocationSpec } from '@backstage/catalog-model'; -import { v4 as uuidv4 } from 'uuid'; +import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; -import { EntitiesCatalog, LocationsCatalog } from '../catalog'; -import { EntityUpsertResponse } from '../catalog/types'; -import { durationText } from '../util/timing'; -import { AddLocationResult, ConfigGenerator, LocationReader } from './types'; +import { ConfigGenerator } from './types'; -/** - * Placeholder for operations that span several catalogs and/or stretches out - * in time. - * - * TODO(freben): Find a better home for these, possibly refactoring to use the - * database more directly. - */ export class ConfigGeneratorClient implements ConfigGenerator { logger: Logger; From dbadbe7982a5885199f86887ab7eadfab528d437 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Wed, 28 Oct 2020 23:45:43 +0100 Subject: [PATCH 05/32] Renames and new types --- packages/backend/src/plugins/catalog.ts | 4 +- packages/catalog-model/src/location/index.ts | 2 +- .../catalog-model/src/location/validation.ts | 6 +- ...ConfigGenerator.ts => LocationAnalyzer.ts} | 30 ++++---- .../catalog-backend/src/ingestion/types.ts | 63 +++++++++++++++- .../src/service/CatalogBuilder.ts | 10 +-- plugins/catalog-backend/src/service/router.ts | 19 +++-- yarn.lock | 75 ++++--------------- 8 files changed, 115 insertions(+), 94 deletions(-) rename plugins/catalog-backend/src/ingestion/{ConfigGenerator.ts => LocationAnalyzer.ts} (60%) diff --git a/packages/backend/src/plugins/catalog.ts b/packages/backend/src/plugins/catalog.ts index 8d6c823dce..1338fab440 100644 --- a/packages/backend/src/plugins/catalog.ts +++ b/packages/backend/src/plugins/catalog.ts @@ -28,7 +28,7 @@ export default async function createPlugin(env: PluginEnvironment) { entitiesCatalog, locationsCatalog, higherOrderOperation, - configGenerator, + locationAnalyzer, } = await builder.build(); useHotCleanup( @@ -40,7 +40,7 @@ export default async function createPlugin(env: PluginEnvironment) { entitiesCatalog, locationsCatalog, higherOrderOperation, - configGenerator, + locationAnalyzer, logger: env.logger, }); } diff --git a/packages/catalog-model/src/location/index.ts b/packages/catalog-model/src/location/index.ts index 1b7587c1f0..ce64b988a6 100644 --- a/packages/catalog-model/src/location/index.ts +++ b/packages/catalog-model/src/location/index.ts @@ -18,6 +18,6 @@ export type { Location, LocationSpec } from './types'; export { locationSchema, locationSpecSchema, - repoPathSchema, + analyzeLocationSchema, } from './validation'; export { LOCATION_ANNOTATION } from './annotation'; diff --git a/packages/catalog-model/src/location/validation.ts b/packages/catalog-model/src/location/validation.ts index 28662119b0..4d2e602862 100644 --- a/packages/catalog-model/src/location/validation.ts +++ b/packages/catalog-model/src/location/validation.ts @@ -35,9 +35,9 @@ export const locationSchema = yup .noUnknown() .required(); -export const repoPathSchema = yup - .object<{ repoPath: string }>({ - repoPath: yup.string().required(), +export const analyzeLocationSchema = yup + .object<{ location: LocationSpec }>({ + location: locationSpecSchema, }) .noUnknown() .required(); diff --git a/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts similarity index 60% rename from plugins/catalog-backend/src/ingestion/ConfigGenerator.ts rename to plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts index d4d586b4de..f6991b1c90 100644 --- a/plugins/catalog-backend/src/ingestion/ConfigGenerator.ts +++ b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts @@ -14,32 +14,36 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; -import { ConfigGenerator } from './types'; +import { + AnalyzeLocationRequest, + AnalyzeLocationResponse, + LocationAnalyzer, +} from './types'; -export class ConfigGeneratorClient implements ConfigGenerator { - logger: Logger; +export class LocationAnalyzerClient implements LocationAnalyzer { + private readonly logger: Logger; constructor(logger: Logger) { this.logger = logger; } - async generateConfig(repoPath: string): Promise { - const [ownerName, repoName] = [ - repoPath.split('/')[0], - repoPath.split('/')[1], - ]; - const config = { + async generateConfig( + request: AnalyzeLocationRequest, + ): Promise { + const [ownerName, repoName] = request.location.target.split('/').slice(-2); + const entity = { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', metadata: { name: repoName, - description: '', - annotations: { 'github.com/project-slug': repoPath }, + annotations: { 'github.com/project-slug': `${ownerName}/${repoName}` }, }, spec: { type: 'service', owner: ownerName, lifecycle: 'experimental' }, }; - return [config]; + return { + existingEntityFiles: [], + generateEntities: [{ entity, fields: [] }], + }; } } diff --git a/plugins/catalog-backend/src/ingestion/types.ts b/plugins/catalog-backend/src/ingestion/types.ts index 2d7165c140..19d472b3ab 100644 --- a/plugins/catalog-backend/src/ingestion/types.ts +++ b/plugins/catalog-backend/src/ingestion/types.ts @@ -20,6 +20,7 @@ import type { Location, LocationSpec, } from '@backstage/catalog-model'; +import { RecursivePartial } from './processors/ldap/util'; // // HigherOrderOperation @@ -70,6 +71,64 @@ export type ReadLocationError = { // ConfigGenerator // -export type ConfigGenerator = { - generateConfig(repoPath: string): Promise; +export type LocationAnalyzer = { + generateConfig( + location: AnalyzeLocationRequest, + ): Promise; +}; + +export type AnalyzeLocationRequest = { + location: LocationSpec; +}; + +export type AnalyzeLocationResponse = { + existingEntityFiles: AnalyzeLocationExistingEntity[]; + generateEntities: AnalyzeLocationGenerateEntity[]; +}; + +// If the folder pointed to already contained catalog info yaml files, they are +// read and emitted like this so that the frontend can inform the user that it +// located them and can make sure to register them as well if they weren't +// already +type AnalyzeLocationExistingEntity = { + location: LocationSpec; + isRegistered: boolean; + entity: Entity; +}; + +// This is some form of representation of what the analyzer could deduce. +// We should probably have a chat about how this can best be conveyed to +// the frontend. It'll probably contain a (possibly incomplete) entity, plus +// enough info for the frontend to know what form data to show to the user +// for overriding/completing the info. +type AnalyzeLocationGenerateEntity = { + // Some form of partial representation of the entity + entity: RecursivePartial; + // Lists the suggestions that the user may want to override + fields: AnalyzeLocationEntityField[]; +}; + +// This is where I get really vague. Something like this perhaps? Or it could be +// something like a json-schema that contains enough info for the frontend to +// be able to present a form and explanations +type AnalyzeLocationEntityField = { + // e.g. "spec.owner"? The frontend needs to know how to "inject" the field into the + // entity again if the user wants to change it + field: string; + + // The outcome of the analysis for this particular field + state: + | 'analysis_suggested_value' + | 'analysis_suggested_no_value' + | 'needs_user_input'; + + // If the analysis did suggest a value, this is where it would be. Not sure if we want + // to limit this to strings or if we want it to be any JsonValue + value: string | null; + + // A text to show to the user to inform about the choices made. Like, it could say + // "Found a CODEOWNERS file that covers this target, so we suggest leaving this + // field empty; which would currently make it owned by X" where X is taken from the + // codeowners file. + description: string; }; diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 39417dfd6f..439b85591f 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -52,7 +52,7 @@ import { UrlReaderProcessor, } from '../ingestion'; import { CatalogRulesEnforcer } from '../ingestion/CatalogRules'; -import { ConfigGeneratorClient } from '../ingestion/ConfigGenerator'; +import { LocationAnalyzerClient } from '../ingestion/LocationAnalyzer'; import { BuiltinKindsEntityProcessor } from '../ingestion/processors/BuiltinKindsEntityProcessor'; import { LdapOrgReaderProcessor } from '../ingestion/processors/LdapOrgReaderProcessor'; import { @@ -60,7 +60,7 @@ import { textPlaceholderResolver, yamlPlaceholderResolver, } from '../ingestion/processors/PlaceholderProcessor'; -import { ConfigGenerator } from '../ingestion/types'; +import { LocationAnalyzer } from '../ingestion/types'; export type CatalogEnvironment = { logger: Logger; @@ -204,7 +204,7 @@ export class CatalogBuilder { entitiesCatalog: EntitiesCatalog; locationsCatalog: LocationsCatalog; higherOrderOperation: HigherOrderOperation; - configGenerator: ConfigGenerator; + locationAnalyzer: LocationAnalyzer; }> { const { config, database, logger } = this.env; @@ -232,13 +232,13 @@ export class CatalogBuilder { locationReader, logger, ); - const configGenerator = new ConfigGeneratorClient(logger); + const locationAnalyzer = new LocationAnalyzerClient(logger); return { entitiesCatalog, locationsCatalog, higherOrderOperation, - configGenerator, + locationAnalyzer, }; } diff --git a/plugins/catalog-backend/src/service/router.ts b/plugins/catalog-backend/src/service/router.ts index b11572b180..8d5fb73c37 100644 --- a/plugins/catalog-backend/src/service/router.ts +++ b/plugins/catalog-backend/src/service/router.ts @@ -15,13 +15,16 @@ */ import { errorHandler } from '@backstage/backend-common'; -import { locationSpecSchema, repoPathSchema } from '@backstage/catalog-model'; +import { + locationSpecSchema, + analyzeLocationSchema, +} from '@backstage/catalog-model'; import type { Entity } from '@backstage/catalog-model'; import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; import { EntitiesCatalog, LocationsCatalog } from '../catalog'; -import { ConfigGenerator, HigherOrderOperation } from '../ingestion/types'; +import { LocationAnalyzer, HigherOrderOperation } from '../ingestion/types'; import { translateQueryToEntityFilters, translateQueryToFieldMapper, @@ -32,7 +35,7 @@ export interface RouterOptions { entitiesCatalog?: EntitiesCatalog; locationsCatalog?: LocationsCatalog; higherOrderOperation?: HigherOrderOperation; - configGenerator?: ConfigGenerator; + locationAnalyzer?: LocationAnalyzer; logger: Logger; } @@ -43,7 +46,7 @@ export async function createRouter( entitiesCatalog, locationsCatalog, higherOrderOperation, - configGenerator, + locationAnalyzer: locationAnalyzer, } = options; const router = Router(); @@ -135,10 +138,10 @@ export async function createRouter( }); } - if (configGenerator) { - router.post('/generate-config', async (req, res) => { - const input = await validateRequestBody(req, repoPathSchema); - const output = await configGenerator.generateConfig(input.repoPath); + if (locationAnalyzer) { + router.post('/analyze-location', async (req, res) => { + const input = await validateRequestBody(req, analyzeLocationSchema); + const output = await locationAnalyzer.generateConfig(input); res.status(201).send(output); }); } diff --git a/yarn.lock b/yarn.lock index 7f85f649c9..1c6125854e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3691,50 +3691,18 @@ react-router "^6.0.0-beta.0" react-use "^15.3.3" -"@roadiehq/backstage-plugin-github-pull-requests@^0.5.2": - version "0.5.2" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-0.5.2.tgz#455355fe5cdcc43c22b80a8ef3697378084680a1" - integrity sha512-GM+nWQZ+aehMclN70Pp35UQe3I46SQCjWiGZ6/0TfDzrueHln39L2UspUj1L/713xDDtDK8ZnTJdFn/qKx7j4A== +"@rollup/plugin-commonjs@^14.0.0": + version "14.0.0" + resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz#4285f9ec2db686a31129e5a2b415c94aa1f836f0" + integrity sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw== dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.25" - "@backstage/core" "^0.1.1-alpha.25" - "@backstage/plugin-catalog" "^0.1.1-alpha.25" - "@backstage/theme" "^0.1.1-alpha.25" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "^4.0.0-alpha.56" - "@octokit/rest" "^18.0.0" - "@octokit/types" "^5.0.1" - "@types/react-dom" "^16.9.8" - history "^5.0.0" - moment "^2.27.0" - react "^16.13.1" - react-dom "^16.13.1" - react-router "6.0.0-beta.0" - react-use "^15.3.3" - -"@roadiehq/backstage-plugin-travis-ci@^0.2.5": - version "0.2.5" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.2.5.tgz#588cd8b4a4dd4bd426c0012f8d35eae4504b55f4" - integrity sha512-4aJizmvIeunpl8D/YDvzagNzikPU51DSZFz1tN0XCwRR+buTPknV141qsKP+yxUbs6nx3Xuh+T/vNkb9lk6FlA== - dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.24" - "@backstage/core" "^0.1.1-alpha.24" - "@backstage/core-api" "^0.1.1-alpha.24" - "@backstage/plugin-catalog" "^0.1.1-alpha.24" - "@backstage/theme" "^0.1.1-alpha.24" - "@material-ui/core" "^4.9.1" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - date-fns "^2.15.0" - history "^5.0.0" - moment "^2.27.0" - react "^16.13.1" - react-dom "^16.13.1" - 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" + "@rollup/pluginutils" "^3.0.8" + commondir "^1.0.1" + estree-walker "^1.0.1" + glob "^7.1.2" + is-reference "^1.1.2" + magic-string "^0.25.2" + resolve "^1.11.0" "@rollup/plugin-commonjs@^16.0.0": version "16.0.0" @@ -3749,19 +3717,6 @@ magic-string "^0.25.7" resolve "^1.17.0" -"@rollup/plugin-commonjs@^14.0.0": - version "14.0.0" - resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz#4285f9ec2db686a31129e5a2b415c94aa1f836f0" - integrity sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw== - dependencies: - "@rollup/pluginutils" "^3.0.8" - commondir "^1.0.1" - estree-walker "^1.0.1" - glob "^7.1.2" - is-reference "^1.1.2" - magic-string "^0.25.2" - resolve "^1.11.0" - "@rollup/plugin-json@^4.0.2": version "4.1.0" resolved "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3" @@ -9881,7 +9836,7 @@ dateformat@^3.0.0: resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -dayjs@^1.9.4: +dayjs@^1.9.1, dayjs@^1.9.4: version "1.9.4" resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.9.4.tgz#fcde984e227f4296f04e7b05720adad2e1071f1b" integrity sha512-ABSF3alrldf7nM9sQ2U+Ln67NRwmzlLOqG7kK03kck0mw3wlSSEKv/XhKGGxUjQcS57QeiCyNdrFgtj9nWlrng== @@ -14227,7 +14182,7 @@ is-promise@^2.1, is-promise@^2.1.0: resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-reference@^1.2.1: +is-reference@^1.1.2, is-reference@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== @@ -16125,7 +16080,7 @@ macos-release@^2.2.0: resolved "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== -magic-string@^0.25.7: +magic-string@^0.25.2, magic-string@^0.25.7: version "0.25.7" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== @@ -20782,7 +20737,7 @@ resolve@1.17.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0 dependencies: path-parse "^1.0.6" -resolve@^1.18.1: +resolve@^1.11.0, resolve@^1.18.1: version "1.18.1" resolved "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== From babbd50ddb67d63be60bee495f5f41b00989b9b1 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 29 Oct 2020 09:56:28 +0100 Subject: [PATCH 06/32] Create import-component frontend plugin --- .../catalog-backend/src/ingestion/index.ts | 9 +- plugins/import-component/.eslintrc.js | 3 + plugins/import-component/README.md | 7 + plugins/import-component/dev/index.tsx | 22 +++ plugins/import-component/package.json | 56 ++++++ .../src/api/CatalogImportApi.ts | 56 ++++++ .../src/api/CatalogImportClient.ts | 135 ++++++++++++++ plugins/import-component/src/api/index.ts | 34 ++++ plugins/import-component/src/api/types.ts | 38 ++++ .../ImportComponentForm.tsx | 170 ++++++++++++++++++ .../components/ImportComponentForm/index.ts | 17 ++ .../ComponentConfigDisplay.tsx | 98 ++++++++++ .../ImportComponentPage.tsx | 95 ++++++++++ .../ImportComponentPage/ImportFinished.tsx | 73 ++++++++ .../ImportComponentPage/ImportStepper.tsx | 42 +++++ .../components/ImportComponentPage/index.ts | 17 ++ .../ImportComponentPage/useGithubRepos.ts | 74 ++++++++ .../src/components/Router.tsx | 26 +++ plugins/import-component/src/index.ts | 18 ++ plugins/import-component/src/plugin.test.ts | 23 +++ plugins/import-component/src/plugin.ts | 54 ++++++ plugins/import-component/src/setupTests.ts | 17 ++ plugins/import-component/src/util/types.ts | 22 +++ .../src/util/validate.test.ts | 33 ++++ plugins/import-component/src/util/validate.ts | 21 +++ plugins/import-component/tsconfig.json | 5 + 26 files changed, 1157 insertions(+), 8 deletions(-) create mode 100644 plugins/import-component/.eslintrc.js create mode 100644 plugins/import-component/README.md create mode 100644 plugins/import-component/dev/index.tsx create mode 100644 plugins/import-component/package.json create mode 100644 plugins/import-component/src/api/CatalogImportApi.ts create mode 100644 plugins/import-component/src/api/CatalogImportClient.ts create mode 100644 plugins/import-component/src/api/index.ts create mode 100644 plugins/import-component/src/api/types.ts create mode 100644 plugins/import-component/src/components/ImportComponentForm/ImportComponentForm.tsx create mode 100644 plugins/import-component/src/components/ImportComponentForm/index.ts create mode 100644 plugins/import-component/src/components/ImportComponentPage/ComponentConfigDisplay.tsx create mode 100644 plugins/import-component/src/components/ImportComponentPage/ImportComponentPage.tsx create mode 100644 plugins/import-component/src/components/ImportComponentPage/ImportFinished.tsx create mode 100644 plugins/import-component/src/components/ImportComponentPage/ImportStepper.tsx create mode 100644 plugins/import-component/src/components/ImportComponentPage/index.ts create mode 100644 plugins/import-component/src/components/ImportComponentPage/useGithubRepos.ts create mode 100644 plugins/import-component/src/components/Router.tsx create mode 100644 plugins/import-component/src/index.ts create mode 100644 plugins/import-component/src/plugin.test.ts create mode 100644 plugins/import-component/src/plugin.ts create mode 100644 plugins/import-component/src/setupTests.ts create mode 100644 plugins/import-component/src/util/types.ts create mode 100644 plugins/import-component/src/util/validate.test.ts create mode 100644 plugins/import-component/src/util/validate.ts create mode 100644 plugins/import-component/tsconfig.json diff --git a/plugins/catalog-backend/src/ingestion/index.ts b/plugins/catalog-backend/src/ingestion/index.ts index 4ebb2edc79..fad4ae34f7 100644 --- a/plugins/catalog-backend/src/ingestion/index.ts +++ b/plugins/catalog-backend/src/ingestion/index.ts @@ -16,12 +16,5 @@ export { HigherOrderOperations } from './HigherOrderOperations'; export { LocationReaders } from './LocationReaders'; -export type { - AddLocationResult, - HigherOrderOperation, - LocationReader, - ReadLocationEntity, - ReadLocationError, - ReadLocationResult, -} from './types'; +export * from './types'; export * from './processors'; diff --git a/plugins/import-component/.eslintrc.js b/plugins/import-component/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/plugins/import-component/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/plugins/import-component/README.md b/plugins/import-component/README.md new file mode 100644 index 0000000000..682212d98d --- /dev/null +++ b/plugins/import-component/README.md @@ -0,0 +1,7 @@ +# Register component plugin + +Welcome to the import-component plugin! + +This plugin allows you to create a component-config YAML file for your repository. + +When installed it is accessible on [localhost:3000/import-component](localhost:3000/import-component). diff --git a/plugins/import-component/dev/index.tsx b/plugins/import-component/dev/index.tsx new file mode 100644 index 0000000000..d97643057b --- /dev/null +++ b/plugins/import-component/dev/index.tsx @@ -0,0 +1,22 @@ +/* + * 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 { createDevApp } from '@backstage/dev-utils'; +import { plugin } from '../src/plugin'; + +createDevApp() + .registerPlugin(plugin) + .render(); diff --git a/plugins/import-component/package.json b/plugins/import-component/package.json new file mode 100644 index 0000000000..73a9aa007f --- /dev/null +++ b/plugins/import-component/package.json @@ -0,0 +1,56 @@ +{ + "name": "@backstage/plugin-import-component", + "version": "0.1.1-alpha.26", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": false, + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "build": "backstage-cli plugin:build", + "start": "backstage-cli plugin:serve", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "diff": "backstage-cli plugin:diff", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/plugin-catalog-backend": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", + "@material-ui/core": "^4.11.0", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.45", + "@octokit/rest": "^18.0.6", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-hook-form": "^6.6.0", + "react-router": "^5.2.0", + "react-router-dom": "6.0.0-beta.0", + "react-use": "^15.3.3", + "yaml": "^1.10.0" + }, + "devDependencies": { + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^10.4.1", + "@testing-library/user-event": "^12.0.7", + "@types/jest": "^26.0.7", + "@types/node": "^12.0.0", + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/import-component/src/api/CatalogImportApi.ts b/plugins/import-component/src/api/CatalogImportApi.ts new file mode 100644 index 0000000000..58d1f87f00 --- /dev/null +++ b/plugins/import-component/src/api/CatalogImportApi.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ +/* + * Copyright 2020 Roadie 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 { createApiRef } from '@backstage/core'; +import { Entity } from '@backstage/catalog-model'; +import { RecursivePartial } from '../util/types'; + +export const catalogImportApiRef = createApiRef({ + id: 'plugin.catalogimport.service', + description: 'Used by the catalog import plugin to make requests', +}); + +export interface CatalogImportApi { + submitPRToRepo(options: { + token: string; + owner: string; + repo: string; + fileContent: string; + }): Promise<{ errorMessage: string | null; link: string }>; + createRepositoryLocation(options: { + token: string; + owner: string; + repo: string; + }): Promise<{ errorMessage: string | null }>; + generateEntityDefinitions(options: { + repo: string; + }): Promise[]>; +} diff --git a/plugins/import-component/src/api/CatalogImportClient.ts b/plugins/import-component/src/api/CatalogImportClient.ts new file mode 100644 index 0000000000..d67febe2c8 --- /dev/null +++ b/plugins/import-component/src/api/CatalogImportClient.ts @@ -0,0 +1,135 @@ +/* + * 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. + */ +/* + * Copyright 2020 Roadie 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 { Octokit } from '@octokit/rest'; +import { Entity } from '@backstage/catalog-model'; +import { DiscoveryApi } from '@backstage/core'; +import { CatalogImportApi } from './CatalogImportApi'; +import { AnalyzeLocationResponse } from '@backstage/plugin-catalog-backend'; +import { RecursivePartial } from '../util/types'; + +export const API_BASE_URL = '/api/catalog/locations'; + +export class CatalogImportClient implements CatalogImportApi { + private readonly discoveryApi: DiscoveryApi; + + constructor(options: { discoveryApi: DiscoveryApi }) { + this.discoveryApi = options.discoveryApi; + } + + async generateEntityDefinitions({ + repo, + }: { + repo: string; + }): Promise[]> { + const response = await fetch( + `${await this.discoveryApi.getBaseUrl('catalog')}/analyze-location`, + { + headers: { + 'Content-Type': 'application/json', + }, + method: 'POST', + body: JSON.stringify({ + location: { type: 'github', target: repo }, + }), + }, + ); + const payload = (await response.json()) as AnalyzeLocationResponse; + return payload.generateEntities.map(x => x.entity); + } + + async createRepositoryLocation({ + owner, + repo, + }: { + token: string; + owner: string; + repo: string; + }): Promise<{ errorMessage: string | null }> { + await fetch(`${await this.discoveryApi.getBaseUrl('catalog')}/locations`, { + headers: { + 'Content-Type': 'application/json', + }, + method: 'POST', + body: JSON.stringify({ + type: 'github', + target: `https://github.com/${owner}/${repo}/blob/master/catalog-info.yaml`, + presence: 'optional', + }), + }); + return { errorMessage: null }; + } + + async submitPRToRepo({ + token, + owner, + repo, + fileContent, + }: { + token: string; + owner: string; + repo: string; + fileContent: string; + }): Promise<{ errorMessage: string | null; link: string }> { + const octo = new Octokit({ + auth: token, + }); + + const parentRef = await octo.git.getRef({ + owner, + repo, + ref: 'heads/master', + }); + await octo.git.createRef({ + owner, + repo, + ref: 'refs/heads/backstage-integration', + sha: parentRef.data.object.sha, + }); + await octo.repos.createOrUpdateFileContents({ + owner, + repo, + path: 'backstage.yaml', + message: 'Add backstage.yaml config file', + content: btoa(fileContent), + branch: 'backstage-integration', + }); + const pullRequestRespone = await octo.pulls.create({ + owner, + repo, + title: 'Add backstage.yaml config file', + head: 'backstage-integration', + base: 'master', + }); + + return { errorMessage: null, link: pullRequestRespone.data.html_url }; + } +} diff --git a/plugins/import-component/src/api/index.ts b/plugins/import-component/src/api/index.ts new file mode 100644 index 0000000000..9ebc110843 --- /dev/null +++ b/plugins/import-component/src/api/index.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ +/* + * Copyright 2020 Roadie 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 * from './CatalogImportApi'; +export * from './CatalogImportClient'; +export * from './types'; diff --git a/plugins/import-component/src/api/types.ts b/plugins/import-component/src/api/types.ts new file mode 100644 index 0000000000..c18d0cf547 --- /dev/null +++ b/plugins/import-component/src/api/types.ts @@ -0,0 +1,38 @@ +/* + * 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. + */ +/* + * Copyright 2020 Roadie 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 type GithubRepoDto = { + full_name: string; + private: boolean; + description: string; + html_url: string; + language: string; +}; diff --git a/plugins/import-component/src/components/ImportComponentForm/ImportComponentForm.tsx b/plugins/import-component/src/components/ImportComponentForm/ImportComponentForm.tsx new file mode 100644 index 0000000000..c28e5889ac --- /dev/null +++ b/plugins/import-component/src/components/ImportComponentForm/ImportComponentForm.tsx @@ -0,0 +1,170 @@ +/* + * 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 { errorApiRef, useApi } from '@backstage/core'; +import { BackstageTheme } from '@backstage/theme'; +import { + Button, + FormControl, + FormHelperText, + InputLabel, + MenuItem, + Select, + TextField, +} from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import React from 'react'; +import { Controller, useForm } from 'react-hook-form'; +import { useMountedState } from 'react-use'; +import { RecursivePartial } from '../../util/types'; +import { ComponentIdValidators } from '../../util/validate'; +import { useGithubRepos } from '../ImportComponentPage/useGithubRepos'; + +const useStyles = makeStyles(theme => ({ + form: { + alignItems: 'flex-start', + display: 'flex', + flexFlow: 'column nowrap', + }, + submit: { + marginTop: theme.spacing(1), + }, + select: { + minWidth: 120, + }, +})); + +type Props = { + nextStep: () => void; + saveConfig: (configFile: { + repo: string; + config: RecursivePartial[]; + }) => void; +}; + +export const RegisterComponentForm = ({ nextStep, saveConfig }: Props) => { + const { control, register, handleSubmit, errors, formState } = useForm({ + mode: 'onChange', + }); + const classes = useStyles(); + const hasErrors = !!errors.componentLocation; + const dirty = formState?.isDirty; + + const isMounted = useMountedState(); + const errorApi = useApi(errorApiRef); + const { generateEntityDefinitions } = useGithubRepos(); + + const onSubmit = async (formData: Record) => { + const { componentLocation: target } = formData; + try { + // const typeMapping = [ + // { url: /^https:\/\/gitlab\.com\/.*/, type: 'gitlab/api' }, + // { url: /^https:\/\/bitbucket\.org\/.*/, type: 'bitbucket/api' }, + // { url: /^https:\/\/dev\.azure\.com\/.*/, type: 'azure/api' }, + // { url: /.*/, type: 'github' }, + // ]; + + // const type = + // scmType === 'AUTO' + // ? typeMapping.filter(item => item.url.test(target))[0].type + // : scmType; + + if (!isMounted()) return; + + const repo = target + .split('/') + .slice(-2) + .join('/'); + + const config = await generateEntityDefinitions(repo); + saveConfig({ + repo, + config, + }); + nextStep(); + } catch (e) { + errorApi.post(e); + } + }; + + return ( +
+ + + + {errors.componentLocation && ( + + {errors.componentLocation.message} + + )} + + + + Host type + ( + + )} + /> + + +
+ ); +}; diff --git a/plugins/import-component/src/components/ImportComponentForm/index.ts b/plugins/import-component/src/components/ImportComponentForm/index.ts new file mode 100644 index 0000000000..ed118f5412 --- /dev/null +++ b/plugins/import-component/src/components/ImportComponentForm/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export * from './ImportComponentForm'; diff --git a/plugins/import-component/src/components/ImportComponentPage/ComponentConfigDisplay.tsx b/plugins/import-component/src/components/ImportComponentPage/ComponentConfigDisplay.tsx new file mode 100644 index 0000000000..22d3dac322 --- /dev/null +++ b/plugins/import-component/src/components/ImportComponentPage/ComponentConfigDisplay.tsx @@ -0,0 +1,98 @@ +/* + * 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. + */ +/* + * Copyright 2020 RoadieHQ + * + * 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 React, { useCallback, useState } from 'react'; +import { Button, CircularProgress, Grid, Tooltip } from '@material-ui/core'; +import Alert from '@material-ui/lab/Alert'; +import { useGithubRepos } from './useGithubRepos'; +import { Entity } from '@backstage/catalog-model'; +import { RecursivePartial } from '../../util/types'; + +type Props = { + nextStep: () => void; + configFile: { repo: string; config: RecursivePartial[] }; + savePRLink: (PRLink: string) => void; +}; + +const ComponentConfigDisplay: React.FC = ({ + nextStep, + configFile, + savePRLink, +}) => { + const [submitting, setSubmitting] = useState(false); + const { submitPRToRepo } = useGithubRepos(); + const onNext = useCallback(async () => { + setSubmitting(true); + const result = await submitPRToRepo(configFile); + savePRLink(result.link); + setSubmitting(false); + nextStep(); + }, [submitPRToRepo, configFile, nextStep, savePRLink]); + + return ( + + + + config file has been generated. You can optionally edit it before + submitting Pull Request + + + + + + + + + + + {submitting ? ( + + + + ) : null} + + + + + + ); +}; + +export default ComponentConfigDisplay; diff --git a/plugins/import-component/src/components/ImportComponentPage/ImportComponentPage.tsx b/plugins/import-component/src/components/ImportComponentPage/ImportComponentPage.tsx new file mode 100644 index 0000000000..719d5e93f4 --- /dev/null +++ b/plugins/import-component/src/components/ImportComponentPage/ImportComponentPage.tsx @@ -0,0 +1,95 @@ +/* + * 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 React, { useState } from 'react'; +import { Grid } from '@material-ui/core'; +import { + InfoCard, + Page, + Content, + Header, + SupportButton, + ContentHeader, +} from '@backstage/core'; +import { RegisterComponentForm } from '../ImportComponentForm'; +import { Entity } from '@backstage/catalog-model'; +import ImportStepper from './ImportStepper'; +import ComponentConfigDisplay from './ComponentConfigDisplay'; +import { ImportFinished } from './ImportFinished'; +import { RecursivePartial } from '../../util/types'; + +export const ImportComponentPage = () => { + const [activeStep, setActiveStep] = useState(0); + const [configFile, setConfigFile] = useState<{ + repo: string; + config: RecursivePartial[]; + }>({ repo: '', config: [] }); + const [PRLink, setPRLink] = useState(''); + const nextStep = (options?: { reset: boolean }) => { + setActiveStep(step => (options?.reset ? 0 : step + 1)); + }; + + return ( + +
+ + + + Generate a component definition file and automatically submit it as + a pull request. TODO: Add more information about what this is. + + + + + + + ), + }, + { + step: 'Review generated component config files', + content: ( + + ), + }, + { + step: 'Finish', + content: ( + + ), + }, + ]} + activeStep={activeStep} + nextStep={nextStep} + /> + + + + + + ); +}; diff --git a/plugins/import-component/src/components/ImportComponentPage/ImportFinished.tsx b/plugins/import-component/src/components/ImportComponentPage/ImportFinished.tsx new file mode 100644 index 0000000000..6abe551f96 --- /dev/null +++ b/plugins/import-component/src/components/ImportComponentPage/ImportFinished.tsx @@ -0,0 +1,73 @@ +/* + * 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 React from 'react'; +import Button from '@material-ui/core/Button'; +import { + Grid, + Link, + Typography, + createStyles, + makeStyles, + Theme, +} from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + width: '100%', + }, + heading: { + fontSize: theme.typography.pxToRem(15), + fontWeight: theme.typography.fontWeightRegular, + }, + linkList: { + display: 'flex', + flexDirection: 'column', + }, + }), +); +type Props = { + nextStep: (options?: { reset: boolean }) => void; + PRLink: string; +}; + +export const ImportFinished: React.FC = ({ nextStep, PRLink }) => { + const classes = useStyles(); + return ( + + + + Pull requests have been successfully opened. You can start again to + import more repositories + + + + Pull request link: + {PRLink} + + + + + + ); +}; diff --git a/plugins/import-component/src/components/ImportComponentPage/ImportStepper.tsx b/plugins/import-component/src/components/ImportComponentPage/ImportStepper.tsx new file mode 100644 index 0000000000..03752fa7d4 --- /dev/null +++ b/plugins/import-component/src/components/ImportComponentPage/ImportStepper.tsx @@ -0,0 +1,42 @@ +/* + * 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 React from 'react'; +import Stepper from '@material-ui/core/Stepper'; +import Step from '@material-ui/core/Step'; +import StepLabel from '@material-ui/core/StepLabel'; +import { StepContent } from '@material-ui/core'; + +type Props = { + steps: { step: string; content: React.ReactNode }[]; + activeStep: number; + nextStep: (options?: { reset: boolean }) => void; +}; + +export default function ImportStepper({ steps, activeStep }: Props) { + return ( + + {steps.map(({ step }) => { + const stepProps: { completed?: boolean } = {}; + return ( + + {step} + {steps[activeStep].content} + + ); + })} + + ); +} diff --git a/plugins/import-component/src/components/ImportComponentPage/index.ts b/plugins/import-component/src/components/ImportComponentPage/index.ts new file mode 100644 index 0000000000..dee2816011 --- /dev/null +++ b/plugins/import-component/src/components/ImportComponentPage/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export * from './ImportComponentPage'; diff --git a/plugins/import-component/src/components/ImportComponentPage/useGithubRepos.ts b/plugins/import-component/src/components/ImportComponentPage/useGithubRepos.ts new file mode 100644 index 0000000000..f28d5a444e --- /dev/null +++ b/plugins/import-component/src/components/ImportComponentPage/useGithubRepos.ts @@ -0,0 +1,74 @@ +/* + * 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. + */ +/* + * Copyright 2020 Roadie + * + * 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 * as YAML from 'yaml'; +import { useApi, githubAuthApiRef } from '@backstage/core'; +import { Entity } from '@backstage/catalog-model'; +import { catalogImportApiRef } from '../../api/CatalogImportApi'; +import { RecursivePartial } from '../../util/types'; + +export function useGithubRepos() { + const api = useApi(catalogImportApiRef); + const auth = useApi(githubAuthApiRef); + + const submitPRToRepo = async (selectedRepo: { + repo: string; + config: RecursivePartial[]; + }) => { + const token = await auth.getAccessToken(['repo']); + + const [ownerName, repoName] = [ + selectedRepo.repo.split('/')[0], + selectedRepo.repo.split('/')[1], + ]; + const submitPRResponse = await api.submitPRToRepo({ + token, + owner: ownerName, + repo: repoName, + fileContent: selectedRepo.config + .map(entity => `---\n${YAML.stringify(entity)}`) + .join('\n'), + }); + + await api.createRepositoryLocation({ + token, + owner: selectedRepo.repo.split('/')[0], + repo: selectedRepo.repo.split('/')[1], + }); + + return submitPRResponse; + }; + + return { + submitPRToRepo, + generateEntityDefinitions: (repo: string) => + api.generateEntityDefinitions({ repo }), + }; +} diff --git a/plugins/import-component/src/components/Router.tsx b/plugins/import-component/src/components/Router.tsx new file mode 100644 index 0000000000..c877d3a208 --- /dev/null +++ b/plugins/import-component/src/components/Router.tsx @@ -0,0 +1,26 @@ +/* + * 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 React from 'react'; +import { Route, Routes } from 'react-router'; +import { ImportComponentPage } from './ImportComponentPage'; + +// As we don't know which path the catalog's router mounted on +// We need to inject this from the app +export const Router = () => ( + + } /> + +); diff --git a/plugins/import-component/src/index.ts b/plugins/import-component/src/index.ts new file mode 100644 index 0000000000..ff7857cacd --- /dev/null +++ b/plugins/import-component/src/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +export { plugin } from './plugin'; +export { Router } from './components/Router'; diff --git a/plugins/import-component/src/plugin.test.ts b/plugins/import-component/src/plugin.test.ts new file mode 100644 index 0000000000..dd10754a87 --- /dev/null +++ b/plugins/import-component/src/plugin.test.ts @@ -0,0 +1,23 @@ +/* + * 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 { plugin } from './plugin'; + +describe('import-component', () => { + it('should export plugin', () => { + expect(plugin).toBeDefined(); + }); +}); diff --git a/plugins/import-component/src/plugin.ts b/plugins/import-component/src/plugin.ts new file mode 100644 index 0000000000..a5db8337da --- /dev/null +++ b/plugins/import-component/src/plugin.ts @@ -0,0 +1,54 @@ +/* + * 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. + */ +/* + * Copyright 2020 Roadie 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 { + createApiFactory, + createPlugin, + createRouteRef, + discoveryApiRef, +} from '@backstage/core'; +import { catalogImportApiRef } from './api/CatalogImportApi'; +import { CatalogImportClient } from './api/CatalogImportClient'; + +export const rootRouteRef = createRouteRef({ + path: '', + title: 'import-component', +}); + +export const plugin = createPlugin({ + id: 'import-component', + apis: [ + createApiFactory({ + api: catalogImportApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new CatalogImportClient({ discoveryApi }), + }), + ], +}); diff --git a/plugins/import-component/src/setupTests.ts b/plugins/import-component/src/setupTests.ts new file mode 100644 index 0000000000..825bcd4115 --- /dev/null +++ b/plugins/import-component/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * 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 '@testing-library/jest-dom'; diff --git a/plugins/import-component/src/util/types.ts b/plugins/import-component/src/util/types.ts new file mode 100644 index 0000000000..77b96f5036 --- /dev/null +++ b/plugins/import-component/src/util/types.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ +export type RecursivePartial = { + [P in keyof T]?: T[P] extends (infer U)[] + ? RecursivePartial[] + : T[P] extends object + ? RecursivePartial + : T[P]; +}; diff --git a/plugins/import-component/src/util/validate.test.ts b/plugins/import-component/src/util/validate.test.ts new file mode 100644 index 0000000000..139c7fb0f8 --- /dev/null +++ b/plugins/import-component/src/util/validate.test.ts @@ -0,0 +1,33 @@ +/* + * 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 { ComponentIdValidators } from './validate'; + +describe('ComponentIdValidators', () => { + describe('httpsValidator validator', () => { + const errorMessage = 'Must start with https://.'; + test.each([ + [true, 'https://example.com'], + [errorMessage, 'http://example.com'], + [errorMessage, 'example.com'], + [errorMessage, 'www.example.com'], + [errorMessage, ''], + [errorMessage, undefined], + ])('should return %p for %s', (expected: string | boolean, arg: any) => { + expect(ComponentIdValidators.httpsValidator(arg)).toBe(expected); + }); + }); +}); diff --git a/plugins/import-component/src/util/validate.ts b/plugins/import-component/src/util/validate.ts new file mode 100644 index 0000000000..056131aaae --- /dev/null +++ b/plugins/import-component/src/util/validate.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +export const ComponentIdValidators = { + httpsValidator: (value: any) => + (typeof value === 'string' && value.match(/^https:\/\//) !== null) || + 'Must start with https://.', +}; diff --git a/plugins/import-component/tsconfig.json b/plugins/import-component/tsconfig.json new file mode 100644 index 0000000000..b663b01fa2 --- /dev/null +++ b/plugins/import-component/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src", "dev"], + "compilerOptions": {} +} From 29a3a074c6394b22913bb6bd91b70be9efbe9dda Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 29 Oct 2020 10:00:16 +0100 Subject: [PATCH 07/32] Add import component button to the create page --- packages/app/package.json | 1 + packages/app/src/App.tsx | 4 +-- packages/app/src/plugins.ts | 2 +- .../src/ingestion/LocationAnalyzer.ts | 1 + .../catalog-backend/src/ingestion/types.ts | 4 +-- .../src/components/Router.tsx | 2 +- .../ScaffolderPage/ScaffolderPage.tsx | 9 +++++++ yarn.lock | 27 ++++++++++++++++++- 8 files changed, 43 insertions(+), 7 deletions(-) diff --git a/packages/app/package.json b/packages/app/package.json index 656de82ade..5a344a98b8 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -22,6 +22,7 @@ "@backstage/plugin-lighthouse": "^0.1.1-alpha.26", "@backstage/plugin-newrelic": "^0.1.1-alpha.26", "@backstage/plugin-register-component": "^0.1.1-alpha.26", + "@backstage/plugin-import-component": "^0.1.1-alpha.26", "@backstage/plugin-rollbar": "^0.1.1-alpha.26", "@backstage/plugin-scaffolder": "^0.1.1-alpha.26", "@backstage/plugin-sentry": "^0.1.1-alpha.26", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 8b10366c6e..cb85d9afc2 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -27,7 +27,6 @@ import * as plugins from './plugins'; import { apis } from './apis'; import { hot } from 'react-hot-loader/root'; import { providers } from './identityProviders'; -import { Router as CatalogImportRouter } from '@roadiehq/backstage-plugin-catalog-import'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql'; @@ -35,6 +34,7 @@ import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; import { Router as LighthouseRouter } from '@backstage/plugin-lighthouse'; import { Router as RegisterComponentRouter } from '@backstage/plugin-register-component'; import { Router as SettingsRouter } from '@backstage/plugin-user-settings'; +import { Router as ImportComponentRouter } from '@backstage/plugin-import-component'; import { Route, Routes, Navigate } from 'react-router'; import { EntityPage } from './components/catalog/EntityPage'; @@ -83,8 +83,8 @@ const AppRoutes = () => ( path="/register-component" element={} /> + } /> } /> - } /> {...deprecatedAppRoutes} ); diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts index 64c49eceba..30715b617a 100644 --- a/packages/app/src/plugins.ts +++ b/packages/app/src/plugins.ts @@ -37,5 +37,5 @@ export { plugin as Kubernetes } from '@backstage/plugin-kubernetes'; export { plugin as Cloudbuild } from '@backstage/plugin-cloudbuild'; export { plugin as CostInsights } from '@backstage/plugin-cost-insights'; export { plugin as GitHubInsights } from '@roadiehq/backstage-plugin-github-insights'; -export { plugin as CatalogImport } from '@roadiehq/backstage-plugin-catalog-import'; +export { plugin as CatalogImport } from '@backstage/plugin-import-component'; export { plugin as UserSettings } from '@backstage/plugin-user-settings'; diff --git a/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts index f6991b1c90..435ed4f872 100644 --- a/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts +++ b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts @@ -41,6 +41,7 @@ export class LocationAnalyzerClient implements LocationAnalyzer { spec: { type: 'service', owner: ownerName, lifecycle: 'experimental' }, }; + this.logger.silly(`entity created for ${request.location.target}`); return { existingEntityFiles: [], generateEntities: [{ entity, fields: [] }], diff --git a/plugins/catalog-backend/src/ingestion/types.ts b/plugins/catalog-backend/src/ingestion/types.ts index 19d472b3ab..4f229cbc6c 100644 --- a/plugins/catalog-backend/src/ingestion/types.ts +++ b/plugins/catalog-backend/src/ingestion/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { +import { Entity, EntityRelationSpec, Location, @@ -68,7 +68,7 @@ export type ReadLocationError = { }; // -// ConfigGenerator +// LocationAnalyzer // export type LocationAnalyzer = { diff --git a/plugins/import-component/src/components/Router.tsx b/plugins/import-component/src/components/Router.tsx index c877d3a208..9b9c445bb8 100644 --- a/plugins/import-component/src/components/Router.tsx +++ b/plugins/import-component/src/components/Router.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { Route, Routes } from 'react-router'; +import { Route, Routes } from 'react-router-dom'; import { ImportComponentPage } from './ImportComponentPage'; // As we don't know which path the catalog's router mounted on diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index d0cb25f254..306db4db84 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -77,6 +77,15 @@ export const ScaffolderPage = () => { /> + - - - + {submitting ? ( diff --git a/plugins/catalog-import/src/components/ImportComponentForm.tsx b/plugins/catalog-import/src/components/ImportComponentForm.tsx index da078e10f0..9a4fd38a06 100644 --- a/plugins/catalog-import/src/components/ImportComponentForm.tsx +++ b/plugins/catalog-import/src/components/ImportComponentForm.tsx @@ -26,9 +26,11 @@ import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { useForm } from 'react-hook-form'; import { useMountedState } from 'react-use'; +import parseGitUri from 'git-url-parse'; import { ComponentIdValidators } from '../util/validate'; import { useGithubRepos } from '../util/useGithubRepos'; import { ConfigSpec } from './ImportComponentPage'; +import { catalogApiRef } from '@backstage/plugin-catalog'; const useStyles = makeStyles(theme => ({ form: { @@ -53,6 +55,7 @@ export const RegisterComponentForm = ({ nextStep, saveConfig }: Props) => { const classes = useStyles(); const hasErrors = !!errors.componentLocation; const dirty = formState?.isDirty; + const catalogApi = useApi(catalogApiRef); const isMounted = useMountedState(); const errorApi = useApi(errorApiRef); @@ -62,12 +65,22 @@ export const RegisterComponentForm = ({ nextStep, saveConfig }: Props) => { const { componentLocation: target } = formData; try { if (!isMounted()) return; + const type = !parseGitUri(target).filepathtype ? 'repo' : 'file'; - const config = await generateEntityDefinitions(target); - saveConfig({ - repo: target, - config, - }); + if (type === 'repo') { + saveConfig({ + type, + location: target, + config: await generateEntityDefinitions(target), + }); + } else { + const data = await catalogApi.addLocation({ target }); + saveConfig({ + type, + location: data.location.target, + config: data.entities, + }); + } nextStep(); } catch (e) { errorApi.post(e); @@ -111,7 +124,7 @@ export const RegisterComponentForm = ({ nextStep, saveConfig }: Props) => { disabled={!dirty || hasErrors} className={classes.submit} > - Submit + Next ); diff --git a/plugins/catalog-import/src/components/ImportComponentPage.tsx b/plugins/catalog-import/src/components/ImportComponentPage.tsx index 8371eda927..c2eb935e54 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage.tsx +++ b/plugins/catalog-import/src/components/ImportComponentPage.tsx @@ -23,6 +23,7 @@ import { Header, SupportButton, ContentHeader, + RouteRef, } from '@backstage/core'; import { RegisterComponentForm } from './ImportComponentForm'; import ImportStepper from './ImportStepper'; @@ -31,29 +32,35 @@ import { ImportFinished } from './ImportFinished'; import { PartialEntity } from '../util/types'; export type ConfigSpec = { - repo: string; + type: 'repo' | 'file'; + location: string; config: PartialEntity[]; }; -export const ImportComponentPage = () => { +export const ImportComponentPage = ({ + catalogRouteRef, +}: { + catalogRouteRef: RouteRef; +}) => { const [activeStep, setActiveStep] = useState(0); const [configFile, setConfigFile] = useState({ - repo: '', + type: 'repo', + location: '', config: [], }); - const [PRLink, setPRLink] = useState(''); + const [endLink, setEndLink] = useState(''); const nextStep = (options?: { reset: boolean }) => { setActiveStep(step => (options?.reset ? 0 : step + 1)); }; return ( -
+
- + - Generate a component definition file and automatically submit it as - a pull request. TODO: Add more information about what this is. + Start tracking your component in Backstage. TODO: Add more + information about what this is. @@ -62,7 +69,7 @@ export const ImportComponentPage = () => { { ), }, { - step: 'Review generated component config files', + step: 'Review', content: ( ), }, { step: 'Finish', content: ( - + ), }, ]} diff --git a/plugins/catalog-import/src/components/ImportFinished.tsx b/plugins/catalog-import/src/components/ImportFinished.tsx index e7680dbf90..d4ff66ddab 100644 --- a/plugins/catalog-import/src/components/ImportFinished.tsx +++ b/plugins/catalog-import/src/components/ImportFinished.tsx @@ -13,52 +13,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import Button from '@material-ui/core/Button'; -import { - Grid, - Link, - Typography, - createStyles, - makeStyles, - Theme, -} from '@material-ui/core'; -import { Alert } from '@material-ui/lab'; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - heading: { - fontSize: theme.typography.pxToRem(15), - fontWeight: theme.typography.fontWeightRegular, - }, - }), -); +import React from 'react'; +import { Alert } from '@material-ui/lab'; +import { Link as RouterLink } from 'react-router-dom'; +import { Button, Grid, Link } from '@material-ui/core'; + type Props = { + type: 'repo' | 'file'; nextStep: (options?: { reset: boolean }) => void; PRLink: string; }; -export const ImportFinished = ({ nextStep, PRLink }: Props) => { - const classes = useStyles(); +export const ImportFinished = ({ nextStep, PRLink, type }: Props) => { return ( - Pull requests have been successfully opened. You can start again to - import more repositories + {type === 'repo' + ? 'Pull requests have been successfully opened. You can start again to import more repositories' + : 'Entity added to catalog successfully'} - Pull request link: - {PRLink} - - + {type === 'repo' ? ( + + 'View pull request on GitHub' + + ) : null} diff --git a/plugins/catalog-import/src/components/Router.tsx b/plugins/catalog-import/src/components/Router.tsx index bc3c776d0b..5175f8f077 100644 --- a/plugins/catalog-import/src/components/Router.tsx +++ b/plugins/catalog-import/src/components/Router.tsx @@ -14,12 +14,15 @@ * limitations under the License. */ +import { RouteRef } from '@backstage/core'; import React from 'react'; import { Route, Routes } from 'react-router-dom'; import { ImportComponentPage } from './ImportComponentPage'; -export const Router = () => ( +export const Router = ({ catalogRouteRef }: { catalogRouteRef: RouteRef }) => ( - } /> + } + /> ); diff --git a/plugins/catalog-import/src/util/useGithubRepos.ts b/plugins/catalog-import/src/util/useGithubRepos.ts index 3ec4f56c68..84c594c913 100644 --- a/plugins/catalog-import/src/util/useGithubRepos.ts +++ b/plugins/catalog-import/src/util/useGithubRepos.ts @@ -26,7 +26,7 @@ export function useGithubRepos() { const submitPrToRepo = async (selectedRepo: ConfigSpec) => { const token = await auth.getAccessToken(['repo']); - const [ownerName, repoName] = selectedRepo.repo.split('/').slice(-2); + const [ownerName, repoName] = selectedRepo.location.split('/').slice(-2); const submitPRResponse = await api .submitPrToRepo({ oAuthToken: token, @@ -55,5 +55,7 @@ export function useGithubRepos() { submitPrToRepo, generateEntityDefinitions: (repo: string) => api.generateEntityDefinitions({ repo }), + addLocation: (location: string) => + api.createRepositoryLocation({ location }), }; } diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index cc57db2161..8ab8c10ddb 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -82,15 +82,6 @@ export const ScaffolderPage = () => { color="primary" component={RouterLink} to="/catalog-import" - style={{ marginRight: '8px' }} - > - Import Repository - - From 7008e042f93079ef84a6e09799a7bf48a1a9a7f4 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 12 Nov 2020 10:13:18 +0100 Subject: [PATCH 14/32] Fix link to PR --- plugins/catalog-import/src/components/ImportFinished.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-import/src/components/ImportFinished.tsx b/plugins/catalog-import/src/components/ImportFinished.tsx index d4ff66ddab..6ea5c9ab82 100644 --- a/plugins/catalog-import/src/components/ImportFinished.tsx +++ b/plugins/catalog-import/src/components/ImportFinished.tsx @@ -37,12 +37,8 @@ export const ImportFinished = ({ nextStep, PRLink, type }: Props) => { {type === 'repo' ? ( - - 'View pull request on GitHub' + + View pull request on GitHub ) : null} From ecd89ca8a8f97101f729f5ddaacceee49cdd378c Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 12 Nov 2020 22:59:40 +0100 Subject: [PATCH 16/32] Fix leftover codefrom otherwork --- packages/app/src/plugins.ts | 1 - yarn.lock | 355 ++---------------------------------- 2 files changed, 16 insertions(+), 340 deletions(-) diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts index 81d2c2cdec..90c0287b08 100644 --- a/packages/app/src/plugins.ts +++ b/packages/app/src/plugins.ts @@ -38,5 +38,4 @@ export { plugin as Cloudbuild } from '@backstage/plugin-cloudbuild'; export { plugin as CostInsights } from '@backstage/plugin-cost-insights'; export { plugin as GitHubInsights } from '@roadiehq/backstage-plugin-github-insights'; export { plugin as CatalogImport } from '@backstage/plugin-catalog-import'; -export { plugin as BulkCatalogImport } from '@roadiehq/backstage-plugin-bulk-catalog-import'; export { plugin as UserSettings } from '@backstage/plugin-user-settings'; diff --git a/yarn.lock b/yarn.lock index f0c7c3df0f..695157637c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3228,7 +3228,7 @@ resolved "https://registry.npmjs.org/@material-icons/font/-/font-1.0.3.tgz#f722e5a69a03f20ef47d015cb69420bebeeaabe5" integrity sha512-aIRd0Z9b/HJ/O24KOaP7dNsXypMnXhpWrpLVYvQB/JesVqXYSbioYND200sR+C14a0LSCp+qWnWCnSXmN1hWGw== -"@material-ui/core@^4.11.0", "@material-ui/core@^4.9.1", "@material-ui/core@^4.9.10": +"@material-ui/core@^4.11.0", "@material-ui/core@^4.9.1": version "4.11.0" resolved "https://registry.npmjs.org/@material-ui/core/-/core-4.11.0.tgz#b69b26e4553c9e53f2bfaf1053e216a0af9be15a" integrity sha512-bYo9uIub8wGhZySHqLQ833zi4ZML+XCBE1XwJ8EuUVSpTWWG57Pm+YugQToJNFsEyiKFhPh8DPD0bgupz8n01g== @@ -3264,7 +3264,7 @@ prop-types "^15.7.2" react-is "^16.8.0" -"@material-ui/lab@^4.0.0-alpha.49", "@material-ui/lab@^4.0.0-alpha.56": +"@material-ui/lab@^4.0.0-alpha.56": version "4.0.0-alpha.56" resolved "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.56.tgz#ff63080949b55b40625e056bbda05e130d216d34" integrity sha512-xPlkK+z/6y/24ka4gVJgwPfoCF4RCh8dXb1BNE7MtF9bXEBLN/lBxNTK8VAa0qm3V2oinA6xtUIdcRh0aeRtVw== @@ -3582,7 +3582,7 @@ dependencies: "@types/node" ">= 8" -"@open-draft/until@^1.0.0", "@open-draft/until@^1.0.3": +"@open-draft/until@^1.0.3": version "1.0.3" resolved "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca" integrity sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q== @@ -3663,11 +3663,6 @@ prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" -"@rehooks/local-storage@^2.4.0": - version "2.4.0" - resolved "https://registry.npmjs.org/@rehooks/local-storage/-/local-storage-2.4.0.tgz#fb884b2b657cad5f77aa6ab60bb3532f0e0725d2" - integrity sha512-LoXDbEHsuIckVgBsFAv8SuU/M7memjyfWut9Zf36TQXqqCHBRFv8bweg9PymQCa1aWIMjNrZQflFdo55FDlXYg== - "@rjsf/core@^2.4.0": version "2.4.0" resolved "https://registry.npmjs.org/@rjsf/core/-/core-2.4.0.tgz#c50bcff0d8178948ce08123177399d8816d51929" @@ -3776,19 +3771,6 @@ dependencies: "@rollup/pluginutils" "^3.0.8" -"@rollup/plugin-node-resolve@^8.4.0": - version "8.4.0" - resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz#261d79a680e9dc3d86761c14462f24126ba83575" - integrity sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ== - dependencies: - "@rollup/pluginutils" "^3.1.0" - "@types/resolve" "1.17.1" - builtin-modules "^3.1.0" - deep-freeze "^0.0.1" - deepmerge "^4.2.2" - is-module "^1.0.0" - resolve "^1.17.0" - "@rollup/plugin-node-resolve@^9.0.0": version "9.0.0" resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-9.0.0.tgz#39bd0034ce9126b39c1699695f440b4b7d2b62e6" @@ -3819,15 +3801,6 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@rollup/pluginutils@^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.0.0.tgz#e18e9f5a3925779fc15209dd316c1bd260d195ef" - integrity sha512-b5QiJRye4JlSg29bKNEECoKbLuPXZkPEHSgEjjP1CJV1CPdDBybfYHfm6kyq8yK51h/Zsyl8OvWUrp0FUBukEQ== - dependencies: - "@types/estree" "0.0.45" - estree-walker "^2.0.1" - picomatch "^2.2.2" - "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -4759,7 +4732,7 @@ "@babel/runtime" "^7.5.4" "@types/testing-library__react-hooks" "^3.3.0" -"@testing-library/react-hooks@^3.4.1", "@testing-library/react-hooks@^3.4.2": +"@testing-library/react-hooks@^3.4.2": version "3.4.2" resolved "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-3.4.2.tgz#8deb94f7684e0d896edd84a4c90e5b79a0810bc2" integrity sha512-RfPG0ckOzUIVeIqlOc1YztKgFW+ON8Y5xaSPbiBkfj9nMkkiLhLeBXT5icfPX65oJV/zCZu4z8EVnUc6GY9C5A== @@ -4999,11 +4972,6 @@ dependencies: "@types/express" "*" -"@types/cookie@^0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" - integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== - "@types/cookie@^0.4.0": version "0.4.0" resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108" @@ -5095,11 +5063,6 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/estree@0.0.45": - version "0.0.45" - resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" - integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== - "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.5": version "4.17.9" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz#2d7b34dcfd25ec663c25c85d76608f8b249667f1" @@ -5190,11 +5153,6 @@ resolved "https://registry.npmjs.org/@types/history/-/history-4.7.5.tgz#527d20ef68571a4af02ed74350164e7a67544860" integrity sha512-wLD/Aq2VggCJXSjxEwrMafIP51Z+13H78nXIX0ABEuIGhmB5sNGbR113MOKo+yfw+RDo1ZU3DM6yfnnRF/+ouw== -"@types/history@^4.7.7": - version "4.7.8" - resolved "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" - integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== - "@types/html-minifier-terser@^5.0.0": version "5.1.0" resolved "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880" @@ -6068,7 +6026,7 @@ resolved "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== -"@typescript-eslint/eslint-plugin@^3.8.0", "@typescript-eslint/eslint-plugin@^v3.10.1": +"@typescript-eslint/eslint-plugin@^v3.10.1": version "3.10.1" resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== @@ -6103,7 +6061,7 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^3.8.0", "@typescript-eslint/parser@^v3.10.1": +"@typescript-eslint/parser@^v3.10.1": version "3.10.1" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== @@ -9324,7 +9282,7 @@ cross-env@^7.0.0: dependencies: cross-spawn "^7.0.1" -cross-fetch@3.0.6, cross-fetch@^3.0.4, cross-fetch@^3.0.5, cross-fetch@^3.0.6: +cross-fetch@3.0.6, cross-fetch@^3.0.5, cross-fetch@^3.0.6: version "3.0.6" resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c" integrity sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ== @@ -9690,7 +9648,7 @@ cyclist@^1.0.1: resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= -cypress@*, cypress@^4.11.0, cypress@^4.2.0: +cypress@*, cypress@^4.2.0: version "4.12.1" resolved "https://registry.npmjs.org/cypress/-/cypress-4.12.1.tgz#0ead1b9f4c0917d69d8b57f996b6e01fe693b6ec" integrity sha512-9SGIPEmqU8vuRA6xst2CMTYd9sCFCxKSzrHt0wr+w2iAQMCIIsXsQ5Gplns1sT6LDbZcmLv6uehabAOl3fhc9Q== @@ -9890,7 +9848,7 @@ dateformat@^3.0.0: resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -dayjs@^1.9.1, dayjs@^1.9.4: +dayjs@^1.9.4: version "1.9.4" resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.9.4.tgz#fcde984e227f4296f04e7b05720adad2e1071f1b" integrity sha512-ABSF3alrldf7nM9sQ2U+Ln67NRwmzlLOqG7kK03kck0mw3wlSSEKv/XhKGGxUjQcS57QeiCyNdrFgtj9nWlrng== @@ -10023,11 +9981,6 @@ deep-extend@0.6.0, deep-extend@^0.6.0, deep-extend@~0.6.0: resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-freeze@^0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84" - integrity sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ= - deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -10774,41 +10727,6 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es- string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" -es-abstract@^1.17.5: - version "1.17.7" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" - integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - -es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: - version "1.18.0-next.1" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" - integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-negative-zero "^2.0.0" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - es-array-method-boxes-properly@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" @@ -10899,11 +10817,6 @@ es6-weak-map@^2.0.2: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -esbuild@^0.6.18: - version "0.6.34" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.6.34.tgz#76565a60e006f45d5f273b6e59e61ed0816551f5" - integrity sha512-InRdL/Q96pUucPqovJzvuLhquZr6jOn81FDVwFjCKz1rYKIm9OdOC+7Fs4vr6x48vKBl5LzKgtjU39BUpO636A== - esbuild@^0.7.7: version "0.7.7" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.7.7.tgz#fd86332d1c0a047231bd6da930666028c40c14bf" @@ -10992,13 +10905,6 @@ eslint-plugin-cypress@^2.10.3: dependencies: globals "^11.12.0" -eslint-plugin-cypress@^2.11.1: - version "2.11.2" - resolved "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.2.tgz#a8f3fe7ec840f55e4cea37671f93293e6c3e76a0" - integrity sha512-1SergF1sGbVhsf7MYfOLiBhdOg6wqyeV9pXUAIDIffYTGMN3dTBQS9nFAzhLsHhO+Bn0GaVM1Ecm71XUidQ7VA== - dependencies: - globals "^11.12.0" - eslint-plugin-graphql@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/eslint-plugin-graphql/-/eslint-plugin-graphql-4.0.0.tgz#d238ff2baee4d632cfcbe787a7a70a1f50428358" @@ -11095,23 +11001,6 @@ eslint-plugin-react@^7.12.4: string.prototype.matchall "^4.0.2" xregexp "^4.3.0" -eslint-plugin-react@^7.20.5: - version "7.21.5" - resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz#50b21a412b9574bfe05b21db176e8b7b3b15bff3" - integrity sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g== - dependencies: - array-includes "^3.1.1" - array.prototype.flatmap "^1.2.3" - doctrine "^2.1.0" - has "^1.0.3" - jsx-ast-utils "^2.4.1 || ^3.0.0" - object.entries "^1.1.2" - object.fromentries "^2.0.2" - object.values "^1.1.1" - prop-types "^15.7.2" - resolve "^1.18.1" - string.prototype.matchall "^4.0.2" - eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -11140,11 +11029,6 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - eslint-visitor-keys@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" @@ -11193,49 +11077,6 @@ eslint@^7.1.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@^7.6.0: - version "7.12.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-7.12.0.tgz#7b6a85f87a9adc239e979bb721cde5ce0dc27da6" - integrity sha512-n5pEU27DRxCSlOhJ2rO57GDLcNsxO0LPpAbpFdh7xmcDmjmlGUfoyrsB3I7yYdQXO5N3gkSTiDrPSPNFiiirXA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.2.0" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.0.1" - doctrine "^3.0.0" - enquirer "^2.3.5" - eslint-scope "^5.1.1" - eslint-utils "^2.1.0" - eslint-visitor-keys "^2.0.0" - espree "^7.3.0" - esquery "^1.2.0" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash "^4.17.19" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - esm@^3.2.25: version "3.2.25" resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" @@ -11250,15 +11091,6 @@ espree@^7.3.0: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.3.0" -espree@^7.3.0: - version "7.3.0" - resolved "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" - integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== - dependencies: - acorn "^7.4.0" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.3.0" - esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -12935,7 +12767,7 @@ graphql-upload@^8.0.2: http-errors "^1.7.3" object-path "^0.11.4" -graphql@15.3.0, graphql@^15.0.0, graphql@^15.3.0: +graphql@15.3.0, graphql@^15.3.0: version "15.3.0" resolved "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278" integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w== @@ -13111,7 +12943,7 @@ he@^1.1.0, he@^1.2.0: resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -headers-utils@^1.1.9, headers-utils@^1.2.0: +headers-utils@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/headers-utils/-/headers-utils-1.2.0.tgz#5e10d1bc9d2bccf789547afca5b991a3167241e8" integrity sha512-4/BMXcWrJErw7JpM87gF8MNEXcIMLzepYZjNRv/P9ctgupl2Ywa3u1PgHtNhSRq84bHH9Ndlkdy7bSi+bZ9I9A== @@ -13919,11 +13751,6 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== -is-callable@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" - integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== - is-ci@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -13943,13 +13770,6 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz#58531b70aed1db7c0e8d4eb1a0a2d1ddd64bd12d" - integrity sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw== - dependencies: - has "^1.0.3" - is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -14118,11 +13938,6 @@ is-module@^1.0.0: resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= -is-negative-zero@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" - integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= - is-npm@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" @@ -14225,7 +14040,7 @@ is-promise@^2.1, is-promise@^2.1.0: resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-reference@^1.1.2, is-reference@^1.2.1: +is-reference@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== @@ -14646,14 +14461,6 @@ jest-esm-transformer@^1.0.0: "@babel/core" "^7.4.4" "@babel/plugin-transform-modules-commonjs" "^7.4.4" -jest-fetch-mock@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz#31749c456ae27b8919d69824f1c2bd85fe0a1f3b" - integrity sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw== - dependencies: - cross-fetch "^3.0.4" - promise-polyfill "^8.1.3" - jest-get-type@^25.2.6: version "25.2.6" resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" @@ -14948,11 +14755,6 @@ jose@^2.0.2: dependencies: "@panva/asn1.js" "^1.0.0" -joycon@^2.2.5: - version "2.2.5" - resolved "https://registry.npmjs.org/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615" - integrity sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ== - js-cookie@^2.2.1: version "2.2.1" resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" @@ -15358,14 +15160,6 @@ jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3: array-includes "^3.0.3" object.assign "^4.1.0" -"jsx-ast-utils@^2.4.1 || ^3.0.0": - version "3.1.0" - resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz#642f1d7b88aa6d7eb9d8f2210e166478444fa891" - integrity sha512-d4/UOjg+mxAWxCiF0c5UTSwyqbchkbqCvK87aBovhnh8GtysTjWmgC63tY0cJx/HzGgm9qnA147jVBdpOiQ2RA== - dependencies: - array-includes "^3.1.1" - object.assign "^4.1.1" - jwa@^1.4.1: version "1.4.1" resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" @@ -16126,7 +15920,7 @@ macos-release@^2.2.0: resolved "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== -magic-string@^0.25.2, magic-string@^0.25.7: +magic-string@^0.25.7: version "0.25.7" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== @@ -16919,22 +16713,6 @@ ms@2.1.2, ms@^2.0.0, ms@^2.1.1: resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -msw@^0.19.5: - version "0.19.5" - resolved "https://registry.npmjs.org/msw/-/msw-0.19.5.tgz#7d2a1a852ccf1644d3db6735d69fff6777aac33f" - integrity sha512-J5eQ++gDVZoHPC8gVXtWcakLjgmPipvFj/sEnlRV/WViXuiq2CamSqO3Wbh6H8bAmj+k2vUWCfcVT1HjMdKB2Q== - dependencies: - "@open-draft/until" "^1.0.0" - "@types/cookie" "^0.3.3" - chalk "^4.0.0" - cookie "^0.4.1" - graphql "^15.0.0" - headers-utils "^1.1.9" - node-match-path "^0.4.2" - node-request-interceptor "^0.2.5" - statuses "^2.0.0" - yargs "^15.3.1" - msw@^0.20.5: version "0.20.5" resolved "https://registry.npmjs.org/msw/-/msw-0.20.5.tgz#b6141080c0d8b17c451d9ca36c28cc47b4ac487a" @@ -17248,7 +17026,7 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-match-path@^0.4.2, node-match-path@^0.4.4: +node-match-path@^0.4.4: version "0.4.4" resolved "https://registry.npmjs.org/node-match-path/-/node-match-path-0.4.4.tgz#516a10926093c0cc6f237d020685b593b19baebb" integrity sha512-pBq9gp7TG0r0VXuy/oeZmQsjBSnYQo7G886Ly/B3azRwZuEtHCY155dzmfoKWcDPGgyfIGD8WKVC7h3+6y7yTg== @@ -17307,14 +17085,6 @@ node-releases@^1.1.52, node-releases@^1.1.58: resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== -node-request-interceptor@^0.2.5: - version "0.2.6" - resolved "https://registry.npmjs.org/node-request-interceptor/-/node-request-interceptor-0.2.6.tgz#541278d7033bb6a8befb5dd793f83428cf6446a2" - integrity sha512-aJW1tPSM7nzuZFRe+C/KSz22GJO3CVFMxHHmMGX8Z+tjP7TCIVbzeckLFVfJG68BdVgrdOOP7Ejc57ag820eyA== - dependencies: - debug "^4.1.1" - headers-utils "^1.2.0" - node-request-interceptor@^0.3.5: version "0.3.5" resolved "https://registry.npmjs.org/node-request-interceptor/-/node-request-interceptor-0.3.5.tgz#4b26159617829c9a70643012c0fdc3ae4c78ae43" @@ -17577,11 +17347,6 @@ object-inspect@^1.7.0: resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-inspect@^1.8.0: - version "1.8.0" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" - integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== - object-is@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" @@ -17614,16 +17379,6 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.assign@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" - integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.0" - has-symbols "^1.0.1" - object-keys "^1.1.1" - object.defaults@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" @@ -17644,15 +17399,6 @@ object.entries@^1.1.0, object.entries@^1.1.1: function-bind "^1.1.1" has "^1.0.3" -object.entries@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" - integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - has "^1.0.3" - "object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" @@ -19303,11 +19049,6 @@ promise-inflight@^1.0.1: resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= -promise-polyfill@^8.1.3: - version "8.2.0" - resolved "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.0.tgz#367394726da7561457aba2133c9ceefbd6267da0" - integrity sha512-k/TC0mIcPVF6yHhUvwAp7cvL6I2fFV7TzF1DuGPI8mBh4QQazf36xCKEHKTZKRysEoTQoQdKyP25J8MPJp7j5g== - promise-retry@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" @@ -20062,7 +19803,7 @@ react-router-dom@^5.2.0: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.2.0, react-router@^5.2.0: +react-router@5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293" integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw== @@ -20931,14 +20672,6 @@ resolve@1.17.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0 dependencies: path-parse "^1.0.6" -resolve@^1.11.0, resolve@^1.18.1: - version "1.18.1" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" - integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== - dependencies: - is-core-module "^2.0.0" - path-parse "^1.0.6" - responselike@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -21053,20 +20786,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rollup-plugin-dts@1.4.13, rollup-plugin-dts@^1.4.10: +rollup-plugin-dts@1.4.13: version "1.4.13" resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-1.4.13.tgz#4f086e84f4fdcc1f49160799ebc66f6b09db292b" integrity sha512-7mxoQ6PcmCkBE5ZhrjGDL4k42XLy8BkSqpiRi1MipwiGs+7lwi4mQkp2afX+OzzLjJp/TGM8llfe8uayIUhPEw== optionalDependencies: "@babel/code-frame" "^7.10.4" -rollup-plugin-dts@1.4.8: - version "1.4.8" - resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-1.4.8.tgz#3b0eadc285aede11c3f5ced72b56b5f7735df95c" - integrity sha512-2qHB4B3oaTyi1mDmqDzsRGKlev32v3EhMUAmc45Cn9eB22R7FsYDiigvT9XdM/oQzfd0qv5MkeZju8DP0nauiA== - optionalDependencies: - "@babel/code-frame" "^7.10.4" - rollup-plugin-esbuild@^2.0.0: version "2.3.0" resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-2.3.0.tgz#7c107d4508af80d30966a148b306cb7d5b36b258" @@ -21074,25 +20800,11 @@ rollup-plugin-esbuild@^2.0.0: dependencies: "@rollup/pluginutils" "^3.1.0" -rollup-plugin-esbuild@^2.4.2: - version "2.5.2" - resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-2.5.2.tgz#fd7d4a88518898012a9d07e4c3ef8b4009c244d3" - integrity sha512-E4q3ac1AlMd0m0ZRYffdiorOt2eZcxfbdPaqBLs7JLnPE8krgIAihOD6cTUc54UJjoOMA9WcY63TR+JKWLzYNw== - dependencies: - "@rollup/pluginutils" "^4.0.0" - joycon "^2.2.5" - strip-json-comments "^3.1.1" - rollup-plugin-peer-deps-external@^2.2.2: version "2.2.3" resolved "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.3.tgz#059a8aec1eefb48a475e9fcedc3b9e3deb521213" integrity sha512-W6IePXTExGXVDAlfZbNUUrx3GxUOZP248u5n4a4ID1XZMrbQ+uGeNiEfapvdzwx0qZi5DNH/hDLiPUP+pzFIxg== -rollup-plugin-peer-deps-external@^2.2.3: - version "2.2.4" - resolved "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz#8a420bbfd6dccc30aeb68c9bf57011f2f109570d" - integrity sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g== - rollup-plugin-postcss@^3.1.1: version "3.1.8" resolved "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-3.1.8.tgz#d1bcaf8eb0fcb0936e3684c22dd8628d13a82fd1" @@ -21131,13 +20843,6 @@ rollup-pluginutils@^2.8.2: dependencies: estree-walker "^0.6.1" -rollup@2.23.1: - version "2.23.1" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.23.1.tgz#d458d28386dc7660c2e8a4978bea6f9494046c20" - integrity sha512-Heyl885+lyN/giQwxA8AYT2GY3U+gOlTqVLrMQYno8Z1X9lAOpfXPiKiZCyPc25e9BLJM3Zlh957dpTlO4pa8A== - optionalDependencies: - fsevents "~2.1.2" - rollup@2.23.x: version "2.23.0" resolved "https://registry.npmjs.org/rollup/-/rollup-2.23.0.tgz#b7ab1fee0c0e60132fd0553c4df1e9cdacfada9d" @@ -21153,13 +20858,6 @@ rollup@^0.63.4: "@types/estree" "0.0.39" "@types/node" "*" -rollup@^2.23.1: - version "2.32.1" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz#625a92c54f5b4d28ada12d618641491d4dbb548c" - integrity sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw== - optionalDependencies: - fsevents "~2.1.2" - rsvp@^4.8.4: version "4.8.5" resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -22281,14 +21979,6 @@ string.prototype.padstart@^3.0.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -string.prototype.trimend@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" - integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - string.prototype.trimleft@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" @@ -22305,14 +21995,6 @@ string.prototype.trimright@^2.1.1: define-properties "^1.1.3" function-bind "^1.1.1" -string.prototype.trimstart@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" - integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -22415,11 +22097,6 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" From c6332546e6d8445db5d8dbccabfb73d2cd809035 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Wed, 18 Nov 2020 23:23:54 +0100 Subject: [PATCH 17/32] Apply Code review fixes --- plugins/catalog-backend/src/service/router.ts | 2 +- plugins/catalog-import/package.json | 12 +++++------ .../src/api/CatalogImportApi.ts | 1 - .../src/api/CatalogImportClient.ts | 20 ++++++++++++++----- plugins/catalog-import/src/plugin.ts | 6 ++++-- .../catalog-import/src/util/useGithubRepos.ts | 6 +----- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/plugins/catalog-backend/src/service/router.ts b/plugins/catalog-backend/src/service/router.ts index fd9062bf94..e850792936 100644 --- a/plugins/catalog-backend/src/service/router.ts +++ b/plugins/catalog-backend/src/service/router.ts @@ -144,7 +144,7 @@ export async function createRouter( router.post('/analyze-location', async (req, res) => { const input = await validateRequestBody(req, analyzeLocationSchema); const output = await locationAnalyzer.generateConfig(input); - res.status(201).send(output); + res.status(200).send(output); }); } diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index d6a08a35c7..ee157235ca 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/plugin-catalog-backend": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/plugin-catalog-backend": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", diff --git a/plugins/catalog-import/src/api/CatalogImportApi.ts b/plugins/catalog-import/src/api/CatalogImportApi.ts index 7ecb4a543b..49012764e2 100644 --- a/plugins/catalog-import/src/api/CatalogImportApi.ts +++ b/plugins/catalog-import/src/api/CatalogImportApi.ts @@ -24,7 +24,6 @@ export const catalogImportApiRef = createApiRef({ export interface CatalogImportApi { submitPrToRepo(options: { - oAuthToken: string; owner: string; repo: string; fileContent: string; diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index cef4b2da0e..f8b4e5d17e 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -15,16 +15,26 @@ */ import { Octokit } from '@octokit/rest'; -import { DiscoveryApi } from '@backstage/core'; +import { + DiscoveryApi, + githubAuthApiRef, + OAuthApi, + useApi, +} from '@backstage/core'; import { CatalogImportApi } from './CatalogImportApi'; import { AnalyzeLocationResponse } from '@backstage/plugin-catalog-backend'; import { PartialEntity } from '../util/types'; export class CatalogImportClient implements CatalogImportApi { private readonly discoveryApi: DiscoveryApi; + private readonly githubAuthApi: OAuthApi; - constructor(options: { discoveryApi: DiscoveryApi }) { + constructor(options: { + discoveryApi: DiscoveryApi; + githubAuthApi: OAuthApi; + }) { this.discoveryApi = options.discoveryApi; + this.githubAuthApi = options.githubAuthApi; } async generateEntityDefinitions({ @@ -83,18 +93,18 @@ export class CatalogImportClient implements CatalogImportApi { } async submitPrToRepo({ - oAuthToken, owner, repo, fileContent, }: { - oAuthToken: string; owner: string; repo: string; fileContent: string; }): Promise<{ link: string; location: string }> { + const token = await this.githubAuthApi.getAccessToken(['repo']); + const octo = new Octokit({ - auth: oAuthToken, + auth: token, }); const branchName = 'backstage-integration'; diff --git a/plugins/catalog-import/src/plugin.ts b/plugins/catalog-import/src/plugin.ts index caac764513..3ce4918553 100644 --- a/plugins/catalog-import/src/plugin.ts +++ b/plugins/catalog-import/src/plugin.ts @@ -19,6 +19,7 @@ import { createPlugin, createRouteRef, discoveryApiRef, + githubAuthApiRef, } from '@backstage/core'; import { catalogImportApiRef } from './api/CatalogImportApi'; import { CatalogImportClient } from './api/CatalogImportClient'; @@ -33,8 +34,9 @@ export const plugin = createPlugin({ apis: [ createApiFactory({ api: catalogImportApiRef, - deps: { discoveryApi: discoveryApiRef }, - factory: ({ discoveryApi }) => new CatalogImportClient({ discoveryApi }), + deps: { discoveryApi: discoveryApiRef, githubAuthApi: githubAuthApiRef }, + factory: ({ discoveryApi, githubAuthApi }) => + new CatalogImportClient({ discoveryApi, githubAuthApi }), }), ], }); diff --git a/plugins/catalog-import/src/util/useGithubRepos.ts b/plugins/catalog-import/src/util/useGithubRepos.ts index 84c594c913..a18edc2777 100644 --- a/plugins/catalog-import/src/util/useGithubRepos.ts +++ b/plugins/catalog-import/src/util/useGithubRepos.ts @@ -15,21 +15,17 @@ */ import * as YAML from 'yaml'; -import { useApi, githubAuthApiRef } from '@backstage/core'; +import { useApi } from '@backstage/core'; import { catalogImportApiRef } from '../api/CatalogImportApi'; import { ConfigSpec } from '../components/ImportComponentPage'; export function useGithubRepos() { const api = useApi(catalogImportApiRef); - const auth = useApi(githubAuthApiRef); const submitPrToRepo = async (selectedRepo: ConfigSpec) => { - const token = await auth.getAccessToken(['repo']); - const [ownerName, repoName] = selectedRepo.location.split('/').slice(-2); const submitPRResponse = await api .submitPrToRepo({ - oAuthToken: token, owner: ownerName, repo: repoName, fileContent: selectedRepo.config From eb422ee1bf2c888ee68aca0ea94e4b8e83ddc3ea Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 19 Nov 2020 15:35:25 +0100 Subject: [PATCH 18/32] Fixes after merge --- packages/app/package.json | 1 + plugins/catalog-backend/src/ingestion/types.ts | 2 +- plugins/catalog-import/package.json | 8 ++++---- plugins/catalog-import/src/api/CatalogImportClient.ts | 7 +------ 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/app/package.json b/packages/app/package.json index de6b61684a..6d31adfa65 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -9,6 +9,7 @@ "@backstage/core": "^0.3.0", "@backstage/plugin-api-docs": "^0.2.1", "@backstage/plugin-catalog": "^0.2.1", + "@backstage/plugin-catalog-import": "^0.2.0", "@backstage/plugin-circleci": "^0.2.1", "@backstage/plugin-cloudbuild": "^0.2.1", "@backstage/plugin-cost-insights": "^0.3.0", diff --git a/plugins/catalog-backend/src/ingestion/types.ts b/plugins/catalog-backend/src/ingestion/types.ts index 29308fdd92..79a5387247 100644 --- a/plugins/catalog-backend/src/ingestion/types.ts +++ b/plugins/catalog-backend/src/ingestion/types.ts @@ -20,7 +20,7 @@ import { Location, LocationSpec, } from '@backstage/catalog-model'; -import { RecursivePartial } from './processors/ldap/util'; +import { RecursivePartial } from '../util/RecursivePartial'; // // HigherOrderOperation diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index ee157235ca..4666e22f10 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.2.0", - "@backstage/core": "^0.2.0", + "@backstage/core": "^0.3.0", "@backstage/plugin-catalog": "^0.2.0", "@backstage/plugin-catalog-backend": "^0.2.0", "@backstage/theme": "^0.2.0", @@ -40,9 +40,9 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.0", + "@backstage/test-utils": "^0.1.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index f8b4e5d17e..94ba260d55 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -15,12 +15,7 @@ */ import { Octokit } from '@octokit/rest'; -import { - DiscoveryApi, - githubAuthApiRef, - OAuthApi, - useApi, -} from '@backstage/core'; +import { DiscoveryApi, OAuthApi } from '@backstage/core'; import { CatalogImportApi } from './CatalogImportApi'; import { AnalyzeLocationResponse } from '@backstage/plugin-catalog-backend'; import { PartialEntity } from '../util/types'; From 46e9cf5b63b8a10c32bf830a00339d035bf570d8 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 19 Nov 2020 15:55:27 +0100 Subject: [PATCH 19/32] Bump package versions --- plugins/catalog-import/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 4666e22f10..b53c4ec00d 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -25,7 +25,7 @@ "@backstage/core": "^0.3.0", "@backstage/plugin-catalog": "^0.2.0", "@backstage/plugin-catalog-backend": "^0.2.0", - "@backstage/theme": "^0.2.0", + "@backstage/theme": "^0.2.1", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,8 +41,8 @@ }, "devDependencies": { "@backstage/cli": "^0.2.0", - "@backstage/dev-utils": "^0.1.0", - "@backstage/test-utils": "^0.1.0", + "@backstage/dev-utils": "^0.1.3", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", From 9183042be7a4ffb5c10d7ae16819f2b4e295caa3 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Fri, 20 Nov 2020 09:37:56 +0100 Subject: [PATCH 20/32] Bump backstage-cli dependency --- plugins/catalog-import/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index b53c4ec00d..25d2523dd8 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -40,7 +40,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.2.0", + "@backstage/cli": "^0.3.0", "@backstage/dev-utils": "^0.1.3", "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", From cb27aac51506134c5be4a91eed8837444f154b1e Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Fri, 20 Nov 2020 12:42:10 +0100 Subject: [PATCH 21/32] Bump package versions --- plugins/catalog-import/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 25d2523dd8..2fbea6a17c 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.2.0", - "@backstage/core": "^0.3.0", + "@backstage/core": "^0.3.1", "@backstage/plugin-catalog": "^0.2.0", "@backstage/plugin-catalog-backend": "^0.2.0", "@backstage/theme": "^0.2.1", @@ -41,8 +41,8 @@ }, "devDependencies": { "@backstage/cli": "^0.3.0", - "@backstage/dev-utils": "^0.1.3", - "@backstage/test-utils": "^0.1.2", + "@backstage/dev-utils": "^0.1.4", + "@backstage/test-utils": "^0.1.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", From bd613dd8509b5173e050fff196e480f46b0f0d42 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Fri, 20 Nov 2020 14:30:49 +0100 Subject: [PATCH 22/32] Code review adjustments --- plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts | 6 +++--- plugins/catalog-backend/src/ingestion/types.ts | 8 +++++++- plugins/catalog-backend/src/service/CatalogBuilder.ts | 4 ++-- plugins/catalog-backend/src/service/router.ts | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts index 611505d707..97df326fc5 100644 --- a/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts +++ b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts @@ -22,13 +22,13 @@ import { LocationAnalyzer, } from './types'; -export class LocationAnalyzerClient implements LocationAnalyzer { +export class RepoLocationAnalyzer implements LocationAnalyzer { private readonly logger: Logger; constructor(logger: Logger) { this.logger = logger; } - async generateConfig( + async analyzeLocation( request: AnalyzeLocationRequest, ): Promise { const { owner, name, source } = parseGitUri(request.location.target); @@ -40,7 +40,7 @@ export class LocationAnalyzerClient implements LocationAnalyzer { // Probably won't handle properly self-hosted git providers with custom url annotations: { [`${source}/project-slug`]: `${owner}/${name}` }, }, - spec: { type: 'other', owner: owner, lifecycle: 'unknown' }, + spec: { type: 'other', lifecycle: 'unknown' }, }; this.logger.debug(`entity created for ${request.location.target}`); diff --git a/plugins/catalog-backend/src/ingestion/types.ts b/plugins/catalog-backend/src/ingestion/types.ts index 79a5387247..c8d642b6b5 100644 --- a/plugins/catalog-backend/src/ingestion/types.ts +++ b/plugins/catalog-backend/src/ingestion/types.ts @@ -75,7 +75,13 @@ export type ReadLocationError = { // export type LocationAnalyzer = { - generateConfig( + /** + * Generates an entity configuration for given git repository. It's used for + * importing new component to the backstage app. + * + * @param location Git repository to analyze and generate config for. + */ + analyzeLocation( location: AnalyzeLocationRequest, ): Promise; }; diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 439b85591f..0fee610ce6 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -52,7 +52,7 @@ import { UrlReaderProcessor, } from '../ingestion'; import { CatalogRulesEnforcer } from '../ingestion/CatalogRules'; -import { LocationAnalyzerClient } from '../ingestion/LocationAnalyzer'; +import { RepoLocationAnalyzer } from '../ingestion/LocationAnalyzer'; import { BuiltinKindsEntityProcessor } from '../ingestion/processors/BuiltinKindsEntityProcessor'; import { LdapOrgReaderProcessor } from '../ingestion/processors/LdapOrgReaderProcessor'; import { @@ -232,7 +232,7 @@ export class CatalogBuilder { locationReader, logger, ); - const locationAnalyzer = new LocationAnalyzerClient(logger); + const locationAnalyzer = new RepoLocationAnalyzer(logger); return { entitiesCatalog, diff --git a/plugins/catalog-backend/src/service/router.ts b/plugins/catalog-backend/src/service/router.ts index d11ed49253..43c2967233 100644 --- a/plugins/catalog-backend/src/service/router.ts +++ b/plugins/catalog-backend/src/service/router.ts @@ -139,7 +139,7 @@ export async function createRouter( if (locationAnalyzer) { router.post('/analyze-location', async (req, res) => { const input = await validateRequestBody(req, analyzeLocationSchema); - const output = await locationAnalyzer.generateConfig(input); + const output = await locationAnalyzer.analyzeLocation(input); res.status(200).send(output); }); } From a9fd599f7a374ec14c83c964ed7c6054813feb33 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Fri, 20 Nov 2020 15:41:47 +0100 Subject: [PATCH 23/32] Add chengeset --- .changeset/smart-turkeys-bathe.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/smart-turkeys-bathe.md diff --git a/.changeset/smart-turkeys-bathe.md b/.changeset/smart-turkeys-bathe.md new file mode 100644 index 0000000000..9e8ca1270e --- /dev/null +++ b/.changeset/smart-turkeys-bathe.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-catalog-backend': minor +'@backstage/plugin-catalog-import': minor +'example-app': patch +'example-backend': patch +'@backstage/catalog-model': patch +'@backstage/plugin-scaffolder': patch +--- + +Add Analyze location endpoint to catalog backend. Add catalog-import plugin and replace import-component with it. From d74f239d5cf4e29af2767ebf28016b3242e5a2d3 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Fri, 20 Nov 2020 16:03:51 +0100 Subject: [PATCH 24/32] Bump packages and add migration instruction Migration instruction added to the changeset file. --- .changeset/smart-turkeys-bathe.md | 22 ++++++++++++++++++++- packages/backend/package.json | 2 +- plugins/catalog-backend/package.json | 2 +- plugins/catalog-import/package.json | 2 +- yarn.lock | 29 ++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/.changeset/smart-turkeys-bathe.md b/.changeset/smart-turkeys-bathe.md index 9e8ca1270e..f7776a81aa 100644 --- a/.changeset/smart-turkeys-bathe.md +++ b/.changeset/smart-turkeys-bathe.md @@ -7,4 +7,24 @@ '@backstage/plugin-scaffolder': patch --- -Add Analyze location endpoint to catalog backend. Add catalog-import plugin and replace import-component with it. +Add Analyze location endpoint to catalog backend. Add catalog-import plugin and replace import-component with it. To start using Analyze location endpoint, you have add it to the `createRouter` function options in the `\backstage\packages\backend\src\plugins\catalog.ts` file: + +```ts +export default async function createPlugin(env: PluginEnvironment) { + const builder = new CatalogBuilder(env); + const { + entitiesCatalog, + locationsCatalog, + higherOrderOperation, + locationAnalyzer, //<-- + } = await builder.build(); + + return await createRouter({ + entitiesCatalog, + locationsCatalog, + higherOrderOperation, + locationAnalyzer, //<-- + logger: env.logger, + }); +} +``` diff --git a/packages/backend/package.json b/packages/backend/package.json index 014a3f78d5..5011c21c14 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -23,7 +23,7 @@ "@backstage/config": "^0.1.1", "@backstage/plugin-app-backend": "^0.3.0", "@backstage/plugin-auth-backend": "^0.2.2", - "@backstage/plugin-catalog-backend": "^0.2.1", + "@backstage/plugin-catalog-backend": "^0.3.0", "@backstage/plugin-graphql-backend": "^0.1.3", "@backstage/plugin-kubernetes-backend": "^0.1.3", "@backstage/plugin-proxy-backend": "^0.2.1", diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 711a91dd8d..36ebbedab4 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.2.1", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 2fbea6a17c..ac41d70c30 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -24,7 +24,7 @@ "@backstage/catalog-model": "^0.2.0", "@backstage/core": "^0.3.1", "@backstage/plugin-catalog": "^0.2.0", - "@backstage/plugin-catalog-backend": "^0.2.0", + "@backstage/plugin-catalog-backend": "^0.3.0", "@backstage/theme": "^0.2.1", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/yarn.lock b/yarn.lock index c7e518ede3..23e422b9ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1325,6 +1325,35 @@ react-use "^15.3.3" remark-gfm "^1.0.0" +"@backstage/plugin-catalog-backend@^0.2.1": + version "0.2.1" + resolved "https://registry.npmjs.org/@backstage/plugin-catalog-backend/-/plugin-catalog-backend-0.2.1.tgz#d63d1d145d97a5f1021c3e6c2ab680729be43e74" + integrity sha512-9OwM7JobjCvmNomsT2HbMyzgoWX+ztVGG4ebN3x/r75+sI55Dj3J29O9CRP7r86BIJ7bi1RWaLTycXX+CmuQ0Q== + dependencies: + "@backstage/backend-common" "^0.3.0" + "@backstage/catalog-model" "^0.2.0" + "@backstage/config" "^0.1.1" + "@octokit/graphql" "^4.5.6" + "@types/express" "^4.17.6" + codeowners-utils "^1.0.2" + core-js "^3.6.5" + cross-fetch "^3.0.6" + express "^4.17.1" + express-promise-router "^3.0.3" + fs-extra "^9.0.0" + git-url-parse "^11.4.0" + knex "^0.21.6" + ldapjs "^2.2.0" + lodash "^4.17.15" + morgan "^1.10.0" + p-limit "^3.0.2" + sqlite3 "^5.0.0" + uuid "^8.0.0" + winston "^3.2.1" + yaml "^1.9.2" + yn "^4.0.0" + yup "^0.29.3" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" From cb16f9ebfc61caaa65d5c3d3f3fdfe81977c1b97 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Mon, 23 Nov 2020 19:34:15 +0100 Subject: [PATCH 25/32] Code review fixes --- packages/app/src/App.tsx | 2 +- .../src/components/ComponentConfigDisplay.tsx | 32 ++++++++++++++++--- .../src/components/ImportFinished.tsx | 7 +++- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index c02d83841f..28aebeeb79 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -69,7 +69,7 @@ const AppRoutes = () => ( } /> void; + nextStep: (options?: { reset: boolean }) => void; configFile: ConfigSpec; savePRLink: (PRLink: string) => void; catalogRouteRef: RouteRef; @@ -74,6 +74,7 @@ const ComponentConfigDisplay = ({ savePRLink, catalogRouteRef, }: Props) => { + const [errorOccured, setErrorOccured] = useState(false); const [submitting, setSubmitting] = useState(false); const errorApi = useApi(errorApiRef); const { submitPrToRepo, addLocation } = useGithubRepos(); @@ -91,6 +92,7 @@ const ComponentConfigDisplay = ({ nextStep(); } } catch (e) { + setErrorOccured(true); setSubmitting(false); errorApi.post(e); } @@ -102,13 +104,25 @@ const ComponentConfigDisplay = ({ Following config object will be submitted in a pull request to the repository{' '} - {configFile.location} and - added as a new location to the backend + + {configFile.location} + {' '} + and added as a new location to the backend ) : ( Following config object will be added as a new location to the backend{' '} - {configFile.location} + + {configFile.location} + )} @@ -164,6 +178,16 @@ const ComponentConfigDisplay = ({ > Next + {errorOccured ? ( + + ) : null} diff --git a/plugins/catalog-import/src/components/ImportFinished.tsx b/plugins/catalog-import/src/components/ImportFinished.tsx index 9a06de234b..caba678999 100644 --- a/plugins/catalog-import/src/components/ImportFinished.tsx +++ b/plugins/catalog-import/src/components/ImportFinished.tsx @@ -36,7 +36,12 @@ export const ImportFinished = ({ nextStep, PRLink, type }: Props) => { {type === 'repo' ? ( - + View pull request on GitHub ) : null} From faa73389f2c87f7afcd99674c6655a2bf4c628f5 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 26 Nov 2020 06:29:29 +0100 Subject: [PATCH 26/32] Change package versions --- .changeset/smart-turkeys-bathe.md | 2 -- packages/app/package.json | 2 +- packages/backend/package.json | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.changeset/smart-turkeys-bathe.md b/.changeset/smart-turkeys-bathe.md index f7776a81aa..5f429b5b37 100644 --- a/.changeset/smart-turkeys-bathe.md +++ b/.changeset/smart-turkeys-bathe.md @@ -1,8 +1,6 @@ --- '@backstage/plugin-catalog-backend': minor '@backstage/plugin-catalog-import': minor -'example-app': patch -'example-backend': patch '@backstage/catalog-model': patch '@backstage/plugin-scaffolder': patch --- diff --git a/packages/app/package.json b/packages/app/package.json index 0ee1b47e57..52906bb65a 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.2", + "version": "0.2.1", "private": true, "bundled": true, "dependencies": { diff --git a/packages/backend/package.json b/packages/backend/package.json index 5011c21c14..410aca1087 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.2", + "version": "0.2.1", "main": "dist/index.cjs.js", "types": "src/index.ts", "private": true, @@ -35,7 +35,7 @@ "@octokit/rest": "^18.0.0", "azure-devops-node-api": "^10.1.1", "dockerode": "^3.2.0", - "example-app": "^0.2.2", + "example-app": "^0.2.1", "express": "^4.17.1", "express-promise-router": "^3.0.3", "knex": "^0.21.6", From 8e7696d533c31610f66b977c561f7118994c2ea1 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 26 Nov 2020 09:24:30 +0100 Subject: [PATCH 27/32] Fix after merge --- packages/app/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/app/package.json b/packages/app/package.json index 9e54005cd3..37919b2d31 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -9,6 +9,7 @@ "@backstage/core": "^0.3.2", "@backstage/plugin-api-docs": "^0.2.2", "@backstage/plugin-catalog": "^0.2.3", + "@backstage/plugin-catalog-import": "^0.2.0", "@backstage/plugin-circleci": "^0.2.2", "@backstage/plugin-cloudbuild": "^0.2.2", "@backstage/plugin-cost-insights": "^0.4.1", From 8bef6b9a5f65e5f4fa33002fe89975f051a62217 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 26 Nov 2020 10:18:45 +0100 Subject: [PATCH 28/32] Fix after merge --- plugins/catalog-import/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index ac41d70c30..2a44d7555a 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.2.0", - "@backstage/core": "^0.3.1", + "@backstage/core": "^0.3.2", "@backstage/plugin-catalog": "^0.2.0", "@backstage/plugin-catalog-backend": "^0.3.0", "@backstage/theme": "^0.2.1", @@ -40,7 +40,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.3.0", + "@backstage/cli": "^0.3.1", "@backstage/dev-utils": "^0.1.4", "@backstage/test-utils": "^0.1.3", "@testing-library/jest-dom": "^5.10.1", From 0dedb26e10e4972951c1c7d9c6cdf72c07bb086e Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 26 Nov 2020 11:54:20 +0100 Subject: [PATCH 29/32] Revert catalog-backend version to 0.2.2 --- packages/backend/package.json | 2 +- plugins/catalog-backend/package.json | 2 +- plugins/catalog-import/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index b9daf224f0..5d3678a284 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -23,7 +23,7 @@ "@backstage/config": "^0.1.1", "@backstage/plugin-app-backend": "^0.3.0", "@backstage/plugin-auth-backend": "^0.2.3", - "@backstage/plugin-catalog-backend": "^0.3.0", + "@backstage/plugin-catalog-backend": "^0.2.2", "@backstage/plugin-graphql-backend": "^0.1.3", "@backstage/plugin-kubernetes-backend": "^0.2.0", "@backstage/plugin-proxy-backend": "^0.2.1", diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index d3c77db6dc..26f7180d43 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.3.0", + "version": "0.2.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 2a44d7555a..8efa765224 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -24,7 +24,7 @@ "@backstage/catalog-model": "^0.2.0", "@backstage/core": "^0.3.2", "@backstage/plugin-catalog": "^0.2.0", - "@backstage/plugin-catalog-backend": "^0.3.0", + "@backstage/plugin-catalog-backend": "^0.2.2", "@backstage/theme": "^0.2.1", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", From 852229a3b88b77f1f3221a84967e61e6178deb1a Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Thu, 26 Nov 2020 15:47:21 +0100 Subject: [PATCH 30/32] Update yarn.lock --- yarn.lock | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3a64cb0f25..b8093d125d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1320,37 +1320,6 @@ uuid "^8.0.0" yup "^0.29.3" -"@backstage/plugin-catalog-backend@^0.2.2": - version "0.2.2" - resolved "https://registry.npmjs.org/@backstage/plugin-catalog-backend/-/plugin-catalog-backend-0.2.2.tgz#4e17e0376a920f1425de5b0997d34134ff101a11" - integrity sha512-2pxcqQ3C+FGqYDwL7dkMm76zNM75IF1P8rb3iKrbv8qRRwPqtT0wUx+Gctv3RSL8WgGyCxP1Ho9dQ+FC7o2YSQ== - dependencies: - "@azure/msal-node" "^1.0.0-alpha.8" - "@backstage/backend-common" "^0.3.1" - "@backstage/catalog-model" "^0.3.0" - "@backstage/config" "^0.1.1" - "@octokit/graphql" "^4.5.6" - "@types/express" "^4.17.6" - codeowners-utils "^1.0.2" - core-js "^3.6.5" - cross-fetch "^3.0.6" - express "^4.17.1" - express-promise-router "^3.0.3" - fs-extra "^9.0.0" - git-url-parse "^11.4.0" - knex "^0.21.6" - ldapjs "^2.2.0" - lodash "^4.17.15" - morgan "^1.10.0" - p-limit "^3.0.2" - qs "^6.9.4" - sqlite3 "^5.0.0" - uuid "^8.0.0" - winston "^3.2.1" - yaml "^1.9.2" - yn "^4.0.0" - yup "^0.29.3" - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" From b26e3dacd9b4084e812f73f27afe59bede8b0e69 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Fri, 27 Nov 2020 16:37:48 +0100 Subject: [PATCH 31/32] Fixdependency version --- plugins/catalog-import/package.json | 2 +- yarn.lock | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 8efa765224..eb3ce1bd2c 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -21,7 +21,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.2.0", + "@backstage/catalog-model": "^0.3.0", "@backstage/core": "^0.3.2", "@backstage/plugin-catalog": "^0.2.0", "@backstage/plugin-catalog-backend": "^0.2.2", diff --git a/yarn.lock b/yarn.lock index b8093d125d..b37657b34a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1308,9 +1308,7 @@ to-fast-properties "^2.0.0" "@backstage/catalog-model@^0.2.0": - version "0.2.0" - resolved "https://registry.npmjs.org/@backstage/catalog-model/-/catalog-model-0.2.0.tgz#e3fe2a4ddeb6a9b6ec480c80cb2b9c39cb245576" - integrity sha512-Y1ocdRpBlxK/VrJQjHlQd0bgADECd1B2NRjwd8ss46ibT5hwLvMOfD80+Fa7oPLu0ktJrH4lq0pNIIJIml48zA== + version "0.3.0" dependencies: "@backstage/config" "^0.1.1" "@types/json-schema" "^7.0.5" From 880ba03d20bee94e98c92a843e25d4803e916f36 Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Sun, 29 Nov 2020 19:05:02 +0100 Subject: [PATCH 32/32] Update package.json --- plugins/catalog-import/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index eb3ce1bd2c..11562b741e 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -40,7 +40,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.3.1", + "@backstage/cli": "^0.3.2", "@backstage/dev-utils": "^0.1.4", "@backstage/test-utils": "^0.1.3", "@testing-library/jest-dom": "^5.10.1",